Skip to content

Commit b5dabd4

Browse files
fixed issues & added improvements
1 parent 34b3b48 commit b5dabd4

16 files changed

+111
-97
lines changed

EsotericDevZone.RuleBasedParser.csproj

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@
3131
<WarningLevel>4</WarningLevel>
3232
</PropertyGroup>
3333
<PropertyGroup>
34-
<ApplicationIcon>esodev2.ico</ApplicationIcon>
34+
<ApplicationIcon>
35+
</ApplicationIcon>
3536
</PropertyGroup>
3637
<ItemGroup>
37-
<Reference Include="EsotericDevZone.Core, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
38-
<HintPath>..\packages\EsotericDevZone.Core.1.0.0\lib\net46\EsotericDevZone.Core.dll</HintPath>
38+
<Reference Include="EsotericDevZone.Core, Version=1.0.6.0, Culture=neutral, processorArchitecture=MSIL">
39+
<HintPath>..\packages\EsotericDevZone.Core.1.0.6\lib\net46\EsotericDevZone.Core.dll</HintPath>
3940
</Reference>
4041
<Reference Include="System" />
4142
<Reference Include="System.Core" />
@@ -83,9 +84,5 @@
8384
<ItemGroup>
8485
<None Include="packages.config" />
8586
</ItemGroup>
86-
<ItemGroup>
87-
<Content Include="esodev2.ico" />
88-
<Content Include="icon.png" />
89-
</ItemGroup>
9087
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
9188
</Project>

Helpers/CommentsStyleHelper.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Linq;
1+
using System;
2+
using System.Linq;
23
using System.Text.RegularExpressions;
34

45
namespace EsotericDevZone.RuleBasedParser.Helpers
@@ -11,7 +12,7 @@ private static string EscapeChars(string s)
1112
}
1213

1314
internal static string GetBlockCommentsRegex((string Begin, string End)[] styles)
14-
{
15+
{
1516
return string.Join("|", styles.Select(s => $"({EscapeChars(s.Begin)}.*?{EscapeChars(s.End)})"));
1617
}
1718

Helpers/TokenSplitHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ internal static string GetSplitBreakingRegex(string[] splitBreakingCharacters)
3737
var splitChars = splitBreakingCharacters.SelectMany(s => s).Select(c => Regex.Escape(c.ToString()));
3838

3939
return string.Join("|", splitBreakingCharacters.Select(BuildSplitBreakingRegex)
40-
.Concat(Collections.ListOf(
40+
.Concat(Lists.Of(
4141
// tokens that don't contain any delimiters
4242
"[^"
4343
+ string.Join("", splitChars)

ParseRulesCollection.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public ParseRulesCollection(Parser parser)
1717

1818
private List<ParseRule> ParseRules = new List<ParseRule>();
1919

20+
public List<(string Key, string Pattern)> Rules => ParseRules.Select(r => (r.Key, string.Join(" ", r.ParsePattern.ToList()))).ToList();
21+
2022
internal IEnumerable<ParseRule> GetRulesByKey(string ruleKey)
2123
=> ParseRules.Where(r => r.Key == ruleKey);
2224

Parser.cs

Lines changed: 60 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
using EsotericDevZone.RuleBasedParser.Presets;
33
using System;
44
using System.Collections.Generic;
5+
using System.Diagnostics;
56
using System.Linq;
7+
using System.Web;
68

79
namespace EsotericDevZone.RuleBasedParser
810
{
@@ -32,13 +34,13 @@ public object Parse(string input)
3234
try
3335
{
3436
var tokens = input.SplitToTokens(TokensSplitOptions, CommentStyle);
37+
tokens.ForEach(_ => Debug.WriteLine(_));
3538

3639
if(tokens.Count==0)
3740
{
3841
throw new NoTokensProvidedException("No tokens provided");
3942
}
40-
41-
//tokens.ForEach(Console.WriteLine);
43+
4244
var result = LookFor(RootRuleKey, tokens, 0);
4345
if(result!=null)
4446
{
@@ -59,7 +61,7 @@ public object Parse(string input)
5961

6062
private ParseRecord LookFor(ParseRule rule, List<Token> tokens, int pos)
6163
{
62-
//Console.WriteLine($"{pos,5}. Looking for {rule}");
64+
Debug.WriteLine($"{pos,5}. Looking for {rule}");
6365

6466
var pattern = rule.ParsePattern;
6567

@@ -71,70 +73,71 @@ private ParseRecord LookFor(ParseRule rule, List<Token> tokens, int pos)
7173

7274

7375
Exception raisedException = null;
76+
77+
int originalPos = pos;
7478

75-
int tailReturn = -1;
76-
int originalPos = pos;
77-
int i = 0;
78-
for (i = 0; i < pattern.Length; i++)
79-
{
80-
var item = pattern[i];
79+
var mandatoryPattern = pattern.TakeWhile(_ => !(_ is RepeatableTailItem)).ToArray();
80+
var optionalPattern = pattern.SkipWhile(_ => !(_ is RepeatableTailItem)).ToArray().Skip(1).ToArray();
8181

82-
if (item is RepeatableTailItem)
83-
{
84-
tailReturn = i;
82+
Debug.WriteLine($"Mandatory = {string.Join(" ",mandatoryPattern.ToList())}");
83+
Debug.WriteLine($"Optional = {string.Join(" ", optionalPattern.ToList())}");
8584

86-
finalRecords = records.ToList();
87-
finalSelectorMatches = selectorsMatches.ToList();
88-
continue;
89-
}
90-
91-
try
85+
void dealWithPatternItem(IParseRulePatternItem item)
86+
{
87+
if (pos >= tokens.Count)
9288
{
93-
if (pos >= tokens.Count)
94-
{
95-
throw new ParseException(tokens.Last(), "Insufficient tokens");
96-
}
97-
98-
var match = item.Match(this, tokens, pos);
99-
//Console.WriteLine(match);
89+
throw new ParseException(tokens.Last(), "Insufficient tokens");
90+
}
10091

101-
if (match is WildcardMatch wildcardMatch)
102-
{
103-
selectorsMatches.Add(wildcardMatch.Value);
104-
}
105-
else if (match is ParseRecord record)
106-
{
107-
records.Add(record);
108-
AddToCache(record);
109-
}
110-
else if (match is IgnoreMatch)
111-
{
112-
}
113-
else throw new NotImplementedException("Invalid match");
92+
var match = item.Match(this, tokens, pos);
11493

115-
pos += match.TokensCount;
94+
if (match is WildcardMatch wildcardMatch)
95+
{
96+
selectorsMatches.Add(wildcardMatch.Value);
11697
}
117-
catch (ParseException ex)
98+
else if (match is ParseRecord record)
11899
{
119-
raisedException = ex;
120-
break;
100+
records.Add(record);
101+
AddToCache(record);
121102
}
122-
123-
if(i==pattern.Length-1)
103+
else if (match is IgnoreMatch)
124104
{
125-
finalRecords = records.ToList();
126-
finalSelectorMatches = selectorsMatches.ToList();
127-
if (tailReturn >= 0)
128-
{
129-
i = tailReturn;
130-
raisedException = null;
131-
}
132-
}
105+
}
106+
else throw new NotImplementedException("Invalid match");
107+
108+
pos += match.TokensCount;
133109
}
134110

135-
if (finalRecords == null || (raisedException != null && i != tailReturn + 1))
111+
try
136112
{
137-
throw raisedException;
113+
foreach (var item in mandatoryPattern)
114+
dealWithPatternItem(item);
115+
}
116+
catch (ParseException e) { raisedException = e; }
117+
118+
if (raisedException != null) throw raisedException;
119+
finalRecords = records.ToList();
120+
finalSelectorMatches = selectorsMatches.ToList();
121+
122+
int posBackup = pos;
123+
if (optionalPattern.Length>0 && pos < tokens.Count)
124+
{
125+
while(raisedException==null)
126+
{
127+
posBackup = pos;
128+
try
129+
{
130+
foreach (var item in optionalPattern)
131+
dealWithPatternItem(item);
132+
finalRecords = records.ToList();
133+
finalSelectorMatches = selectorsMatches.ToList();
134+
}
135+
catch (ParseException e)
136+
{
137+
raisedException = e;
138+
}
139+
}
140+
pos = posBackup;
138141
}
139142

140143
var value = rule.BuildMethod(
@@ -161,6 +164,8 @@ internal ParseRecord LookFor(string ruleKey, List<Token> tokens, int pos)
161164
if (rec != null)
162165
{
163166
AddToCache(rec);
167+
168+
//Debug.WriteLine($"Found: {rec.Result.Value}, {rec.Position}:{rec.TokensCount}");
164169
return rec;
165170
}
166171
}
@@ -182,7 +187,7 @@ internal ParseRecord LookFor(string ruleKey, List<Token> tokens, int pos)
182187
if(raisedException!=null)
183188
throw new ParseException(raisedException);
184189
//throw new ParseException("Parse failed");
185-
190+
186191
return null;
187192
}
188193

Presets/AtomBuilders.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ public static object GenericString(string input, char startDelimiter, char endDe
3333

3434
public static object Symbol(string input)
3535
{
36-
if (!Regex.IsMatch(input, @"^[_A-Za-z][_A-Aa-z0-9]*$"))
36+
if (!Regex.IsMatch(input, @"^[_A-Za-z][_A-Za-z0-9]*$"))
3737
throw new ParseException("Invalid symbol");
3838
return input;
39-
}
39+
}
4040
}
4141
}

Presets/CommentStyles.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,26 @@ public static class CommentStyles
66
{
77
public static readonly CommentStyle NoCommentsStyle = new CommentStyle
88
(
9-
Collections.EmptyList<string>(),
10-
Collections.EmptyList<(string, string)>()
9+
Lists.Empty<string>(),
10+
Lists.Empty<(string, string)>()
1111
);
1212

1313
public static readonly CommentStyle CStyle = new CommentStyle
1414
(
15-
Collections.ListOf("//"),
16-
Collections.ListOf(("/*", "*/"))
15+
Lists.Of("//"),
16+
Lists.Of(("/*", "*/"))
1717
);
1818

1919
public static readonly CommentStyle PascalStyle = new CommentStyle
2020
(
21-
Collections.ListOf("//"),
22-
Collections.ListOf(("/*", "*/"), ("(*", "*)"))
21+
Lists.Of("//"),
22+
Lists.Of(("/*", "*/"), ("(*", "*)"))
2323
);
2424

2525
public static readonly CommentStyle PythonStyle = new CommentStyle
2626
(
27-
Collections.ListOf("#"),
28-
Collections.ListOf(("\"\"\"", "\"\"\""))
27+
Lists.Of("#"),
28+
Lists.Of(("\"\"\"", "\"\"\""))
2929
);
3030
}
3131
}

Presets/ParseResultBuilders.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ namespace EsotericDevZone.RuleBasedParser.Presets
44
{
55
public class ParseResultBuilders
66
{
7-
public static ParseResult Self(ParseResult result) => result;
8-
public static ParseResult Null(ParseResult _) => null;
7+
public static ParseResult Self(ParseResult[] result, Token[] tokens) => result[0];
8+
public static ParseResult Null(ParseResult[] _, Token[] _tks) => null;
99

1010
public static Func<ParseResult[], Token[], ParseResult> LeftAssociate(Func<ParseResult, ParseResult, Token, ParseResult> op)
1111
{
@@ -18,6 +18,17 @@ public static Func<ParseResult[], Token[], ParseResult> LeftAssociate(Func<Parse
1818
};
1919
}
2020

21+
public static Func<ParseResult[], Token[], ParseResult> LeftAssociate(Func<ParseResult, ParseResult, ParseResult> op)
22+
{
23+
return (results, tokens) =>
24+
{
25+
ParseResult result = results[0];
26+
for (int i = 1; i < results.Length; i++)
27+
result = op(result, results[i]);
28+
return result;
29+
};
30+
}
31+
2132
public static Func<ParseResult[], Token[], ParseResult> RightAssociate(Func<ParseResult, ParseResult, Token, ParseResult> op)
2233
{
2334
return (results, tokens) =>

Presets/Parsers/ArithmeticsParser.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ public class ArithmeticsParser<T> : Parser
1414
public ArithmeticsParser(Func<string, object> numberBuilder) : base()
1515
{
1616
this.TokensSplitOptions = new TokensSplitOptions(
17-
Collections.EmptyList<string>(),
18-
Collections.ListOf(@"\+", @"\-", @"\*", @"\/", @"\(", @"\)")
17+
Lists.Empty<string>(),
18+
Lists.Of(@"\+", @"\-", @"\*", @"\/", @"\(", @"\)")
1919
);
2020
base.CommentStyle = CommentStyles.NoCommentsStyle;
2121
NumberBuilder = numberBuilder;

Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@
3232
// You can specify all the values or you can default the Build and Revision Numbers
3333
// by using the '*' as shown below:
3434
// [assembly: AssemblyVersion("1.0.*")]
35-
[assembly: AssemblyVersion("1.0.0.0")]
36-
[assembly: AssemblyFileVersion("1.0.0.0")]
35+
[assembly: AssemblyVersion("1.0.2.0")]
36+
[assembly: AssemblyFileVersion("1.0.2.0")]

0 commit comments

Comments
 (0)