Skip to content

Commit 756e427

Browse files
committed
fix #596
1 parent ec3c2db commit 756e427

File tree

5 files changed

+149
-7
lines changed

5 files changed

+149
-7
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using sly.lexer;
2+
using sly.parser.generator;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
namespace ParserExample
10+
{
11+
internal enum GettingStartedLexer
12+
{
13+
[Lexeme("[0-9]+")]
14+
INT = 1,
15+
16+
[Lexeme("\\+")]
17+
PLUS = 2,
18+
19+
[Lexeme("[ \\t]+", isSkippable: true)] // the lexeme is marked isSkippable : it will not be sent to the parser and simply discarded.
20+
WS = 3
21+
}
22+
23+
internal class GettingStartedParser
24+
{
25+
26+
[Production("expression: INT")]
27+
public int intExpr(Token<GettingStartedLexer> intToken)
28+
{
29+
return intToken.IntValue;
30+
}
31+
32+
[Production("expression: term PLUS expression")]
33+
public int Expression(int left, Token<GettingStartedLexer> operatorToken, int right)
34+
{
35+
return left + right;
36+
}
37+
38+
[Production("term: INT")]
39+
public int Expression(Token<GettingStartedLexer> intToken)
40+
{
41+
return intToken.IntValue;
42+
}
43+
}
44+
}

src/samples/ParserExample/Program.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1357,7 +1357,8 @@ print a
13571357
}
13581358
private static void Main(string[] args)
13591359
{
1360-
testIssue516();
1360+
TestIssue596GettingStartedParser();
1361+
//testIssue516();
13611362
//TestIssue507();
13621363
//TestFStrings();
13631364
//TestIssue495();
@@ -1848,6 +1849,21 @@ private static void TestFStrings()
18481849
IndentedWhileTests tests = new IndentedWhileTests();
18491850
tests.TestFString();
18501851
}
1852+
1853+
1854+
private static void TestIssue596GettingStartedParser() {
1855+
var parserInstance = new GettingStartedParser();
1856+
var builder = new ParserBuilder<GettingStartedLexer, int>();
1857+
var buildResult = builder.BuildParser(parserInstance, ParserType.LL_RECURSIVE_DESCENT, "expression");
1858+
Assert.True(buildResult.IsOk);
1859+
var parser = buildResult.Result;
1860+
var result = parser.Parse("1+2+3");
1861+
Assert.True(result.IsOk);
1862+
Assert.Equal(6, result.Result);
1863+
1864+
result = parser.Parse("");
1865+
Assert.True(result.IsError);
1866+
}
18511867
}
18521868

18531869
public enum TestGrammarToken

src/sly/parser/parser/ParseError.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,15 @@ protected string GetContextualMessage(string fullSource, int line, int column, s
4747
{
4848
StringBuilder sb = new StringBuilder();
4949
sb.AppendLine(ErrorMessage);
50-
var theLine = fullSource.GetLines()[line];
51-
var tab = " ".Multiply(line.ToString().Length);
52-
sb.Append(tab).AppendLine(" |");
53-
sb.Append(line).Append(" |").AppendLine(theLine);
54-
sb.Append($"{tab} |").Append(" ".Multiply(column)).Append("^^^").AppendLine($" {message}");
55-
50+
var allLines = fullSource.GetLines();
51+
if (line < allLines.Count)
52+
{
53+
var theLine = fullSource.GetLines()[line];
54+
var tab = " ".Multiply(line.ToString().Length);
55+
sb.Append(tab).AppendLine(" |");
56+
sb.Append(line).Append(" |").AppendLine(theLine);
57+
sb.Append($"{tab} |").Append(" ".Multiply(column)).Append("^^^").AppendLine($" {message}");
58+
}
5659
return sb.ToString();
5760
}
5861
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using sly;
2+
using sly.lexer;
3+
using sly.parser.generator;
4+
5+
namespace ParserTests.Issue596
6+
{
7+
internal enum GettingStartedLexer
8+
{
9+
[Lexeme("[0-9]+")]
10+
INT = 1,
11+
12+
[Lexeme("\\+")]
13+
PLUS = 2,
14+
15+
[Lexeme("[ \\t]+", isSkippable: true)] // the lexeme is marked isSkippable : it will not be sent to the parser and simply discarded.
16+
WS = 3
17+
}
18+
19+
internal class GettingStartedParser
20+
{
21+
22+
[Production("expression: INT")]
23+
public int intExpr(Token<GettingStartedLexer> intToken)
24+
{
25+
return intToken.IntValue;
26+
}
27+
28+
[Production("expression: term PLUS expression")]
29+
public int Expression(int left, Token<GettingStartedLexer> operatorToken, int right)
30+
{
31+
return left + right;
32+
}
33+
34+
[Production("term: INT")]
35+
public int Expression(Token<GettingStartedLexer> intToken)
36+
{
37+
return intToken.IntValue;
38+
}
39+
}
40+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using NFluent;
2+
using sly.parser;
3+
using sly.parser.generator;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
using Xunit;
10+
11+
namespace ParserTests.Issue596
12+
{
13+
public class TestIssue596
14+
{
15+
[Fact]
16+
public void Issue596Test()
17+
{
18+
var parserInstance = new GettingStartedParser();
19+
var builder = new ParserBuilder<GettingStartedLexer, int>();
20+
var buildResult = builder.BuildParser(parserInstance, ParserType.LL_RECURSIVE_DESCENT, "expression");
21+
Check.That(buildResult).IsOk();
22+
Assert.True(buildResult.IsOk);
23+
var parser = buildResult.Result;
24+
25+
var result = parser.Parse("1+2+3");
26+
Check.That(result).IsOkParsing();
27+
Check.That(result.Result).IsEqualTo(6);
28+
29+
30+
result = parser.Parse("");
31+
Check.That(result).Not.IsOkParsing();
32+
var error = result.Errors.First();
33+
Check.That(error.ErrorType).IsEqualTo(ErrorType.UnexpectedEOS);
34+
Check.That(error.ErrorMessage).Contains("INT");
35+
36+
}
37+
38+
}
39+
}

0 commit comments

Comments
 (0)