parse with antlr (#2747)
* grammar and libs * gitignore * parsing * allow empty line as root statement * tolerate #if * config def changes * s * ant build * workaround * compiled tool * console should not build config def tool * ugh the dependency tree is insane * this should fix hw ci * console build * console jenkins script * test * Revert "test" This reverts commit 73f2da50f990bee9b51a1f919e8fcc6b06327d9a. * throw on parse failure * jar * fix #2821 * comment
This commit is contained in:
parent
5e97d7e11f
commit
5ae4af23fe
|
@ -20,6 +20,10 @@ jobs:
|
|||
- name: Install Tools
|
||||
run: sudo apt-get install ncftp
|
||||
|
||||
- name: Generate Java (Antlr)
|
||||
working-directory: ./java_tools/configuration_definition
|
||||
run: ant antlr
|
||||
|
||||
- name: Build console
|
||||
working-directory: ./java_console
|
||||
run: ant server_jar
|
||||
|
|
|
@ -47,6 +47,10 @@ jobs:
|
|||
working-directory: ./firmware
|
||||
run: openocd -f "interface/stlink.cfg" -f "target/stm32f4x.cfg" -c init -c targets -c "reset halt" -c "flash erase_sector 0 0 11" -c "flash write_image "build/rusefi.bin" 0x08000000" -c "reset run" -c "shutdown"
|
||||
|
||||
- name: Generate Java (Antlr)
|
||||
working-directory: ./java_tools/configuration_definition
|
||||
run: ant antlr
|
||||
|
||||
# This both compiles and runs HW CI tests
|
||||
- name: Run Hardware CI
|
||||
working-directory: ./java_console
|
||||
|
|
|
@ -47,6 +47,10 @@ jobs:
|
|||
working-directory: ./firmware
|
||||
run: openocd -f "interface/stlink.cfg" -f "target/stm32f4x.cfg" -c init -c targets -c "reset halt" -c "flash erase_sector 0 0 11" -c "flash write_image "build/rusefi.bin" 0x08000000" -c "reset run" -c "shutdown"
|
||||
|
||||
- name: Generate Java (Antlr)
|
||||
working-directory: ./java_tools/configuration_definition
|
||||
run: ant antlr
|
||||
|
||||
# This both compiles and runs HW CI tests
|
||||
- name: Run Hardware CI
|
||||
working-directory: ./java_console
|
||||
|
|
|
@ -87,7 +87,7 @@ struct_no_prefix engine_configuration_s
|
|||
#define CAM_INPUTS_COUNT @@BANKS_COUNT@@ * @@CAMS_PER_BANK@@
|
||||
#define CAM_INPUTS_COUNT_padding 0
|
||||
|
||||
// https://github.com/rusefi/rusefi/issues/2010 shows the corner case wheel with huge depth requirement
|
||||
! https://github.com/rusefi/rusefi/issues/2010 shows the corner case wheel with huge depth requirement
|
||||
#define GAP_TRACKING_LENGTH 18
|
||||
|
||||
#define SERVO_COUNT 8
|
||||
|
@ -569,8 +569,8 @@ int16_t tpsErrorDetectionTooHigh;+TPS error detection: what throttle % is unreal
|
|||
cranking_parameters_s cranking
|
||||
float primingSquirtDurationMs;;"*C", 1, 0, -40, 200, 1
|
||||
float ignitionDwellForCrankingMs;+Dwell duration while cranking;"ms", 1, 0, 0, 200, 1
|
||||
uint16_t etbRevLimitStart;+Once engine speed passes this value, start reducing ETB angle.;1, 0, 0, 15000, 0
|
||||
uint16_t etbRevLimitRange;+This far above 'Soft limiter start', fully close the throttle. At the bottom of the range, throttle control is normal. At the top of the range, the throttle is fully closed.;1, 0, 0, 2000, 0
|
||||
uint16_t etbRevLimitStart;+Once engine speed passes this value, start reducing ETB angle.;"rpm",1, 0, 0, 15000, 0
|
||||
uint16_t etbRevLimitRange;+This far above 'Soft limiter start', fully close the throttle. At the bottom of the range, throttle control is normal. At the top of the range, the throttle is fully closed.;"rpm",1, 0, 0, 2000, 0
|
||||
|
||||
MAP_sensor_config_s map;@see hasMapSensor\n@see isMapAveragingEnabled
|
||||
|
||||
|
@ -1954,7 +1954,8 @@ end_struct
|
|||
#define ENGINE_SNIFFER_UNIT_US 10
|
||||
|
||||
! These commands are used exclusively by the rusEfi console
|
||||
#define TS_TEST_COMMAND 't' // 0x74
|
||||
! 0x74
|
||||
#define TS_TEST_COMMAND 't'
|
||||
|
||||
#define TS_SD_R_COMMAND 'r'
|
||||
#define TS_SD_W_COMMAND 'w'
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<property name="hw_tests" value="build_hw"/>
|
||||
<property name="jar_file" value="${jar_file_folder}/rusefi_console.jar"/>
|
||||
<property name="server_jar_file" value="${jar_file_folder}/rusefi_server.jar"/>
|
||||
<property name="lib_list" value="lib/mockito-all-1.10.19.jar:../java_tools/configuration_definition/lib/snakeyaml.jar:lib/log4j-api-2.13.3.jar:lib/log4j-core-2.13.3.jar:lib/jsr305-2.0.1.jar:lib/dfu/dfu_java.jar:lib/dfu/IntelHexParser.jar:lib/json-simple-1.1.1.jar:lib/server/javax.json.jar:lib/server/cactoos.jar:lib/server/takes.jar:lib/json-simple-1.1.1.jar:lib/jaxb-api.jar:lib/httpclient.jar:lib/httpmime.jar:lib/httpcore.jar:lib/jSerialComm.jar:lib/jcip-annotations-1.0.jar:lib/jlatexmath-1.0.6.jar:lib/swing-layout-1.0.jar:lib/jep.jar:lib/log4j.jar:lib/junit.jar:lib/SteelSeries-3.9.30.jar:lib/annotations.jar:lib/miglayout-4.0.jar:lib/surfaceplotter-2.0.1.jar"/>
|
||||
<property name="lib_list" value="lib/mockito-all-1.10.19.jar:../java_tools/configuration_definition/lib/snakeyaml.jar:lib/log4j-api-2.13.3.jar:lib/log4j-core-2.13.3.jar:lib/jsr305-2.0.1.jar:lib/dfu/dfu_java.jar:lib/dfu/IntelHexParser.jar:lib/json-simple-1.1.1.jar:lib/server/javax.json.jar:lib/server/cactoos.jar:lib/server/takes.jar:lib/json-simple-1.1.1.jar:lib/jaxb-api.jar:lib/httpclient.jar:lib/httpmime.jar:lib/httpcore.jar:lib/jSerialComm.jar:lib/jcip-annotations-1.0.jar:lib/jlatexmath-1.0.6.jar:lib/swing-layout-1.0.jar:lib/jep.jar:lib/log4j.jar:lib/junit.jar:lib/SteelSeries-3.9.30.jar:lib/annotations.jar:lib/miglayout-4.0.jar:lib/surfaceplotter-2.0.1.jar:../java_tools/configuration_definition/lib/antlr-4.5-complete.jar"/>
|
||||
|
||||
<target name="clean">
|
||||
<delete dir="build"/>
|
||||
|
|
Binary file not shown.
|
@ -1,2 +1,3 @@
|
|||
out/
|
||||
rusefi_tool.log
|
||||
.antlr
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
grammar RusefiConfigGrammar;
|
||||
|
||||
@header {
|
||||
package com.rusefi.generated;
|
||||
}
|
||||
|
||||
// ...be generous in line endings...
|
||||
ENDL: ('\n' | '\r\n' | '\r');
|
||||
|
||||
LINE_COMMENT: '!' ~[\r\n]* -> skip;
|
||||
WS: [ \t]+ -> skip ;
|
||||
|
||||
// Special tokens need highest priority
|
||||
Struct: 'struct';
|
||||
StructNoPrefix: 'struct_no_prefix';
|
||||
EndStruct: 'end_struct';
|
||||
Definition: '#define';
|
||||
Unused: 'unused';
|
||||
Custom: 'custom';
|
||||
Datatype: (('S'|'U')('08'|'16'|'32')) | 'F32';
|
||||
Iterate: 'iterate';
|
||||
Bits: 'bits';
|
||||
Bit: 'bit';
|
||||
Array: 'array';
|
||||
Scalar: 'scalar';
|
||||
FsioVisible: 'fsio_visible';
|
||||
|
||||
ArrayDimensionSeparator: 'x';
|
||||
|
||||
MUL: '*';
|
||||
DIV: '/';
|
||||
ADD: '+';
|
||||
SUB: '-';
|
||||
|
||||
IntegerChars: [-]?[0-9]+;
|
||||
FloatChars: IntegerChars [.] ([0-9]+)?;
|
||||
|
||||
IdentifierChars : [a-zA-Z_]([a-zA-Z0-9_]*);
|
||||
|
||||
// TODO: do we need replacementIdent AND identifier to be here?
|
||||
replacementIdent: '@@' IdentifierChars '@@' | identifier;
|
||||
|
||||
String: [a-zA-Z_0-9.']+;
|
||||
|
||||
// match a quote, then anything not a quote, then another quote
|
||||
QuotedString: '"' ~'"'* '"';
|
||||
|
||||
// legacy, remove me!
|
||||
SemicolonedSuffix: ';' ~([;] | '\n')*;
|
||||
SemicolonedString: SemicolonedSuffix ';';
|
||||
|
||||
integer: IntegerChars;
|
||||
floatNum: FloatChars | IntegerChars;
|
||||
|
||||
expr
|
||||
: floatNum # EvalNumber
|
||||
| '{' expr '}' # EvalParens
|
||||
| expr MUL expr # EvalMul
|
||||
| expr DIV expr # EvalDiv
|
||||
| expr ADD expr # EvalAdd
|
||||
| expr SUB expr # EvalSub
|
||||
| replacementIdent # EvalReplacement
|
||||
;
|
||||
|
||||
numexpr: expr;
|
||||
|
||||
identifier: IdentifierChars | 'offset' | 'ArrayDimension';
|
||||
|
||||
restOfLine
|
||||
: ~ENDL*
|
||||
| 'true'
|
||||
| 'false';
|
||||
|
||||
definition
|
||||
: Definition identifier numexpr
|
||||
| Definition identifier restOfLine;
|
||||
struct: (Struct | StructNoPrefix) identifier ('@brief' restOfLine)? ENDL+ statements EndStruct;
|
||||
|
||||
fieldOption
|
||||
: ('min' | 'max' | 'scale' | 'offset' | ) ':' numexpr
|
||||
| 'digits' ':' integer
|
||||
| ('unit' | 'comment') ':' QuotedString
|
||||
;
|
||||
|
||||
fieldOptionsList
|
||||
: '(' fieldOption? (',' fieldOption)* ')'
|
||||
// TODO: why does the next line have a comma?
|
||||
| /* legacy! */ (',' | SemicolonedString) (QuotedString ',' numexpr ',' numexpr ',' numexpr ',' numexpr ',' /*digits =*/integer)?
|
||||
| /* legacy! */ SemicolonedSuffix
|
||||
;
|
||||
|
||||
arrayLengthSpec: numexpr (ArrayDimensionSeparator numexpr)?;
|
||||
|
||||
scalarField: identifier FsioVisible? identifier (fieldOptionsList)?;
|
||||
arrayField: identifier '[' arrayLengthSpec Iterate? ']' identifier SemicolonedString? (fieldOptionsList)?;
|
||||
bitField: Bit identifier (',' QuotedString ',' QuotedString)? ('(' 'comment' ':' QuotedString ')')? SemicolonedSuffix?;
|
||||
|
||||
field
|
||||
: scalarField
|
||||
| arrayField
|
||||
| bitField
|
||||
;
|
||||
|
||||
// Indicates X bytes of free space
|
||||
unusedField: Unused integer;
|
||||
|
||||
enumVal: QuotedString | integer;
|
||||
|
||||
enumRhs
|
||||
: replacementIdent
|
||||
| enumVal (',' enumVal)*
|
||||
;
|
||||
|
||||
enumTypedefSuffix: /*ignored*/integer Bits ',' Datatype ',' '@OFFSET@' ',' '[' integer ':' integer ']' ',' enumRhs ;
|
||||
scalarTypedefSuffix: /*ignored*/integer Scalar ',' Datatype ',' '@OFFSET@' fieldOptionsList ;
|
||||
arrayTypedefSuffix: /*ignored*/arrayLengthSpec Array ',' Datatype ',' '@OFFSET@' ',' '[' arrayLengthSpec ']' fieldOptionsList;
|
||||
stringTypedefSuffix: /*ignored*/replacementIdent 'string' ',' 'ASCII' ',' '@OFFSET@' ',' numexpr;
|
||||
|
||||
typedef: Custom identifier (enumTypedefSuffix | scalarTypedefSuffix | arrayTypedefSuffix | stringTypedefSuffix);
|
||||
|
||||
// Root statement is allowed to appear in the root of the file
|
||||
rootStatement
|
||||
: definition
|
||||
| struct
|
||||
| typedef
|
||||
// TODO: remove me, and build multi-lambda-table in to the language
|
||||
| ('#if' | '#else' | '#endif') restOfLine
|
||||
| // empty line counts as a statement
|
||||
;
|
||||
|
||||
rootStatements
|
||||
: (rootStatement ENDL+)*
|
||||
;
|
||||
|
||||
// Statements are allowed to appear inside a struct
|
||||
statement
|
||||
: rootStatement
|
||||
| field /* tolerate trailing semicolon */ (';')?
|
||||
| unusedField
|
||||
;
|
||||
|
||||
statements
|
||||
: (statement ENDL+)+
|
||||
;
|
||||
|
||||
content: rootStatements EOF;
|
|
@ -8,6 +8,10 @@
|
|||
<delete dir="build"/>
|
||||
</target>
|
||||
|
||||
<target name="antlr">
|
||||
<java jar="lib/antlr-4.5-complete.jar" args="-o src/com/rusefi/generated RusefiConfigGrammar.g4" fork="true" />
|
||||
</target>
|
||||
|
||||
<target name="compile">
|
||||
<mkdir dir="build/classes"/>
|
||||
<javac
|
||||
|
@ -15,7 +19,7 @@
|
|||
debug="true"
|
||||
target="${javac.target}"
|
||||
destdir="build/classes"
|
||||
classpath="${console_path}/lib/jsr305-2.0.1.jar:lib/junit.jar:../../java_console/lib/annotations.jar:lib/snakeyaml.jar">
|
||||
classpath="${console_path}/lib/jsr305-2.0.1.jar:lib/junit.jar:../../java_console/lib/annotations.jar:lib/snakeyaml.jar:lib/antlr-4.5-complete.jar">
|
||||
<src path="src"/>
|
||||
<src path="${console_path}/autoupdate/src"/>
|
||||
<src path="${console_path}/inifile/src"/>
|
||||
|
@ -34,7 +38,7 @@
|
|||
<jvmarg value="-ea"/>
|
||||
<jvmarg value="-XX:+HeapDumpOnOutOfMemoryError"/>
|
||||
<formatter type="brief"/>
|
||||
<classpath path="build/classes:lib/junit.jar:lib/annotations.jar:lib/snakeyaml.jar"/>
|
||||
<classpath path="build/classes:lib/junit.jar:lib/annotations.jar:lib/snakeyaml.jar:lib/antlr-4.5-complete.jar"/>
|
||||
<batchtest todir="build">
|
||||
<fileset dir="src" includes="**/test/**/*Test.java"/>
|
||||
<fileset dir="../enum_to_string/src" includes="**/test/**/*Test.java"/>
|
||||
|
@ -51,6 +55,7 @@
|
|||
</manifest>
|
||||
<zipfileset dir="build/classes" includes="**/*.class"/>
|
||||
<zipfileset src="lib/snakeyaml.jar" includes="**/*.class"/>
|
||||
<zipfileset src="lib/antlr-4.5-complete.jar" includes="**/*.class"/>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
|
|
|
@ -14,5 +14,14 @@
|
|||
<orderEntry type="module" module-name="inifile" />
|
||||
<orderEntry type="module" module-name="shared_io" />
|
||||
<orderEntry type="module" module-name="models" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/lib/antlr-4.5-complete.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
</module>
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
generated/
|
|
@ -1,7 +1,14 @@
|
|||
package com.rusefi;
|
||||
|
||||
import com.rusefi.generated.*;
|
||||
import com.rusefi.newparse.ParseState;
|
||||
import com.rusefi.newparse.parsing.Definition;
|
||||
import com.rusefi.output.*;
|
||||
import com.rusefi.util.*;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
|
||||
import com.rusefi.enum_reader.Value;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
|
@ -241,6 +248,46 @@ public class ConfigDefinition {
|
|||
processYamls(VariableRegistry.INSTANCE, yamlFiles, state);
|
||||
}
|
||||
|
||||
// Parse the input files
|
||||
{
|
||||
ParseState listener = new ParseState();
|
||||
|
||||
// First process yaml files
|
||||
//processYamls(listener, yamlFiles);
|
||||
|
||||
// First load prepend files
|
||||
{
|
||||
// Ignore duplicates of definitions made during prepend phase
|
||||
listener.setDefinitionPolicy(Definition.OverwritePolicy.IgnoreNew);
|
||||
|
||||
for (String prependFile : prependFiles) {
|
||||
// TODO: fix signature define file parsing
|
||||
//parseFile(listener, prependFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Now load the main config file
|
||||
{
|
||||
// don't allow duplicates in the main file
|
||||
listener.setDefinitionPolicy(Definition.OverwritePolicy.NotAllowed);
|
||||
parseFile(listener, definitionInputFile);
|
||||
}
|
||||
|
||||
// Write C structs
|
||||
// PrintStream cPrintStream = new PrintStream(new FileOutputStream(destCHeaderFileName));
|
||||
// for (Struct s : listener.getStructs()) {
|
||||
// StructLayout sl = new StructLayout(0, "root", s);
|
||||
// sl.writeCLayoutRoot(cPrintStream);
|
||||
// }
|
||||
// cPrintStream.close();
|
||||
|
||||
// Write tunerstudio layout
|
||||
// PrintStream tsPrintStream = new PrintStream(new FileOutputStream(tsPath + "/test.ini"));
|
||||
// StructLayout root = new StructLayout(0, "root", listener.getLastStruct());
|
||||
// root.writeTunerstudioLayout(tsPrintStream, new StructNamePrefixer());
|
||||
// tsPrintStream.close();
|
||||
}
|
||||
|
||||
BufferedReader definitionReader = new BufferedReader(new InputStreamReader(new FileInputStream(definitionInputFile), IoUtils.CHARSET.name()));
|
||||
|
||||
List<ConfigurationConsumer> destinations = new ArrayList<>();
|
||||
|
@ -554,4 +601,48 @@ public class ConfigDefinition {
|
|||
return c.getValue();
|
||||
}
|
||||
|
||||
public static class RusefiParseErrorStrategy extends DefaultErrorStrategy {
|
||||
private boolean hadError = false;
|
||||
|
||||
public boolean hadError() {
|
||||
return this.hadError;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recover(Parser recognizer, RecognitionException e) {
|
||||
this.hadError = true;
|
||||
|
||||
super.recover(recognizer, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token recoverInline(Parser recognizer) throws RecognitionException {
|
||||
this.hadError = true;
|
||||
|
||||
return super.recoverInline(recognizer);
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseFile(ParseState listener, String filePath) throws FileNotFoundException, IOException {
|
||||
SystemOut.println("Parsing file (Antlr) " + filePath);
|
||||
|
||||
CharStream in = new ANTLRInputStream(new FileInputStream(filePath));
|
||||
|
||||
long start = System.nanoTime();
|
||||
|
||||
RusefiConfigGrammarParser parser = new RusefiConfigGrammarParser(new CommonTokenStream(new RusefiConfigGrammarLexer(in)));
|
||||
|
||||
RusefiParseErrorStrategy errorStrategy = new RusefiParseErrorStrategy();
|
||||
parser.setErrorHandler(errorStrategy);
|
||||
|
||||
ParseTree tree = parser.content();
|
||||
new ParseTreeWalker().walk(listener, tree);
|
||||
double durationMs = (System.nanoTime() - start) / 1e6;
|
||||
|
||||
if (errorStrategy.hadError()) {
|
||||
throw new RuntimeException("Parse failed, see error output above!");
|
||||
}
|
||||
|
||||
SystemOut.println("Successfully parsed " + filePath + " in " + durationMs + "ms");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,475 @@
|
|||
package com.rusefi.newparse;
|
||||
|
||||
import com.rusefi.generated.RusefiConfigGrammarBaseListener;
|
||||
import com.rusefi.generated.RusefiConfigGrammarParser;
|
||||
import com.rusefi.newparse.parsing.*;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.StringType;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ParseState extends RusefiConfigGrammarBaseListener {
|
||||
Map<String, Definition> definitions = new HashMap<>();
|
||||
Map<String, Struct> structs = new HashMap<>();
|
||||
List<Struct> structList = new ArrayList<>();
|
||||
Map<String, Typedef> typedefs = new HashMap<>();
|
||||
|
||||
public List<Struct> getStructs() {
|
||||
return structList;
|
||||
}
|
||||
|
||||
class Scope {
|
||||
public List<Field> structFields = new ArrayList<>();
|
||||
}
|
||||
|
||||
Scope scope = null;
|
||||
Stack<Scope> scopes = new Stack<>();
|
||||
|
||||
@Override
|
||||
public void exitContent(RusefiConfigGrammarParser.ContentContext ctx) {
|
||||
assert(this.scopes.empty());
|
||||
assert(this.scope == null);
|
||||
|
||||
assert(this.typedefName == null);
|
||||
|
||||
assert(evalResults.isEmpty());
|
||||
assert(evalStack.empty());
|
||||
}
|
||||
|
||||
private Definition.OverwritePolicy definitionOverwritePolicy = Definition.OverwritePolicy.NotAllowed;
|
||||
|
||||
public void addDefinition(String name, String value, Definition.OverwritePolicy overwritePolicy) {
|
||||
Definition existingDefinition = definitions.getOrDefault(name, null);
|
||||
|
||||
if (existingDefinition != null) {
|
||||
switch (existingDefinition.overwritePolicy) {
|
||||
case NotAllowed:
|
||||
throw new IllegalStateException("Tried to add definition for " + name + ", but one already existed.");
|
||||
case Replace:
|
||||
definitions.remove(existingDefinition);
|
||||
case IgnoreNew:
|
||||
// ignore the new definition, do nothing
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
definitions.put(name, new Definition(name, value, overwritePolicy));
|
||||
}
|
||||
|
||||
public void setDefinitionPolicy(Definition.OverwritePolicy policy) {
|
||||
this.definitionOverwritePolicy = policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitDefinition(RusefiConfigGrammarParser.DefinitionContext ctx) {
|
||||
String name = ctx.identifier().getText();
|
||||
|
||||
String value;
|
||||
|
||||
if (!this.evalResults.isEmpty()) {
|
||||
value = this.evalResults.remove().toString();
|
||||
} else {
|
||||
// glue the list of definitions back together
|
||||
value = ctx.restOfLine().getText();
|
||||
}
|
||||
|
||||
addDefinition(name, value, this.definitionOverwritePolicy);
|
||||
}
|
||||
|
||||
String typedefName = null;
|
||||
|
||||
@Override
|
||||
public void enterTypedef(RusefiConfigGrammarParser.TypedefContext ctx) {
|
||||
this.typedefName = ctx.identifier().getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitTypedef(RusefiConfigGrammarParser.TypedefContext ctx) {
|
||||
this.typedefName = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitScalarTypedefSuffix(RusefiConfigGrammarParser.ScalarTypedefSuffixContext ctx) {
|
||||
Type datatype = Type.findByTsType(ctx.Datatype().getText());
|
||||
|
||||
FieldOptions options = new FieldOptions();
|
||||
handleFieldOptionsList(options, ctx.fieldOptionsList());
|
||||
|
||||
this.typedefs.put(this.typedefName, new ScalarTypedef(this.typedefName, datatype, options));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterEnumTypedefSuffix(RusefiConfigGrammarParser.EnumTypedefSuffixContext ctx) {
|
||||
int startBit = Integer.parseInt(ctx.integer(1).getText());
|
||||
int endBit = Integer.parseInt(ctx.integer(2).getText());
|
||||
Type datatype = Type.findByTsType(ctx.Datatype().getText());
|
||||
|
||||
String values = ctx.enumRhs().getText();
|
||||
|
||||
// TODO: many enum defs are missing so this doesn't work yet
|
||||
/*
|
||||
if (values.startsWith("@@")) {
|
||||
Definition def = this.definitions.get(values.replaceAll("@", ""));
|
||||
|
||||
if (def == null) {
|
||||
throw new RuntimeException("couldn't find definition for " + values);
|
||||
}
|
||||
|
||||
values = def.value;
|
||||
}*/
|
||||
|
||||
this.typedefs.put(this.typedefName, new EnumTypedef(this.typedefName, datatype, startBit, endBit, values));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitArrayTypedefSuffix(RusefiConfigGrammarParser.ArrayTypedefSuffixContext ctx) {
|
||||
int arrayLength = this.arrayDim;
|
||||
|
||||
Type datatype = Type.findByTsType(ctx.Datatype().getText());
|
||||
|
||||
FieldOptions options = new FieldOptions();
|
||||
handleFieldOptionsList(options, ctx.fieldOptionsList());
|
||||
|
||||
this.typedefs.put(this.typedefName, new ArrayTypedef(this.typedefName, arrayLength, datatype, options));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitStringTypedefSuffix(RusefiConfigGrammarParser.StringTypedefSuffixContext ctx) {
|
||||
Float stringLength = this.evalResults.remove();
|
||||
|
||||
this.typedefs.put(this.typedefName, new StringTypedef(this.typedefName, stringLength.intValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterStruct(RusefiConfigGrammarParser.StructContext ctx) {
|
||||
// If we're already inside a struct, push that context on to the stack
|
||||
if (scope != null) {
|
||||
scopes.push(scope);
|
||||
}
|
||||
|
||||
// Create new scratch space for this scope
|
||||
scope = new Scope();
|
||||
}
|
||||
|
||||
void handleFieldOptionsList(FieldOptions options, RusefiConfigGrammarParser.FieldOptionsListContext ctx) {
|
||||
// Null means no options were configured, use defaults
|
||||
if (ctx == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.fieldOption().size() == 0) {
|
||||
if (ctx.SemicolonedString() != null) {
|
||||
options.comment = ctx.SemicolonedString().getText();
|
||||
} else if (ctx.SemicolonedSuffix() != null) {
|
||||
options.comment = ctx.SemicolonedSuffix().getText();
|
||||
} else {
|
||||
options.comment = "";
|
||||
}
|
||||
|
||||
// this is a legacy field option list, parse it as such
|
||||
if (!ctx.numexpr().isEmpty()) {
|
||||
options.units = ctx.QuotedString().getText();
|
||||
options.scale = evalResults.remove();
|
||||
options.offset = evalResults.remove();
|
||||
options.min = evalResults.remove();
|
||||
options.max = evalResults.remove();
|
||||
options.digits = Integer.parseInt(ctx.integer().getText());
|
||||
|
||||
// we should have consumed everything on the results list
|
||||
assert(evalResults.size() == 0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (RusefiConfigGrammarParser.FieldOptionContext fo : ctx.fieldOption()) {
|
||||
String key = fo.getChild(0).getText();
|
||||
|
||||
String sValue = fo.getChild(2).getText();
|
||||
|
||||
if (key.equals("unit")) {
|
||||
options.units = sValue;
|
||||
} else if (key.equals("comment")) {
|
||||
options.comment = sValue;
|
||||
} else if (key.equals("digits")) {
|
||||
options.digits = Integer.parseInt(sValue);
|
||||
} else {
|
||||
Float value = evalResults.remove();
|
||||
|
||||
switch (key) {
|
||||
case "min": options.min = value; break;
|
||||
case "max": options.max = value; break;
|
||||
case "scale": options.scale = value; break;
|
||||
case "offset": options.offset = value; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we should have consumed everything on the results list
|
||||
assert(evalResults.size() == 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitScalarField(RusefiConfigGrammarParser.ScalarFieldContext ctx) {
|
||||
String type = ctx.identifier(0).getText();
|
||||
String name = ctx.identifier(1).getText();
|
||||
|
||||
// First check if this is an instance of a struct
|
||||
if (structs.containsKey(type)) {
|
||||
scope.structFields.add(new StructField(structs.get(type), name));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check first if we have a typedef for this type
|
||||
Typedef typedef = this.typedefs.get(type);
|
||||
|
||||
FieldOptions options = null;
|
||||
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 ArrayTypedef) {
|
||||
ArrayTypedef arTypedef = (ArrayTypedef) typedef;
|
||||
// Copy the typedef's options list - we don't want to edit it
|
||||
options = arTypedef.options.copy();
|
||||
|
||||
// Merge the read-in options list with the default from the typedef (if exists)
|
||||
handleFieldOptionsList(options, ctx.fieldOptionsList());
|
||||
|
||||
ScalarField prototype = new ScalarField(arTypedef.type, name, options);
|
||||
scope.structFields.add(new ArrayField<ScalarField>(prototype, arTypedef.length, false));
|
||||
return;
|
||||
} else if (typedef instanceof EnumTypedef) {
|
||||
EnumTypedef bTypedef = (EnumTypedef) typedef;
|
||||
|
||||
options = new FieldOptions();
|
||||
|
||||
// Merge the read-in options list with the default from the typedef (if exists)
|
||||
handleFieldOptionsList(options, ctx.fieldOptionsList());
|
||||
|
||||
scope.structFields.add(new EnumField(bTypedef.type, type, name, bTypedef.values, options));
|
||||
return;
|
||||
} else if (typedef instanceof StringTypedef) {
|
||||
StringTypedef sTypedef = (StringTypedef) typedef;
|
||||
scope.structFields.add(new StringField(name, sTypedef.size));
|
||||
return;
|
||||
} else {
|
||||
// TODO: throw
|
||||
}
|
||||
} 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());
|
||||
|
||||
scope.structFields.add(new ScalarField(Type.findByCtype(type).get(), name, options));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterBitField(RusefiConfigGrammarParser.BitFieldContext ctx) {
|
||||
String name = ctx.identifier().getText();
|
||||
|
||||
// Check if there's already a bit group at the end of the current struct
|
||||
BitGroup group = null;
|
||||
if (!scope.structFields.isEmpty()) {
|
||||
Object lastElement = scope.structFields.get(scope.structFields.size() - 1);
|
||||
|
||||
if (lastElement instanceof BitGroup) {
|
||||
group = (BitGroup)lastElement;
|
||||
}
|
||||
}
|
||||
|
||||
// there was no group, create and add it
|
||||
if (group == null) {
|
||||
group = new BitGroup();
|
||||
scope.structFields.add(group);
|
||||
}
|
||||
|
||||
String comment = ctx.SemicolonedSuffix() == null ? null : ctx.SemicolonedSuffix().getText();
|
||||
|
||||
group.addBitField(new BitField(name, comment));
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
|
||||
// First check if this is an array of structs
|
||||
if (structs.containsKey(type)) {
|
||||
// iterate required for structs
|
||||
assert(iterate);
|
||||
|
||||
scope.structFields.add(new ArrayField<StructField>(new StructField(structs.get(type), name), length, iterate));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check first if we have a typedef for this type
|
||||
Typedef typedef = this.typedefs.get(type);
|
||||
|
||||
FieldOptions options = null;
|
||||
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.values, options);
|
||||
|
||||
scope.structFields.add(new ArrayField<EnumField>(prototype, length, iterate));
|
||||
return;
|
||||
} else if (typedef instanceof StringTypedef) {
|
||||
StringTypedef sTypedef = (StringTypedef) typedef;
|
||||
|
||||
// iterate required for strings
|
||||
assert(iterate);
|
||||
|
||||
StringField prototype = new StringField(name, sTypedef.size);
|
||||
scope.structFields.add(new ArrayField<StringField>(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);
|
||||
|
||||
scope.structFields.add(new ArrayField(prototype, length, iterate));
|
||||
}
|
||||
|
||||
private int arrayDim = 0;
|
||||
|
||||
@Override
|
||||
public void exitArrayLengthSpec(RusefiConfigGrammarParser.ArrayLengthSpecContext ctx) {
|
||||
arrayDim = evalResults.remove().intValue();
|
||||
|
||||
if (ctx.ArrayDimensionSeparator() != null) {
|
||||
arrayDim *= evalResults.remove().intValue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterUnusedField(RusefiConfigGrammarParser.UnusedFieldContext ctx) {
|
||||
scope.structFields.add(new UnusedField(Integer.parseInt(ctx.integer().getText())));
|
||||
}
|
||||
|
||||
private Struct lastStruct = null;
|
||||
|
||||
public Struct getLastStruct() {
|
||||
return lastStruct;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitStruct(RusefiConfigGrammarParser.StructContext ctx) {
|
||||
String structName = ctx.identifier().getText();
|
||||
|
||||
assert(scope != null);
|
||||
assert(scope.structFields != null);
|
||||
|
||||
String comment = ctx.restOfLine() == null ? null : ctx.restOfLine().getText().toString();
|
||||
|
||||
Struct s = new Struct(structName, scope.structFields, ctx.StructNoPrefix() != null, comment);
|
||||
structs.put(structName, s);
|
||||
structList.add(s);
|
||||
lastStruct = s;
|
||||
|
||||
// We're leaving with this struct, re-apply the next struct out so more fields can be added to it
|
||||
if (scopes.empty()) {
|
||||
scope = null;
|
||||
} else {
|
||||
scope = scopes.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private Stack<Float> evalStack = new Stack<>();
|
||||
|
||||
|
||||
@Override
|
||||
public void exitEvalNumber(RusefiConfigGrammarParser.EvalNumberContext ctx) {
|
||||
evalStack.push(Float.parseFloat(ctx.floatNum().getText()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitEvalReplacement(RusefiConfigGrammarParser.EvalReplacementContext ctx) {
|
||||
// Strip any @@ symbols
|
||||
String defName = ctx.getText().replaceAll("@", "");
|
||||
|
||||
if (!this.definitions.containsKey(defName)) {
|
||||
throw new RuntimeException("Definition not found for " + ctx.getText());
|
||||
}
|
||||
|
||||
// Find the matching definition, parse it, and push on to the eval stack
|
||||
evalStack.push(Float.parseFloat(this.definitions.get(defName).value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitEvalMul(RusefiConfigGrammarParser.EvalMulContext ctx) {
|
||||
Float right = evalStack.pop();
|
||||
Float left = evalStack.pop();
|
||||
|
||||
evalStack.push(left * right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitEvalDiv(RusefiConfigGrammarParser.EvalDivContext ctx) {
|
||||
Float right = evalStack.pop();
|
||||
Float left = evalStack.pop();
|
||||
|
||||
evalStack.push(left / right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitEvalAdd(RusefiConfigGrammarParser.EvalAddContext ctx) {
|
||||
Float right = evalStack.pop();
|
||||
Float left = evalStack.pop();
|
||||
|
||||
evalStack.push(left + right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitEvalSub(RusefiConfigGrammarParser.EvalSubContext ctx) {
|
||||
Float right = evalStack.pop();
|
||||
Float left = evalStack.pop();
|
||||
|
||||
evalStack.push(left - right);
|
||||
}
|
||||
|
||||
private Queue<Float> evalResults = new LinkedList<>();
|
||||
|
||||
@Override
|
||||
public void exitNumexpr(RusefiConfigGrammarParser.NumexprContext ctx) {
|
||||
assert(evalStack.size() == 1);
|
||||
evalResults.add(evalStack.pop());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public class ArrayField<PrototypeType extends PrototypeField> implements Field {
|
||||
public final int length;
|
||||
public final Boolean iterate;
|
||||
public final PrototypeType prototype;
|
||||
|
||||
public ArrayField(PrototypeType prototype, int length, Boolean iterate) {
|
||||
this.length = length;
|
||||
this.iterate = iterate;
|
||||
this.prototype = prototype;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public class ArrayTypedef extends Typedef {
|
||||
public final FieldOptions options;
|
||||
public final Type type;
|
||||
public final int length;
|
||||
|
||||
public ArrayTypedef(String name, int length, Type type, FieldOptions options) {
|
||||
super(name);
|
||||
|
||||
this.length = length;
|
||||
this.type = type;
|
||||
this.options = options;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public class BitField {
|
||||
public final String name;
|
||||
public final String comment;
|
||||
|
||||
public BitField(String name, String comment) {
|
||||
this.name = name;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BitField: " + this.name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BitGroup implements Field {
|
||||
public final List<BitField> bitFields = new ArrayList<>();
|
||||
|
||||
public void addBitField(BitField b) {
|
||||
bitFields.add(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BitGroup: " + bitFields.size() + " bits";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public class Definition {
|
||||
public final String name;
|
||||
public final String value;
|
||||
public final OverwritePolicy overwritePolicy;
|
||||
|
||||
public enum OverwritePolicy {
|
||||
NotAllowed,
|
||||
Replace,
|
||||
IgnoreNew
|
||||
}
|
||||
|
||||
public Definition(String name, String value, OverwritePolicy overwritePolicy) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.overwritePolicy = overwritePolicy;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public class EnumField extends PrototypeField {
|
||||
public final Type type;
|
||||
public final String enumType;
|
||||
public final String values;
|
||||
public final FieldOptions options;
|
||||
|
||||
public EnumField(Type type, String enumType, String name, String values, FieldOptions options) {
|
||||
super(name);
|
||||
|
||||
this.type = type;
|
||||
this.enumType = enumType;
|
||||
this.values = values;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "enum " + type.cType + " " + this.name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public class EnumTypedef extends Typedef {
|
||||
public final Type type;
|
||||
public final int startBit;
|
||||
public final int endBit;
|
||||
public final String values;
|
||||
|
||||
public EnumTypedef(String name, Type type, int startBit, int endBit, String values) {
|
||||
super(name);
|
||||
|
||||
this.type = type;
|
||||
this.startBit = startBit;
|
||||
this.endBit = endBit;
|
||||
this.values = values;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public interface Field {
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class FieldOptions {
|
||||
public float min;
|
||||
public float max;
|
||||
public float scale;
|
||||
public float offset;
|
||||
public int digits;
|
||||
public String units;
|
||||
public String comment;
|
||||
|
||||
public FieldOptions() {
|
||||
min = 0;
|
||||
max = 0;
|
||||
scale = 1;
|
||||
offset = 0;
|
||||
digits = 0;
|
||||
units = "\"\"";
|
||||
comment = "";
|
||||
}
|
||||
|
||||
// Produce a deep copy of this object
|
||||
public FieldOptions copy() {
|
||||
FieldOptions other = new FieldOptions();
|
||||
|
||||
other.min = this.min;
|
||||
other.max = this.max;
|
||||
other.scale = this.scale;
|
||||
other.offset = this.offset;
|
||||
other.digits = this.digits;
|
||||
other.units = this.units;
|
||||
other.comment = this.comment;
|
||||
|
||||
return other;
|
||||
}
|
||||
|
||||
public void printTsFormat(PrintStream ps) {
|
||||
ps.print(units);
|
||||
ps.print(", ");
|
||||
ps.print(scale);
|
||||
ps.print(", ");
|
||||
ps.print(offset);
|
||||
ps.print(", ");
|
||||
ps.print(min);
|
||||
ps.print(", ");
|
||||
ps.print(max);
|
||||
ps.print(", ");
|
||||
ps.print(digits);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public abstract class PrototypeField implements Field {
|
||||
public final String name;
|
||||
|
||||
protected PrototypeField(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public class ScalarField extends PrototypeField {
|
||||
public final Type type;
|
||||
public final FieldOptions options;
|
||||
|
||||
public ScalarField(Type type, String name, FieldOptions options) {
|
||||
super(name);
|
||||
|
||||
this.type = type;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type.cType + " " + name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public class ScalarTypedef extends Typedef {
|
||||
public final FieldOptions options;
|
||||
public final Type type;
|
||||
|
||||
public ScalarTypedef(String name, Type type, FieldOptions options) {
|
||||
super(name);
|
||||
|
||||
this.options = options;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public class StringField extends PrototypeField{
|
||||
public final int size;
|
||||
|
||||
public StringField(String name, int size) {
|
||||
super(name);
|
||||
|
||||
this.size = size;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public class StringTypedef extends Typedef {
|
||||
public final int size;
|
||||
|
||||
public StringTypedef(String name, int size) {
|
||||
super(name);
|
||||
|
||||
this.size = size;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
|
||||
public class Struct implements Field {
|
||||
public final String name;
|
||||
public final Boolean noPrefix;
|
||||
public final List<Field> fields;
|
||||
public final String comment;
|
||||
|
||||
public Struct(String name, List<Field> fields, boolean noPrefix, String comment) {
|
||||
this.name = name;
|
||||
this.noPrefix = noPrefix;
|
||||
this.fields = fields;
|
||||
this.comment = comment;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public class StructField extends PrototypeField {
|
||||
public final Struct struct;
|
||||
|
||||
public StructField(Struct struct, String name) {
|
||||
super(name);
|
||||
|
||||
this.struct = struct;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
public enum Type {
|
||||
U08("uint8_t", "U08", 1),
|
||||
S08("int8_t", "S08", 1),
|
||||
U16("uint16_t", "U16", 2),
|
||||
S16("int16_t", "S16", 2),
|
||||
U32("uint32_t", "U32", 4),
|
||||
S32("int32_t", "S32", 4),
|
||||
F32("float", "F32", 4),
|
||||
ANGLE_T("angle_t", "F32", 4),
|
||||
|
||||
// TODO: remove I32
|
||||
I32("int", "S32", 4);
|
||||
|
||||
public final String cType;
|
||||
public final String tsType;
|
||||
public final int size;
|
||||
|
||||
Type(String cType, String tunerstudioType, int size) {
|
||||
this.cType = cType;
|
||||
this.tsType = tunerstudioType;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public static Optional<Type> findByCtype(String cType) {
|
||||
return Arrays.stream(Type.values()).filter(t -> t.cType.equals(cType)).findFirst();
|
||||
}
|
||||
|
||||
public static Type findByTsType(String tsType) {
|
||||
return Arrays.stream(Type.values()).filter(t -> t.tsType.equals(tsType)).findFirst().get();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public class Typedef {
|
||||
public final String name;
|
||||
|
||||
protected Typedef (String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.rusefi.newparse.parsing;
|
||||
|
||||
public class UnusedField implements Field {
|
||||
public final int size;
|
||||
|
||||
public UnusedField(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,11 @@
|
|||
echo "java version"
|
||||
java -version
|
||||
|
||||
echo "Generating Java (Antlr)"
|
||||
cd java_tools/configuration_definition
|
||||
ant antlr
|
||||
cd ../..
|
||||
|
||||
echo "Building java console"
|
||||
pwd
|
||||
cd java_console
|
||||
|
|
Loading…
Reference in New Issue