Skip to content

Commit 44a1ef8

Browse files
committed
Rule parsing
1 parent ab67089 commit 44a1ef8

30 files changed

+736
-47
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
using System;
2+
using System.Collections.Immutable;
3+
using System.Linq;
4+
5+
namespace SimpleStateMachine.StructuralSearch.Sandbox
6+
{
7+
public interface IExpr : IEquatable<IExpr>
8+
{
9+
}
10+
11+
public class Identifier : IExpr
12+
{
13+
public string Name { get; }
14+
15+
public Identifier(string name)
16+
{
17+
Name = name;
18+
}
19+
20+
public bool Equals(IExpr? other)
21+
=> other is Identifier i && this.Name == i.Name;
22+
}
23+
24+
public class Literal : IExpr
25+
{
26+
public int Value { get; }
27+
28+
public Literal(int value)
29+
{
30+
Value = value;
31+
}
32+
33+
public bool Equals(IExpr? other)
34+
=> other is Literal l && this.Value == l.Value;
35+
}
36+
37+
public class Call : IExpr
38+
{
39+
public IExpr Expr { get; }
40+
public ImmutableArray<IExpr> Arguments { get; }
41+
42+
public Call(IExpr expr, ImmutableArray<IExpr> arguments)
43+
{
44+
Expr = expr;
45+
Arguments = arguments;
46+
}
47+
48+
public bool Equals(IExpr? other)
49+
=> other is Call c
50+
&& ((Object)this.Expr).Equals(c.Expr)
51+
&& this.Arguments.SequenceEqual(c.Arguments);
52+
}
53+
54+
public enum UnaryOperatorType
55+
{
56+
Neg,
57+
Complement
58+
}
59+
public class UnaryOp : IExpr
60+
{
61+
public UnaryOperatorType Type { get; }
62+
public IExpr Expr { get; }
63+
64+
public UnaryOp(UnaryOperatorType type, IExpr expr)
65+
{
66+
Type = type;
67+
Expr = expr;
68+
}
69+
70+
public bool Equals(IExpr? other)
71+
=> other is UnaryOp u
72+
&& this.Type == u.Type
73+
&& ((Object)this.Expr).Equals(u.Expr);
74+
}
75+
76+
public enum BinaryOperatorType
77+
{
78+
Add,
79+
Mul
80+
}
81+
public class BinaryOp : IExpr
82+
{
83+
public BinaryOperatorType Type { get; }
84+
public IExpr Left { get; }
85+
public IExpr Right { get; }
86+
87+
public BinaryOp(BinaryOperatorType type, IExpr left, IExpr right)
88+
{
89+
Type = type;
90+
Left = left;
91+
Right = right;
92+
}
93+
94+
public bool Equals(IExpr? other)
95+
=> other is BinaryOp b
96+
&& this.Type == b.Type
97+
&& ((Object)this.Left).Equals(b.Left)
98+
&& ((Object)this.Right).Equals(b.Right);
99+
}
100+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using System;
2+
using System.Collections.Immutable;
3+
using Pidgin;
4+
using Pidgin.Expression;
5+
6+
namespace SimpleStateMachine.StructuralSearch.Sandbox
7+
{
8+
public static class ExprParser
9+
{
10+
private static Parser<char, T> Tok<T>(Parser<char, T> token)
11+
=> Parser.Try(token).Before(Parser.SkipWhitespaces);
12+
private static Parser<char, string> Tok(string token)
13+
=> Tok(Parser.String(token));
14+
15+
private static Parser<char, T> Parenthesised<T>(Parser<char, T> parser)
16+
=> parser.Between(Tok("("), Tok(")"));
17+
18+
private static Parser<char, Func<IExpr, IExpr, IExpr>> Binary(Parser<char, BinaryOperatorType> op)
19+
=> op.Select<Func<IExpr, IExpr, IExpr>>(type => (l, r) => new BinaryOp(type, l, r));
20+
private static Parser<char, Func<IExpr, IExpr>> Unary(Parser<char, UnaryOperatorType> op)
21+
=> op.Select<Func<IExpr, IExpr>>(type => o => new UnaryOp(type, o));
22+
23+
private static readonly Parser<char, Func<IExpr, IExpr, IExpr>> Add
24+
= Binary(Tok("+").ThenReturn(BinaryOperatorType.Add));
25+
private static readonly Parser<char, Func<IExpr, IExpr, IExpr>> Mul
26+
= Binary(Tok("*").ThenReturn(BinaryOperatorType.Mul));
27+
private static readonly Parser<char, Func<IExpr, IExpr>> Neg
28+
= Unary(Tok("-").ThenReturn(UnaryOperatorType.Neg));
29+
private static readonly Parser<char, Func<IExpr, IExpr>> Complement
30+
= Unary(Tok("~").ThenReturn(UnaryOperatorType.Complement));
31+
32+
private static readonly Parser<char, IExpr> Identifier
33+
= Tok(Parser.Letter.Then(Parser.LetterOrDigit.ManyString(), (h, t) => h + t))
34+
.Select<IExpr>(name => new Identifier(name))
35+
.Labelled("identifier");
36+
private static readonly Parser<char, IExpr> Literal
37+
= Tok(Parser.Num)
38+
.Select<IExpr>(value => new Literal(value))
39+
.Labelled("integer literal");
40+
41+
private static Parser<char, Func<IExpr, IExpr>> Call(Parser<char, IExpr> subExpr)
42+
=> Parenthesised(subExpr.Separated(Tok(",")))
43+
.Select<Func<IExpr, IExpr>>(args => method => new Call(method, args.ToImmutableArray()))
44+
.Labelled("function call");
45+
46+
private static readonly Parser<char, IExpr> Expr = ExpressionParser.Build<char, IExpr>(
47+
expr => (
48+
Parser.OneOf(
49+
Identifier,
50+
Literal,
51+
Parenthesised(expr).Labelled("parenthesised expression")
52+
),
53+
new[]
54+
{
55+
Operator.PostfixChainable(Call(expr)),
56+
Operator.Prefix(Neg).And(Operator.Prefix(Complement)),
57+
Operator.InfixL(Mul),
58+
Operator.InfixL(Add)
59+
}
60+
)
61+
).Labelled("expression");
62+
63+
public static IExpr ParseOrThrow(string input)
64+
=> Expr.ParseOrThrow(input);
65+
}
66+
}

src/SimpleStateMachine.StructuralSearch.Sandbox/Program.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,18 @@ internal static class Program
1010
{
1111
static void Main(string[] args)
1212
{
13-
13+
var str = Console.ReadLine();
14+
var parser = (Parser.String("test").Trim().Then(Parser.Num.Between(Char('"')))).Between(Char('"'));
15+
var res1 = parser.ParseOrThrow(str);
16+
var t = ExprParser.ParseOrThrow("10 + -5");
1417
var test = String("return ")
1518
.Then(AnyCharExcept(';').ManyString())
1619
.Then(Char(';').AtLeastOnceString())
1720
.Before(Char(';'));
1821

1922

23+
24+
2025
// var template = StructuralSearch.ParseTemplate("");
2126
// var test = Parser.OneOf(String("Test"), CommonParser.Empty);
2227
var res = test.ParseOrThrow("return 125;;;;");

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/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)
67+
where TEnum: struct, Enum
68+
{
69+
return parser.Select(Enum.Parse<TEnum>);
70+
}
6071
}
6172
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System.Linq;
2+
3+
namespace SimpleStateMachine.StructuralSearch
4+
{
5+
public static partial class Constant
6+
{
7+
public static class FindTemplate
8+
{
9+
public static char[] All()
10+
{
11+
var all = new char[]{
12+
LeftParenthesis,
13+
RightParenthesis,
14+
LeftSquareParenthesis,
15+
RightSquareParenthesis,
16+
LeftCurlyParenthesis,
17+
RightCurlyParenthesis,
18+
PlaceholderSeparator,
19+
CarriageReturn,
20+
LineFeed,
21+
Space
22+
};
23+
24+
return all;
25+
}
26+
27+
public static char[] AllExclude(params char[] excluded)
28+
{
29+
return All().Where(x => !excluded.Contains(x)).ToArray();
30+
}
31+
}
32+
}
33+
}

src/SimpleStateMachine.StructuralSearch/FindTemplate/ParserToParser.cs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,33 @@ namespace SimpleStateMachine.StructuralSearch
1010
{
1111
public static class ParserToParser
1212
{
13-
public static Parser<char, Parser<char, string>> String(string token)
13+
public static Parser<char, Parser<char, string>> String(string token, bool ignoreCase = false)
1414
{
15-
return Parser.String(token).Select(x => Parser.String(token));
15+
return Parsers.String(token, ignoreCase).Select(x => Parsers.String(token, ignoreCase));
1616
}
1717

18-
public static Parser<char, Parser<char, string>> Stringc(char token)
18+
public static Parser<char, Parser<char, string>> Stringc(char token, bool ignoreCase = false)
1919
{
2020
var _token = token.ToString();
21-
return Parser.String(_token).Select(x => Parser.String(_token));
21+
return Parsers.String(_token, ignoreCase).Select(x => Parsers.String(_token, ignoreCase));
2222
}
23-
24-
public static Parser<char, Parser<char, SourceMatch>> StringcMatch(char token)
23+
24+
public static Parser<char, Parser<char, SourceMatch>> StringcMatch(char token, bool ignoreCase = false)
2525
{
2626
var _token = token.ToString();
27-
return Parser.String(_token).Select(x => Parser.String(_token).AsMatch());
27+
return Parsers.String(_token, ignoreCase).Select(x => Parsers.String(_token, ignoreCase).AsMatch());
2828
}
2929

30-
public static Parser<char, Parser<char, string>> ResultAsParser(Parser<char, string> parser)
30+
public static Parser<char, Parser<char, string>> ResultAsParser(Parser<char, string> parser, bool ignoreCase = false)
3131
{
32-
return parser.Select(Parser.String);
32+
return parser.Select(value => Parsers.String(value, ignoreCase));
3333
}
3434

35-
public static Parser<char, Parser<char, SourceMatch>> ResultAsMatch(Parser<char, string> parser)
35+
public static Parser<char, Parser<char, SourceMatch>> ResultAsMatch(Parser<char, string> parser, bool ignoreCase = false)
3636
{
37-
return parser.Select(x=> Parser.String(x).AsMatch());
37+
return parser.Select(x=> Parsers.String(x, ignoreCase).AsMatch());
3838
}
39+
3940

4041
}
4142
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System.Text.RegularExpressions;
2+
3+
namespace SimpleStateMachine.StructuralSearch.Helper
4+
{
5+
public static class CharHelper
6+
{
7+
// public static char Escape(char сh)
8+
// {
9+
// return сh switch
10+
// {
11+
// 'n' => '\n',
12+
// 't'
13+
// };
14+
// }
15+
}
16+
}

0 commit comments

Comments
 (0)