composition better than inheritance

This commit is contained in:
rusefillc 2021-10-16 21:01:30 -04:00
parent e6973e2446
commit 315ae3d982
3 changed files with 67 additions and 57 deletions

View File

@ -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));

View File

@ -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<>();
}
}

View File

@ -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();
}