Skip to content

Commit ca859c6

Browse files
authored
Merge pull request #521 from b3b00/bugfix/oeration-implicit-operators
Bugfix/oeration implicit operators
2 parents cea2935 + a58cc84 commit ca859c6

16 files changed

+419
-62
lines changed

src/samples/SimpleExpressionParser/SimpleExpressionParser.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public class SimpleExpressionParser
1515

1616
[Operation((int) ExpressionToken.PLUS, Affix.InFix, Associativity.Right, 10)]
1717
[Operation("MINUS", Affix.InFix, Associativity.Left, 10)]
18+
[NodeName("addition_or_substraction")]
1819
public double BinaryTermExpression(double left, Token<ExpressionToken> operation, double right)
1920
{
2021
double result = 0;
@@ -61,11 +62,13 @@ public double BinaryFactorExpression(double left, Token<ExpressionToken> operati
6162

6263

6364
[Prefix((int) ExpressionToken.MINUS, Associativity.Right, 100)]
65+
[NodeName("minus")]
6466
public double PreFixExpression(Token<ExpressionToken> operation, double value)
6567
{
6668
return -value;
6769
}
6870

71+
[NodeName("factorial")]
6972
[Postfix((int) ExpressionToken.FACTORIAL, Associativity.Right, 100)]
7073
public double PostFixExpression(double value, Token<ExpressionToken> operation)
7174
{
@@ -76,29 +79,29 @@ public double PostFixExpression(double value, Token<ExpressionToken> operation)
7679

7780
[Operand]
7881
[Production("operand : primary_value")]
79-
[NodeName("double")]
82+
[NodeName("op_prim")]
8083
public double OperandValue(double value)
8184
{
8285
return value;
8386
}
8487

8588

8689
[Production("primary_value : DOUBLE")]
87-
[NodeName("double")]
90+
[NodeName("prim_double")]
8891
public double OperandDouble(Token<ExpressionToken> value)
8992
{
9093
return value.DoubleValue;
9194
}
9295

9396
[Production("primary_value : INT")]
94-
[NodeName("integer")]
97+
[NodeName("prim_int")]
9598
public double OperandInt(Token<ExpressionToken> value)
9699
{
97100
return value.DoubleValue;
98101
}
99102

100103
[Production("primary_value : LPAREN SimpleExpressionParser_expressions RPAREN")]
101-
[NodeName("group")]
104+
[NodeName("prim_group")]
102105
public double OperandParens(Token<ExpressionToken> lparen, double value, Token<ExpressionToken> rparen)
103106
{
104107
return value;

src/sly/parser/fluent/FluentEBNFParserBuilder.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,4 +368,13 @@ public IFluentEbnfParserBuilder<IN, OUT> Named(string name)
368368
}
369369
return this;
370370
}
371+
372+
public IFluentEbnfParserBuilder<IN, OUT> WithSubNodeNamed(params string[] subNodeNames)
373+
{
374+
if (_currentRule != null)
375+
{
376+
_currentRule.SubNodeNames = subNodeNames;
377+
}
378+
return this;
379+
}
371380
}

src/sly/parser/fluent/IFluentEbnfParserBuilder.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ namespace sly.parser.generator;
77
public interface IFluentEbnfRuleBuilder<IN, OUT> : IFluentEbnfParserBuilder<IN, OUT> where IN : struct
88
{
99
public IFluentEbnfParserBuilder<IN, OUT> Named(string name);
10+
11+
public IFluentEbnfParserBuilder<IN, OUT> WithSubNodeNamed(params string[] subNodeNames);
1012
}
1113

1214
public interface IFluentEbnfParserBuilder<IN,OUT> where IN : struct

src/sly/parser/generator/EBNFParserBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ protected virtual ParserConfiguration<IN, OUT> ExtractEbnfParserConfiguration(Ty
167167

168168
var nodeNames = (NodeNameAttribute[])m.GetCustomAttributes(typeof(NodeNameAttribute), true);
169169
string nodeName = nodeNames != null && nodeNames.Any() ? nodeNames[0].Name : null;
170-
171170
var subNodeNamesAttributes = (SubNodeNamesAttribute[])m.GetCustomAttributes(typeof(SubNodeNamesAttribute), true);
172171
string[] subNodeNames = subNodeNamesAttributes != null && subNodeNamesAttributes.Any() ? subNodeNamesAttributes[0].Names : null;
173172

@@ -178,6 +177,7 @@ protected virtual ParserConfiguration<IN, OUT> ExtractEbnfParserConfiguration(Ty
178177
if (!parseResult.IsError)
179178
{
180179
var rule = (Rule<IN, OUT>)parseResult.Result;
180+
rule.ForcedName = nodeName != null;
181181
rule.NodeName = nodeName;
182182
rule.SubNodeNames = subNodeNames;
183183
rule.RuleString = ruleString;

src/sly/parser/generator/ExpressionRulesGenerator.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ private void GenerateExpressionParser(ParserConfiguration<IN, OUT> configuration
256256
rule.IsByPassRule = true;
257257
rule.IsExpressionRule = true;
258258
rule.ExpressionAffix = Affix.NotOperator;
259+
rule.SetLambdaVisitor((args) => (OUT)args[0]);
259260
configuration.NonTerminals[entrypoint.Name] = entrypoint;
260261
entrypoint.Rules.Add(rule);
261262
}
@@ -283,7 +284,9 @@ private NonTerminal<IN, OUT> BuildPrecedenceNonTerminal(string name, string next
283284
{
284285
ExpressionAffix = Affix.InFix,
285286
IsExpressionRule = true,
286-
NonTerminalName = name
287+
NonTerminalName = name,
288+
NodeName = InFixOps[0].NodeName,
289+
ForcedName = !string.IsNullOrEmpty(InFixOps[0].NodeName)
287290
};
288291

289292
rule.Clauses.Add(new NonTerminalClause<IN, OUT>(nextName));
@@ -295,7 +298,8 @@ private NonTerminal<IN, OUT> BuildPrecedenceNonTerminal(string name, string next
295298
rule.SetVisitor(x);
296299
rule.IsExpressionRule = true;
297300
rule.IsInfixExpressionRule = true;
298-
301+
rule.NodeName = x.NodeName;
302+
rule.ForcedName = !string.IsNullOrEmpty(x.NodeName);
299303
});
300304
nonTerminal.Rules.Add(rule);
301305
if (isLastLevel)
@@ -306,7 +310,7 @@ private NonTerminal<IN, OUT> BuildPrecedenceNonTerminal(string name, string next
306310
ExpressionAffix = Affix.NotOperator,
307311
IsExpressionRule = true,
308312
NonTerminalName = name,
309-
IsByPassRule = true
313+
IsByPassRule = true,
310314
};
311315

312316
rule2.Clauses.Add(new NonTerminalClause<IN, OUT>(nextName));
@@ -336,7 +340,9 @@ private NonTerminal<IN, OUT> BuildPrecedenceNonTerminal(string name, string next
336340
var rule = new Rule<IN, OUT>
337341
{
338342
ExpressionAffix = Affix.PreFix,
339-
IsExpressionRule = true
343+
IsExpressionRule = true,
344+
NodeName = PreFixOps[0].NodeName,
345+
ForcedName = !string.IsNullOrEmpty(PreFixOps[0].NodeName)
340346
};
341347

342348
rule.Clauses.Add(PreFixClauses.Count == 1 ? PreFixClauses[0] : new ChoiceClause<IN, OUT>(PreFixClauses));
@@ -365,7 +371,9 @@ private NonTerminal<IN, OUT> BuildPrecedenceNonTerminal(string name, string next
365371
var rule = new Rule<IN, OUT>
366372
{
367373
ExpressionAffix = Affix.PostFix,
368-
IsExpressionRule = true
374+
IsExpressionRule = true,
375+
NodeName = PostFixOps[0].NodeName,
376+
ForcedName = !string.IsNullOrEmpty(PostFixOps[0].NodeName)
369377
};
370378

371379
rule.Clauses.Add(new NonTerminalClause<IN, OUT>(nextName));

src/sly/parser/generator/OperationMetaData.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public OperationMetaData(int precedence, Associativity assoc, Func<object[],OUT>
3030
{
3131
Precedence = precedence;
3232
Associativity = assoc;
33-
VisitorLambda = lambda;
33+
LambdaVisitor = lambda;
3434
OperatorToken = oper;
3535
Affix = affix;
3636
NodeName = nodeName;
@@ -40,7 +40,7 @@ public OperationMetaData(int precedence, Associativity assoc, Func<object[],OUT>
4040
{
4141
Precedence = precedence;
4242
Associativity = assoc;
43-
VisitorLambda = lambda;
43+
LambdaVisitor = lambda;
4444
ExplicitOperatorToken = oper;
4545
Affix = affix;
4646
NodeName = nodeName;
@@ -52,11 +52,11 @@ public OperationMetaData(int precedence, Associativity assoc, Func<object[],OUT>
5252

5353
public MethodInfo VisitorMethod { get; set; }
5454

55-
public Func<object[],OUT> VisitorLambda { get; set; }
55+
public Func<object[],OUT> LambdaVisitor { get; set; }
5656

5757
public IN OperatorToken { get; set; }
5858

59-
public string Operatorkey => NodeName ?? (IsExplicitOperatorToken ? ExplicitOperatorToken : OperatorToken.ToString());
59+
public string Operatorkey => (IsExplicitOperatorToken ? ExplicitOperatorToken : OperatorToken.ToString());
6060

6161
public Affix Affix { get; set; }
6262

src/sly/parser/generator/ParserBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ private BuildResult<Parser<IN, OUT>> CheckVisitorSignature(BuildResult<Parser<IN
471471
{
472472
if (!rule.IsExpressionRule)
473473
{
474-
var visitor = rule.GetVisitor();
474+
var visitor = rule.GetVisitorMethod();
475475

476476
var returnInfo = visitor.ReturnParameter;
477477
var expectedReturn = typeof(OUT);

src/sly/parser/generator/visitor/EBNFSyntaxTreeVisitor.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ private SyntaxVisitorResult<IN, OUT> Visit(OptionSyntaxNode<IN, OUT> node, objec
8686
private SyntaxVisitorResult<IN, OUT> Visit(SyntaxNode<IN, OUT> node, object context = null)
8787
{
8888
var result = SyntaxVisitorResult<IN, OUT>.NoneResult();
89-
if (node.LambdaVisitor != null || node.Visitor != null || node.IsByPassNode)
89+
if (!node .IsByPassNode && (node.LambdaVisitor != null || node.Visitor != null ))
9090
{
9191
int parametersArrayLength = node.Children.Count + (context is NoContext ? 0 : 1);
9292
var parameters = new object[parametersArrayLength];
@@ -176,6 +176,12 @@ private SyntaxVisitorResult<IN, OUT> Visit(SyntaxNode<IN, OUT> node, object cont
176176
}
177177
}
178178
}
179+
else if (node.IsByPassNode)
180+
{
181+
var child = node.Children[0];
182+
var v = Visit(child, context);
183+
return v;
184+
}
179185

180186
return result;
181187
}

src/sly/parser/parser/llparser/bnf/RecursiveDescentSyntaxParser.Expressions.cs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,37 +27,38 @@ protected SyntaxNode<IN, OUT> ManageExpressionRules(Rule<IN, OUT> rule, SyntaxNo
2727
case 2 when node.ExpressionAffix == Affix.PreFix:
2828
operatorIndex = 0;
2929
break;
30-
case 2:
30+
case 2 when node.ExpressionAffix == Affix.PostFix:
3131
{
32-
if (node.ExpressionAffix == Affix.PostFix) operatorIndex = 1;
32+
operatorIndex = 1;
3333
break;
3434
}
3535
}
3636

3737
if (operatorIndex >= 0 && node.Children[operatorIndex] is SyntaxLeaf<IN, OUT> operatorNode)
3838
{
39-
var visitor = rule.GetVisitor(operatorNode.Token.TokenID);
40-
if (visitor != null)
41-
{
42-
node.Visitor = visitor;
43-
node.Operation = rule.GetOperation(operatorNode.Token.TokenID);
44-
}
45-
var lmabdaVisitor = rule.getLambdaVisitor(operatorNode.Token.TokenID);
46-
if (lmabdaVisitor != null)
39+
var token = operatorNode.Token;
40+
string key = (token.IsExplicit ? $"'{token.Value}'" : token.TokenID.ToString());
41+
var operation = rule.GetOperation(key);
42+
if (operation != null)
4743
{
48-
node.LambdaVisitor = lmabdaVisitor;
49-
node.Operation = rule.GetOperation(operatorNode.Token.TokenID);
44+
node.Visitor = operation.VisitorMethod;
45+
node.LambdaVisitor = operation.LambdaVisitor;
46+
node.Operation = operation;
47+
if (!string.IsNullOrEmpty(operation.NodeName))
48+
{
49+
node.Name = operation.NodeName;
50+
}
5051
}
5152
}
52-
5353
break;
5454
}
5555
case false:
56-
node.LambdaVisitor = rule.getLambdaVisitor();
57-
node.Visitor = rule.GetVisitor();
56+
{
57+
node.LambdaVisitor = rule.getLambdaVisitor(null);
58+
node.Visitor = rule.GetVisitorMethod(null);
5859
break;
60+
}
5961
}
60-
6162
return node;
6263
}
6364

src/sly/parser/parser/llparser/ebnf/EBNFRecursiveDescentSyntaxParser.Expressions.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Collections.Generic;
22
using sly.lexer;
33
using sly.parser;
4+
using sly.parser.generator;
45
using sly.parser.syntax.grammar;
56
using sly.parser.syntax.tree;
67

@@ -14,6 +15,7 @@ public virtual SyntaxParseResult<IN, OUT> ParseInfixExpressionRule(IList<Token<I
1415
int position,
1516
string nonTerminalName, SyntaxParsingContext<IN, OUT> parsingContext)
1617
{
18+
OperationMetaData<IN,OUT> operation = null;
1719
var currentPosition = position;
1820
var children = new List<ISyntaxNode<IN, OUT>>();
1921
if (!tokens[position].IsEOS && rule.Match(tokens, position, Configuration) && rule.Clauses != null &&
@@ -34,6 +36,7 @@ public virtual SyntaxParseResult<IN, OUT> ParseInfixExpressionRule(IList<Token<I
3436
currentPosition = firstResult.EndingPosition;
3537
var second = rule.Clauses[1];
3638
SyntaxParseResult<IN, OUT> secondResult = null;
39+
3740
switch (second)
3841
{
3942
case ChoiceClause<IN, OUT> secondChoice:
@@ -90,7 +93,7 @@ public virtual SyntaxParseResult<IN, OUT> ParseInfixExpressionRule(IList<Token<I
9093
children.Add(secondResult.Root);
9194
children.Add(thirdResult.Root);
9295
currentPosition = thirdResult.EndingPosition;
93-
var finalNode = new SyntaxNode<IN, OUT>(nonTerminalName, children);
96+
var finalNode = new SyntaxNode<IN, OUT>(rule.NodeName ?? nonTerminalName, children);
9497
finalNode.ExpressionAffix = rule.ExpressionAffix;
9598
finalNode = ManageExpressionRules(rule, finalNode);
9699
var finalResult = new SyntaxParseResult<IN, OUT>();

0 commit comments

Comments
 (0)