From c3b7c1dc4c385749b8fb9ab77caf3bc56e09a0f1 Mon Sep 17 00:00:00 2001 From: b3b00 Date: Fri, 5 Nov 2021 09:08:15 +0100 Subject: [PATCH] shorter attributes for operations --- ParserTests/ExpressionGeneratorTests.cs | 104 +++++++++++++++++- samples/ParserExample/Program.cs | 16 ++- .../generator/ExpressionRulesGenerator.cs | 8 +- sly/parser/generator/InfixAttribute.cs | 13 +++ sly/parser/generator/PostfixAttribute.cs | 13 +++ sly/parser/generator/PrefixAttribute.cs | 13 +++ 6 files changed, 161 insertions(+), 6 deletions(-) create mode 100644 sly/parser/generator/InfixAttribute.cs create mode 100644 sly/parser/generator/PostfixAttribute.cs create mode 100644 sly/parser/generator/PrefixAttribute.cs diff --git a/ParserTests/ExpressionGeneratorTests.cs b/ParserTests/ExpressionGeneratorTests.cs index 007dfebc..49c4bbe9 100644 --- a/ParserTests/ExpressionGeneratorTests.cs +++ b/ParserTests/ExpressionGeneratorTests.cs @@ -22,7 +22,93 @@ public double BinaryTermExpression(double left, Token operation } } - + + + public class ShortOperationAttributesParser + { + [Infix((int) ExpressionToken.PLUS, Associativity.Right, 10)] + [Infix("MINUS", Associativity.Left, 10)] + public double BinaryTermExpression(double left, Token operation, double right) + { + double result = 0; + switch (operation.TokenID) + { + case ExpressionToken.PLUS: + { + result = left + right; + break; + } + case ExpressionToken.MINUS: + { + result = left - right; + break; + } + } + + return result; + } + + + [Infix((int) ExpressionToken.TIMES, Associativity.Right, 50)] + [Infix("DIVIDE", Associativity.Left, 50)] + public double BinaryFactorExpression(double left, Token operation, double right) + { + double result = 0; + switch (operation.TokenID) + { + case ExpressionToken.TIMES: + { + result = left * right; + break; + } + case ExpressionToken.DIVIDE: + { + result = left / right; + break; + } + } + + return result; + } + + + [Prefix((int) ExpressionToken.MINUS, Associativity.Right, 100)] + public double PreFixExpression(Token operation, double value) + { + return -value; + } + + [Postfix((int) ExpressionToken.FACTORIAL, Associativity.Right, 100)] + public double PostFixExpression(double value, Token operation) + { + var factorial = 1; + for (var i = 1; i <= value; i++) factorial = factorial * i; + return factorial; + } + + + + [Operand] + [Production("double_value : DOUBLE")] + public double OperandDouble(Token value) + { + return value.DoubleValue; + } + + [Operand] + [Production("int_value : INT")] + public double OperandInt(Token value) + { + return value.DoubleValue; + } + + [Operand] + [Production("group : LPAREN ShortOperationAttributesParser_expressions RPAREN")] + public double OperandGroup(Token lparen, double value, Token rparen) + { + return value; + } + } public class ExpressionGeneratorTests { @@ -249,5 +335,21 @@ public void TestBadOperatorString() builder.BuildParser(parserInstance, ParserType.EBNF_LL_RECURSIVE_DESCENT, StartingRule)); Assert.Contains("bad enum name MINUSCULE",exception.Message); } + + [Fact] + public void TestShortOperationAttributes() + { + StartingRule = $"{typeof(ShortOperationAttributesParser).Name}_expressions"; + var parserInstance = new ShortOperationAttributesParser(); + var builder = new ParserBuilder(); + var buildResult = builder.BuildParser(parserInstance, ParserType.EBNF_LL_RECURSIVE_DESCENT, StartingRule); + Assert.True(buildResult.IsOk); + var parser = buildResult.Result; + Assert.NotNull(parser); + var result = parser.Parse("-1 +2 * (5 + 6) - 4 "); + Assert.True(result.IsOk); + Assert.Equal(-1+2*(5+6)-4, result.Result); + + } } } \ No newline at end of file diff --git a/samples/ParserExample/Program.cs b/samples/ParserExample/Program.cs index 2e3b08f0..41e631c4 100644 --- a/samples/ParserExample/Program.cs +++ b/samples/ParserExample/Program.cs @@ -928,7 +928,8 @@ private static void Main(string[] args) // TestI18N(); // Console.ReadLine(); // TestShortGeneric(); - TestIssue239(); + //TestIssue239(); + TestShortOperations(); } @@ -967,6 +968,19 @@ private static void TestShortGeneric() ; } + private static void TestShortOperations() + { + var startingRule = $"{typeof(ShortOperationAttributesParser).Name}_expressions"; + var parserInstance = new ShortOperationAttributesParser(); + var builder = new ParserBuilder(); + var buildResult = builder.BuildParser(parserInstance, ParserType.EBNF_LL_RECURSIVE_DESCENT, startingRule); + Assert.True(buildResult.IsOk); + var parser = buildResult.Result; + Assert.NotNull(parser); + var result = parser.Parse("-1 +2 * (5 + 6) - 4 "); + Assert.Equal(-1+2*(5+6)-4, result.Result); + } + private static void TestIssue239() { Issue239Tests.TestOk(); diff --git a/sly/parser/generator/ExpressionRulesGenerator.cs b/sly/parser/generator/ExpressionRulesGenerator.cs index 55b8d054..bd2a0b8d 100644 --- a/sly/parser/generator/ExpressionRulesGenerator.cs +++ b/sly/parser/generator/ExpressionRulesGenerator.cs @@ -59,16 +59,16 @@ public BuildResult> BuildExpressionRules( ParserConfiguration configuration, Type parserClass, BuildResult> result) { + var methods = parserClass.GetMethods().ToList(); methods = methods.Where(m => { - var attributes = m.GetCustomAttributes().ToList(); - var attr = attributes.Find(a => a.GetType() == typeof(OperationAttribute)); - return attr != null; + var attributes = m.GetCustomAttributes(typeof(OperationAttribute),true).ToList(); + + return attributes.Any(); }).ToList(); var operationsByPrecedence = new Dictionary>>(); - methods.ForEach(m => { var attributes = diff --git a/sly/parser/generator/InfixAttribute.cs b/sly/parser/generator/InfixAttribute.cs new file mode 100644 index 00000000..ea2982b4 --- /dev/null +++ b/sly/parser/generator/InfixAttribute.cs @@ -0,0 +1,13 @@ +namespace sly.parser.generator +{ + public class InfixAttribute : OperationAttribute + { + public InfixAttribute(int intToken, Associativity assoc, int precedence) : base(intToken,Affix.InFix,assoc,precedence) + { + } + + public InfixAttribute(string stringToken, Associativity assoc, int precedence) : base(stringToken,Affix.InFix, assoc,precedence) + { + } + } +} \ No newline at end of file diff --git a/sly/parser/generator/PostfixAttribute.cs b/sly/parser/generator/PostfixAttribute.cs new file mode 100644 index 00000000..14ef5fdf --- /dev/null +++ b/sly/parser/generator/PostfixAttribute.cs @@ -0,0 +1,13 @@ +namespace sly.parser.generator +{ + public class PostfixAttribute : OperationAttribute + { + public PostfixAttribute(int intToken, Associativity assoc, int precedence) : base(intToken,Affix.PostFix,assoc,precedence) + { + } + + public PostfixAttribute(string stringToken, Associativity assoc, int precedence) : base(stringToken,Affix.PostFix, assoc,precedence) + { + } + } +} \ No newline at end of file diff --git a/sly/parser/generator/PrefixAttribute.cs b/sly/parser/generator/PrefixAttribute.cs new file mode 100644 index 00000000..3471e1b9 --- /dev/null +++ b/sly/parser/generator/PrefixAttribute.cs @@ -0,0 +1,13 @@ +namespace sly.parser.generator +{ + public class PrefixAttribute : OperationAttribute + { + public PrefixAttribute(int intToken, Associativity assoc, int precedence) : base(intToken,Affix.PreFix,assoc,precedence) + { + } + + public PrefixAttribute(string stringToken, Associativity assoc, int precedence) : base(stringToken,Affix.PreFix, assoc,precedence) + { + } + } +} \ No newline at end of file