diff --git a/sly.sln b/sly.sln
index de101a0e..c1a0e16b 100644
--- a/sly.sln
+++ b/sly.sln
@@ -45,6 +45,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CslyGenerator.Tests", "test
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeneratedXML", "src\samples\GeneratedXML\GeneratedXML.csproj", "{7FEF0D32-FFC7-4886-A4B7-71314C25627E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExplicitTokens", "src\samples\ExplicitTokens\ExplicitTokens.csproj", "{94B9B654-82CB-4969-8DCA-250916E53724}"
+EndProject
Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
@@ -138,6 +140,10 @@ Global
{7FEF0D32-FFC7-4886-A4B7-71314C25627E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7FEF0D32-FFC7-4886-A4B7-71314C25627E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7FEF0D32-FFC7-4886-A4B7-71314C25627E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {94B9B654-82CB-4969-8DCA-250916E53724}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {94B9B654-82CB-4969-8DCA-250916E53724}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {94B9B654-82CB-4969-8DCA-250916E53724}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {94B9B654-82CB-4969-8DCA-250916E53724}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -155,6 +161,7 @@ Global
{81E72CFA-A6D6-4DB4-B3B5-E167064E7858} = {36ED7F1A-2E81-4A71-81FE-A357E5840A33}
{BC5020CA-6BFC-4895-9A1E-99B4A0AEDB11} = {36ED7F1A-2E81-4A71-81FE-A357E5840A33}
{7FEF0D32-FFC7-4886-A4B7-71314C25627E} = {36ED7F1A-2E81-4A71-81FE-A357E5840A33}
+ {94B9B654-82CB-4969-8DCA-250916E53724} = {36ED7F1A-2E81-4A71-81FE-A357E5840A33}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {43254130-CF3E-480E-952F-E50CA5D2E417}
diff --git a/src/samples/ExplicitTokens/ExplicitTokens.csproj b/src/samples/ExplicitTokens/ExplicitTokens.csproj
new file mode 100644
index 00000000..2d531923
--- /dev/null
+++ b/src/samples/ExplicitTokens/ExplicitTokens.csproj
@@ -0,0 +1,11 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
diff --git a/src/samples/ExplicitTokens/ExplicitTokensExpressionParser.cs b/src/samples/ExplicitTokens/ExplicitTokensExpressionParser.cs
new file mode 100644
index 00000000..611ead82
--- /dev/null
+++ b/src/samples/ExplicitTokens/ExplicitTokensExpressionParser.cs
@@ -0,0 +1,89 @@
+using sly.lexer;
+using sly.parser.generator;
+
+namespace ExplicitTokens;
+
+[ParserRoot("ExplicitTokensExpressionParser_expressions")]
+public class ExplicitTokensExpressionParser
+{
+ [Production("primary: DOUBLE")]
+ [Operand]
+ public double Primary(Token doubleToken)
+ {
+ return doubleToken.DoubleValue;
+ }
+
+ [Operand]
+ [Production("primary : 'bozzo'[d]")]
+ public double Bozzo()
+ {
+ return 42.0;
+ }
+
+ [Operand]
+ [Production("primary : TEST[d]")]
+ public double Test()
+ {
+ return 0.0;
+ }
+
+
+ [Infix("'+'",Associativity.Left, 10)]
+ [Infix("'-'", Associativity.Left, 10)]
+ public double BinaryTermExpression(double left, Token operation, double right)
+ {
+ switch (operation.Value)
+ {
+ case "+" : return left + right;
+ case "-" : return left - right;
+ default : throw new InvalidOperationException($"that is not possible ! {operation.Value} is not a valid operation");
+ }
+ }
+
+ [Operation((int) ExplicitTokensTokens.TIMES, Affix.InFix, Associativity.Left, 50)]
+ [Operation("DIVIDE", Affix.InFix, Associativity.Left, 50)]
+ public double BinaryFactorExpression(double left, Token operation, double right)
+ {
+ double result = 0;
+ switch (operation.TokenID)
+ {
+ case ExplicitTokensTokens.TIMES:
+ {
+ result = left * right;
+ break;
+ }
+ case ExplicitTokensTokens.DIVIDE:
+ {
+ result = left / right;
+ break;
+ }
+ }
+
+ return result;
+ }
+
+
+ [Prefix("'-'", Associativity.Right, 100)]
+ public double PreFixExpression(Token operation, double value)
+ {
+ return -value;
+ }
+
+ [Postfix("'!'", Associativity.Left, 110)]
+ public double PostFixExpression(double value, Token operation)
+ {
+ double factorial = 1;
+ for (int i = 0; i < value; i++)
+ {
+ factorial *= i;
+ }
+
+ return factorial;
+ }
+
+
+
+
+
+
+}
\ No newline at end of file
diff --git a/src/samples/ExplicitTokens/ExplicitTokensExpressionParserGenerator.cs b/src/samples/ExplicitTokens/ExplicitTokensExpressionParserGenerator.cs
new file mode 100644
index 00000000..a3a7245e
--- /dev/null
+++ b/src/samples/ExplicitTokens/ExplicitTokensExpressionParserGenerator.cs
@@ -0,0 +1,10 @@
+using sly.sourceGenerator;
+
+namespace ExplicitTokens;
+
+
+[ParserGenerator(typeof(ExplicitTokensTokens), typeof(ExplicitTokensExpressionParser),typeof(double))]
+public partial class ExplicitTokensExpressionParserGenerator : AbstractParserGenerator
+{
+
+}
\ No newline at end of file
diff --git a/src/samples/ExplicitTokens/ExplicitTokensParser.cs b/src/samples/ExplicitTokens/ExplicitTokensParser.cs
new file mode 100644
index 00000000..82e4e6fe
--- /dev/null
+++ b/src/samples/ExplicitTokens/ExplicitTokensParser.cs
@@ -0,0 +1,63 @@
+using sly.lexer;
+using sly.parser.generator;
+
+namespace ExplicitTokens;
+
+[ParserRoot("expression")]
+public class ExplicitTokensParser
+{
+ [Production("primary: DOUBLE")]
+ public double Primary(Token doubleToken)
+ {
+ return doubleToken.DoubleValue;
+ }
+
+ [Production("primary : 'bozzo'[d]")]
+ public double Bozzo()
+ {
+ return 42.0;
+ }
+
+ [Production("primary : TEST[d]")]
+ public double Test()
+ {
+ return 0.0;
+ }
+
+
+ [Production("expression : primary ['+' | '-'] expression")]
+
+
+ public double Expression(double left, Token operatorToken, double right)
+ {
+ double result = 0.0;
+
+
+ switch (operatorToken.StringWithoutQuotes)
+ {
+ case "+":
+ {
+ result = left + right;
+ break;
+ }
+ case "-":
+ {
+ result = left - right;
+ break;
+ }
+ }
+
+ return result;
+ }
+
+
+ [Production("expression : primary ")]
+ public double Simple(double value)
+ {
+ return value;
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/src/samples/ExplicitTokens/ExplicitTokensParserGenerator.cs b/src/samples/ExplicitTokens/ExplicitTokensParserGenerator.cs
new file mode 100644
index 00000000..9b0ac2b7
--- /dev/null
+++ b/src/samples/ExplicitTokens/ExplicitTokensParserGenerator.cs
@@ -0,0 +1,9 @@
+using sly.sourceGenerator;
+
+namespace ExplicitTokens;
+
+[ParserGenerator(typeof(ExplicitTokensTokens), typeof(ExplicitTokensParser), typeof(double))]
+public partial class ExplicitTokensParserGenerator : AbstractParserGenerator
+{
+
+}
\ No newline at end of file
diff --git a/src/samples/ExplicitTokens/ExplicitTokensTokens.cs b/src/samples/ExplicitTokens/ExplicitTokensTokens.cs
new file mode 100644
index 00000000..bd9bc792
--- /dev/null
+++ b/src/samples/ExplicitTokens/ExplicitTokensTokens.cs
@@ -0,0 +1,27 @@
+using sly.lexer;
+
+namespace ExplicitTokens;
+
+[Lexer(IgnoreWS = true, IgnoreEOL = true)]
+public enum ExplicitTokensTokens
+{
+ [MultiLineComment("/*","*/")]
+ MULTILINECOMMENT = 1,
+
+ [SingleLineComment("//")]
+ SINGLELINECOMMENT = 2,
+
+ [Lexeme(GenericToken.Identifier, IdentifierType.AlphaNumeric)]
+ ID = 3,
+
+ [Lexeme(GenericToken.Double, channel:101)]
+ DOUBLE = 4,
+
+ [Keyword("Test")]
+ TEST = 5,
+ [Sugar("*")]
+ TIMES = 6,
+
+ [Sugar("/")]
+ DIVIDE = 7
+}
\ No newline at end of file
diff --git a/tests/CslyGenerator.Tests/CslyGenerator.Tests.csproj b/tests/CslyGenerator.Tests/CslyGenerator.Tests.csproj
index 602743d6..ede69ce6 100644
--- a/tests/CslyGenerator.Tests/CslyGenerator.Tests.csproj
+++ b/tests/CslyGenerator.Tests/CslyGenerator.Tests.csproj
@@ -26,6 +26,7 @@
+
diff --git a/tests/CslyGenerator.Tests/SourceGeneratorTests.cs b/tests/CslyGenerator.Tests/SourceGeneratorTests.cs
index ede64612..3d4feca9 100644
--- a/tests/CslyGenerator.Tests/SourceGeneratorTests.cs
+++ b/tests/CslyGenerator.Tests/SourceGeneratorTests.cs
@@ -63,6 +63,7 @@ private ImmutableArray generateSource(string source, string classNam
[InlineData("/data/callbacks.txt", "ParserCallbacksGenerator")]
[InlineData("/data/labels.txt", "DuplicateLabelLexerGenerator")]
[InlineData("/data/expression.txt", "ExpressionParserGenerator")]
+ [InlineData("/data/explicits.txt", "ExplicitTokensExpressionParserGenerator")]
public void TestGenerator(string source, string className)
{
var code = _embeddedResourceFileSystem.ReadAllText(source);
diff --git a/tests/ParserTests/ExplicitTokensExpressionParser.cs b/tests/CslyGenerator.Tests/data/explicits.txt
similarity index 75%
rename from tests/ParserTests/ExplicitTokensExpressionParser.cs
rename to tests/CslyGenerator.Tests/data/explicits.txt
index 24f811ef..238256b8 100644
--- a/tests/ParserTests/ExplicitTokensExpressionParser.cs
+++ b/tests/CslyGenerator.Tests/data/explicits.txt
@@ -1,11 +1,35 @@
-using System;
-using expressionparser;
-using sly.lexer;
-using sly.parser.generator;
+[ParserGenerator(typeof(ExplicitTokensTokens), typeof(ExplicitTokensExpressionParser),typeof(double))]
+public class ExplicitTokensExpressionParserGenerator : AbstractParserGenerator
+{
+
+}
-namespace ParserTests
+[Lexer(IgnoreWS = true, IgnoreEOL = true)]
+public enum ExplicitTokensTokens
{
- public class ExplicitTokensExpressionParser
+ [MultiLineComment("/*","*/")]
+ MULTILINECOMMENT = 1,
+
+ [SingleLineComment("//")]
+ SINGLELINECOMMENT = 2,
+
+ [Lexeme(GenericToken.Identifier, IdentifierType.AlphaNumeric)]
+ ID = 3,
+
+ [Lexeme(GenericToken.Double, channel:101)]
+ DOUBLE = 4,
+
+ [Keyword("Test")]
+ TEST = 5,
+ [Sugar("*")]
+ TIMES = 6,
+
+ [Sugar("/")]
+ DIVIDE = 7
+}
+
+
+public class ExplicitTokensExpressionParser
{
[Production("primary: DOUBLE")]
[Operand]
@@ -87,5 +111,4 @@ public double PostFixExpression(double value, Token operat
- }
-}
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/tests/ParserTests/ExplicitTokensGeneratorTests.cs b/tests/ParserTests/ExplicitTokensGeneratorTests.cs
new file mode 100644
index 00000000..5715eae6
--- /dev/null
+++ b/tests/ParserTests/ExplicitTokensGeneratorTests.cs
@@ -0,0 +1,120 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using csly.whileLang.model;
+using ExplicitTokens;
+using NFluent;
+using sly.buildresult;
+using sly.lexer;
+using sly.parser;
+using sly.parser.generator;
+using sly.parser.generator.visitor;
+using Xunit;
+
+namespace ParserTests
+{
+
+
+
+ public class ExplicitTokensGeneratorTests
+ {
+ private BuildResult> BuildParser()
+ {
+ var generator = new ExplicitTokensParserGenerator();
+ var result = generator.GetParser();
+ return result;
+ }
+
+ private BuildResult> BuildExpressionParser()
+ {
+ var generator = new ExplicitTokensExpressionParserGenerator();
+ var result = generator.GetParser();
+ return result;
+ }
+
+ [Fact]
+ public void BuildParserTest()
+ {
+ var parser = BuildParser();
+ Check.That(parser.IsOk).IsTrue();
+ Check.That(parser.Result).IsNotNull();
+ var r = parser.Result.Parse("2.0 - 2.0 + bozzo + Test");
+
+
+
+ Check.That(r).IsOkParsing();
+ // grammar is left associative so expression really is
+ // (2.0 - (2.0 + (bozzo + Test))) = 2 - ( 2 + (42 + 0)) = 2 - (2 + 42) = 2 - 44 = -42
+ Check.That(r.Result).IsEqualTo(-42.0d);
+ }
+
+ [Fact]
+ public void BuildExpressionParserTest()
+ {
+ var parser = BuildExpressionParser();
+ Check.That(parser.IsOk).IsTrue();
+ Check.That(parser.Result).IsNotNull();
+ var r = parser.Result.Parse("2.0 - 2.0 + bozzo + Test");
+ Check.That(r).IsOkParsing();
+ var tree = r.SyntaxTree;
+ var graphviz = new GraphVizEBNFSyntaxTreeVisitor();
+ var dump = tree.Dump("\t");
+ var json = $@"{{
+{tree.ToJson()}
+}}";
+
+ var root = graphviz.VisitTree(tree);
+ string graph = graphviz.Graph.Compile();
+ Check.That(graph).Contains(@"label=""\""bozzo\""""")
+ .And.Contains(@"label=""\""+\""""");
+
+ Check.That(r.Result).IsEqualTo(2 - 2 + 42 + 0);
+ }
+
+ [Fact]
+ public void TestErrorWhenUsingImplicitTokensAndRegexLexer()
+ {
+ var parserInstance = new RegexLexAndExplicitTokensParser();
+ var builder = new ParserBuilder();
+ var result = builder.BuildParser(parserInstance, ParserType.EBNF_LL_RECURSIVE_DESCENT, nameof(RegexLexAndExplicitTokensParser)+"_expressions");
+ Check.That(result.IsError).IsTrue();
+ Check.That(result.Errors).CountIs(1);
+ Check.That(result.Errors.First().Code).IsEqualTo(ErrorCodes.LEXER_CANNOT_USE_IMPLICIT_TOKENS_WITH_REGEX_LEXER);
+ }
+
+ [Fact]
+ public void TestNoIdentifierPatternSuppliedWithImplicitTokens()
+ {
+ var parserInstance = new NoIdentifierParser();
+ var builder = new ParserBuilder();
+ var result = builder.BuildParser(parserInstance, ParserType.EBNF_LL_RECURSIVE_DESCENT, "main");
+ Check.That(result.IsError).IsFalse();
+ Check.That(result.Result).IsNotNull();
+ var r = result.Result.Parse("test 1 test 2 test 3");
+ Check.That(r.IsError).IsFalse();
+ Check.That(r.Result).IsEqualTo("test:1,test:2,test:3");
+ }
+
+ [Fact]
+ public void Test()
+ {
+ var parserInstance = new Parse();
+ var builder = new ParserBuilder();
+ var result = builder.BuildParser(parserInstance, ParserType.EBNF_LL_RECURSIVE_DESCENT, "program");
+ Check.That(result).IsOk();
+ var r = result.Result.Parse(@"
+if a == 1.0 then
+ b = 1.0 + 2.0 * 3.0
+else
+ b = 2.0 + a
+c = 3.0
+");
+ Check.That(r).IsOkParsing();
+ //"(condition:(a == 1.0,(b = ( 1.0 + ( 2.0 * 3.0 ) )),(b = ( 2.0 + a ))))(c = 3.0)"
+ Check.That(r.Result).IsEqualTo("((condition:(a == 1.0,(b = ( 1.0 + ( 2.0 * 3.0 ) )),(b = ( 2.0 + a )))),(c = 3.0))");
+ }
+
+ }
+
+}
diff --git a/tests/ParserTests/ExplicitTokensParser.cs b/tests/ParserTests/ExplicitTokensParser.cs
deleted file mode 100644
index 3578ef13..00000000
--- a/tests/ParserTests/ExplicitTokensParser.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using sly.lexer;
-using sly.parser.generator;
-
-namespace ParserTests
-{
- public class ExplicitTokensParser
- {
- [Production("primary: DOUBLE")]
- public double Primary(Token doubleToken)
- {
- return doubleToken.DoubleValue;
- }
-
- [Production("primary : 'bozzo'[d]")]
- public double Bozzo()
- {
- return 42.0;
- }
-
- [Production("primary : TEST[d]")]
- public double Test()
- {
- return 0.0;
- }
-
-
- [Production("expression : primary ['+' | '-'] expression")]
-
-
- public double Expression(double left, Token operatorToken, double right)
- {
- double result = 0.0;
-
-
- switch (operatorToken.StringWithoutQuotes)
- {
- case "+":
- {
- result = left + right;
- break;
- }
- case "-":
- {
- result = left - right;
- break;
- }
- }
-
- return result;
- }
-
-
- [Production("expression : primary ")]
- public double Simple(double value)
- {
- return value;
- }
-
-
-
-
- }
-}
\ No newline at end of file
diff --git a/tests/ParserTests/ExplicitTokensTests.cs b/tests/ParserTests/ExplicitTokensTests.cs
index fbc8caec..724186f2 100644
--- a/tests/ParserTests/ExplicitTokensTests.cs
+++ b/tests/ParserTests/ExplicitTokensTests.cs
@@ -3,6 +3,7 @@
using System.Linq;
using System.Text;
using csly.whileLang.model;
+using ExplicitTokens;
using NFluent;
using sly.buildresult;
using sly.lexer;
diff --git a/tests/ParserTests/ExplicitTokensTokens.cs b/tests/ParserTests/ExplicitTokensTokens.cs
deleted file mode 100644
index b484f6c8..00000000
--- a/tests/ParserTests/ExplicitTokensTokens.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using sly.lexer;
-
-namespace ParserTests
-{
- [Lexer(IgnoreWS = true, IgnoreEOL = true)]
- public enum ExplicitTokensTokens
- {
- [MultiLineComment("/*","*/")]
- MULTILINECOMMENT = 1,
-
- [SingleLineComment("//")]
- SINGLELINECOMMENT = 2,
-
- [Lexeme(GenericToken.Identifier, IdentifierType.AlphaNumeric)]
- ID = 3,
-
- [Lexeme(GenericToken.Double, channel:101)]
- DOUBLE = 4,
-
- [Keyword("Test")]
- TEST = 5,
- [Sugar("*")]
- TIMES = 6,
-
- [Sugar("/")]
- DIVIDE = 7
- }
-}
\ No newline at end of file
diff --git a/tests/ParserTests/ParserTests.csproj b/tests/ParserTests/ParserTests.csproj
index 789aa3e9..9cc4a390 100644
--- a/tests/ParserTests/ParserTests.csproj
+++ b/tests/ParserTests/ParserTests.csproj
@@ -22,6 +22,7 @@
+
@@ -33,7 +34,7 @@
-
+