-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #467 from b3b00/refactoring/split-parsers-into-par…
…tials Refactoring/split parsers into partials
- Loading branch information
Showing
16 changed files
with
917 additions
and
817 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
609 changes: 0 additions & 609 deletions
609
src/sly/parser/parser/llparser/EBNFRecursiveDescentSyntaxParser.cs
This file was deleted.
Oops, something went wrong.
59 changes: 59 additions & 0 deletions
59
src/sly/parser/parser/llparser/bnf/RecursiveDescentSyntaxParser.Expressions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
using sly.parser.generator; | ||
using sly.parser.syntax.grammar; | ||
using sly.parser.syntax.tree; | ||
|
||
namespace sly.parser.llparser.bnf; | ||
|
||
public partial class RecursiveDescentSyntaxParser<IN, OUT> where IN : struct | ||
{ | ||
|
||
protected SyntaxNode<IN> ManageExpressionRules(Rule<IN> rule, SyntaxNode<IN> node) | ||
{ | ||
var operatorIndex = -1; | ||
switch (rule.IsExpressionRule) | ||
{ | ||
case true when rule.IsByPassRule: | ||
node.IsByPassNode = true; | ||
node.HasByPassNodes = true; | ||
break; | ||
case true when !rule.IsByPassRule: | ||
{ | ||
node.ExpressionAffix = rule.ExpressionAffix; | ||
switch (node.Children.Count) | ||
{ | ||
case 3: | ||
operatorIndex = 1; | ||
break; | ||
case 2 when node.ExpressionAffix == Affix.PreFix: | ||
operatorIndex = 0; | ||
break; | ||
case 2: | ||
{ | ||
if (node.ExpressionAffix == Affix.PostFix) operatorIndex = 1; | ||
break; | ||
} | ||
} | ||
|
||
if (operatorIndex >= 0) | ||
if (node.Children[operatorIndex] is SyntaxLeaf<IN> operatorNode) | ||
if (operatorNode != null) | ||
{ | ||
var visitor = rule.GetVisitor(operatorNode.Token.TokenID); | ||
if (visitor != null) | ||
{ | ||
node.Visitor = visitor; | ||
node.Operation = rule.GetOperation(operatorNode.Token.TokenID); | ||
} | ||
} | ||
|
||
break; | ||
} | ||
case false: | ||
node.Visitor = rule.GetVisitor(); | ||
break; | ||
} | ||
|
||
return node; | ||
} | ||
|
||
} |
132 changes: 132 additions & 0 deletions
132
src/sly/parser/parser/llparser/bnf/RecursiveDescentSyntaxParser.NonTerminal.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using sly.lexer; | ||
using sly.parser.syntax.grammar; | ||
|
||
namespace sly.parser.llparser.bnf; | ||
|
||
public partial class RecursiveDescentSyntaxParser<IN, OUT> where IN : struct | ||
{ | ||
#region parsing | ||
|
||
public SyntaxParseResult<IN> ParseNonTerminal(IList<Token<IN>> tokens, NonTerminalClause<IN> nonTermClause, | ||
int currentPosition, SyntaxParsingContext<IN> parsingContext) | ||
{ | ||
var result = ParseNonTerminal(tokens, nonTermClause.NonTerminalName, currentPosition, parsingContext); | ||
return result; | ||
} | ||
|
||
public SyntaxParseResult<IN> ParseNonTerminal(IList<Token<IN>> tokens, string nonTerminalName, | ||
int currentPosition, SyntaxParsingContext<IN> parsingContext) | ||
{ | ||
if (parsingContext.TryGetParseResult(new NonTerminalClause<IN>(nonTerminalName), currentPosition, | ||
out var memoizedResult)) | ||
{ | ||
return memoizedResult; | ||
} | ||
|
||
var startPosition = currentPosition; | ||
var nt = Configuration.NonTerminals[nonTerminalName]; | ||
var errors = new List<UnexpectedTokenSyntaxError<IN>>(); | ||
|
||
var i = 0; | ||
var rules = nt.Rules; | ||
|
||
var innerRuleErrors = new List<UnexpectedTokenSyntaxError<IN>>(); | ||
var greaterIndex = 0; | ||
var rulesResults = new List<SyntaxParseResult<IN>>(); | ||
while (i < rules.Count) | ||
{ | ||
var innerrule = rules[i]; | ||
if (startPosition < tokens.Count && !tokens[startPosition].IsEOS && | ||
innerrule.Match(tokens, startPosition, Configuration)) | ||
{ | ||
var innerRuleRes = Parse(tokens, innerrule, startPosition, nonTerminalName, parsingContext); | ||
rulesResults.Add(innerRuleRes); | ||
|
||
var other = greaterIndex == 0 && innerRuleRes.EndingPosition == 0; | ||
if (innerRuleRes.EndingPosition > greaterIndex && innerRuleRes.Errors != null && | ||
innerRuleRes.Errors.Count == 0 || other) | ||
{ | ||
greaterIndex = innerRuleRes.EndingPosition; | ||
innerRuleErrors.AddRange(innerRuleRes.Errors); | ||
} | ||
|
||
innerRuleErrors.AddRange(innerRuleRes.Errors); | ||
} | ||
|
||
i++; | ||
} | ||
|
||
if (rulesResults.Count == 0) | ||
{ | ||
var allAcceptableTokens = new List<LeadingToken<IN>>(); | ||
nt.Rules.ForEach(r => | ||
{ | ||
if (r != null && r.PossibleLeadingTokens != null) | ||
allAcceptableTokens.AddRange(r.PossibleLeadingTokens); | ||
}); | ||
|
||
var noMatching = NoMatchingRuleError(tokens, currentPosition, allAcceptableTokens); | ||
parsingContext.Memoize(new NonTerminalClause<IN>(nonTerminalName), currentPosition, noMatching); | ||
return noMatching; | ||
} | ||
|
||
errors.AddRange(innerRuleErrors); | ||
SyntaxParseResult<IN> max = null; | ||
int okEndingPosition = -1; | ||
int koEndingPosition = -1; | ||
bool hasOk = false; | ||
SyntaxParseResult<IN> maxOk = null; | ||
SyntaxParseResult<IN> maxKo = null; | ||
foreach (var rulesResult in rulesResults) | ||
{ | ||
if (rulesResult.IsOk) | ||
{ | ||
hasOk = true; | ||
if (rulesResult.EndingPosition > okEndingPosition) | ||
{ | ||
okEndingPosition = rulesResult.EndingPosition; | ||
maxOk = rulesResult; | ||
} | ||
} | ||
|
||
if (rulesResult.IsError && rulesResult.EndingPosition > koEndingPosition) | ||
{ | ||
koEndingPosition = rulesResult.EndingPosition; | ||
maxKo = rulesResult; | ||
} | ||
} | ||
|
||
if (hasOk) | ||
{ | ||
max = maxOk; | ||
} | ||
else | ||
{ | ||
max = maxKo; | ||
} | ||
|
||
|
||
var result = new SyntaxParseResult<IN>(); | ||
result.Errors = errors; | ||
result.Root = max.Root; | ||
result.EndingPosition = max.EndingPosition; | ||
result.IsError = max.IsError; | ||
result.IsEnded = max.IsEnded; | ||
result.HasByPassNodes = max.HasByPassNodes; | ||
|
||
|
||
List<UnexpectedTokenSyntaxError<IN>> terr = new List<UnexpectedTokenSyntaxError<IN>>(); | ||
foreach (var ruleResult in rulesResults) | ||
{ | ||
terr.AddRange(ruleResult.Errors); | ||
result.AddExpectings(ruleResult.Errors.SelectMany(x => x.ExpectedTokens)); | ||
} | ||
|
||
parsingContext.Memoize(new NonTerminalClause<IN>(nonTerminalName), currentPosition, result); | ||
return result; | ||
} | ||
|
||
#endregion | ||
} |
40 changes: 40 additions & 0 deletions
40
src/sly/parser/parser/llparser/bnf/RecursiveDescentSyntaxParser.Terminal.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using System.Collections.Generic; | ||
using sly.lexer; | ||
using sly.parser.syntax.grammar; | ||
using sly.parser.syntax.tree; | ||
|
||
namespace sly.parser.llparser.bnf; | ||
|
||
public partial class RecursiveDescentSyntaxParser<IN, OUT> where IN : struct | ||
{ | ||
#region parsing | ||
|
||
public SyntaxParseResult<IN> ParseTerminal(IList<Token<IN>> tokens, TerminalClause<IN> terminal, int position, | ||
SyntaxParsingContext<IN> parsingContext) | ||
{ | ||
if (parsingContext.TryGetParseResult(terminal, position, out var parseResult)) | ||
{ | ||
return parseResult; | ||
} | ||
|
||
var result = new SyntaxParseResult<IN>(); | ||
result.IsError = !terminal.Check(tokens[position]); | ||
result.EndingPosition = !result.IsError ? position + 1 : position; | ||
var token = tokens[position]; | ||
token.Discarded = terminal.Discarded; | ||
token.IsExplicit = terminal.IsExplicitToken; | ||
result.Root = new SyntaxLeaf<IN>(token, terminal.Discarded); | ||
result.HasByPassNodes = false; | ||
if (result.IsError) | ||
{ | ||
result.Errors.Add( | ||
new UnexpectedTokenSyntaxError<IN>(token, LexemeLabels, I18n, terminal.ExpectedToken)); | ||
result.AddExpecting(terminal.ExpectedToken); | ||
} | ||
|
||
parsingContext.Memoize(terminal, position, result); | ||
return result; | ||
} | ||
|
||
#endregion | ||
} |
Oops, something went wrong.