Skip to content

Commit 62e9e2d

Browse files
committed
parsing context, lookahead optimization
1 parent 98920c8 commit 62e9e2d

File tree

18 files changed

+246
-97
lines changed

18 files changed

+246
-97
lines changed

src/SimpleStateMachine.StructuralSearch.Tests/FindTemplate/IfElseTemplate.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
if($var1$ $sign$ $value1$)
1+
if($var1$ $sign$ $some1$)
22
{
33
$var$ = $value1$;
44
}

src/SimpleStateMachine.StructuralSearch.Tests/FindTemplateTests.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class FindTemplateTests
1313
public void TemplateParsingShouldBeSuccess(string templatePath)
1414
{
1515
var findTemplate = File.ReadAllText(templatePath);
16-
var template = StructuralSearch.ParseFindTemplate(findTemplate);
16+
var template = StructuralSearch.ParseFindTemplate(findTemplate, new ParsingContext());
1717

1818
Assert.NotNull(template);
1919
}
@@ -27,7 +27,8 @@ public void SourceParsingBeFindTemplateShouldBeSuccess(string templatePath, stri
2727
var findTemplate = File.ReadAllText(templatePath);
2828
var source = File.ReadAllText(sourcePath);
2929

30-
var template = StructuralSearch.ParseFindTemplate(findTemplate);
30+
var context = new ParsingContext();
31+
var template = StructuralSearch.ParseFindTemplate(findTemplate, context);
3132
var result = template.ParseOrThrow(source);
3233

3334
Assert.NotNull(template);

src/SimpleStateMachine.StructuralSearch.Tests/PlaceholderParserTests.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,32 @@ public class PlaceholderParserTests
88
[Fact]
99
public void FindTemplateShouldBeNotEmpty()
1010
{
11-
Assert.Throws<ParseException>(() => StructuralSearch.ParseFindTemplate(string.Empty));
11+
Assert.Throws<ParseException>(() => StructuralSearch.ParseFindTemplate(string.Empty, new ParsingContext()));
1212
}
1313

1414
[Theory]
1515
[InlineData("($test$)", "(value )", "value ")]
1616
[InlineData("($test$ )", "(value )", "value")]
1717
[InlineData("($test$)", "(value (test))", "value (test)")]
18+
[InlineData("($test$)", "(value (test) )", "value (test) ")]
1819
public void TemplateParsingShouldBeSuccess(string template, string source, string result)
1920
{
20-
var templateParser = StructuralSearch.ParseFindTemplate(template);
21+
var context = new ParsingContext();
22+
var templateParser = StructuralSearch.ParseFindTemplate(template, context);
2123
var res = templateParser.ParseOrThrow(source);
24+
var value = context.GetPlaceholder("test");
2225

23-
// var templateStr = File.ReadAllText(templatePath);
24-
// var template = StructuralSearch.ParseTemplate(templateStr);
25-
//
26-
// Assert.NotNull(template);
26+
Assert.Equal(value, result);
2727
}
2828

2929
[Theory]
3030
[InlineData("$var$;$var2$;", "test;;;test;;;", "value ")]
3131
public void TemplateParsingShouldBeSuccess2(string template, string source, string result)
3232
{
33-
var templateParser = StructuralSearch.ParseFindTemplate(template);
33+
var context = new ParsingContext();
34+
var templateParser = StructuralSearch.ParseFindTemplate(template, context);
3435
var res = templateParser.ParseOrThrow(source);
36+
3537

3638
// var templateStr = File.ReadAllText(templatePath);
3739
// var template = StructuralSearch.ParseTemplate(templateStr);

src/SimpleStateMachine.StructuralSearch.Tests/ReplaceTemplateTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public class ReplaceTemplateTests
1212
public void TemplateParsingShouldBeSuccess(string templatePath, int stepsCount)
1313
{
1414
var replaceTemplate = File.ReadAllText(templatePath);
15-
var replaceBuilder = StructuralSearch.ParseReplaceTemplate(replaceTemplate);
15+
var replaceBuilder = StructuralSearch.ParseReplaceTemplate(replaceTemplate, new ParsingContext());
1616
var result = replaceBuilder.Build();
1717

1818
Assert.NotNull(replaceTemplate);

src/SimpleStateMachine.StructuralSearch/Extensions/SourceMatchManyParserExtensions.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ public static class SourceMatchParserExtensions
99
// {
1010
// return parsers.Select(x => Parsers.Series(x, getResult));
1111
// }
12-
public static Parser<char, Parser<char, string>> JoinResults(this Parser<char, IEnumerable<Parser<char, string>>> parsers)
12+
public static Parser<char, Parser<char, string>> JoinResults(this Parser<char, IEnumerable<Parser<char, string>>> parsers, ParsingContext context)
1313
{
14-
return parsers.Select(x => Parsers.Series(x, y => string.Join(string.Empty, y)));
14+
return parsers.Select(x => Parsers.Series(context, x, y => string.Join(string.Empty, y)));
1515
}
16-
public static Parser<char, Parser<char, SourceMatch>> JoinResults(this Parser<char, IEnumerable<Parser<char, SourceMatch>>> parsers)
16+
public static Parser<char, Parser<char, SourceMatch>> JoinResults(this Parser<char, IEnumerable<Parser<char, SourceMatch>>> parsers, ParsingContext context)
1717
{
18-
return parsers.Select(x => Parsers.Series(x, y => y.Concatenate()));
18+
return parsers.Select(x => Parsers.Series(context, x, y => y.Concatenate()));
1919
}
2020
}
2121
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace SimpleStateMachine.StructuralSearch
2+
{
3+
public interface IContextDependent
4+
{
5+
void SetContext(ParsingContext context);
6+
}
7+
}
Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
1-
using System;
1+
using System.Diagnostics.CodeAnalysis;
22
using Pidgin;
33

44
namespace SimpleStateMachine.StructuralSearch
55
{
6-
public abstract class LookaheadParser<TToken, T> : Parser<TToken, T>
6+
internal sealed class LookaheadParser<TToken, T> : Parser<TToken, T>
77
{
8-
private Parser<TToken, T> _parser { get; set; }
8+
private readonly Parser<TToken, T> _parser;
99

10-
public abstract Parser<TToken, T> BuildParser(Func<Parser<TToken, T>?> next,
11-
Func<Parser<TToken, T>?> nextNext);
12-
13-
public void Lookahead(Func<Parser<TToken, T>?> next, Func<Parser<TToken, T>?> nextNext)
14-
{
15-
_parser = BuildParser(next, nextNext);
16-
}
17-
18-
public override bool TryParse(ref ParseState<TToken> state, ref PooledList<Expected<TToken>> expected,
19-
out T result)
10+
public LookaheadParser(Parser<TToken, T> parser) => this._parser = parser;
11+
12+
public override bool TryParse(ref ParseState<TToken> state, ref PooledList<Expected<TToken>> expecteds, out T result)
2013
{
21-
var res = _parser.TryParse(ref state, ref expected, out result);
22-
return res;
14+
state.PushBookmark();
15+
if (this._parser.TryParse(ref state, ref expecteds, out result))
16+
{
17+
state.Rewind();
18+
return true;
19+
}
20+
state.PopBookmark();
21+
return false;
2322
}
2423
}
2524
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Pidgin;
4+
5+
namespace SimpleStateMachine.StructuralSearch
6+
{
7+
public abstract class ParserWithLookahead<TToken, T> : Parser<TToken, T>
8+
{
9+
private Parser<TToken, T> _parser { get; set; }
10+
11+
public Func<IEnumerable<LookaheadResult<TToken, T>>> OnLookahead { get; set; }
12+
13+
public abstract Parser<TToken, T> BuildParser(Func<Parser<TToken, T>?> next,
14+
Func<Parser<TToken, T>?> nextNext);
15+
16+
public void Lookahead(Func<Parser<TToken, T>?> next, Func<Parser<TToken, T>?> nextNext)
17+
{
18+
_parser = BuildParser(next, nextNext);
19+
}
20+
21+
public override bool TryParse(ref ParseState<TToken> state, ref PooledList<Expected<TToken>> expected,
22+
out T result)
23+
{
24+
var res = _parser.TryParse(ref state, ref expected, out result);
25+
return res;
26+
}
27+
}
28+
29+
public class LookaheadResult<TToken, T>
30+
{
31+
public LookaheadResult(Parser<TToken, T> parser, T result, int tokensCount)
32+
{
33+
Parser = parser;
34+
Result = result;
35+
TokensCount = tokensCount;
36+
}
37+
38+
public T Result { get; }
39+
public int TokensCount { get; }
40+
public Parser<TToken, T> Parser;
41+
}
42+
}

src/SimpleStateMachine.StructuralSearch/Parsers/Parsers.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,15 @@ public static Parser<TToken, IEnumerable<T>> MapToMany<TToken, T>(Parser<TToken,
7878
}
7979

8080

81-
public static Parser<TToken, R> Series<TToken, T, R>(IEnumerable<Parser<TToken, T>> parsers,
81+
public static Parser<TToken, R> Series<TToken, T, R>(ParsingContext context, IEnumerable<Parser<TToken, T>> parsers,
8282
Func<IEnumerable<T>, R> func)
8383
{
8484
if (parsers == null)
8585
throw new ArgumentNullException(nameof(parsers));
8686
if (func == null)
8787
throw new ArgumentNullException(nameof(func));
8888

89-
return new SeriesParser<TToken, T, R>(parsers, func);
89+
return new SeriesParser<TToken, T, R>(context, parsers, func);
9090
}
9191

9292
public static Parser<char, IEnumerable<T>> BetweenChars<T>(char left, char right,
@@ -134,5 +134,10 @@ public static Parser<char, TEnum> EnumValue<TEnum>(TEnum value, bool ignoreCase
134134
{
135135
return Parsers.String(value.ToString(), ignoreCase).AsEnum<TEnum>(ignoreCase);
136136
}
137+
138+
public static Parser<TToken, T> Lookahead<TToken, T>(Parser<TToken, T> parser) =>
139+
parser != null ? (Parser<TToken, T>)
140+
new LookaheadParser<TToken, T>(parser)
141+
: throw new ArgumentNullException(nameof (parser));
137142
}
138143
}

src/SimpleStateMachine.StructuralSearch/Parsers/PlaceholderParser.cs

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,69 @@
11
using System;
2+
using System.Collections.Generic;
23
using Pidgin;
34
using SimpleStateMachine.StructuralSearch.Extensions;
45

56
namespace SimpleStateMachine.StructuralSearch
67
{
7-
public class PlaceholderParser : LookaheadParser<char, string>
8+
public class PlaceholderParser : ParserWithLookahead<char, string>, IContextDependent
89
{
9-
public string Name { get; }
10-
11-
public string Value { get; }
10+
private ParsingContext _context;
11+
1212
public PlaceholderParser(string name)
1313
{
1414
Name = name;
1515
}
16-
16+
17+
public string Name { get; }
18+
1719
public override Parser<char, string> BuildParser(Func<Parser<char, string>> next,
1820
Func<Parser<char, string>> nextNext)
1921
{
2022
var _next = next();
2123
var _nextNext = nextNext() ?? Parser<char>.End.ThenReturn(string.Empty);
22-
var _lookahead = Parser.Lookahead(_next.Then(_nextNext).Try());
23-
24-
Parser<char, string> lookahead = new DebugParser<char, string>(_lookahead);
24+
var lookahead = Parsers.Lookahead(_next.Then(_nextNext, (s1, s2) =>
25+
{
26+
OnLookahead = () => new List<LookaheadResult<char, string>>
27+
{
28+
new(_next, s1, s1.Length),
29+
new(_nextNext, s2, s2.Length),
30+
};
31+
return Unit.Value;
32+
}).Try());
33+
2534
var anyString = CommonTemplateParser.AnyCharWithPlshd
2635
.AtLeastOnceAsStringUntil(lookahead);
27-
36+
2837
var simpleString = CommonTemplateParser.StringWithPlshd.Labelled("simpleString");
2938
var token = Parser.OneOf(simpleString, CommonParser.WhiteSpaces).Try();
3039
Parser<char, string> term = null;
3140

3241
var parenthesised = Parsers.BetweenOneOfChars(x => Parsers.Stringc(x),
3342
expr: Parser.Rec(() => term),
3443
Constant.AllParenthesised).JoinToString();
35-
44+
3645
term = Parser.OneOf(parenthesised, token).Many().JoinToString();
37-
46+
3847
//parenthesised and tokens and whiteSpaces
3948
var prdsAndTokens = Parser.OneOf(parenthesised, token)
4049
.Until(lookahead)
4150
.JoinToString()
4251
.Try();
43-
52+
4453
var parser = prdsAndTokens.Or(anyString);
4554
return parser;
4655
}
47-
56+
4857
public override bool TryParse(ref ParseState<char> state, ref PooledList<Expected<char>> expected,
4958
out string result)
5059
{
5160
var res = base.TryParse(ref state, ref expected, out result);
61+
62+
if (res)
63+
res &= _context.TryAdd(Name, result);
64+
5265
return res;
53-
}
66+
}
5467

5568

5669
// internal Parser<char, SourceMatch> GetParser()
@@ -80,5 +93,9 @@ public override bool TryParse(ref ParseState<char> state, ref PooledList<Expecte
8093
// var parser = term.JoinToString().AsMatch();
8194
// return parser;
8295
// }
96+
public void SetContext(ParsingContext context)
97+
{
98+
_context = context;
99+
}
83100
}
84101
}

0 commit comments

Comments
 (0)