Skip to content

Commit d67cb56

Browse files
Merge pull request #2 from SimpleStateMachine/dev
Dev
2 parents 31daf24 + e89b9e2 commit d67cb56

36 files changed

+1023
-47
lines changed
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
using System;
2+
using System.Collections.Immutable;
3+
using System.Linq;
4+
5+
namespace SimpleStateMachine.StructuralSearch.Sandbox
6+
{
7+
public interface IExpr
8+
{
9+
public double Invoke();
10+
}
11+
12+
public class Identifier : IExpr
13+
{
14+
public string Name { get; }
15+
16+
public Identifier(string name)
17+
{
18+
Name = name;
19+
}
20+
21+
public bool Equals(IExpr? other)
22+
=> other is Identifier i && this.Name == i.Name;
23+
24+
public double Invoke()
25+
{
26+
return 0;
27+
}
28+
}
29+
30+
public class Literal : IExpr
31+
{
32+
public double Value { get; }
33+
34+
public Literal(double value)
35+
{
36+
Value = value;
37+
}
38+
39+
public bool Equals(IExpr? other)
40+
=> other is Literal l && this.Value == l.Value;
41+
42+
public double Invoke()
43+
{
44+
return Value;
45+
}
46+
}
47+
48+
public class Call : IExpr
49+
{
50+
public IExpr Expr { get; }
51+
public ImmutableArray<IExpr> Arguments { get; }
52+
53+
public Call(IExpr expr, ImmutableArray<IExpr> arguments)
54+
{
55+
Expr = expr;
56+
Arguments = arguments;
57+
}
58+
59+
public bool Equals(IExpr? other)
60+
=> other is Call c
61+
&& ((Object)this.Expr).Equals(c.Expr)
62+
&& this.Arguments.SequenceEqual(c.Arguments);
63+
64+
public double Invoke()
65+
{
66+
throw new NotImplementedException();
67+
}
68+
}
69+
70+
public enum UnaryOperatorType
71+
{
72+
Increment,
73+
Decrement,
74+
Plus,
75+
Minus
76+
}
77+
public class UnaryOp : IExpr
78+
{
79+
public UnaryOperatorType Type { get; }
80+
public IExpr Expr { get; }
81+
82+
public UnaryOp(UnaryOperatorType type, IExpr expr)
83+
{
84+
Type = type;
85+
Expr = expr;
86+
}
87+
88+
public bool Equals(IExpr? other)
89+
=> other is UnaryOp u
90+
&& this.Type == u.Type
91+
&& ((Object)this.Expr).Equals(u.Expr);
92+
93+
public double Invoke()
94+
{
95+
return Type switch
96+
{
97+
UnaryOperatorType.Increment => Expr.Invoke() + 1,
98+
UnaryOperatorType.Decrement => Expr.Invoke() - 1,
99+
UnaryOperatorType.Plus => - Expr.Invoke(),
100+
UnaryOperatorType.Minus => + Expr.Invoke(),
101+
_ => throw new ArgumentOutOfRangeException()
102+
};
103+
}
104+
}
105+
106+
public enum BinaryOperatorType
107+
{
108+
Add, // +
109+
Sub, // -
110+
Mul, // *
111+
Div, // /
112+
}
113+
public class BinaryOp : IExpr
114+
{
115+
public BinaryOperatorType Type { get; }
116+
public IExpr Left { get; }
117+
public IExpr Right { get; }
118+
119+
public BinaryOp(BinaryOperatorType type, IExpr left, IExpr right)
120+
{
121+
Type = type;
122+
Left = left;
123+
Right = right;
124+
}
125+
126+
public bool Equals(IExpr? other)
127+
=> other is BinaryOp b
128+
&& this.Type == b.Type
129+
&& ((Object)this.Left).Equals(b.Left)
130+
&& ((Object)this.Right).Equals(b.Right);
131+
132+
public double Invoke()
133+
{
134+
return Type switch
135+
{
136+
BinaryOperatorType.Add => Left.Invoke() + Right.Invoke(),
137+
BinaryOperatorType.Mul => Left.Invoke() * Right.Invoke(),
138+
BinaryOperatorType.Div => Left.Invoke() / Right.Invoke(),
139+
BinaryOperatorType.Sub => Left.Invoke() - Right.Invoke(),
140+
};
141+
}
142+
}
143+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using System;
2+
using System.Collections.Immutable;
3+
using Pidgin;
4+
using Pidgin.Expression;
5+
6+
using System;
7+
using System.Collections.Immutable;
8+
using Pidgin;
9+
using Pidgin.Expression;
10+
using static Pidgin.Parser;
11+
using static Pidgin.Parser<char>;
12+
13+
namespace SimpleStateMachine.StructuralSearch.Sandbox
14+
{
15+
public static class ExprParser
16+
{
17+
private static Parser<char, T> Tok<T>(Parser<char, T> token)
18+
=> Try(token).Before(SkipWhitespaces);
19+
private static Parser<char, string> Tok(string token)
20+
=> Tok(String(token));
21+
22+
private static Parser<char, T> Parenthesised<T>(Parser<char, T> parser)
23+
=> parser.Between(Tok("("), Tok(")"));
24+
25+
private static Parser<char, Func<IExpr, IExpr, IExpr>> Binary(Parser<char, BinaryOperatorType> op)
26+
=> op.Select<Func<IExpr, IExpr, IExpr>>(type => (l, r) => new BinaryOp(type, l, r));
27+
private static Parser<char, Func<IExpr, IExpr>> Unary(Parser<char, UnaryOperatorType> op)
28+
=> op.Select<Func<IExpr, IExpr>>(type => o => new UnaryOp(type, o));
29+
30+
private static readonly Parser<char, Func<IExpr, IExpr, IExpr>> Add
31+
= Binary(Tok("+").ThenReturn(BinaryOperatorType.Add));
32+
private static readonly Parser<char, Func<IExpr, IExpr, IExpr>> Sub
33+
= Binary(Tok("-").ThenReturn(BinaryOperatorType.Sub));
34+
private static readonly Parser<char, Func<IExpr, IExpr, IExpr>> Div
35+
= Binary(Tok("/").ThenReturn(BinaryOperatorType.Div));
36+
private static readonly Parser<char, Func<IExpr, IExpr, IExpr>> Mul
37+
= Binary(Tok("*").ThenReturn(BinaryOperatorType.Mul));
38+
private static readonly Parser<char, Func<IExpr, IExpr>> Decrement
39+
= Unary(Tok("--").ThenReturn(UnaryOperatorType.Decrement));
40+
private static readonly Parser<char, Func<IExpr, IExpr>> Increment
41+
= Unary(Tok("++").ThenReturn(UnaryOperatorType.Increment));
42+
43+
private static readonly Parser<char, Func<IExpr, IExpr>> Minus
44+
= Unary(Tok("-").ThenReturn(UnaryOperatorType.Minus));
45+
private static readonly Parser<char, Func<IExpr, IExpr>> Plus
46+
= Unary(Tok("+").ThenReturn(UnaryOperatorType.Plus));
47+
48+
private static readonly Parser<char, IExpr> Identifier
49+
= Tok(Letter.Then(LetterOrDigit.ManyString(), (h, t) => h + t))
50+
.Select<IExpr>(name => new Identifier(name))
51+
.Labelled("identifier");
52+
53+
private static readonly Parser<char, IExpr> Literal
54+
= Tok(LongNum)
55+
.Select<IExpr>(value => new Literal(value))
56+
.Labelled("integer literal");
57+
58+
private static readonly Parser<char, IExpr> Expr = ExpressionParser.Build<char, IExpr>(
59+
expr => (
60+
OneOf(
61+
Identifier,
62+
Literal,
63+
Parenthesised(expr).Labelled("parenthesised expression")
64+
),
65+
new[]
66+
{
67+
Operator.Prefix(Decrement)
68+
.And(Operator.Prefix(Increment))
69+
.And(Operator.Prefix(Minus))
70+
.And(Operator.Prefix(Plus)),
71+
Operator.InfixL(Mul),
72+
Operator.InfixL(Div),
73+
Operator.InfixL(Add),
74+
Operator.InfixL(Sub)
75+
}
76+
)
77+
).Labelled("expression");
78+
79+
public static IExpr ParseOrThrow(string input)
80+
=> Expr.ParseOrThrow(input);
81+
82+
}
83+
}

src/SimpleStateMachine.StructuralSearch.Sandbox/Program.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,20 @@ internal static class Program
1010
{
1111
static void Main(string[] args)
1212
{
13-
13+
var result = FindRuleParser.ParseTemplate("$var$ Is int");
14+
var result1 = result.Execute("125");
15+
16+
17+
var t = ExprParser.ParseOrThrow("( 2 + 2 ) * 2");
18+
var resw = t.Invoke();
1419
var test = String("return ")
1520
.Then(AnyCharExcept(';').ManyString())
1621
.Then(Char(';').AtLeastOnceString())
1722
.Before(Char(';'));
1823

1924

25+
26+
2027
// var template = StructuralSearch.ParseTemplate("");
2128
// var test = Parser.OneOf(String("Test"), CommonParser.Empty);
2229
var res = test.ParseOrThrow("return 125;;;;");
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace SimpleStateMachine.StructuralSearch.Tests
2+
{
3+
public class RuleParserTests
4+
{
5+
6+
}
7+
}

src/SimpleStateMachine.StructuralSearch/Constant.cs

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@
22

33
namespace SimpleStateMachine.StructuralSearch
44
{
5-
public static class Constant
5+
public static partial class Constant
66
{
77
/// <summary>
88
/// Parenthesis empty string
99
/// </summary>
1010
public static readonly string Empty = string.Empty;
1111

12+
/// <summary>
13+
/// String: "Not"
14+
/// </summary>
15+
public static readonly string Not ="Not";
16+
1217
/// <summary>
1318
/// Parenthesis char: '('
1419
/// </summary>
@@ -59,6 +64,21 @@ public static class Constant
5964
/// </summary>
6065
public static readonly char Space = ' ';
6166

67+
/// <summary>
68+
/// Char: ','
69+
/// </summary>
70+
public static readonly char Comma = ',';
71+
72+
/// <summary>
73+
/// Char: '\''
74+
/// </summary>
75+
public static readonly char SingleQuotes = '\'';
76+
77+
/// <summary>
78+
/// Char: '\"'
79+
/// </summary>
80+
public static readonly char DoubleQuotes = '\"';
81+
6282
/// <summary>
6383
/// Parenthesis chars: '(' and ')'
6484
/// </summary>
@@ -78,28 +98,5 @@ public static class Constant
7898
/// Parenthesis chars: '(' and ')', '{ and '}', '{ and '}'
7999
/// </summary>
80100
public static readonly (char, char)[] AllParenthesised = { Parenthesis, SquareParenthesis, CurlyParenthesis };
81-
82-
public static char[] All()
83-
{
84-
var all = new char[]{
85-
LeftParenthesis,
86-
RightParenthesis,
87-
LeftSquareParenthesis,
88-
RightSquareParenthesis,
89-
LeftCurlyParenthesis,
90-
RightCurlyParenthesis,
91-
PlaceholderSeparator,
92-
CarriageReturn,
93-
LineFeed,
94-
Space
95-
};
96-
97-
return all;
98-
}
99-
100-
public static char[] AllExclude(params char[] excluded)
101-
{
102-
return All().Where(x => !excluded.Contains(x)).ToArray();
103-
}
104101
}
105102
}

src/SimpleStateMachine.StructuralSearch/Extensions/ParserExtensions.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,22 @@ public static Parser<TToken, IEnumerable<T>> UntilNot<TToken, T, U>(this Parser<
4343
? parser.Until(Not(terminator))
4444
: throw new ArgumentNullException(nameof(parser));
4545
}
46+
47+
public static bool TryParse(this Parser<char, string> parser, string value, out string? result)
48+
{
49+
if(parser is null)
50+
throw new ArgumentNullException(nameof(parser));
4651

52+
var res = parser.Try().Optional().ParseOrThrow(value, null);
53+
result = res.HasValue ? res.Value : default;
54+
return res.HasValue;
55+
}
56+
public static Parser<TToken, bool> Contains<TToken, T>(this Parser<TToken, T> parser)
57+
{
58+
return parser != null
59+
? parser.Optional().Select(x => x.HasValue)
60+
: throw new ArgumentNullException(nameof(parser));
61+
}
4762

4863
// public static Parser<TToken, TOut> WithResult<TToken, TOut>(this Parser<TToken, TOut> parser, Func<TToken, SourcePos, TOut> transformResult)
4964
// {

src/SimpleStateMachine.StructuralSearch/Extensions/StringParserExtensions.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,16 @@ public static Parser<TToken, SourceMatch> AsMatch<TToken>(this Parser<TToken, st
5757
{
5858
return parser.Then(Parser<TToken>.CurrentOffset, (s, offset) => new SourceMatch(s, offset - s.Length, offset));
5959
}
60+
61+
public static Parser<char, T> Trim<T>(this Parser<char, T> parser)
62+
{
63+
return parser.Before(SkipWhitespaces);
64+
}
65+
66+
public static Parser<char, TEnum> AsEnum<TEnum>(this Parser<char, string> parser, bool ignoreCase)
67+
where TEnum: struct, Enum
68+
{
69+
return parser.Select(value => Enum.Parse<TEnum>(value, ignoreCase));
70+
}
6071
}
6172
}

0 commit comments

Comments
 (0)