diff --git a/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionBenchmarks.cs b/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionBenchmarks.cs index 711be5e2..17b87a7d 100644 --- a/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionBenchmarks.cs +++ b/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionBenchmarks.cs @@ -29,6 +29,15 @@ public ParseResult WorstManualExpressionParser() { return new WorstManualExpressionParser(new Lexer(source)).ParseProgram(); } + public ParseResult ComplexExpressionParser() + { + return new ComplexExpressionParser(new Lexer("((((((((((2)))))))));")).ParseProgram(); + } + + public ParseResult ManualComplexExpressionParser() + { + return new ManualComplexExpressionParser(new Lexer("((((((((((2)))))))));")).ParseProgram(); + } [Benchmark] public List> Lex() diff --git a/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionParser.cs b/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionParser.cs index 922d7b62..7f0de6cd 100644 --- a/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionParser.cs +++ b/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionParser.cs @@ -25,6 +25,11 @@ public enum TokenType [Token("%")] Mod, [Token("^")] Exp, + [Token("?")] Conditional, + [Token(":")] Colon, + [Token(",")] Comma, + [Token("=")] Assignment, + [Token(";")] Semicol, [Regex(Regexes.IntLiteral)] IntLit, @@ -170,3 +175,68 @@ public partial class WorstManualExpressionParser [Rule("expression_atomic : IntLit")] public static int IntLit(IToken token) => int.Parse(token.Text); } + +[Parser(typeof(TokenType))] +public partial class ComplexExpressionParser +{ + [Rule("program: expression ';'")] + public static int Program(int n, IToken _) => n; + + [Rule("conditional_expression: primary_expression")] + [Rule("assignment_expression: conditional_expression")] + [Rule("constant_expression: conditional_expression")] + [Rule("expression: assignment_expression")] + [Rule("expression: constant_expression")] + public static int TrivialRules(int n) => n; + + [Rule("conditional_expression: primary_expression '?' expression ':' conditional_expression")] + public static int MakeConditionalExpression(int condition, IToken _1, int trueExpression, IToken _2, int falseExpression) => condition == 0 ? falseExpression : trueExpression; + + [Rule("assignment_expression: primary_expression '=' assignment_expression")] + public static int MakeConditionalExpression(int condition, IToken _1, int trueExpression) => trueExpression; + + [Rule("primary_expression : '(' expression ')'")] + public static int Grouping(IToken _1, int n, IToken _2) => n; + + [Rule("primary_expression : IntLit")] + public static int IntLit(IToken token) => int.Parse(token.Text); +} + +[Parser(typeof(TokenType))] +public partial class ManualComplexExpressionParser +{ + [Rule("program: expression ';'")] + public static int Program(int n, IToken _) => n; + + /** + * This is optimized parse tree. + * expression - assignment_expression + * + * assignment_expression -- primary_expression + * \--- primary_expression '?' expression ':' conditional_expression + * \--- primary_expression '=' assignment_expression + * + * conditional_expression - primary_expression + * \--- primary_expression '?' expression ':' conditional_expression + * + */ + [Rule("conditional_expression: primary_expression")] + [Rule("assignment_expression: primary_expression")] + [Rule("constant_expression: conditional_expression")] + [Rule("expression: assignment_expression")] + public static int TrivialRules(int n) => n; + + [Rule("conditional_expression: primary_expression '?' expression ':' conditional_expression")] + [Rule("assignment_expression: primary_expression '?' expression ':' conditional_expression")] + public static int MakeConditionalExpression(int condition, IToken _1, int trueExpression, IToken _2, int falseExpression) => condition == 0 ? falseExpression : trueExpression; + + [Rule("assignment_expression: primary_expression '=' assignment_expression")] + public static int MakeConditionalExpression(int condition, IToken _1, int trueExpression) => trueExpression; + + [Rule("primary_expression : '(' expression ')'")] + public static int Grouping(IToken _1, int n, IToken _2) => n; + + [Rule("primary_expression : IntLit")] + public static int IntLit(IToken token) => int.Parse(token.Text); +} + diff --git a/Sources/SynKit/Benchmarks/Parser.Benchmarks/Program.cs b/Sources/SynKit/Benchmarks/Parser.Benchmarks/Program.cs index d7d8cdda..d6fa8c44 100644 --- a/Sources/SynKit/Benchmarks/Parser.Benchmarks/Program.cs +++ b/Sources/SynKit/Benchmarks/Parser.Benchmarks/Program.cs @@ -16,6 +16,14 @@ { new Yoakke.SynKit.Parser.Benchmarks.ExpressionBenchmarks().WorstManualExpressionParser(); } +else if (args.Length == 1 && args[0] == "complex") +{ + new Yoakke.SynKit.Parser.Benchmarks.ExpressionBenchmarks().ComplexExpressionParser(); +} +else if (args.Length == 1 && args[0] == "manual_complex") +{ + new Yoakke.SynKit.Parser.Benchmarks.ExpressionBenchmarks().ManualComplexExpressionParser(); +} else { BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args); diff --git a/Sources/SynKit/Benchmarks/Parser.Benchmarks/Properties/launchSettings.json b/Sources/SynKit/Benchmarks/Parser.Benchmarks/Properties/launchSettings.json index bd7d20b1..3c72ae8d 100644 --- a/Sources/SynKit/Benchmarks/Parser.Benchmarks/Properties/launchSettings.json +++ b/Sources/SynKit/Benchmarks/Parser.Benchmarks/Properties/launchSettings.json @@ -3,9 +3,17 @@ "Parser.Benchmarks": { "commandName": "Project" }, - "Parser": { + "parser": { "commandName": "Project", "commandLineArgs": "parser" + }, + "complex": { + "commandName": "Project", + "commandLineArgs": "complex" + }, + "manual_complex": { + "commandName": "Project", + "commandLineArgs": "manual_complex" } } -} \ No newline at end of file +}