We have to move either forward or backwards with newparse #4441
This commit is contained in:
parent
e6ca0a42ba
commit
752a10ee05
Binary file not shown.
|
@ -452,78 +452,6 @@ public class ParseState implements DefinitionsState {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exitArrayField(RusefiConfigGrammarParser.ArrayFieldContext ctx) {
|
public void exitArrayField(RusefiConfigGrammarParser.ArrayFieldContext ctx) {
|
||||||
String type = ctx.identifier(0).getText();
|
|
||||||
String name = ctx.identifier(1).getText();
|
|
||||||
int[] length = this.arrayDim;
|
|
||||||
// check if the iterate token is present
|
|
||||||
boolean iterate = ctx.Iterate() != null;
|
|
||||||
boolean autoscale = ctx.Autoscale() != null;
|
|
||||||
|
|
||||||
if (iterate && length.length != 1) {
|
|
||||||
throw new IllegalStateException("Cannot iterate multi dimensional array: " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// First check if this is an array of structs
|
|
||||||
if (structs.containsKey(type)) {
|
|
||||||
// iterate required for structs
|
|
||||||
assert(iterate);
|
|
||||||
|
|
||||||
scope.structFields.add(new ArrayField<>(new StructField(structs.get(type), name), length, iterate));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check first if we have a typedef for this type
|
|
||||||
Typedef typedef = typedefs.get(type);
|
|
||||||
|
|
||||||
FieldOptions options;
|
|
||||||
if (typedef != null) {
|
|
||||||
if (typedef instanceof ScalarTypedef) {
|
|
||||||
ScalarTypedef scTypedef = (ScalarTypedef) typedef;
|
|
||||||
// Copy the typedef's options list - we don't want to edit it
|
|
||||||
options = scTypedef.options.copy();
|
|
||||||
// Switch to the "real" type, that is the typedef's type
|
|
||||||
type = scTypedef.type.cType;
|
|
||||||
} else if (typedef instanceof EnumTypedef) {
|
|
||||||
EnumTypedef bTypedef = (EnumTypedef) typedef;
|
|
||||||
|
|
||||||
options = new FieldOptions();
|
|
||||||
handleFieldOptionsList(options, ctx.fieldOptionsList());
|
|
||||||
|
|
||||||
EnumField prototype = new EnumField(bTypedef.type, type, name, bTypedef.endBit, bTypedef.values, options);
|
|
||||||
|
|
||||||
scope.structFields.add(new ArrayField<>(prototype, length, iterate));
|
|
||||||
return;
|
|
||||||
} else if (typedef instanceof StringTypedef) {
|
|
||||||
StringTypedef sTypedef = (StringTypedef) typedef;
|
|
||||||
|
|
||||||
// iterate required for strings
|
|
||||||
assert(iterate);
|
|
||||||
|
|
||||||
options = new FieldOptions();
|
|
||||||
handleFieldOptionsList(options, ctx.fieldOptionsList());
|
|
||||||
|
|
||||||
StringField prototype = new StringField(name, sTypedef.size, options.comment);
|
|
||||||
scope.structFields.add(new ArrayField<>(prototype, length, iterate));
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("didn't understand type " + type + " for element " + name);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If no typedef found, it MUST be a native type
|
|
||||||
if (!Type.findByCtype(type).isPresent()) {
|
|
||||||
throw new RuntimeException("didn't understand type " + type + " for element " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// no typedef found, create new options list
|
|
||||||
options = new FieldOptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge the read-in options list with the default from the typedef (if exists)
|
|
||||||
handleFieldOptionsList(options, ctx.fieldOptionsList());
|
|
||||||
|
|
||||||
ScalarField prototype = new ScalarField(Type.findByCtype(type).get(), name, options, autoscale);
|
|
||||||
|
|
||||||
scope.structFields.add(new ArrayField<>(prototype, length, iterate));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int[] arrayDim = null;
|
private int[] arrayDim = null;
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
package com.rusefi.newparse.outputs;
|
|
||||||
|
|
||||||
import com.rusefi.newparse.ParseState;
|
|
||||||
import com.rusefi.newparse.layout.StructLayout;
|
|
||||||
import com.rusefi.newparse.parsing.Struct;
|
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
public class CStructWriter {
|
|
||||||
public void writeCStructs(ParseState parser, String outputFile) throws FileNotFoundException {
|
|
||||||
writeCStructs(parser, new PrintStreamAlwaysUnix(new FileOutputStream(outputFile)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeCStructs(ParseState parser, PrintStream ps) {
|
|
||||||
ps.println(
|
|
||||||
"// begin\n" +
|
|
||||||
"#pragma once\n" +
|
|
||||||
"#include \"rusefi_types.h\""
|
|
||||||
);
|
|
||||||
|
|
||||||
for (Struct s : parser.getStructs()) {
|
|
||||||
StructLayout sl = new StructLayout(0, "root", s);
|
|
||||||
sl.writeCLayoutRoot(ps);
|
|
||||||
}
|
|
||||||
|
|
||||||
ps.println("// end");
|
|
||||||
|
|
||||||
ps.close();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package com.rusefi.newparse.outputs;
|
|
||||||
|
|
||||||
import com.rusefi.newparse.ParseState;
|
|
||||||
import com.rusefi.newparse.layout.StructLayout;
|
|
||||||
import com.rusefi.newparse.parsing.Struct;
|
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.PrintStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* As of Nov 2022 this implementation is not used in prod :(
|
|
||||||
*/
|
|
||||||
public class OutputChannelWriter {
|
|
||||||
private final PrintStream ps;
|
|
||||||
|
|
||||||
public OutputChannelWriter(String outputFile) throws FileNotFoundException {
|
|
||||||
this.ps = new PrintStreamAlwaysUnix(new FileOutputStream(outputFile));
|
|
||||||
}
|
|
||||||
|
|
||||||
public OutputChannelWriter(PrintStream ps) {
|
|
||||||
this.ps = ps;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int cumulativeSize = 0;
|
|
||||||
|
|
||||||
public void writeOutputChannels(ParseState parser, String namePrefix) {
|
|
||||||
// Assume the last struct is the one we want...
|
|
||||||
Struct s = parser.getStructs().get(parser.getStructs().size() - 1);
|
|
||||||
|
|
||||||
StructLayout sl = new StructLayout(0, "root", s);
|
|
||||||
sl.writeOutputChannelLayout(ps, namePrefix, cumulativeSize);
|
|
||||||
|
|
||||||
cumulativeSize += sl.getSize();
|
|
||||||
ps.println("; total TS size = " + cumulativeSize);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,106 +0,0 @@
|
||||||
package com.rusefi.newparse.outputs;
|
|
||||||
|
|
||||||
import com.rusefi.newparse.ParseState;
|
|
||||||
import com.rusefi.newparse.layout.StructLayout;
|
|
||||||
import com.rusefi.newparse.parsing.Definition;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* As of Nov 2022 this implementation is not used in prod :(
|
|
||||||
*/
|
|
||||||
public class TsWriter {
|
|
||||||
// matches strings in the form of @@MY_var_123@@
|
|
||||||
private static final Pattern VAR = Pattern.compile("@@([a-zA-Z0-9_]+?)@@");
|
|
||||||
|
|
||||||
private static final Pattern OPTIONAL_LINE = Pattern.compile("@@if_([a-zA-Z0-9_]+)");
|
|
||||||
|
|
||||||
// TODO: We have to move either forward or backwards with newparse #4441
|
|
||||||
public void writeTunerstudio(ParseState parser, String inputFile, String outputFile) throws IOException {
|
|
||||||
PrintStream ps = new PrintStreamAlwaysUnix(new FileOutputStream(outputFile));
|
|
||||||
writeTunerstudio(parser, inputFile, ps);
|
|
||||||
ps.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeTunerstudio(ParseState parser, String inputFile, PrintStream ps) throws IOException {
|
|
||||||
BufferedReader is = new BufferedReader(new FileReader(inputFile));
|
|
||||||
|
|
||||||
while (is.ready()) {
|
|
||||||
String line = is.readLine();
|
|
||||||
|
|
||||||
if (line.contains("CONFIG_DEFINITION_START")) {
|
|
||||||
writeLayoutAndComments(parser, ps);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if this line has a "skip me" suffix
|
|
||||||
Matcher match = OPTIONAL_LINE.matcher(line);
|
|
||||||
if (match.find()) {
|
|
||||||
String varName = match.group(1);
|
|
||||||
|
|
||||||
Definition def = parser.findDefinition(varName);
|
|
||||||
|
|
||||||
if (def == null || def.toString().equals("false")) {
|
|
||||||
// Definition was missing or false, skip this line
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete that part of the line
|
|
||||||
line = line.replace(match.group(0), "");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't strip surrounding quotes of the FIRST replace of the line - only do it in nested replacements
|
|
||||||
boolean isNested = false;
|
|
||||||
|
|
||||||
// While there is a line to replace, do it
|
|
||||||
while (line.contains("@@")) {
|
|
||||||
match = VAR.matcher(line);
|
|
||||||
|
|
||||||
if (!match.find()) {
|
|
||||||
throw new RuntimeException("Failed to resolve definition in line: " + line);
|
|
||||||
}
|
|
||||||
|
|
||||||
String varName = match.group(1);
|
|
||||||
Definition def = parser.findDefinition(varName);
|
|
||||||
|
|
||||||
String replacement = def != null ? def.toString() : "MISSING DEFINITION";
|
|
||||||
|
|
||||||
// Strip off any quotes from the resolved string - we may be trying to concatenate inside a string literal where quotes aren't allowed
|
|
||||||
while (isNested && replacement.startsWith("\"") && replacement.endsWith("\"")) {
|
|
||||||
replacement = replacement.substring(1, replacement.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
line = line.replaceAll(match.group(0), replacement);
|
|
||||||
|
|
||||||
if (!isNested) {
|
|
||||||
isNested = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove extra whitespace from the line
|
|
||||||
|
|
||||||
// Copy the line to the output stream
|
|
||||||
ps.println(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
is.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeLayoutAndComments(ParseState parser, PrintStream ps) {
|
|
||||||
StructLayout root = new StructLayout(0, "root", parser.getLastStruct());
|
|
||||||
TsMetadata meta = new TsMetadata();
|
|
||||||
|
|
||||||
// Print configuration layout
|
|
||||||
int size = root.getSize();
|
|
||||||
ps.println("pageSize = " + size);
|
|
||||||
ps.println("page = 1");
|
|
||||||
root.writeTunerstudioLayout(ps, meta);
|
|
||||||
ps.println("; total TS size = " + size);
|
|
||||||
|
|
||||||
// Print context help
|
|
||||||
ps.println("[SettingContextHelp]");
|
|
||||||
meta.writeComments(ps);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,22 +2,17 @@ package com.rusefi.test;
|
||||||
|
|
||||||
import com.rusefi.BitState;
|
import com.rusefi.BitState;
|
||||||
import com.rusefi.ReaderStateImpl;
|
import com.rusefi.ReaderStateImpl;
|
||||||
import com.rusefi.newparse.outputs.OutputChannelWriter;
|
|
||||||
import com.rusefi.output.DataLogConsumer;
|
import com.rusefi.output.DataLogConsumer;
|
||||||
import com.rusefi.output.GaugeConsumer;
|
import com.rusefi.output.GaugeConsumer;
|
||||||
import com.rusefi.output.GetOutputValueConsumer;
|
|
||||||
import com.rusefi.output.OutputsSectionConsumer;
|
import com.rusefi.output.OutputsSectionConsumer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import static com.rusefi.test.newParse.NewParseHelper.parseToOutputChannels;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
public class OutputsTest {
|
public class OutputsTest {
|
||||||
@Test
|
@Test
|
||||||
public void generateSomething() throws IOException {
|
public void generateSomething() {
|
||||||
ReaderStateImpl state = new ReaderStateImpl();
|
ReaderStateImpl state = new ReaderStateImpl();
|
||||||
state.getVariableRegistry().register("GAUGE_NAME_FUEL_WALL_CORRECTION", "wall");
|
state.getVariableRegistry().register("GAUGE_NAME_FUEL_WALL_CORRECTION", "wall");
|
||||||
String test = "struct total\n" +
|
String test = "struct total\n" +
|
||||||
|
@ -29,15 +24,6 @@ public class OutputsTest {
|
||||||
"float tCharge;speed density\n" +
|
"float tCharge;speed density\n" +
|
||||||
"end_struct\n";
|
"end_struct\n";
|
||||||
|
|
||||||
String expected = "root_afr_type = scalar, F32, 0, \"ms\", 1, 0\n" +
|
|
||||||
"root_afr_typet = scalar, U08, 4, \"ms\", 1, 0\n" +
|
|
||||||
"root_isForcedInduction = bits, U32, 8, [0:0]\n" +
|
|
||||||
"root_enableFan1WithAc = bits, U32, 8, [1:1]\n" +
|
|
||||||
"root_m_requested_pump = scalar, F32, 12, \"\", 1, 0\n" +
|
|
||||||
"root_tCharge = scalar, F32, 16, \"\", 1, 0\n" +
|
|
||||||
"; total TS size = 20\n";
|
|
||||||
assertEquals(expected, parseToOutputChannels(test));
|
|
||||||
|
|
||||||
String expectedLegacy = "afr_type = scalar, F32, 0, \"ms\", 1, 0\n" +
|
String expectedLegacy = "afr_type = scalar, F32, 0, \"ms\", 1, 0\n" +
|
||||||
"afr_typet = scalar, U08, 4, \"ms\", 1, 0\n" +
|
"afr_typet = scalar, U08, 4, \"ms\", 1, 0\n" +
|
||||||
"isForcedInduction = bits, U32, 8, [0:0]\n" +
|
"isForcedInduction = bits, U32, 8, [0:0]\n" +
|
||||||
|
@ -59,9 +45,6 @@ public class OutputsTest {
|
||||||
runOriginalImplementation(test);
|
runOriginalImplementation(test);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* while we have {@link OutputChannelWriter} here we use the current 'legacy' implementation
|
|
||||||
*/
|
|
||||||
private static OutputsSectionConsumer runOriginalImplementation(String test) {
|
private static OutputsSectionConsumer runOriginalImplementation(String test) {
|
||||||
ReaderStateImpl state = new ReaderStateImpl();
|
ReaderStateImpl state = new ReaderStateImpl();
|
||||||
|
|
||||||
|
|
|
@ -1,307 +0,0 @@
|
||||||
package com.rusefi.test.newParse;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import static com.rusefi.test.newParse.NewParseHelper.parseToOutputChannels;
|
|
||||||
import static com.rusefi.test.newParse.NewParseHelper.parseToTs;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
public class LayoutTest {
|
|
||||||
@Test
|
|
||||||
public void singleField() throws IOException {
|
|
||||||
String input = "struct_no_prefix myStruct\n" +
|
|
||||||
"int8_t xyz;comment;\"units\", 1, 2, 3, 4, 5\n" +
|
|
||||||
"end_struct";
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"pageSize = 4\n" +
|
|
||||||
"page = 1\n" +
|
|
||||||
"xyz = scalar, S08, 0, \"units\", 1, 2, 3, 4, 5\n" +
|
|
||||||
"; unused 3 bytes at offset 1\n" +
|
|
||||||
"; total TS size = 4\n" +
|
|
||||||
"[SettingContextHelp]\n" +
|
|
||||||
"\txyz = \"comment\"\n", parseToTs(input));
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"xyz = scalar, S08, 0, \"units\", 1, 2\n" +
|
|
||||||
"; total TS size = 4\n"
|
|
||||||
, parseToOutputChannels(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void twoFieldsSameSize() throws IOException {
|
|
||||||
String input = "struct_no_prefix myStruct\n" +
|
|
||||||
"int32_t abc;;\"\", 1, 2, 3, 4, 5\n" +
|
|
||||||
"int32_t xyz;;\"\", 6, 7, 8, 9, 10\n" +
|
|
||||||
"end_struct";
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"pageSize = 8\n" +
|
|
||||||
"page = 1\n" +
|
|
||||||
"abc = scalar, S32, 0, \"\", 1, 2, 3, 4, 5\n" +
|
|
||||||
"xyz = scalar, S32, 4, \"\", 6, 7, 8, 9, 10\n" +
|
|
||||||
"; total TS size = 8\n" +
|
|
||||||
"[SettingContextHelp]\n", parseToTs(input));
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"abc = scalar, S32, 0, \"\", 1, 2\n" +
|
|
||||||
"xyz = scalar, S32, 4, \"\", 6, 7\n" +
|
|
||||||
"; total TS size = 8\n", parseToOutputChannels(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void twoFieldsBigThenSmall() throws IOException {
|
|
||||||
String input = "struct_no_prefix myStruct\n" +
|
|
||||||
"int32_t abc;;\"\", 1, 2, 3, 4, 5\n" +
|
|
||||||
"int8_t xyz;;\"\", 6, 7, 8, 9, 10\n" +
|
|
||||||
"end_struct";
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"pageSize = 8\n" +
|
|
||||||
"page = 1\n" +
|
|
||||||
"abc = scalar, S32, 0, \"\", 1, 2, 3, 4, 5\n" +
|
|
||||||
"xyz = scalar, S08, 4, \"\", 6, 7, 8, 9, 10\n" +
|
|
||||||
"; unused 3 bytes at offset 5\n" +
|
|
||||||
"; total TS size = 8\n" +
|
|
||||||
"[SettingContextHelp]\n", parseToTs(input));
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"abc = scalar, S32, 0, \"\", 1, 2\n" +
|
|
||||||
"xyz = scalar, S08, 4, \"\", 6, 7\n" +
|
|
||||||
"; total TS size = 8\n", parseToOutputChannels(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void twoFieldsSmallThenBig() throws IOException {
|
|
||||||
String input = "struct_no_prefix myStruct\n" +
|
|
||||||
"int8_t abc;;\"\", 1, 2, 3, 4, 5\n" +
|
|
||||||
"int32_t xyz;;\"\", 6, 7, 8, 9, 10\n" +
|
|
||||||
"end_struct";
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"pageSize = 8\n" +
|
|
||||||
"page = 1\n" +
|
|
||||||
"abc = scalar, S08, 0, \"\", 1, 2, 3, 4, 5\n" +
|
|
||||||
"; unused 3 bytes at offset 1\n" +
|
|
||||||
"xyz = scalar, S32, 4, \"\", 6, 7, 8, 9, 10\n" +
|
|
||||||
"; total TS size = 8\n" +
|
|
||||||
"[SettingContextHelp]\n", parseToTs(input));
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"abc = scalar, S08, 0, \"\", 1, 2\n" +
|
|
||||||
"xyz = scalar, S32, 4, \"\", 6, 7\n" +
|
|
||||||
"; total TS size = 8\n", parseToOutputChannels(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void threeFieldsSmallInMisalignment() throws IOException {
|
|
||||||
String input = "struct_no_prefix myStruct\n" +
|
|
||||||
"int16_t abc\n" +
|
|
||||||
"int8_t def\n" +
|
|
||||||
"int32_t xyz\n" +
|
|
||||||
"end_struct";
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"pageSize = 8\n" +
|
|
||||||
"page = 1\n" +
|
|
||||||
"abc = scalar, S16, 0, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"def = scalar, S08, 2, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"; unused 1 bytes at offset 3\n" +
|
|
||||||
"xyz = scalar, S32, 4, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"; total TS size = 8\n" +
|
|
||||||
"[SettingContextHelp]\n", parseToTs(input));
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"abc = scalar, S16, 0, \"\", 1, 0\n" +
|
|
||||||
"def = scalar, S08, 2, \"\", 1, 0\n" +
|
|
||||||
"xyz = scalar, S32, 4, \"\", 1, 0\n" +
|
|
||||||
"; total TS size = 8\n", parseToOutputChannels(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void twoFieldsArrayThenBig() throws IOException {
|
|
||||||
String input = "struct_no_prefix myStruct\n" +
|
|
||||||
"int8_t[10] abc;;\"\", 1, 2, 3, 4, 5\n" +
|
|
||||||
"int32_t xyz;;\"\", 6, 7, 8, 9, 10\n" +
|
|
||||||
"end_struct";
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"pageSize = 16\n" +
|
|
||||||
"page = 1\n" +
|
|
||||||
"abc = array, S08, 0, [10], \"\", 1, 2, 3, 4, 5\n" +
|
|
||||||
"; unused 2 bytes at offset 10\n" +
|
|
||||||
"xyz = scalar, S32, 12, \"\", 6, 7, 8, 9, 10\n" +
|
|
||||||
"; total TS size = 16\n" +
|
|
||||||
"[SettingContextHelp]\n", parseToTs(input));
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"abc1 = scalar, S08, 0, \"\", 1, 2\n" +
|
|
||||||
"abc2 = scalar, S08, 1, \"\", 1, 2\n" +
|
|
||||||
"abc3 = scalar, S08, 2, \"\", 1, 2\n" +
|
|
||||||
"abc4 = scalar, S08, 3, \"\", 1, 2\n" +
|
|
||||||
"abc5 = scalar, S08, 4, \"\", 1, 2\n" +
|
|
||||||
"abc6 = scalar, S08, 5, \"\", 1, 2\n" +
|
|
||||||
"abc7 = scalar, S08, 6, \"\", 1, 2\n" +
|
|
||||||
"abc8 = scalar, S08, 7, \"\", 1, 2\n" +
|
|
||||||
"abc9 = scalar, S08, 8, \"\", 1, 2\n" +
|
|
||||||
"abc10 = scalar, S08, 9, \"\", 1, 2\n" +
|
|
||||||
"xyz = scalar, S32, 12, \"\", 6, 7\n" +
|
|
||||||
"; total TS size = 16\n", parseToOutputChannels(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void singleFieldMultiDimArray() throws IOException {
|
|
||||||
String ts = parseToTs("struct_no_prefix myStruct\n" +
|
|
||||||
"int8_t[10 x 5] abc;;\"\", 1, 2, 3, 4, 5\n" +
|
|
||||||
"end_struct");
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"pageSize = 52\n" +
|
|
||||||
"page = 1\n" +
|
|
||||||
"abc = array, S08, 0, [10x5], \"\", 1, 2, 3, 4, 5\n" +
|
|
||||||
"; unused 2 bytes at offset 50\n" +
|
|
||||||
"; total TS size = 52\n" +
|
|
||||||
"[SettingContextHelp]\n", ts);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void structs() throws IOException {
|
|
||||||
String ts = parseToTs(
|
|
||||||
"struct s1\n" +
|
|
||||||
"int32_t abc\n" +
|
|
||||||
"uint8_t def\n" +
|
|
||||||
"end_struct\n" +
|
|
||||||
"struct_no_prefix rootStruct\n" +
|
|
||||||
"s1 a\n" +
|
|
||||||
"s1 b\n" +
|
|
||||||
"end_struct");
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"pageSize = 16\n" +
|
|
||||||
"page = 1\n" +
|
|
||||||
"a_abc = scalar, S32, 0, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"a_def = scalar, U08, 4, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"; unused 3 bytes at offset 5\n" +
|
|
||||||
"b_abc = scalar, S32, 8, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"b_def = scalar, U08, 12, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"; unused 3 bytes at offset 13\n" +
|
|
||||||
"; total TS size = 16\n" +
|
|
||||||
"[SettingContextHelp]\n", ts);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void arrayIterate() throws IOException {
|
|
||||||
String input = "struct_no_prefix rootStruct\n" +
|
|
||||||
"int32_t[4 iterate] myArr\n" +
|
|
||||||
"end_struct";
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"pageSize = 16\n" +
|
|
||||||
"page = 1\n" +
|
|
||||||
"myArr1 = scalar, S32, 0, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"myArr2 = scalar, S32, 4, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"myArr3 = scalar, S32, 8, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"myArr4 = scalar, S32, 12, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"; total TS size = 16\n" +
|
|
||||||
"[SettingContextHelp]\n", parseToTs(input));
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"myArr1 = scalar, S32, 0, \"\", 1, 0\n" +
|
|
||||||
"myArr2 = scalar, S32, 4, \"\", 1, 0\n" +
|
|
||||||
"myArr3 = scalar, S32, 8, \"\", 1, 0\n" +
|
|
||||||
"myArr4 = scalar, S32, 12, \"\", 1, 0\n" +
|
|
||||||
"; total TS size = 16\n", parseToOutputChannels(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void arrayZeroLength() throws IOException {
|
|
||||||
String ts = parseToTs(
|
|
||||||
"struct_no_prefix rootStruct\n" +
|
|
||||||
"int32_t[0] myArr\n" +
|
|
||||||
"end_struct");
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"pageSize = 0\n" +
|
|
||||||
"page = 1\n" +
|
|
||||||
"; total TS size = 0\n" +
|
|
||||||
"[SettingContextHelp]\n", ts);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void arrayOfStructsIterate() throws IOException {
|
|
||||||
String ts = parseToTs(
|
|
||||||
"struct s1\n" +
|
|
||||||
"uint8_t var1\n" +
|
|
||||||
"uint16_t var2\n" +
|
|
||||||
"end_struct\n" +
|
|
||||||
"struct_no_prefix rootStruct\n" +
|
|
||||||
"s1[4 iterate] arr\n" +
|
|
||||||
"end_struct");
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"pageSize = 16\n" +
|
|
||||||
"page = 1\n" +
|
|
||||||
"arr1_var1 = scalar, U08, 0, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"; unused 1 bytes at offset 1\n" +
|
|
||||||
"arr1_var2 = scalar, U16, 2, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"arr2_var1 = scalar, U08, 4, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"; unused 1 bytes at offset 5\n" +
|
|
||||||
"arr2_var2 = scalar, U16, 6, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"arr3_var1 = scalar, U08, 8, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"; unused 1 bytes at offset 9\n" +
|
|
||||||
"arr3_var2 = scalar, U16, 10, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"arr4_var1 = scalar, U08, 12, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"; unused 1 bytes at offset 13\n" +
|
|
||||||
"arr4_var2 = scalar, U16, 14, \"\", 1, 0, 0, 0, 0\n" +
|
|
||||||
"; total TS size = 16\n" +
|
|
||||||
"[SettingContextHelp]\n", ts);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void bits() throws IOException {
|
|
||||||
String input = "struct_no_prefix myStruct\n" +
|
|
||||||
"bit first\n" +
|
|
||||||
"bit second\n" +
|
|
||||||
"bit withOpt,\"a\",\"b\"\n" +
|
|
||||||
"end_struct";
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"pageSize = 4\n" +
|
|
||||||
"page = 1\n" +
|
|
||||||
"first = bits, U32, 0, [0:0], \"false\", \"true\"\n" +
|
|
||||||
"second = bits, U32, 0, [1:1], \"false\", \"true\"\n" +
|
|
||||||
"withOpt = bits, U32, 0, [2:2], \"b\", \"a\"\n" +
|
|
||||||
"; total TS size = 4\n" +
|
|
||||||
"[SettingContextHelp]\n", parseToTs(input));
|
|
||||||
|
|
||||||
Assert.assertEquals(
|
|
||||||
"first = bits, U32, 0, [0:0]\n" +
|
|
||||||
"second = bits, U32, 0, [1:1]\n" +
|
|
||||||
"withOpt = bits, U32, 0, [2:2]\n" +
|
|
||||||
"; total TS size = 4\n"
|
|
||||||
, parseToOutputChannels(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void bigOutputChannels() throws IOException {
|
|
||||||
String input = "struct_no_prefix total\n" +
|
|
||||||
"float afr_type;PID dTime;\"ms\", 1, 0, 0, 3000, 0\n" +
|
|
||||||
"uint8_t afr_typet;@@GAUGE_NAME_FUEL_WALL_CORRECTION@@;\"ms\", 1, 0, 0, 3000, 0\n" +
|
|
||||||
"bit isForcedInduction;isForcedInduction\\nDoes the vehicle have a turbo or supercharger?\n" +
|
|
||||||
"bit enableFan1WithAc;+Turn on this fan when AC is on.\n" +
|
|
||||||
"angle_t m_requested_pump;Computed requested pump \n" +
|
|
||||||
"float tCharge;speed density\n" +
|
|
||||||
"end_struct\n";
|
|
||||||
|
|
||||||
assertEquals("afr_type = scalar, F32, 0, \"ms\", 1, 0\n" +
|
|
||||||
"afr_typet = scalar, U08, 4, \"ms\", 1, 0\n" +
|
|
||||||
"isForcedInduction = bits, U32, 8, [0:0]\n" +
|
|
||||||
"enableFan1WithAc = bits, U32, 8, [1:1]\n" +
|
|
||||||
"m_requested_pump = scalar, F32, 12, \"\", 1, 0\n" +
|
|
||||||
"tCharge = scalar, F32, 16, \"\", 1, 0\n" +
|
|
||||||
"; total TS size = 20\n", parseToOutputChannels(input));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
package com.rusefi.test.newParse;
|
|
||||||
|
|
||||||
import com.rusefi.RusefiParseErrorStrategy;
|
|
||||||
import com.rusefi.newparse.ParseState;
|
|
||||||
import com.rusefi.newparse.outputs.CStructWriter;
|
|
||||||
import com.rusefi.newparse.outputs.OutputChannelWriter;
|
|
||||||
import com.rusefi.newparse.outputs.PrintStreamAlwaysUnix;
|
|
||||||
import com.rusefi.newparse.outputs.TsWriter;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class NewParseHelper {
|
|
||||||
public static ParseState parse(String input) throws IOException {
|
|
||||||
ParseState parseState = new ParseState();
|
|
||||||
RusefiParseErrorStrategy.parseDefinitionString(parseState.getListener(), input);
|
|
||||||
return parseState;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: We have to move either forward or backwards with newparse #4441
|
|
||||||
public static String parseToTs(String input) throws IOException {
|
|
||||||
ParseState state = parse(input);
|
|
||||||
|
|
||||||
TsWriter writer = new TsWriter();
|
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
final String utf8 = StandardCharsets.UTF_8.name();
|
|
||||||
|
|
||||||
PrintStream ps = new PrintStreamAlwaysUnix(baos, true, utf8);
|
|
||||||
|
|
||||||
writer.writeLayoutAndComments(state, ps);
|
|
||||||
|
|
||||||
return baos.toString(utf8);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String parseToOutputChannels(String input) throws IOException {
|
|
||||||
ParseState state = parse(input);
|
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
final String utf8 = StandardCharsets.UTF_8.name();
|
|
||||||
|
|
||||||
PrintStream ps = new PrintStreamAlwaysUnix(baos, true, utf8);
|
|
||||||
|
|
||||||
OutputChannelWriter writer = new OutputChannelWriter(ps);
|
|
||||||
writer.writeOutputChannels(state, null);
|
|
||||||
|
|
||||||
return baos.toString(utf8);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: We have to move either forward or backwards with newparse #4441
|
|
||||||
public static String parseToC(String input) throws IOException {
|
|
||||||
ParseState state = parse(input);
|
|
||||||
|
|
||||||
CStructWriter writer = new CStructWriter();
|
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
final String utf8 = StandardCharsets.UTF_8.name();
|
|
||||||
|
|
||||||
PrintStream ps = new PrintStreamAlwaysUnix(baos, true, utf8);
|
|
||||||
|
|
||||||
writer.writeCStructs(state, ps);
|
|
||||||
|
|
||||||
return baos.toString(utf8);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,147 +0,0 @@
|
||||||
package com.rusefi.test.newParse;
|
|
||||||
|
|
||||||
import com.rusefi.RusefiParseErrorStrategy;
|
|
||||||
import com.rusefi.newparse.ParseState;
|
|
||||||
import com.rusefi.newparse.parsing.Definition;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import static com.rusefi.test.newParse.NewParseHelper.parse;
|
|
||||||
|
|
||||||
|
|
||||||
public class ParseDefinitionsTest {
|
|
||||||
@Test
|
|
||||||
public void basicIntegerDefinition() throws IOException {
|
|
||||||
ParseState state = parse("#define foo 123");
|
|
||||||
|
|
||||||
Assert.assertNull(state.findDefinition("notFoo"));
|
|
||||||
|
|
||||||
Definition def = state.findDefinition("foo");
|
|
||||||
Assert.assertTrue(def.isNumeric());
|
|
||||||
Assert.assertEquals(123, def.asDouble(), 1e-5);
|
|
||||||
|
|
||||||
Definition defHex = state.findDefinition("foo_16_hex");
|
|
||||||
Assert.assertFalse(defHex.isNumeric());
|
|
||||||
Assert.assertEquals("\\x00\\x7b", defHex.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void basicDoubleDefinition() throws IOException {
|
|
||||||
ParseState state = parse("#define foo 123.5");
|
|
||||||
|
|
||||||
Definition def = state.findDefinition("foo");
|
|
||||||
|
|
||||||
Assert.assertTrue(def.isNumeric());
|
|
||||||
Assert.assertEquals(123.5, def.asDouble(), 1e-5);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void basicStringDefinition() throws IOException {
|
|
||||||
ParseState state = parse("#define foo \"fooValue\"");
|
|
||||||
|
|
||||||
Definition def = state.findDefinition("foo");
|
|
||||||
|
|
||||||
Assert.assertFalse(def.isNumeric());
|
|
||||||
Assert.assertTrue(def.value instanceof String);
|
|
||||||
Assert.assertEquals("\"fooValue\"", def.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void definitionWithNumexprValue() throws IOException {
|
|
||||||
ParseState state = parse("#define foo 5 + 8 * 2 + 3");
|
|
||||||
|
|
||||||
Definition def = state.findDefinition("foo");
|
|
||||||
|
|
||||||
Assert.assertTrue(def.isNumeric());
|
|
||||||
Assert.assertEquals(24, def.asDouble(), 1e-5);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void definitionWithAnotherDefinition() throws IOException {
|
|
||||||
ParseState state = parse(
|
|
||||||
"#define val1 20\n" +
|
|
||||||
"#define val2 val1 + 1\n" +
|
|
||||||
"#define val3 3 * @@val2@@");
|
|
||||||
|
|
||||||
Definition def1 = state.findDefinition("val1");
|
|
||||||
Assert.assertTrue(def1.isNumeric());
|
|
||||||
Assert.assertEquals(20, def1.asDouble(), 1e-5);
|
|
||||||
|
|
||||||
Definition def2 = state.findDefinition("val2");
|
|
||||||
Assert.assertTrue(def2.isNumeric());
|
|
||||||
Assert.assertEquals(21, def2.asDouble(), 1e-5);
|
|
||||||
|
|
||||||
Definition def3 = state.findDefinition("val3");
|
|
||||||
Assert.assertTrue(def3.isNumeric());
|
|
||||||
Assert.assertEquals(63, def3.asDouble(), 1e-5);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test(expected = RuntimeException.class)
|
|
||||||
public void definitionEvalMissingDefinition() throws IOException {
|
|
||||||
parse(
|
|
||||||
"#define val1 20\n" +
|
|
||||||
"#define val2 val1 + 1\n" +
|
|
||||||
"#define val3 3 * valgggggg"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = RuntimeException.class)
|
|
||||||
public void definitionEvalNonNumeric() throws IOException {
|
|
||||||
parse(
|
|
||||||
"#define val1 \"foo\"\n" +
|
|
||||||
"#define val2 val1 + 1"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void definitionOverwritePolicyReplace() throws IOException {
|
|
||||||
ParseState state = new ParseState();
|
|
||||||
state.setDefinitionPolicy(Definition.OverwritePolicy.Replace);
|
|
||||||
RusefiParseErrorStrategy.parseDefinitionString(state.getListener(), "#define val 20");
|
|
||||||
|
|
||||||
Definition def = state.findDefinition("val");
|
|
||||||
Assert.assertEquals(20, def.asDouble(), 1e-5);
|
|
||||||
|
|
||||||
// Now parse another definition with the same name
|
|
||||||
RusefiParseErrorStrategy.parseDefinitionString(state.getListener(), "#define val 40");
|
|
||||||
|
|
||||||
// Should get back the new definition, not the old one
|
|
||||||
Definition def2 = state.findDefinition("val");
|
|
||||||
Assert.assertTrue(def != def2);
|
|
||||||
Assert.assertEquals(40, def2.asDouble(), 1e-5);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void definitionOverwritePolicyIgnoreNew() throws IOException {
|
|
||||||
ParseState state = new ParseState();
|
|
||||||
state.setDefinitionPolicy(Definition.OverwritePolicy.IgnoreNew);
|
|
||||||
RusefiParseErrorStrategy.parseDefinitionString(state.getListener(), "#define val 20");
|
|
||||||
|
|
||||||
Definition def = state.findDefinition("val");
|
|
||||||
Assert.assertEquals(20, def.asDouble(), 1e-5);
|
|
||||||
|
|
||||||
// Now parse another definition with the same name
|
|
||||||
state.setDefinitionPolicy(Definition.OverwritePolicy.IgnoreNew);
|
|
||||||
RusefiParseErrorStrategy.parseDefinitionString(state.getListener(), "#define val 40");
|
|
||||||
|
|
||||||
// New one ignored, still returns the same old one.
|
|
||||||
Assert.assertEquals(def, state.findDefinition("val"));
|
|
||||||
Assert.assertEquals(20, def.asDouble(), 1e-5);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
|
||||||
public void definitionOverwritePolicyNotAllowed() throws IOException {
|
|
||||||
ParseState state = new ParseState();
|
|
||||||
state.setDefinitionPolicy(Definition.OverwritePolicy.NotAllowed);
|
|
||||||
RusefiParseErrorStrategy.parseDefinitionString(state.getListener(), "#define val 20");
|
|
||||||
|
|
||||||
Definition def = state.findDefinition("val");
|
|
||||||
Assert.assertEquals(20, def.asDouble(), 1e-5);
|
|
||||||
|
|
||||||
// Now parse another definition with the same name, this should throw
|
|
||||||
RusefiParseErrorStrategy.parseDefinitionString(state.getListener(), "#define val 40");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,342 +0,0 @@
|
||||||
package com.rusefi.test.newParse;
|
|
||||||
|
|
||||||
import com.rusefi.newparse.ParseState;
|
|
||||||
import com.rusefi.newparse.parsing.*;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static com.rusefi.test.newParse.NewParseHelper.parse;
|
|
||||||
|
|
||||||
public class ParseStructTest {
|
|
||||||
@Test
|
|
||||||
public void structEmpty() throws IOException {
|
|
||||||
ParseState state = parse(
|
|
||||||
"struct myStruct\n\n" +
|
|
||||||
"end_struct\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Parsed exactly one struct
|
|
||||||
Assert.assertEquals(1, state.getStructs().size());
|
|
||||||
|
|
||||||
Struct myStruct = state.getStructs().get(0);
|
|
||||||
|
|
||||||
// It's a real struct!
|
|
||||||
Assert.assertNotNull(myStruct);
|
|
||||||
|
|
||||||
// Check that it was parsed correctly
|
|
||||||
Assert.assertEquals("myStruct", myStruct.name);
|
|
||||||
Assert.assertEquals(0, myStruct.fields.size());
|
|
||||||
Assert.assertEquals(false, myStruct.noPrefix);
|
|
||||||
|
|
||||||
Assert.assertEquals(state.getStructs().get(0), state.getLastStruct());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void structEmptyNoPrefix() throws IOException {
|
|
||||||
ParseState state = parse(
|
|
||||||
"struct_no_prefix myStruct\n\n" +
|
|
||||||
"end_struct\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
Struct myStruct = state.getStructs().get(0);
|
|
||||||
|
|
||||||
// Check that this one is marked as no prefix
|
|
||||||
Assert.assertEquals(true, myStruct.noPrefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void structMultiple() throws IOException {
|
|
||||||
ParseState state = parse(
|
|
||||||
"struct myStruct1\n\n" +
|
|
||||||
"end_struct\n" +
|
|
||||||
"struct myStruct2\n\n" +
|
|
||||||
"end_struct\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Now there are two structs!
|
|
||||||
Assert.assertEquals(2, state.getStructs().size());
|
|
||||||
|
|
||||||
Assert.assertEquals("myStruct1", state.getStructs().get(0).name);
|
|
||||||
Assert.assertEquals("myStruct2", state.getStructs().get(1).name);
|
|
||||||
|
|
||||||
// Check that get last struct returns the last one
|
|
||||||
Assert.assertEquals(state.getStructs().get(1), state.getLastStruct());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void structNested() throws IOException {
|
|
||||||
ParseState state = parse(
|
|
||||||
"struct myStructOuter\n" +
|
|
||||||
"struct myStructInner\n\n" +
|
|
||||||
"end_struct\n" +
|
|
||||||
"end_struct\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Now there are two structs!
|
|
||||||
Assert.assertEquals(2, state.getStructs().size());
|
|
||||||
|
|
||||||
Assert.assertEquals("myStructInner", state.getStructs().get(0).name);
|
|
||||||
Assert.assertEquals("myStructOuter", state.getStructs().get(1).name);
|
|
||||||
|
|
||||||
// Check that get last struct returns the outer one
|
|
||||||
Assert.assertEquals(state.getStructs().get(1), state.getLastStruct());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void structContainsStruct() throws IOException {
|
|
||||||
ParseState state = parse(
|
|
||||||
"struct myStruct\n\n" +
|
|
||||||
"end_struct\n" +
|
|
||||||
"struct myStruct2\n" +
|
|
||||||
"myStruct foo\n" +
|
|
||||||
"end_struct"
|
|
||||||
);
|
|
||||||
|
|
||||||
Assert.assertEquals(2, state.getStructs().size());
|
|
||||||
|
|
||||||
Struct inner = state.getStructs().get(0);
|
|
||||||
Assert.assertEquals(0, inner.fields.size());
|
|
||||||
|
|
||||||
// Check that the outer contains a struct
|
|
||||||
Struct outer = state.getStructs().get(1);
|
|
||||||
Assert.assertEquals(1, outer.fields.size());
|
|
||||||
Assert.assertTrue(outer.fields.get(0) instanceof StructField);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = RuntimeException.class)
|
|
||||||
public void structMissingStruct() throws IOException {
|
|
||||||
parse(
|
|
||||||
"struct myStruct2\n" +
|
|
||||||
"myStruct foo\n" +
|
|
||||||
"end_struct"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Field parseSingleField(String fieldLine) throws IOException {
|
|
||||||
ParseState state = parse(
|
|
||||||
"struct myStruct\n" +
|
|
||||||
fieldLine + "\n" +
|
|
||||||
"end_struct\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
List<Field> fields = state.getLastStruct().fields;
|
|
||||||
|
|
||||||
Assert.assertEquals(1, fields.size());
|
|
||||||
|
|
||||||
return fields.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void scalarOptions() throws IOException {
|
|
||||||
Field f = parseSingleField("int foo;comment;\"units\", 1, 2, 3, 4, 5");
|
|
||||||
ScalarField sf = (ScalarField) f;
|
|
||||||
|
|
||||||
FieldOptions opt = sf.options;
|
|
||||||
|
|
||||||
Assert.assertEquals("comment", opt.comment);
|
|
||||||
Assert.assertEquals("\"units\"", opt.units);
|
|
||||||
Assert.assertEquals(1, opt.scale, 0.001f);
|
|
||||||
Assert.assertEquals(2, opt.offset, 0.001f);
|
|
||||||
Assert.assertEquals(3, opt.min, 0.001f);
|
|
||||||
Assert.assertEquals(4, opt.max, 0.001f);
|
|
||||||
Assert.assertEquals(5, opt.digits);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void checkType(String inputType, int size, String cType, String tsType) throws IOException {
|
|
||||||
ScalarField sf = (ScalarField) parseSingleField(inputType + " foo");
|
|
||||||
|
|
||||||
Assert.assertEquals("foo", sf.name);
|
|
||||||
Assert.assertEquals(false, sf.autoscale);
|
|
||||||
Assert.assertEquals(size, sf.type.size);
|
|
||||||
|
|
||||||
Assert.assertEquals(cType, sf.type.cType);
|
|
||||||
Assert.assertEquals(tsType, sf.type.tsType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void typeMappings() throws IOException {
|
|
||||||
checkType("int", 4, "int", "S32");
|
|
||||||
|
|
||||||
checkType("int8_t", 1, "int8_t", "S08");
|
|
||||||
checkType("int16_t", 2, "int16_t", "S16");
|
|
||||||
checkType("int32_t", 4, "int32_t", "S32");
|
|
||||||
checkType("uint8_t", 1, "uint8_t", "U08");
|
|
||||||
checkType("uint16_t", 2, "uint16_t", "U16");
|
|
||||||
checkType("uint32_t", 4, "uint32_t", "U32");
|
|
||||||
|
|
||||||
checkType("float", 4, "float", "F32");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void arraySingleDimension() throws IOException {
|
|
||||||
Field f = parseSingleField("uint8_t[10] testBins");
|
|
||||||
|
|
||||||
Assert.assertTrue(f instanceof ArrayField);
|
|
||||||
ArrayField af = (ArrayField)f;
|
|
||||||
|
|
||||||
Assert.assertEquals(1, af.length.length);
|
|
||||||
Assert.assertEquals(10, af.length[0]);
|
|
||||||
|
|
||||||
PrototypeField prototype = af.prototype;
|
|
||||||
|
|
||||||
Assert.assertTrue(prototype instanceof ScalarField);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void arrayMultiDimension() throws IOException {
|
|
||||||
Field f = parseSingleField("uint8_t[5 x 8] testBins");
|
|
||||||
|
|
||||||
Assert.assertTrue(f instanceof ArrayField);
|
|
||||||
ArrayField af = (ArrayField)f;
|
|
||||||
|
|
||||||
Assert.assertEquals(2, af.length.length);
|
|
||||||
Assert.assertEquals(5, af.length[0]);
|
|
||||||
Assert.assertEquals(8, af.length[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void arrayIterate() throws IOException {
|
|
||||||
Field f = parseSingleField("uint8_t[10 iterate] testBins");
|
|
||||||
|
|
||||||
Assert.assertTrue(f instanceof ArrayField);
|
|
||||||
ArrayField af = (ArrayField)f;
|
|
||||||
|
|
||||||
Assert.assertEquals(true, af.iterate);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
|
||||||
public void checkMultiDimensionArrayIterateThrows() throws IOException {
|
|
||||||
parseSingleField("uint8_t[5 x 8 iterate] testBins");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void arrayOfStructs() throws IOException {
|
|
||||||
ParseState state = parse(
|
|
||||||
"struct myStruct\n\n" +
|
|
||||||
"end_struct\n" +
|
|
||||||
"struct myStruct2\n" +
|
|
||||||
"myStruct[5 iterate] foo\n" +
|
|
||||||
"end_struct"
|
|
||||||
);
|
|
||||||
|
|
||||||
Assert.assertEquals(2, state.getStructs().size());
|
|
||||||
|
|
||||||
// Inner should be empty
|
|
||||||
Struct inner = state.getStructs().get(0);
|
|
||||||
Assert.assertEquals(0, inner.fields.size());
|
|
||||||
|
|
||||||
// Check that the outer contains an array of structs
|
|
||||||
Struct outer = state.getStructs().get(1);
|
|
||||||
Assert.assertEquals(1, outer.fields.size());
|
|
||||||
|
|
||||||
ArrayField af = (ArrayField)outer.fields.get(0);
|
|
||||||
|
|
||||||
// Check length and that it contains a struct
|
|
||||||
Assert.assertEquals(1, af.length.length);
|
|
||||||
Assert.assertEquals(5, af.length[0]);
|
|
||||||
Assert.assertTrue(af.prototype instanceof StructField);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void typedefScalar() throws IOException {
|
|
||||||
ParseState ps = parse("custom myTypedef 4 scalar, F32, @OFFSET@, \"unit\", 1, 2, 3, 4, 5\n" +
|
|
||||||
"struct myStruct\n" +
|
|
||||||
"myTypedef foo;comment\n" +
|
|
||||||
"end_struct");
|
|
||||||
ScalarField sf = (ScalarField)ps.getLastStruct().fields.get(0);
|
|
||||||
|
|
||||||
Assert.assertEquals("foo", sf.name);
|
|
||||||
|
|
||||||
Assert.assertEquals(false, sf.autoscale);
|
|
||||||
Assert.assertEquals(4, sf.type.size);
|
|
||||||
Assert.assertEquals("float", sf.type.cType);
|
|
||||||
Assert.assertEquals("F32", sf.type.tsType);
|
|
||||||
|
|
||||||
FieldOptions opt = sf.options;
|
|
||||||
Assert.assertEquals("comment", opt.comment);
|
|
||||||
Assert.assertEquals("\"unit\"", opt.units);
|
|
||||||
Assert.assertEquals(1, opt.scale, 0.001f);
|
|
||||||
Assert.assertEquals(2, opt.offset, 0.001f);
|
|
||||||
Assert.assertEquals(3, opt.min, 0.001f);
|
|
||||||
Assert.assertEquals(4, opt.max, 0.001f);
|
|
||||||
Assert.assertEquals(5, opt.digits);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void typedefString() throws IOException {
|
|
||||||
ParseState ps = parse("custom lua_script_t 1000 string, ASCII, @OFFSET@, 1000\n" +
|
|
||||||
"struct myStruct\n" +
|
|
||||||
"lua_script_t luaScript\n" +
|
|
||||||
"end_struct");
|
|
||||||
StringField sf = (StringField)ps.getLastStruct().fields.get(0);
|
|
||||||
|
|
||||||
Assert.assertEquals("luaScript", sf.name);
|
|
||||||
Assert.assertEquals(1000, sf.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void unused() throws IOException {
|
|
||||||
ParseState state = parse(
|
|
||||||
"struct_no_prefix myStruct\n" +
|
|
||||||
"unused 27\n" +
|
|
||||||
"end_struct\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
UnusedField uf = (UnusedField)state.getLastStruct().fields.get(0);
|
|
||||||
|
|
||||||
Assert.assertEquals(27, uf.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void bitFieldsBasic() throws IOException {
|
|
||||||
ParseState state = parse(
|
|
||||||
"struct_no_prefix myStruct\n" +
|
|
||||||
"bit myBit1\n" +
|
|
||||||
"bit myBit2\n" +
|
|
||||||
"end_struct\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
BitGroup bf = (BitGroup)state.getLastStruct().fields.get(0);
|
|
||||||
|
|
||||||
Assert.assertEquals(2, bf.bitFields.size());
|
|
||||||
|
|
||||||
Assert.assertEquals("myBit1", bf.bitFields.get(0).name);
|
|
||||||
Assert.assertEquals("myBit2", bf.bitFields.get(1).name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void bitFieldsAdvanced() throws IOException {
|
|
||||||
ParseState state = parse(
|
|
||||||
"struct_no_prefix myStruct\n" +
|
|
||||||
"bit myBit,\"a\",\"b\";comment\n" +
|
|
||||||
"end_struct\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
BitGroup bg = (BitGroup)state.getLastStruct().fields.get(0);
|
|
||||||
BitField bf = bg.bitFields.get(0);
|
|
||||||
|
|
||||||
Assert.assertEquals("myBit", bf.name);
|
|
||||||
Assert.assertEquals("\"a\"", bf.trueValue);
|
|
||||||
Assert.assertEquals("\"b\"", bf.falseValue);
|
|
||||||
Assert.assertEquals("comment", bf.comment);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void bitFieldsThirtyThreeBits() throws IOException {
|
|
||||||
StringBuilder input = new StringBuilder("struct myStruct\n");
|
|
||||||
for (int i = 0; i < 33; i++) {
|
|
||||||
input.append("bit myBit").append(i).append("\n");
|
|
||||||
}
|
|
||||||
input.append("end_struct\n");
|
|
||||||
|
|
||||||
ParseState state = parse(input.toString());
|
|
||||||
|
|
||||||
Assert.assertEquals(2, state.getLastStruct().fields.size());
|
|
||||||
|
|
||||||
Assert.assertEquals(32, ((BitGroup)state.getLastStruct().fields.get(0)).bitFields.size());
|
|
||||||
Assert.assertEquals(1, ((BitGroup)state.getLastStruct().fields.get(1)).bitFields.size());
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue