diff --git a/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionBenchmarks.cs b/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionBenchmarks.cs index d99c45d9..711be5e2 100644 --- a/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionBenchmarks.cs +++ b/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionBenchmarks.cs @@ -4,9 +4,6 @@ using BenchmarkDotNet.Attributes; using Yoakke.SynKit.Lexer; -using Yoakke.SynKit.Parser; -using Yoakke.SynKit.Lexer.Attributes; -using Yoakke.SynKit.Parser.Attributes; namespace Yoakke.SynKit.Parser.Benchmarks; @@ -20,13 +17,19 @@ public ParseResult ExpressionParser() return new ExpressionParser(new Lexer(source)).ParseProgram(); } - [Benchmark] public ParseResult ManualExpressionParser() { return new ManualExpressionParser(new Lexer(source)).ParseProgram(); } + // This benchmark is very slow + //[Benchmark()] + public ParseResult WorstManualExpressionParser() + { + return new WorstManualExpressionParser(new Lexer(source)).ParseProgram(); + } + [Benchmark] public List> Lex() { diff --git a/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionParser.cs b/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionParser.cs index 8117720d..922d7b62 100644 --- a/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionParser.cs +++ b/Sources/SynKit/Benchmarks/Parser.Benchmarks/ExpressionParser.cs @@ -133,3 +133,40 @@ public static int Pop(Punctuated p) [Rule("expression_atomic : IntLit")] public static int IntLit(IToken token) => int.Parse(token.Text); } + +[Parser(typeof(TokenType))] +public partial class WorstManualExpressionParser +{ + [Rule("program: expression ';'")] + public static int Program(int n, IToken _) => n; + + [Rule("expression_level1_operator: ('+' | '-')")] + [Rule("expression_level2_operator: ('*' | '/' | '%')")] + [Rule("expression_level3_operator: ('^')")] + public static IToken Level1Operator(IToken op) => op; + + [Rule("expression: expression_level1")] + [Rule("expression_level1: expression_level2")] + [Rule("expression_level2: expression_atomic")] + public static int TrivialRules(int n) => n; + + [Rule("expression: expression_level1 expression_level1_operator expression_level1")] + [Rule("expression_level1: expression_level1 expression_level2_operator expression_level2")] + [Rule("expression_level2: expression_atomic expression_level3_operator expression_level2")] + public static int BinOp(int a, IToken op, int b) => op.Text switch + { + "^" => (int)Math.Pow(a, b), + "*" => a * b, + "/" => a / b, + "%" => a % b, + "+" => a + b, + "-" => a - b, + _ => throw new NotImplementedException(), + }; + + [Rule("expression_atomic : '(' expression ')'")] + public static int Grouping(IToken _1, int n, IToken _2) => n; + + [Rule("expression_atomic : 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 e3924678..d7d8cdda 100644 --- a/Sources/SynKit/Benchmarks/Parser.Benchmarks/Program.cs +++ b/Sources/SynKit/Benchmarks/Parser.Benchmarks/Program.cs @@ -5,9 +5,17 @@ using BenchmarkDotNet.Running; if (args.Length == 1 && args[0] == "parser") +{ + new Yoakke.SynKit.Parser.Benchmarks.ExpressionBenchmarks().ExpressionParser(); +} +else if (args.Length == 1 && args[0] == "manual_parser") { new Yoakke.SynKit.Parser.Benchmarks.ExpressionBenchmarks().ManualExpressionParser(); } +else if (args.Length == 1 && args[0] == "worst_parser") +{ + new Yoakke.SynKit.Parser.Benchmarks.ExpressionBenchmarks().WorstManualExpressionParser(); +} else { BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);