Add 3d table support to the java config file parser. (#3464)

This removes the need to use custom for 3d tables.  Syntax (to avoid changing the ANTLR parser) is
to use 'x' instead of separate [], i.e.:
        uint16_t[HPFP_TARGET_SIZE x HPFP_TARGET_SIZE] hpfpTarget;;"kPa", 1, 0, 0, 65000, 0
This commit is contained in:
Scott Smith 2021-11-05 11:27:32 -07:00 committed by GitHub
parent 8c96be4482
commit 8e5d65978a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 89 additions and 48 deletions

View File

@ -1991,6 +1991,3 @@ end_struct
! we need to improve this further - at the moment we need too many boards to prepend 'false'
#define show_test_presets true
#define show_Frankenso_presets true
! poke

Binary file not shown.

View File

@ -14,9 +14,10 @@ import java.util.regex.Pattern;
* 1/15/15
*/
public class ConfigField {
public static final ConfigField VOID = new ConfigField(null, "", null, null, null, 1, null, false, false, null,null, -1, null, null);
public static final ConfigField VOID = new ConfigField(null, "", null, null, null, new int[0], null, false, false, null,null, -1, null, null);
private static final String typePattern = "([\\w\\d_]+)(\\[([\\w\\d]+)(\\sx\\s([\\w\\d]+))?(\\s([\\w\\d]+))?\\])?";
private static final String typePattern = "([\\w\\d_]+)(\\[([\\w\\d]+)(\\s([\\w\\d]+))?\\])?";
private static final String namePattern = "[[\\w\\d\\s<>_]]+";
private static final String commentPattern = ";([^;]*)";
@ -35,7 +36,7 @@ public class ConfigField {
private final String comment;
public final String arraySizeVariableName;
private final String type;
private final int arraySize;
private final int[] arraySizes;
private final String tsInfo;
private final boolean isIterate;
@ -55,7 +56,7 @@ public class ConfigField {
String comment,
String arraySizeAsText,
String type,
int arraySize,
int[] arraySizes,
String tsInfo,
boolean isIterate,
boolean fsioVisible,
@ -81,13 +82,13 @@ public class ConfigField {
Objects.requireNonNull(type);
this.type = type;
this.arraySizeVariableName = arraySizeAsText;
this.arraySize = arraySize;
this.arraySizes = arraySizes;
this.tsInfo = tsInfo == null ? null : state.variableRegistry.applyVariables(tsInfo);
this.isIterate = isIterate;
}
public boolean isArray() {
return arraySizeVariableName != null || arraySize != 1;
return arraySizeVariableName != null || arraySizes.length != 0;
}
public String getTrueName() {
@ -136,7 +137,7 @@ public class ConfigField {
if (!matcher.matches())
return null;
String nameString = matcher.group(6).trim();
String nameString = matcher.group(8).trim();
String[] nameTokens = nameString.split("\\s");
String name = nameTokens[nameTokens.length - 1];
@ -152,23 +153,29 @@ public class ConfigField {
break;
}
String comment = matcher.group(8);
String comment = matcher.group(10);
String type = matcher.group(1);
int arraySize;
int[] arraySizes;
String arraySizeAsText;
if (matcher.group(3) != null) {
if (matcher.group(5) != null) {
arraySizeAsText = matcher.group(3) + "][" + matcher.group(5);
arraySizes = new int[2];
arraySizes[0] = ConfigDefinition.getSize(state.variableRegistry, matcher.group(3));
arraySizes[1] = ConfigDefinition.getSize(state.variableRegistry, matcher.group(5));
} else if (matcher.group(3) != null) {
arraySizeAsText = matcher.group(3);
arraySize = ConfigDefinition.getSize(state.variableRegistry, arraySizeAsText);
arraySizes = new int[1];
arraySizes[0] = ConfigDefinition.getSize(state.variableRegistry, arraySizeAsText);
} else {
arraySize = 1;
arraySizes = new int[0];
arraySizeAsText = null;
}
String tsInfo = matcher.group(10);
String tsInfo = matcher.group(12);
boolean isIterate = "iterate".equalsIgnoreCase(matcher.group(5));
boolean isIterate = "iterate".equalsIgnoreCase(matcher.group(7));
ConfigField field = new ConfigField(state, name, comment, arraySizeAsText, type, arraySize,
ConfigField field = new ConfigField(state, name, comment, arraySizeAsText, type, arraySizes,
tsInfo, isIterate, isFsioVisible, autoscaleSpec, null, -1, null, null);
SystemOut.println("type " + type);
SystemOut.println("name " + name);
@ -187,7 +194,11 @@ public class ConfigField {
return 0;
if (isBit())
return 4;
return getElementSize() * arraySize;
int size = getElementSize();
for (int s : arraySizes) {
size *= s;
}
return size;
}
@Override
@ -195,7 +206,7 @@ public class ConfigField {
return "ConfigField{" +
"name='" + name + '\'' +
", type='" + type + '\'' +
", arraySize=" + arraySize +
", arraySizes=" + arraySizes +
'}';
}
@ -206,8 +217,8 @@ public class ConfigField {
return comment.charAt(0) == TS_COMMENT_TAG ? comment.substring(1) : comment;
}
public int getArraySize() {
return arraySize;
public int[] getArraySizes() {
return arraySizes;
}
public String getComment() {

View File

@ -73,9 +73,16 @@ public class ConfigStructure {
int fillSize = totalSize % 4 == 0 ? 0 : 4 - (totalSize % 4);
if (fillSize != 0) {
int[] fillSizeArray;
if (fillSize != 1) {
fillSizeArray = new int[1];
fillSizeArray[0] = fillSize;
} else {
fillSizeArray = new int[0];
}
ConfigField fill = new ConfigField(state, ALIGNMENT_FILL_AT + totalSize, "need 4 byte alignment",
"" + fillSize,
TypesHelper.UINT8_T, fillSize, "\"units\", 1, 0, -20, 100, 0", false, false, null, null, -1, null, null);
TypesHelper.UINT8_T, fillSizeArray, "\"units\", 1, 0, -20, 100, 0", false, false, null, null, -1, null, null);
addBoth(fill);
}
totalSize += fillSize;
@ -109,7 +116,7 @@ public class ConfigStructure {
return;
int sizeAtStartOfPadding = cFields.size();
while (readingBitState.get() < 32) {
ConfigField bitField = new ConfigField(readerState, "unusedBit_" + sizeAtStartOfPadding + "_" + readingBitState.get(), "", null, BOOLEAN_T, 0, null, false, false, null, null, -1, null, null);
ConfigField bitField = new ConfigField(readerState, "unusedBit_" + sizeAtStartOfPadding + "_" + readingBitState.get(), "", null, BOOLEAN_T, new int[0], null, false, false, null, null, -1, null, null);
addBitField(bitField);
}
readingBitState.reset();

View File

@ -52,7 +52,7 @@ public class ReaderState {
String trueName = bitNameParts.length > 1 ? bitNameParts[1].replaceAll("\"", "") : null;
String falseName = bitNameParts.length > 2 ? bitNameParts[2].replaceAll("\"", "") : null;
ConfigField bitField = new ConfigField(state, bitNameParts[0], comment, null, BOOLEAN_T, 0, null, false, false, null, null, -1, trueName, falseName);
ConfigField bitField = new ConfigField(state, bitNameParts[0], comment, null, BOOLEAN_T, new int[0], null, false, false, null, null, -1, trueName, falseName);
if (state.stack.isEmpty())
throw new IllegalStateException("Parent structure expected");
ConfigStructure structure = state.stack.peek();
@ -246,7 +246,8 @@ public class ReaderState {
if (cf == null) {
if (ConfigField.isPreprocessorDirective(state, line)) {
cf = new ConfigField(state, "", line, null,
ConfigField.DIRECTIVE_T, 0, null, false, false, null, null, 0, null, null);
ConfigField.DIRECTIVE_T, new int[0], null, false, false, null, null, 0,
null, null);
} else {
throw new IllegalStateException("Cannot parse line [" + line + "]");
}
@ -267,9 +268,9 @@ public class ReaderState {
if (cf.isIterate()) {
structure.addC(cf);
for (int i = 1; i <= cf.getArraySize(); i++) {
for (int i = 1; i <= cf.getArraySizes()[0]; i++) {
ConfigField element = new ConfigField(state, cf.getName() + i, cf.getComment(), null,
cf.getType(), 1, cf.getTsInfo(), false, false, null, cf.getName(), i, null, null);
cf.getType(), new int[0], cf.getTsInfo(), false, false, null, cf.getName(), i, null, null);
structure.addTs(element);
}
} else if (cf.isDirective()) {

View File

@ -68,7 +68,7 @@ public abstract class JavaFieldsConsumer implements ConfigurationConsumer {
return tsPosition;
}
if (configField.getArraySize() != 1) {
if (configField.getArraySizes().length != 0) {
// todo: array support
} else if (TypesHelper.isFloat(configField.getType())) {
writeJavaFieldName(nameWithPrefix, tsPosition);
@ -101,7 +101,7 @@ public abstract class JavaFieldsConsumer implements ConfigurationConsumer {
javaFieldsWriter.write(");" + EOL);
}
tsPosition += configField.getArraySize() * configField.getElementSize();
tsPosition += configField.getSize(next);
return tsPosition;
}

View File

@ -80,23 +80,32 @@ public class TSProjectConsumer implements ConfigurationConsumer {
tsPosition += configField.getState().tsCustomSize.get(configField.getType());
} else if (configField.getTsInfo() == null) {
throw new IllegalArgumentException("Need TS info for " + configField.getName() + " at "+ prefix);
} else if (configField.getArraySize() == 0) {
// write nothing for empty array
// TS does not like those
} else if (configField.getArraySize() != 1) {
tsHeader.write(nameWithPrefix + " = array, ");
tsHeader.write(TypesHelper.convertToTs(configField.getType()) + ",");
tsHeader.write(" " + tsPosition + ",");
tsHeader.write(" [" + configField.getArraySize() + "],");
tsHeader.write(" " + handleTsInfo(configField.getTsInfo(), 1));
tsPosition += configField.getArraySize() * configField.getElementSize();
} else {
} else if (configField.getArraySizes().length == 0) {
tsHeader.write(nameWithPrefix + " = scalar, ");
tsHeader.write(TypesHelper.convertToTs(configField.getType()) + ",");
tsHeader.write(" " + tsPosition + ",");
tsHeader.write(" " + handleTsInfo(configField.getTsInfo(), 1));
tsPosition += configField.getArraySize() * configField.getElementSize();
tsPosition += configField.getSize(next);
} else if (configField.getSize(next) == 0) {
// write nothing for empty array
// TS does not like those
} else {
tsHeader.write(nameWithPrefix + " = array, ");
tsHeader.write(TypesHelper.convertToTs(configField.getType()) + ",");
tsHeader.write(" " + tsPosition + ",");
tsHeader.write(" [");
boolean first = true;
for (int size : configField.getArraySizes()) {
if (first) {
first = false;
} else {
tsHeader.write("x");
}
tsHeader.write(Integer.toString(size));
}
tsHeader.write("], " + handleTsInfo(configField.getTsInfo(), 1));
tsPosition += configField.getSize(next);
}
tsHeader.write(EOL);
return tsPosition;

View File

@ -25,12 +25,27 @@ public class ConfigFieldParserTest {
{
ConfigField cf = ConfigField.parse(state, "uint8_t[8] field");
assertEquals(cf.getType(), "uint8_t");
assertEquals(cf.getArraySize(), 8);
assertEquals(cf.getArraySizes().length, 1);
assertEquals(cf.getArraySizes()[0], 8);
assertEquals(cf.getSize(null), 8);
assertFalse("isIterate", cf.isIterate());
}
}
@Test
public void testByte3dArray() {
ReaderState state = new ReaderState();
{
ConfigField cf = ConfigField.parse(state, "uint8_t[8 x 16] field");
assertEquals(cf.getType(), "uint8_t");
assertEquals(cf.getArraySizes().length, 2);
assertEquals(cf.getArraySizes()[0], 8);
assertEquals(cf.getArraySizes()[1], 16);
assertEquals(cf.getSize(null), 128);
assertFalse("isIterate", cf.isIterate());
}
}
@Test
public void testFloatMsAlias() throws IOException {
String test = "struct pid_s\n" +
@ -382,25 +397,26 @@ public class ConfigFieldParserTest {
{
ConfigField cf = ConfigField.parse(state, "int[3 iterate] field");
assertEquals(cf.getType(), "int");
assertEquals(cf.getArraySize(), 3);
assertEquals(cf.getArraySizes().length, 1);
assertEquals(cf.getArraySizes()[0], 3);
assertTrue("isIterate", cf.isIterate());
}
{
ConfigField cf = ConfigField.parse(state, "int16_t crankingRpm;This,. value controls what RPM values we consider 'cranking' (any RPM below 'crankingRpm')\\nAnything above 'crankingRpm' would be 'running'");
assertEquals(cf.getName(), "crankingRpm");
assertEquals(cf.getArraySize(), 1);
assertEquals(cf.getArraySizes().length, 0);
assertEquals(cf.getType(), "int16_t");
}
{
ConfigField cf = ConfigField.parse(state, "MAP_sensor_config_s map");
assertEquals(cf.getName(), "map");
assertEquals(cf.getArraySize(), 1);
assertEquals(cf.getArraySizes().length, 0);
assertEquals(cf.getType(), "MAP_sensor_config_s");
}
{
ConfigField cf = ConfigField.parse(state, "MAP_sensor_config_s map;@see hasMapSensor\\n@see isMapAveragingEnabled");
assertEquals(cf.getName(), "map");
assertEquals(cf.getArraySize(), 1);
assertEquals(cf.getArraySizes().length, 0);
assertEquals(cf.getType(), "MAP_sensor_config_s");
assertEquals(cf.getComment(), "@see hasMapSensor\\n@see isMapAveragingEnabled");
}