From 4a6ddfb12a32756d270b5cbab6bc7050d8a1948a Mon Sep 17 00:00:00 2001 From: b3b00 Date: Tue, 30 Nov 2021 17:40:15 +0100 Subject: [PATCH] bugfix #259 --- ...9ExpressionParser.cs => Issue259Parser.cs} | 66 ++++++++----------- .../Issue259/Issue259ParserSubclass.cs | 35 ---------- ParserTests/Issue259/Issue259Tests.cs | 37 ++++++++++- .../generator/ExpressionRulesGenerator.cs | 3 +- .../EBNFRecursiveDescentSyntaxParser.cs | 13 +--- .../llparser/RecursiveDescentSyntaxParser.cs | 1 + 6 files changed, 64 insertions(+), 91 deletions(-) rename ParserTests/Issue259/{Issue259ExpressionParser.cs => Issue259Parser.cs} (61%) delete mode 100644 ParserTests/Issue259/Issue259ParserSubclass.cs diff --git a/ParserTests/Issue259/Issue259ExpressionParser.cs b/ParserTests/Issue259/Issue259Parser.cs similarity index 61% rename from ParserTests/Issue259/Issue259ExpressionParser.cs rename to ParserTests/Issue259/Issue259Parser.cs index 017ab4a7..ee94909f 100644 --- a/ParserTests/Issue259/Issue259ExpressionParser.cs +++ b/ParserTests/Issue259/Issue259Parser.cs @@ -1,13 +1,10 @@ -using sly.lexer; -using sly.parser; +using System.Globalization; +using sly.lexer; using sly.parser.generator; -using System; -using System.Globalization; -using System.Linq; namespace CslyNullIssue { - public abstract class Issue259ExpressionParser + public class Issue259Parser { [Operand] [Production("logical_literal: OFF")] @@ -69,43 +66,32 @@ public string Comparison(string lhs, Token token, strin { return $"({lhs} {token.Value} {rhs})"; } + - private static Parser cachedParser; - - public static string Parse(string expression) where T : Issue259ExpressionParser, new() + [Operand] + [Production("numeric_literal: LVAR")] + public string Lvar(Token token) { - if (cachedParser == null) - { - var startingRule = $"{typeof(T).Name}_expressions"; - var parserInstance = new T(); - var builder = new ParserBuilder(); - var parser = builder.BuildParser(parserInstance, ParserType.EBNF_LL_RECURSIVE_DESCENT, startingRule); - if (parser.IsError) - { - throw new Exception($"Could not create parser. BNF is not valid. {parser.Errors[0]}"); - } - cachedParser = parser.Result; - } - - // To simplify an ambiguous lexer which would result from having both && and & as well as || and |, we'll - // simplify the incoming expression by turning && into AND and || into OR: - expression = expression.Replace("&&", " AND "); - expression = expression.Replace("||", " OR "); + return token.Value; + } - var parseResult = cachedParser.Parse(expression); - if (parseResult.IsError) - { - if (parseResult.Errors.Any()) - { - throw new Exception(parseResult.Errors[0].ErrorMessage); - } - else - { - throw new Exception("unknwon error "); - } - } + [Operand] + [Production("numeric_literal: SIMVAR")] + public string SimVarExpression(Token simvarToken) + { + var text = simvarToken.Value[2..]; + var bits = text.Split(","); + var varName = bits[0]; + var type = bits[1].Trim(); + return $"A:{varName}, {type}"; + } - return parseResult.Result; + [Operand] + [Production("group : LPAREN Issue259Parser_expressions RPAREN")] + public string Group(Token _1, string child, Token _2) + { + return child; } + } -} \ No newline at end of file +} diff --git a/ParserTests/Issue259/Issue259ParserSubclass.cs b/ParserTests/Issue259/Issue259ParserSubclass.cs deleted file mode 100644 index 72456c17..00000000 --- a/ParserTests/Issue259/Issue259ParserSubclass.cs +++ /dev/null @@ -1,35 +0,0 @@ -using sly.lexer; -using sly.parser.generator; - -namespace CslyNullIssue -{ - public class Issue259ParserSubclass : Issue259ExpressionParser - { - - [Operand] - [Production("numeric_literal: LVAR")] - public string Lvar(Token token) - { - return token.Value; - } - - [Operand] - [Production("numeric_literal: SIMVAR")] - public string SimVarExpression(Token simvarToken) - { - var text = simvarToken.Value[2..]; - var bits = text.Split(","); - var varName = bits[0]; - var type = bits[1].Trim(); - return $"A:{varName}, {type}"; - } - - [Operand] - [Production("group : LPAREN Issue259ParserSubclass_expressions RPAREN")] - public string Group(Token _1, string child, Token _2) - { - return child; - } - - } -} diff --git a/ParserTests/Issue259/Issue259Tests.cs b/ParserTests/Issue259/Issue259Tests.cs index 23a5f07e..780bccb7 100644 --- a/ParserTests/Issue259/Issue259Tests.cs +++ b/ParserTests/Issue259/Issue259Tests.cs @@ -1,4 +1,6 @@ using System; +using sly.parser; +using sly.parser.generator; using Xunit; namespace CslyNullIssue @@ -8,9 +10,38 @@ public class Issue259Tests [Fact] public static void Issue259Test() { - var expression = "1 < 2 && 1 <= 2 && 1 == 2 && 1 >= 2 && 1 > 2 && 1 != 2 && 1 <> 2"; - var exception = Assert.Throws(() => Issue259ExpressionParser.Parse(expression)); - Assert.True(exception.Message.Contains(@"COMPARISON [<] @line 1, column 79")); + var expression = "1 < 2 AND 3 <= 4 AND 5 == 6 AND 7 >= 8 AND 9 > 10 AND 11 != 12 AND 13 <> 14"; + + + var startingRule = $"{typeof(Issue259Parser).Name}_expressions"; + var parserInstance = new Issue259Parser(); + var builder = new ParserBuilder("en"); + var parser = builder.BuildParser(parserInstance, ParserType.EBNF_LL_RECURSIVE_DESCENT, startingRule); + Assert.True(parser.IsOk); + Assert.NotNull(parser.Result); + + Console.WriteLine(parser.Result.Configuration.Dump()); + + var parseResult = parser.Result.Parse(expression); + + Assert.True(parseResult.IsError); + Assert.Single(parseResult.Errors); + + var error = parseResult.Errors[0]; + + var unexpectedTokenError = error as UnexpectedTokenSyntaxError; + Assert.NotNull(unexpectedTokenError); + Assert.Equal(Issue259ExpressionToken.COMPARISON, unexpectedTokenError.UnexpectedToken.TokenID); + Assert.Equal(">",unexpectedTokenError.UnexpectedToken.Value); + Assert.Contains(unexpectedTokenError.ExpectedTokens, x => x == Issue259ExpressionToken.ON); + Assert.Contains(unexpectedTokenError.ExpectedTokens, x => x == Issue259ExpressionToken.OFF); + Assert.Contains(unexpectedTokenError.ExpectedTokens, x => x == Issue259ExpressionToken.MINUS); + Assert.Contains(unexpectedTokenError.ExpectedTokens, x => x == Issue259ExpressionToken.HEX_NUMBER); + Assert.Contains(unexpectedTokenError.ExpectedTokens, x => x == Issue259ExpressionToken.DECIMAL_NUMBER); + Assert.Contains(unexpectedTokenError.ExpectedTokens, x => x == Issue259ExpressionToken.LVAR); + Assert.Contains(unexpectedTokenError.ExpectedTokens, x => x == Issue259ExpressionToken.SIMVAR); + Assert.Contains(unexpectedTokenError.ExpectedTokens, x => x == Issue259ExpressionToken.LPAREN); + } } } \ No newline at end of file diff --git a/sly/parser/generator/ExpressionRulesGenerator.cs b/sly/parser/generator/ExpressionRulesGenerator.cs index 349bf28b..35c0e928 100644 --- a/sly/parser/generator/ExpressionRulesGenerator.cs +++ b/sly/parser/generator/ExpressionRulesGenerator.cs @@ -223,7 +223,8 @@ private NonTerminal BuildPrecedenceNonTerminal(string name, string nextName, var rule = new Rule() { ExpressionAffix = Affix.InFix, - IsExpressionRule = true + IsExpressionRule = true, + NonTerminalName = name }; rule.Clauses.Add(new NonTerminalClause(nextName)); diff --git a/sly/parser/parser/llparser/EBNFRecursiveDescentSyntaxParser.cs b/sly/parser/parser/llparser/EBNFRecursiveDescentSyntaxParser.cs index 0c741e7e..b3667559 100644 --- a/sly/parser/parser/llparser/EBNFRecursiveDescentSyntaxParser.cs +++ b/sly/parser/parser/llparser/EBNFRecursiveDescentSyntaxParser.cs @@ -184,12 +184,6 @@ public virtual SyntaxParseResult ParseInfixExpressionRule(IList> t { if (firstResult.Root is SyntaxNode node) { - if (node.Name == "expr_17_MINUS") - { - ; - } - // node.IsByPassNode = true; - // node.HasByPassNodes = true; firstResult.Errors.AddRange(secondResult.Errors); firstResult.AddExpectings(secondResult.Expecting); return firstResult; @@ -225,14 +219,9 @@ public virtual SyntaxParseResult ParseInfixExpressionRule(IList> t if (third is NonTerminalClause thirdNonTerminal) { thirdResult = ParseNonTerminal(tokens, thirdNonTerminal, currentPosition); - if (thirdResult.IsError) { - if (firstResult.Root is SyntaxNode node) - { - firstResult.AddExpectings(thirdResult.Expecting); - return firstResult; - } + return thirdResult; } else { diff --git a/sly/parser/parser/llparser/RecursiveDescentSyntaxParser.cs b/sly/parser/parser/llparser/RecursiveDescentSyntaxParser.cs index 1d79382a..23449439 100644 --- a/sly/parser/parser/llparser/RecursiveDescentSyntaxParser.cs +++ b/sly/parser/parser/llparser/RecursiveDescentSyntaxParser.cs @@ -397,6 +397,7 @@ private SyntaxParseResult NoMatchingRuleError(IList> tokens, int c error.IsEnded = false; error.Errors = noRuleErrors; error.EndingPosition = currentPosition; + error.Expecting = allAcceptableTokens; return error; }