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