diff --git a/src/samples/SimpleExpressionParser/SimpleExpressionParser.cs b/src/samples/SimpleExpressionParser/SimpleExpressionParser.cs index d161b5d7..49145a52 100644 --- a/src/samples/SimpleExpressionParser/SimpleExpressionParser.cs +++ b/src/samples/SimpleExpressionParser/SimpleExpressionParser.cs @@ -36,6 +36,7 @@ public double BinaryTermExpression(double left, Token operation [Operation((int) ExpressionToken.TIMES, Affix.InFix, Associativity.Right, 50)] [Operation("DIVIDE", Affix.InFix, Associativity.Left, 50)] + [NodeName("multiplication_or_division")] public double BinaryFactorExpression(double left, Token operation, double right) { double result = 0; @@ -73,6 +74,7 @@ public double PostFixExpression(double value, Token operation) [Operand] [Production("operand : primary_value")] + [NodeName("double")] public double OperandValue(double value) { return value; @@ -80,18 +82,21 @@ public double OperandValue(double value) [Production("primary_value : DOUBLE")] + [NodeName("double")] public double OperandDouble(Token value) { return value.DoubleValue; } [Production("primary_value : INT")] + [NodeName("integer")] public double OperandInt(Token value) { return value.DoubleValue; } [Production("primary_value : LPAREN SimpleExpressionParser_expressions RPAREN")] + [NodeName("group")] public double OperandParens(Token lparen, double value, Token rparen) { return value; diff --git a/src/sly/parser/generator/ExpressionRulesGenerator.cs b/src/sly/parser/generator/ExpressionRulesGenerator.cs index fff7e6c3..fcbf3e79 100644 --- a/src/sly/parser/generator/ExpressionRulesGenerator.cs +++ b/src/sly/parser/generator/ExpressionRulesGenerator.cs @@ -40,6 +40,15 @@ public BuildResult> BuildExpressionRules( { var attributes = (OperationAttribute[])m.GetCustomAttributes(typeof(OperationAttribute), true); + var names = + (NodeNameAttribute[])m.GetCustomAttributes(typeof(NodeNameAttribute), true); + + string nodeName = null; + // a visitor method can only have 1 node name (NodeNameAttribute is not multiple) + if (names != null && names.Length > 0) + { + nodeName = names[0].Name; + } foreach (var attr in attributes) { @@ -67,11 +76,11 @@ public BuildResult> BuildExpressionRules( OperationMetaData operation = null; if (!isEnumValue && !string.IsNullOrEmpty(explicitToken) && explicitToken.StartsWith("'") && explicitToken.EndsWith("'")) { - operation = new OperationMetaData(attr.Precedence, attr.Assoc, m, attr.Affix, explicitToken); + operation = new OperationMetaData(attr.Precedence, attr.Assoc, m, attr.Affix, explicitToken ,nodeName); } else if (isEnumValue) { - operation = new OperationMetaData(attr.Precedence, attr.Assoc, m, attr.Affix, oper); + operation = new OperationMetaData(attr.Precedence, attr.Assoc, m, attr.Affix, oper, nodeName); } else { @@ -346,7 +355,7 @@ private string GetNonTerminalNameForPrecedence(int precedence, { if (precedence > 0) { - var tokens = operationsByPrecedence[precedence].Select, string>(o => o.Operatorkey).ToList(); + var tokens = operationsByPrecedence[precedence].Select, string>(o => o.Operatorkey).Distinct().ToList(); return GetNonTerminalNameForPrecedence(precedence, tokens); } @@ -360,7 +369,7 @@ private string GetNonTerminalNameForPrecedence(int precedence, List oper .ToList() .Aggregate((s1, s2) => $"{s1}_{s2}"); - return $"expr_{precedence}_{operatorsPart}"; + return $"{operatorsPart}"; } } } \ No newline at end of file diff --git a/src/sly/parser/generator/OperationMetaData.cs b/src/sly/parser/generator/OperationMetaData.cs index 78d8111d..e9b92a1f 100644 --- a/src/sly/parser/generator/OperationMetaData.cs +++ b/src/sly/parser/generator/OperationMetaData.cs @@ -5,22 +5,24 @@ namespace sly.parser.generator { public class OperationMetaData where T : struct { - public OperationMetaData(int precedence, Associativity assoc, MethodInfo method, Affix affix, T oper) + public OperationMetaData(int precedence, Associativity assoc, MethodInfo method, Affix affix, T oper, string nodeName) { Precedence = precedence; Associativity = assoc; VisitorMethod = method; OperatorToken = oper; Affix = affix; + NodeNodeName = nodeName; } - public OperationMetaData(int precedence, Associativity assoc, MethodInfo method, Affix affix, string oper) + public OperationMetaData(int precedence, Associativity assoc, MethodInfo method, Affix affix, string oper, string nodeNodeName) { Precedence = precedence; Associativity = assoc; VisitorMethod = method; ExplicitOperatorToken = oper; Affix = affix; + NodeNodeName = nodeNodeName; } public int Precedence { get; set; } @@ -31,9 +33,11 @@ public OperationMetaData(int precedence, Associativity assoc, MethodInfo method, public T OperatorToken { get; set; } - public string Operatorkey => IsExplicitOperatorToken ? ExplicitOperatorToken : OperatorToken.ToString(); + public string Operatorkey => NodeNodeName ?? (IsExplicitOperatorToken ? ExplicitOperatorToken : OperatorToken.ToString()); public Affix Affix { get; set; } + + public string NodeNodeName { get; set; } public bool IsBinary => Affix == Affix.InFix; diff --git a/tests/ParserTests/ExpressionGeneratorTests.cs b/tests/ParserTests/ExpressionGeneratorTests.cs index 167ce1ae..3adf2718 100644 --- a/tests/ParserTests/ExpressionGeneratorTests.cs +++ b/tests/ParserTests/ExpressionGeneratorTests.cs @@ -231,19 +231,18 @@ public void TestBuild() nt = nonterminals[2]; Check.That(nt.Rules).CountIs(3); Check.That(nt.Name).Contains("primary_value"); + Check.That(nt.Rules[0].NodeName).IsEqualTo("double"); + Check.That(nt.Rules[1].NodeName).IsEqualTo("integer"); + Check.That(nt.Rules[2].NodeName).IsEqualTo("group"); nt = nonterminals[3]; Check.That(nt.Rules).IsSingle(); - Check.That(nt.Name).Contains("10"); Check.That(nt.Name).Contains("PLUS"); Check.That(nt.Name).Contains("MINUS"); nt = nonterminals[4]; Check.That(nt.Rules).IsSingle(); - Check.That(nt.Name).Contains("50"); - Check.That(nt.Name).Contains("TIMES"); - Check.That(nt.Name).Contains("DIVIDE"); + Check.That(nt.Name).IsEqualTo("multiplication_or_division"); nt = nonterminals[5]; Check.That(nt.Rules).CountIs(3); - Check.That(nt.Name).Contains("100"); Check.That(nt.Name).Contains("MINUS"); nt = nonterminals[6]; Check.That(nt.Rules).IsSingle();