composition better than inheritance
This commit is contained in:
parent
a849845bcf
commit
e8464e212c
|
@ -12,6 +12,7 @@ import com.rusefi.util.LazyFile;
|
|||
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 org.yaml.snakeyaml.Yaml;
|
||||
|
||||
|
@ -252,18 +253,18 @@ public class ConfigDefinition {
|
|||
|
||||
// Parse the input files
|
||||
{
|
||||
ParseState listener = new ParseState(state.enumsReader);
|
||||
ParseState parseState = new ParseState(state.enumsReader);
|
||||
|
||||
// First process yaml files
|
||||
//processYamls(listener, yamlFiles);
|
||||
|
||||
// Process firing order enum
|
||||
handleFiringOrder(firingEnumFileName, listener);
|
||||
handleFiringOrder(firingEnumFileName, parseState);
|
||||
|
||||
// Load prepend files
|
||||
{
|
||||
// Ignore duplicates of definitions made during prepend phase
|
||||
listener.setDefinitionPolicy(Definition.OverwritePolicy.IgnoreNew);
|
||||
parseState.setDefinitionPolicy(Definition.OverwritePolicy.IgnoreNew);
|
||||
|
||||
//for (String prependFile : prependFiles) {
|
||||
// TODO: fix signature define file parsing
|
||||
|
@ -274,8 +275,8 @@ public class ConfigDefinition {
|
|||
// Now load the main config file
|
||||
{
|
||||
// don't allow duplicates in the main file
|
||||
listener.setDefinitionPolicy(Definition.OverwritePolicy.NotAllowed);
|
||||
parseFile(listener, definitionInputFile);
|
||||
parseState.setDefinitionPolicy(Definition.OverwritePolicy.NotAllowed);
|
||||
parseFile(parseState.getListener(), definitionInputFile);
|
||||
}
|
||||
|
||||
// Write C structs
|
||||
|
@ -635,7 +636,7 @@ public class ConfigDefinition {
|
|||
}
|
||||
}
|
||||
|
||||
private static void parseFile(ParseState listener, String filePath) throws IOException {
|
||||
private static void parseFile(ParseTreeListener listener, String filePath) throws IOException {
|
||||
SystemOut.println("Parsing file (Antlr) " + filePath);
|
||||
|
||||
CharStream in = new ANTLRInputStream(new FileInputStream(filePath));
|
||||
|
|
|
@ -6,6 +6,7 @@ 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 org.antlr.v4.runtime.tree.ParseTreeListener;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
@ -13,13 +14,22 @@ import java.util.*;
|
|||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ParseState extends RusefiConfigGrammarBaseListener {
|
||||
public class ParseState {
|
||||
private final Map<String, Definition> definitions = new HashMap<>();
|
||||
private final Map<String, Struct> structs = new HashMap<>();
|
||||
private final List<Struct> structList = new ArrayList<>();
|
||||
private final Map<String, Typedef> typedefs = new HashMap<>();
|
||||
private static final Pattern CHAR_LITERAL = Pattern.compile("'.'");
|
||||
|
||||
private final EnumsReader enumsReader;
|
||||
private Definition.OverwritePolicy definitionOverwritePolicy = Definition.OverwritePolicy.NotAllowed;
|
||||
|
||||
private String typedefName = null;
|
||||
private final Queue<Double> evalResults = new LinkedList<>();
|
||||
private Scope scope = null;
|
||||
private final Stack<Scope> scopes = new Stack<>();
|
||||
|
||||
private Struct lastStruct = null;
|
||||
|
||||
public ParseState(EnumsReader enumsReader) {
|
||||
this.enumsReader = enumsReader;
|
||||
|
@ -34,6 +44,10 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
|
|||
}
|
||||
}
|
||||
|
||||
public Struct getLastStruct() {
|
||||
return lastStruct;
|
||||
}
|
||||
|
||||
private String[] resolveEnumValues(String enumName) {
|
||||
TreeMap<Integer, String> valueNameById = new TreeMap<>();
|
||||
|
||||
|
@ -67,32 +81,12 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
|
|||
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;
|
||||
|
||||
private void addDefinition(String name, Object value) {
|
||||
addDefinition(name, value, this.definitionOverwritePolicy);
|
||||
public Definition findDefinition(String name) {
|
||||
return definitions.getOrDefault(name, null);
|
||||
}
|
||||
|
||||
public void addDefinition(String name, Object value, Definition.OverwritePolicy overwritePolicy) {
|
||||
Definition existingDefinition = this.definitions.getOrDefault(name, null);
|
||||
Definition existingDefinition = definitions.getOrDefault(name, null);
|
||||
|
||||
if (existingDefinition != null) {
|
||||
switch (existingDefinition.overwritePolicy) {
|
||||
|
@ -109,15 +103,32 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
|
|||
definitions.put(name, new Definition(name, value, overwritePolicy));
|
||||
}
|
||||
|
||||
public Definition findDefinition(String name) {
|
||||
return this.definitions.getOrDefault(name, null);
|
||||
private void addDefinition(String name, Object value) {
|
||||
addDefinition(name, value, definitionOverwritePolicy);
|
||||
}
|
||||
|
||||
public void setDefinitionPolicy(Definition.OverwritePolicy policy) {
|
||||
this.definitionOverwritePolicy = policy;
|
||||
}
|
||||
|
||||
private static final Pattern CHAR_LITERAL = Pattern.compile("'.'");
|
||||
public ParseTreeListener getListener() {
|
||||
return new RusefiConfigGrammarBaseListener() {
|
||||
|
||||
@Override
|
||||
public void exitContent(RusefiConfigGrammarParser.ContentContext ctx) {
|
||||
if (!scopes.empty())
|
||||
throw new IllegalStateException();
|
||||
if (scope != null)
|
||||
throw new IllegalStateException();
|
||||
|
||||
if (typedefName != null)
|
||||
throw new IllegalStateException();
|
||||
|
||||
if (!evalResults.isEmpty())
|
||||
throw new IllegalStateException();
|
||||
if (!evalStack.empty())
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
private void handleIntDefinition(String name, int value) {
|
||||
addDefinition(name, value);
|
||||
|
@ -135,7 +146,7 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
|
|||
} else if (ctx.floatNum() != null) {
|
||||
addDefinition(name, Double.parseDouble(ctx.floatNum().getText()));
|
||||
} else if (ctx.numexpr() != null) {
|
||||
double evalResult = this.evalResults.remove();
|
||||
double evalResult = evalResults.remove();
|
||||
double floored = Math.floor(evalResult);
|
||||
|
||||
if (Math.abs(floored - evalResult) < 0.001) {
|
||||
|
@ -157,16 +168,14 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
|
|||
}
|
||||
}
|
||||
|
||||
String typedefName = null;
|
||||
|
||||
@Override
|
||||
public void enterTypedef(RusefiConfigGrammarParser.TypedefContext ctx) {
|
||||
this.typedefName = ctx.identifier().getText();
|
||||
typedefName = ctx.identifier().getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitTypedef(RusefiConfigGrammarParser.TypedefContext ctx) {
|
||||
this.typedefName = null;
|
||||
typedefName = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -176,7 +185,7 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
|
|||
FieldOptions options = new FieldOptions();
|
||||
handleFieldOptionsList(options, ctx.fieldOptionsList());
|
||||
|
||||
typedefs.put(this.typedefName, new ScalarTypedef(this.typedefName, datatype, options));
|
||||
typedefs.put(typedefName, new ScalarTypedef(typedefName, datatype, options));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -196,7 +205,7 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
|
|||
defName = defName.substring(0, defName.length() - 10);
|
||||
values = resolveEnumValues(defName);
|
||||
} else {
|
||||
Definition def = this.definitions.get(defName);
|
||||
Definition def = definitions.get(defName);
|
||||
|
||||
if (def == null) {
|
||||
throw new RuntimeException("couldn't find definition for " + rhs);
|
||||
|
@ -219,7 +228,7 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
|
|||
.toArray(n -> new String[n]); // Convert back to array
|
||||
}
|
||||
|
||||
typedefs.put(this.typedefName, new EnumTypedef(this.typedefName, datatype, endBit, values));
|
||||
typedefs.put(typedefName, new EnumTypedef(typedefName, datatype, endBit, values));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -229,14 +238,14 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
|
|||
FieldOptions options = new FieldOptions();
|
||||
handleFieldOptionsList(options, ctx.fieldOptionsList());
|
||||
|
||||
typedefs.put(this.typedefName, new ArrayTypedef(this.typedefName, this.arrayDim, datatype, options));
|
||||
typedefs.put(typedefName, new ArrayTypedef(ParseState.this.typedefName, this.arrayDim, datatype, options));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitStringTypedefSuffix(RusefiConfigGrammarParser.StringTypedefSuffixContext ctx) {
|
||||
Double stringLength = this.evalResults.remove();
|
||||
Double stringLength = ParseState.this.evalResults.remove();
|
||||
|
||||
this.typedefs.put(this.typedefName, new StringTypedef(this.typedefName, stringLength.intValue()));
|
||||
ParseState.this.typedefs.put(ParseState.this.typedefName, new StringTypedef(ParseState.this.typedefName, stringLength.intValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -428,14 +437,14 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
|
|||
// iterate required for structs
|
||||
assert(iterate);
|
||||
|
||||
scope.structFields.add(new ArrayField<StructField>(new StructField(structs.get(type), name), length, 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 = this.typedefs.get(type);
|
||||
Typedef typedef = typedefs.get(type);
|
||||
|
||||
FieldOptions options = null;
|
||||
FieldOptions options;
|
||||
if (typedef != null) {
|
||||
if (typedef instanceof ScalarTypedef) {
|
||||
ScalarTypedef scTypedef = (ScalarTypedef) typedef;
|
||||
|
@ -501,12 +510,6 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
|
|||
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();
|
||||
|
@ -559,12 +562,12 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
|
|||
// Strip any @@ symbols
|
||||
String defName = ctx.getText().replaceAll("@", "");
|
||||
|
||||
if (!this.definitions.containsKey(defName)) {
|
||||
if (!definitions.containsKey(defName)) {
|
||||
throw new RuntimeException("Definition not found for " + ctx.getText());
|
||||
}
|
||||
|
||||
// Find the matching definition and push on to the eval stack
|
||||
Definition def = this.definitions.get(defName);
|
||||
Definition def = definitions.get(defName);
|
||||
|
||||
if (!def.isNumeric()) {
|
||||
throw new RuntimeException("Tried to use symbol " + defName + " in an expression, but it wasn't a number");
|
||||
|
@ -605,11 +608,16 @@ public class ParseState extends RusefiConfigGrammarBaseListener {
|
|||
evalStack.push(left - right);
|
||||
}
|
||||
|
||||
private Queue<Double> evalResults = new LinkedList<>();
|
||||
|
||||
@Override
|
||||
public void exitNumexpr(RusefiConfigGrammarParser.NumexprContext ctx) {
|
||||
assert(evalStack.size() == 1);
|
||||
evalResults.add(evalStack.pop());
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
static class Scope {
|
||||
public List<Field> structFields = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ public enum Type {
|
|||
}
|
||||
|
||||
public static Optional<Type> findByCtype(String cType) {
|
||||
// todo: better implementation of type aliases!
|
||||
String cTypeWithAlas = "floatms_t".equals(cType) ? "float" : cType;
|
||||
return Arrays.stream(Type.values()).filter(t -> t.cType.equals(cTypeWithAlas)).findFirst();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue