forked from acple/ParsecSharp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ExpressionParser.cs
133 lines (97 loc) · 4.03 KB
/
ExpressionParser.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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using System;
using System.Linq.Expressions;
using static ParsecSharp.Parser;
using static ParsecSharp.Text;
namespace ParsecSharp.Examples
{
public interface INumber<TNumber>
where TNumber : INumber<TNumber>
{
TNumber Add(TNumber value);
TNumber Sub(TNumber value);
TNumber Mul(TNumber value);
TNumber Div(TNumber value);
}
public class ExpressionParser<TNumber>
where TNumber : INumber<TNumber>
{
public Parser<char, TNumber> Parser { get; }
public ExpressionParser(Parser<char, TNumber> number)
{
var addsub = Op('+', (x, y) => x.Add(y)) | Op('-', (x, y) => x.Sub(y));
var muldiv = Op('*', (x, y) => x.Mul(y)) | Op('/', (x, y) => x.Div(y));
var open = Char('(').Between(Spaces());
var close = Char(')').Between(Spaces());
var expr = Fix<TNumber>(expr =>
{
var factor = number | expr.Between(open, close);
var term = factor.ChainLeft(muldiv);
return term.ChainLeft(addsub);
});
this.Parser = expr.Between(Spaces()).End();
}
private static Parser<char, Func<TNumber, TNumber, TNumber>> Op(char symbol, Func<TNumber, TNumber, TNumber> function)
=> Char(symbol).Between(Spaces()).MapConst(function);
public Result<char, TNumber> Parse(string source)
=> this.Parser.Parse(source);
}
public class Integer : INumber<Integer>
{
private static readonly Parser<char, Integer> number =
Many1(DecDigit()).ToInt().Map(x => new Integer(x));
public static ExpressionParser<Integer> Parser { get; } = new(number);
public int Value { get; }
private Integer(int value)
{
this.Value = value;
}
public Integer Add(Integer value)
=> new(this.Value + value.Value);
public Integer Sub(Integer value)
=> new(this.Value - value.Value);
public Integer Mul(Integer value)
=> new(this.Value * value.Value);
public Integer Div(Integer value)
=> new(this.Value / value.Value);
}
public class Double : INumber<Double>
{
private static readonly Parser<char, Double> number =
Many1(DecDigit()).AppendOptional(Char('.').Append(Many1(DecDigit())))
.ToDouble().Map(x => new Double(x));
public static ExpressionParser<Double> Parser { get; } = new(number);
public double Value { get; }
private Double(double value)
{
this.Value = value;
}
public Double Add(Double value)
=> new(this.Value + value.Value);
public Double Sub(Double value)
=> new(this.Value - value.Value);
public Double Mul(Double value)
=> new(this.Value * value.Value);
public Double Div(Double value)
=> new(this.Value / value.Value);
}
public class IntegerExpression : INumber<IntegerExpression>
{
private static readonly Parser<char, IntegerExpression> number =
Many1(DecDigit()).ToInt().Map(x => new IntegerExpression(Expression.Constant(x)));
public static ExpressionParser<IntegerExpression> Parser { get; } = new(number);
private readonly Expression _value;
public Expression<Func<int>> Lambda => Expression.Lambda<Func<int>>(this._value);
private IntegerExpression(Expression value)
{
this._value = value;
}
public IntegerExpression Add(IntegerExpression value)
=> new(Expression.Add(this._value, value._value));
public IntegerExpression Sub(IntegerExpression value)
=> new(Expression.Subtract(this._value, value._value));
public IntegerExpression Mul(IntegerExpression value)
=> new(Expression.Multiply(this._value, value._value));
public IntegerExpression Div(IntegerExpression value)
=> new(Expression.Divide(this._value, value._value));
}
}