only:We have to move either forward or backwards with newparse #4441
This commit is contained in:
parent
126f4a736a
commit
eb651dc526
|
@ -1,155 +0,0 @@
|
|||
grammar RusefiConfigGrammar;
|
||||
|
||||
@header {
|
||||
package com.rusefi.generated;
|
||||
}
|
||||
|
||||
// ...be generous in line endings...
|
||||
ENDL: ('\n' | '\r\n' | '\r');
|
||||
|
||||
LINE_COMMENT: '!' ~[\r\n]* -> skip;
|
||||
LINE_COMMENT2: '//' ~[\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';
|
||||
Autoscale: 'autoscale';
|
||||
|
||||
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: integer | '@@' 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 integer
|
||||
| Definition identifier floatNum
|
||||
| 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 Autoscale? identifier (fieldOptionsList)?;
|
||||
arrayField: identifier '[' arrayLengthSpec Iterate? ']' Autoscale? identifier SemicolonedString? (fieldOptionsList)?;
|
||||
bitField: Bit identifier (',' QuotedString ',' QuotedString)? ('(' 'comment' ':' QuotedString ')')? SemicolonedSuffix?;
|
||||
|
||||
unionField: 'union' ENDL+ fields 'end_union';
|
||||
|
||||
field
|
||||
: scalarField
|
||||
| arrayField
|
||||
| bitField
|
||||
| unionField
|
||||
;
|
||||
|
||||
fields
|
||||
: (field ENDL+)+
|
||||
;
|
||||
|
||||
// Indicates X bytes of free space
|
||||
unusedField: Unused integer;
|
||||
|
||||
enumVal: QuotedString | integer;
|
||||
|
||||
enumRhs
|
||||
: replacementIdent
|
||||
| enumVal (',' enumVal)*
|
||||
;
|
||||
|
||||
enumTypedefSuffix: /*ignored*/replacementIdent Bits ',' Datatype ',' '@OFFSET@' ',' '[' integer ':' integer ']' ',' enumRhs ;
|
||||
scalarTypedefSuffix: /*ignored*/integer Scalar ',' Datatype ',' '@OFFSET@' fieldOptionsList ;
|
||||
stringTypedefSuffix: /*ignored*/replacementIdent 'string' ',' 'ASCII' ',' '@OFFSET@' ',' numexpr;
|
||||
|
||||
typedef: Custom identifier (enumTypedefSuffix | scalarTypedefSuffix | 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+)* rootStatement
|
||||
;
|
||||
|
||||
// Statements are allowed to appear inside a struct
|
||||
statement
|
||||
: rootStatement
|
||||
| field /* tolerate trailing semicolon */ (';')?
|
||||
| unusedField
|
||||
;
|
||||
|
||||
statements
|
||||
: (statement ENDL+)+
|
||||
;
|
||||
|
||||
content: rootStatements EOF;
|
|
@ -1,75 +0,0 @@
|
|||
package com.rusefi;
|
||||
|
||||
import com.rusefi.generated.RusefiConfigGrammarLexer;
|
||||
import com.rusefi.generated.RusefiConfigGrammarParser;
|
||||
import com.rusefi.util.SystemOut;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* dead code? shall we drop it yet?
|
||||
*/
|
||||
public class RusefiParseErrorStrategy extends DefaultErrorStrategy {
|
||||
private boolean hadError = false;
|
||||
|
||||
public static void parseDefinitionFile(ParseTreeListener listener, String filePath) throws IOException {
|
||||
SystemOut.println("Parsing file (Antlr) " + filePath);
|
||||
|
||||
CharStream in = new ANTLRInputStream(new FileInputStream(filePath));
|
||||
|
||||
long start = System.nanoTime();
|
||||
parse(listener, in);
|
||||
double durationMs = (System.nanoTime() - start) / 1e6;
|
||||
|
||||
SystemOut.println("Successfully parsed (Antlr) " + filePath + " in " + durationMs + "ms");
|
||||
}
|
||||
|
||||
public static void parseDefinitionString(ParseTreeListener listener, String content) {
|
||||
SystemOut.println("Parsing string (Antlr)");
|
||||
|
||||
CharStream in = new ANTLRInputStream(content);
|
||||
|
||||
long start = System.nanoTime();
|
||||
parse(listener, in);
|
||||
double durationMs = (System.nanoTime() - start) / 1e6;
|
||||
|
||||
SystemOut.println("Successfully parsed (Antlr) in " + durationMs + "ms");
|
||||
}
|
||||
|
||||
private static void parse(ParseTreeListener listener, CharStream in) {
|
||||
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);
|
||||
|
||||
if (errorStrategy.hadError()) {
|
||||
throw new RuntimeException("Parse failed, see error output above!");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue