Skip to content

Commit

Permalink
Merge pull request #521 from b3b00/bugfix/oeration-implicit-operators
Browse files Browse the repository at this point in the history
Bugfix/oeration implicit operators
  • Loading branch information
b3b00 authored Dec 23, 2024
2 parents cea2935 + a58cc84 commit ca859c6
Show file tree
Hide file tree
Showing 16 changed files with 419 additions and 62 deletions.
11 changes: 7 additions & 4 deletions src/samples/SimpleExpressionParser/SimpleExpressionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class SimpleExpressionParser

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


[Prefix((int) ExpressionToken.MINUS, Associativity.Right, 100)]
[NodeName("minus")]
public double PreFixExpression(Token<ExpressionToken> operation, double value)
{
return -value;
}

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

[Operand]
[Production("operand : primary_value")]
[NodeName("double")]
[NodeName("op_prim")]
public double OperandValue(double value)
{
return value;
}


[Production("primary_value : DOUBLE")]
[NodeName("double")]
[NodeName("prim_double")]
public double OperandDouble(Token<ExpressionToken> value)
{
return value.DoubleValue;
}

[Production("primary_value : INT")]
[NodeName("integer")]
[NodeName("prim_int")]
public double OperandInt(Token<ExpressionToken> value)
{
return value.DoubleValue;
}

[Production("primary_value : LPAREN SimpleExpressionParser_expressions RPAREN")]
[NodeName("group")]
[NodeName("prim_group")]
public double OperandParens(Token<ExpressionToken> lparen, double value, Token<ExpressionToken> rparen)
{
return value;
Expand Down
9 changes: 9 additions & 0 deletions src/sly/parser/fluent/FluentEBNFParserBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -368,4 +368,13 @@ public IFluentEbnfParserBuilder<IN, OUT> Named(string name)
}
return this;
}

public IFluentEbnfParserBuilder<IN, OUT> WithSubNodeNamed(params string[] subNodeNames)
{
if (_currentRule != null)
{
_currentRule.SubNodeNames = subNodeNames;
}
return this;
}
}
2 changes: 2 additions & 0 deletions src/sly/parser/fluent/IFluentEbnfParserBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ namespace sly.parser.generator;
public interface IFluentEbnfRuleBuilder<IN, OUT> : IFluentEbnfParserBuilder<IN, OUT> where IN : struct
{
public IFluentEbnfParserBuilder<IN, OUT> Named(string name);

public IFluentEbnfParserBuilder<IN, OUT> WithSubNodeNamed(params string[] subNodeNames);
}

public interface IFluentEbnfParserBuilder<IN,OUT> where IN : struct
Expand Down
2 changes: 1 addition & 1 deletion src/sly/parser/generator/EBNFParserBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ protected virtual ParserConfiguration<IN, OUT> ExtractEbnfParserConfiguration(Ty

var nodeNames = (NodeNameAttribute[])m.GetCustomAttributes(typeof(NodeNameAttribute), true);
string nodeName = nodeNames != null && nodeNames.Any() ? nodeNames[0].Name : null;

var subNodeNamesAttributes = (SubNodeNamesAttribute[])m.GetCustomAttributes(typeof(SubNodeNamesAttribute), true);
string[] subNodeNames = subNodeNamesAttributes != null && subNodeNamesAttributes.Any() ? subNodeNamesAttributes[0].Names : null;

Expand All @@ -178,6 +177,7 @@ protected virtual ParserConfiguration<IN, OUT> ExtractEbnfParserConfiguration(Ty
if (!parseResult.IsError)
{
var rule = (Rule<IN, OUT>)parseResult.Result;
rule.ForcedName = nodeName != null;
rule.NodeName = nodeName;
rule.SubNodeNames = subNodeNames;
rule.RuleString = ruleString;
Expand Down
18 changes: 13 additions & 5 deletions src/sly/parser/generator/ExpressionRulesGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ private void GenerateExpressionParser(ParserConfiguration<IN, OUT> configuration
rule.IsByPassRule = true;
rule.IsExpressionRule = true;
rule.ExpressionAffix = Affix.NotOperator;
rule.SetLambdaVisitor((args) => (OUT)args[0]);
configuration.NonTerminals[entrypoint.Name] = entrypoint;
entrypoint.Rules.Add(rule);
}
Expand Down Expand Up @@ -283,7 +284,9 @@ private NonTerminal<IN, OUT> BuildPrecedenceNonTerminal(string name, string next
{
ExpressionAffix = Affix.InFix,
IsExpressionRule = true,
NonTerminalName = name
NonTerminalName = name,
NodeName = InFixOps[0].NodeName,
ForcedName = !string.IsNullOrEmpty(InFixOps[0].NodeName)
};

rule.Clauses.Add(new NonTerminalClause<IN, OUT>(nextName));
Expand All @@ -295,7 +298,8 @@ private NonTerminal<IN, OUT> BuildPrecedenceNonTerminal(string name, string next
rule.SetVisitor(x);
rule.IsExpressionRule = true;
rule.IsInfixExpressionRule = true;

rule.NodeName = x.NodeName;
rule.ForcedName = !string.IsNullOrEmpty(x.NodeName);
});
nonTerminal.Rules.Add(rule);
if (isLastLevel)
Expand All @@ -306,7 +310,7 @@ private NonTerminal<IN, OUT> BuildPrecedenceNonTerminal(string name, string next
ExpressionAffix = Affix.NotOperator,
IsExpressionRule = true,
NonTerminalName = name,
IsByPassRule = true
IsByPassRule = true,
};

rule2.Clauses.Add(new NonTerminalClause<IN, OUT>(nextName));
Expand Down Expand Up @@ -336,7 +340,9 @@ private NonTerminal<IN, OUT> BuildPrecedenceNonTerminal(string name, string next
var rule = new Rule<IN, OUT>
{
ExpressionAffix = Affix.PreFix,
IsExpressionRule = true
IsExpressionRule = true,
NodeName = PreFixOps[0].NodeName,
ForcedName = !string.IsNullOrEmpty(PreFixOps[0].NodeName)
};

rule.Clauses.Add(PreFixClauses.Count == 1 ? PreFixClauses[0] : new ChoiceClause<IN, OUT>(PreFixClauses));
Expand Down Expand Up @@ -365,7 +371,9 @@ private NonTerminal<IN, OUT> BuildPrecedenceNonTerminal(string name, string next
var rule = new Rule<IN, OUT>
{
ExpressionAffix = Affix.PostFix,
IsExpressionRule = true
IsExpressionRule = true,
NodeName = PostFixOps[0].NodeName,
ForcedName = !string.IsNullOrEmpty(PostFixOps[0].NodeName)
};

rule.Clauses.Add(new NonTerminalClause<IN, OUT>(nextName));
Expand Down
8 changes: 4 additions & 4 deletions src/sly/parser/generator/OperationMetaData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public OperationMetaData(int precedence, Associativity assoc, Func<object[],OUT>
{
Precedence = precedence;
Associativity = assoc;
VisitorLambda = lambda;
LambdaVisitor = lambda;
OperatorToken = oper;
Affix = affix;
NodeName = nodeName;
Expand All @@ -40,7 +40,7 @@ public OperationMetaData(int precedence, Associativity assoc, Func<object[],OUT>
{
Precedence = precedence;
Associativity = assoc;
VisitorLambda = lambda;
LambdaVisitor = lambda;
ExplicitOperatorToken = oper;
Affix = affix;
NodeName = nodeName;
Expand All @@ -52,11 +52,11 @@ public OperationMetaData(int precedence, Associativity assoc, Func<object[],OUT>

public MethodInfo VisitorMethod { get; set; }

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

public IN OperatorToken { get; set; }

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

public Affix Affix { get; set; }

Expand Down
2 changes: 1 addition & 1 deletion src/sly/parser/generator/ParserBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ private BuildResult<Parser<IN, OUT>> CheckVisitorSignature(BuildResult<Parser<IN
{
if (!rule.IsExpressionRule)
{
var visitor = rule.GetVisitor();
var visitor = rule.GetVisitorMethod();

var returnInfo = visitor.ReturnParameter;
var expectedReturn = typeof(OUT);
Expand Down
8 changes: 7 additions & 1 deletion src/sly/parser/generator/visitor/EBNFSyntaxTreeVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ private SyntaxVisitorResult<IN, OUT> Visit(OptionSyntaxNode<IN, OUT> node, objec
private SyntaxVisitorResult<IN, OUT> Visit(SyntaxNode<IN, OUT> node, object context = null)
{
var result = SyntaxVisitorResult<IN, OUT>.NoneResult();
if (node.LambdaVisitor != null || node.Visitor != null || node.IsByPassNode)
if (!node .IsByPassNode && (node.LambdaVisitor != null || node.Visitor != null ))
{
int parametersArrayLength = node.Children.Count + (context is NoContext ? 0 : 1);
var parameters = new object[parametersArrayLength];
Expand Down Expand Up @@ -176,6 +176,12 @@ private SyntaxVisitorResult<IN, OUT> Visit(SyntaxNode<IN, OUT> node, object cont
}
}
}
else if (node.IsByPassNode)
{
var child = node.Children[0];
var v = Visit(child, context);
return v;
}

return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,37 +27,38 @@ protected SyntaxNode<IN, OUT> ManageExpressionRules(Rule<IN, OUT> rule, SyntaxNo
case 2 when node.ExpressionAffix == Affix.PreFix:
operatorIndex = 0;
break;
case 2:
case 2 when node.ExpressionAffix == Affix.PostFix:
{
if (node.ExpressionAffix == Affix.PostFix) operatorIndex = 1;
operatorIndex = 1;
break;
}
}

if (operatorIndex >= 0 && node.Children[operatorIndex] is SyntaxLeaf<IN, OUT> operatorNode)
{
var visitor = rule.GetVisitor(operatorNode.Token.TokenID);
if (visitor != null)
{
node.Visitor = visitor;
node.Operation = rule.GetOperation(operatorNode.Token.TokenID);
}
var lmabdaVisitor = rule.getLambdaVisitor(operatorNode.Token.TokenID);
if (lmabdaVisitor != null)
var token = operatorNode.Token;
string key = (token.IsExplicit ? $"'{token.Value}'" : token.TokenID.ToString());
var operation = rule.GetOperation(key);
if (operation != null)
{
node.LambdaVisitor = lmabdaVisitor;
node.Operation = rule.GetOperation(operatorNode.Token.TokenID);
node.Visitor = operation.VisitorMethod;
node.LambdaVisitor = operation.LambdaVisitor;
node.Operation = operation;
if (!string.IsNullOrEmpty(operation.NodeName))
{
node.Name = operation.NodeName;
}
}
}

break;
}
case false:
node.LambdaVisitor = rule.getLambdaVisitor();
node.Visitor = rule.GetVisitor();
{
node.LambdaVisitor = rule.getLambdaVisitor(null);
node.Visitor = rule.GetVisitorMethod(null);
break;
}
}

return node;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using sly.lexer;
using sly.parser;
using sly.parser.generator;
using sly.parser.syntax.grammar;
using sly.parser.syntax.tree;

Expand All @@ -14,6 +15,7 @@ public virtual SyntaxParseResult<IN, OUT> ParseInfixExpressionRule(IList<Token<I
int position,
string nonTerminalName, SyntaxParsingContext<IN, OUT> parsingContext)
{
OperationMetaData<IN,OUT> operation = null;

Check warning on line 18 in src/sly/parser/parser/llparser/ebnf/EBNFRecursiveDescentSyntaxParser.Expressions.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

The variable 'operation' is assigned but its value is never used

Check warning on line 18 in src/sly/parser/parser/llparser/ebnf/EBNFRecursiveDescentSyntaxParser.Expressions.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

The variable 'operation' is assigned but its value is never used

Check warning on line 18 in src/sly/parser/parser/llparser/ebnf/EBNFRecursiveDescentSyntaxParser.Expressions.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

The variable 'operation' is assigned but its value is never used

Check warning on line 18 in src/sly/parser/parser/llparser/ebnf/EBNFRecursiveDescentSyntaxParser.Expressions.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

The variable 'operation' is assigned but its value is never used

Check warning on line 18 in src/sly/parser/parser/llparser/ebnf/EBNFRecursiveDescentSyntaxParser.Expressions.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

The variable 'operation' is assigned but its value is never used

Check warning on line 18 in src/sly/parser/parser/llparser/ebnf/EBNFRecursiveDescentSyntaxParser.Expressions.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

The variable 'operation' is assigned but its value is never used

Check warning on line 18 in src/sly/parser/parser/llparser/ebnf/EBNFRecursiveDescentSyntaxParser.Expressions.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

The variable 'operation' is assigned but its value is never used

Check warning on line 18 in src/sly/parser/parser/llparser/ebnf/EBNFRecursiveDescentSyntaxParser.Expressions.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

The variable 'operation' is assigned but its value is never used

Check warning on line 18 in src/sly/parser/parser/llparser/ebnf/EBNFRecursiveDescentSyntaxParser.Expressions.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

The variable 'operation' is assigned but its value is never used

Check warning on line 18 in src/sly/parser/parser/llparser/ebnf/EBNFRecursiveDescentSyntaxParser.Expressions.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

The variable 'operation' is assigned but its value is never used
var currentPosition = position;
var children = new List<ISyntaxNode<IN, OUT>>();
if (!tokens[position].IsEOS && rule.Match(tokens, position, Configuration) && rule.Clauses != null &&
Expand All @@ -34,6 +36,7 @@ public virtual SyntaxParseResult<IN, OUT> ParseInfixExpressionRule(IList<Token<I
currentPosition = firstResult.EndingPosition;
var second = rule.Clauses[1];
SyntaxParseResult<IN, OUT> secondResult = null;

switch (second)
{
case ChoiceClause<IN, OUT> secondChoice:
Expand Down Expand Up @@ -90,7 +93,7 @@ public virtual SyntaxParseResult<IN, OUT> ParseInfixExpressionRule(IList<Token<I
children.Add(secondResult.Root);
children.Add(thirdResult.Root);
currentPosition = thirdResult.EndingPosition;
var finalNode = new SyntaxNode<IN, OUT>(nonTerminalName, children);
var finalNode = new SyntaxNode<IN, OUT>(rule.NodeName ?? nonTerminalName, children);
finalNode.ExpressionAffix = rule.ExpressionAffix;
finalNode = ManageExpressionRules(rule, finalNode);
var finalResult = new SyntaxParseResult<IN, OUT>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public SyntaxParseResult<IN, OUT> ParseOption(IList<Token<IN>> tokens, OptionCla
{
IsError = false,
Root = new OptionSyntaxNode<IN, OUT>(rule.NonTerminalName, new List<ISyntaxNode<IN, OUT>>(),
rule.GetVisitor()),
rule.GetVisitorMethod()),
EndingPosition = position
};
}
Expand All @@ -79,7 +79,7 @@ public SyntaxParseResult<IN, OUT> ParseOption(IList<Token<IN>> tokens, OptionCla
var children = new List<ISyntaxNode<IN, OUT>> { innerResult.Root };
if (innerResult.IsError) children.Clear();
result.Root = new OptionSyntaxNode<IN, OUT>(rule.NonTerminalName, children,
rule.GetVisitor());
rule.GetVisitorMethod());
(result.Root as OptionSyntaxNode<IN, OUT>).IsGroupOption = clause.IsGroupOption;
result.EndingPosition = position;
break;
Expand All @@ -90,7 +90,7 @@ public SyntaxParseResult<IN, OUT> ParseOption(IList<Token<IN>> tokens, OptionCla
{
var children = new List<ISyntaxNode<IN, OUT>> { innerResult.Root };
result.Root =
new OptionSyntaxNode<IN, OUT>(rule.NonTerminalName, children, rule.GetVisitor());
new OptionSyntaxNode<IN, OUT>(rule.NonTerminalName, children, rule.GetVisitorMethod());
result.EndingPosition = innerResult.EndingPosition;
result.HasByPassNodes = innerResult.HasByPassNodes;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ public override SyntaxParseResult<IN, OUT> Parse(IList<Token<IN>> tokens, Rule<I
}
}
node = new SyntaxNode<IN, OUT>( nonTerminalName, children);
node.ForcedName = rule.ForcedName;
node.Name = string.IsNullOrEmpty(rule.NodeName) ? nonTerminalName : rule.NodeName;
node.ExpressionAffix = rule.ExpressionAffix;
node = ManageExpressionRules(rule, node);
Expand Down
Loading

0 comments on commit ca859c6

Please sign in to comment.