-
-
Notifications
You must be signed in to change notification settings - Fork 45
/
FluentParser.cs
67 lines (53 loc) · 2.16 KB
/
FluentParser.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
using Parlot.Fluent;
using static Parlot.Fluent.Parsers;
namespace Parlot.Tests.Calc;
public class FluentParser
{
public static readonly Parser<Expression> Expression;
static FluentParser()
{
/*
* Grammar:
* The top declaration has a lower priority than the lower one.
*
* additive => multiplicative ( ( "-" | "+" ) multiplicative )* ;
* multiplicative => unary ( ( "/" | "*" ) unary )* ;
* unary => ( "-" ) unary
* | primary ;
* primary => NUMBER
* | "(" expression ")" ;
*/
// The Deferred helper creates a parser that can be referenced by others before it is defined
var expression = Deferred<Expression>();
var number = Terms.Decimal()
.Then<Expression>(static d => new Number(d))
;
var divided = Terms.Char('/');
var times = Terms.Char('*');
var minus = Terms.Char('-');
var plus = Terms.Char('+');
var openParen = Terms.Char('(');
var closeParen = Terms.Char(')');
// "(" expression ")"
var groupExpression = Between(openParen, expression, closeParen).Named("group");
// primary => NUMBER | "(" expression ")";
var primary = number.Or(groupExpression).Named("primary");
// ( "-" ) unary | primary;
var unary = primary.Unary(
(minus, x => new NegateExpression(x))
).Named("unary");
// multiplicative => unary ( ( "/" | "*" ) unary )* ;
var multiplicative = unary.LeftAssociative(
(divided, static (a, b) => new Division(a, b)),
(times, static (a, b) => new Multiplication(a, b))
).Named("multiplicative");
// additive => multiplicative(("-" | "+") multiplicative) * ;
var additive = multiplicative.LeftAssociative(
(plus, static (a, b) => new Addition(a, b)),
(minus, static (a, b) => new Subtraction(a, b))
).Named("additive");
expression.Parser = additive;
expression.Named("expression");
Expression = expression;
}
}