Skip to content

Commit

Permalink
bugfix #259
Browse files Browse the repository at this point in the history
  • Loading branch information
b3b00 committed Nov 30, 2021
1 parent a1f11c8 commit 4a6ddfb
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 91 deletions.
Original file line number Diff line number Diff line change
@@ -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")]
Expand Down Expand Up @@ -69,43 +66,32 @@ public string Comparison(string lhs, Token<Issue259ExpressionToken> token, strin
{
return $"({lhs} {token.Value} {rhs})";
}


private static Parser<Issue259ExpressionToken, string> cachedParser;

public static string Parse<T>(string expression) where T : Issue259ExpressionParser, new()
[Operand]
[Production("numeric_literal: LVAR")]
public string Lvar(Token<Issue259ExpressionToken> token)
{
if (cachedParser == null)
{
var startingRule = $"{typeof(T).Name}_expressions";
var parserInstance = new T();
var builder = new ParserBuilder<Issue259ExpressionToken, string>();
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<Issue259ExpressionToken> 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<Issue259ExpressionToken> _1, string child, Token<Issue259ExpressionToken> _2)
{
return child;
}

}
}
}
35 changes: 0 additions & 35 deletions ParserTests/Issue259/Issue259ParserSubclass.cs

This file was deleted.

37 changes: 34 additions & 3 deletions ParserTests/Issue259/Issue259Tests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using sly.parser;
using sly.parser.generator;
using Xunit;

namespace CslyNullIssue
Expand All @@ -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<Exception>(() => Issue259ExpressionParser.Parse<Issue259ParserSubclass>(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<Issue259ExpressionToken, string>("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<Issue259ExpressionToken>;
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);

}
}
}
3 changes: 2 additions & 1 deletion sly/parser/generator/ExpressionRulesGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ private NonTerminal<IN> BuildPrecedenceNonTerminal(string name, string nextName,
var rule = new Rule<IN>()
{
ExpressionAffix = Affix.InFix,
IsExpressionRule = true
IsExpressionRule = true,
NonTerminalName = name
};

rule.Clauses.Add(new NonTerminalClause<IN>(nextName));
Expand Down
13 changes: 1 addition & 12 deletions sly/parser/parser/llparser/EBNFRecursiveDescentSyntaxParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,6 @@ public virtual SyntaxParseResult<IN> ParseInfixExpressionRule(IList<Token<IN>> t
{
if (firstResult.Root is SyntaxNode<IN> node)
{
if (node.Name == "expr_17_MINUS")
{
;
}
// node.IsByPassNode = true;
// node.HasByPassNodes = true;
firstResult.Errors.AddRange(secondResult.Errors);
firstResult.AddExpectings(secondResult.Expecting);
return firstResult;
Expand Down Expand Up @@ -225,14 +219,9 @@ public virtual SyntaxParseResult<IN> ParseInfixExpressionRule(IList<Token<IN>> t
if (third is NonTerminalClause<IN> thirdNonTerminal)
{
thirdResult = ParseNonTerminal(tokens, thirdNonTerminal, currentPosition);

if (thirdResult.IsError)
{
if (firstResult.Root is SyntaxNode<IN> node)
{
firstResult.AddExpectings(thirdResult.Expecting);
return firstResult;
}
return thirdResult;
}
else
{
Expand Down
1 change: 1 addition & 0 deletions sly/parser/parser/llparser/RecursiveDescentSyntaxParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ private SyntaxParseResult<IN> NoMatchingRuleError(IList<Token<IN>> tokens, int c
error.IsEnded = false;
error.Errors = noRuleErrors;
error.EndingPosition = currentPosition;
error.Expecting = allAcceptableTokens;

return error;
}
Expand Down

0 comments on commit 4a6ddfb

Please sign in to comment.