Skip to content

Commit

Permalink
Merge pull request #467 from b3b00/refactoring/split-parsers-into-par…
Browse files Browse the repository at this point in the history
…tials

Refactoring/split parsers into partials
  • Loading branch information
b3b00 authored Jul 30, 2024
2 parents cd0a726 + da62af1 commit 3340e80
Show file tree
Hide file tree
Showing 16 changed files with 917 additions and 817 deletions.
3 changes: 2 additions & 1 deletion src/sly/parser/generator/EBNFParserBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
using sly.lexer;
using sly.lexer.fsm;
using sly.parser.generator.visitor;
using sly.parser.llparser;
using sly.parser.llparser.bnf;
using sly.parser.llparser.ebnf;
using sly.parser.syntax.grammar;

namespace sly.parser.generator
Expand Down
2 changes: 1 addition & 1 deletion src/sly/parser/generator/ParserBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using sly.lexer;
using sly.lexer.fsm;
using sly.parser.generator.visitor;
using sly.parser.llparser;
using sly.parser.llparser.bnf;
using sly.parser.parser;
using sly.parser.syntax.grammar;

Expand Down
3 changes: 2 additions & 1 deletion src/sly/parser/parser/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
using sly.lexer;
using sly.parser.generator;
using sly.parser.generator.visitor;
using sly.parser.llparser;
using sly.parser.llparser.bnf;
using sly.parser.llparser.ebnf;
using sly.parser.parser;
using sly.parser.syntax.grammar;
using sly.parser.syntax.tree;
Expand Down
609 changes: 0 additions & 609 deletions src/sly/parser/parser/llparser/EBNFRecursiveDescentSyntaxParser.cs

This file was deleted.

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;
}

}
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
}
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
}
Loading

0 comments on commit 3340e80

Please sign in to comment.