Skip to content

Commit

Permalink
Merge 6b286d6 into 11b8c8a
Browse files Browse the repository at this point in the history
  • Loading branch information
b3b00 committed Jan 5, 2024
2 parents 11b8c8a + 6b286d6 commit 7924b6b
Show file tree
Hide file tree
Showing 20 changed files with 1,321 additions and 54 deletions.
Binary file added src/samples/ParserExample/memo.dmw
Binary file not shown.
38 changes: 38 additions & 0 deletions src/sly/parser/parser/SyntaxParsingContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using sly.parser.syntax.grammar;

namespace sly.parser
{

public class SyntaxParsingContext<IN> where IN : struct
{
private Dictionary<string, SyntaxParseResult<IN>> _memoizedNonTerminalResults;

public SyntaxParsingContext()
{
_memoizedNonTerminalResults = new Dictionary<string, SyntaxParseResult<IN>>();
}

private string GetKey(IClause<IN> clause, int position)
{
return $"{clause.Dump()} -- @{position}";
}

public void Memoize(IClause<IN> clause, int position, SyntaxParseResult<IN> result)
{
_memoizedNonTerminalResults[GetKey(clause,position)] = result;
}

public bool TryGetParseResult(IClause<IN> clause, int position, out SyntaxParseResult<IN> result)
{
bool found = _memoizedNonTerminalResults.TryGetValue(GetKey(clause, position), out result);
if (!found)
{
Debug.WriteLine($"NOT FOUND ! {clause} - {position}");
}
return found;
}
}
}
98 changes: 60 additions & 38 deletions src/sly/parser/parser/llparser/EBNFRecursiveDescentSyntaxParser.cs

Large diffs are not rendered by default.

50 changes: 37 additions & 13 deletions src/sly/parser/parser/llparser/RecursiveDescentSyntaxParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public partial class RecursiveDescentSyntaxParser<IN, OUT> where IN : struct
public RecursiveDescentSyntaxParser(ParserConfiguration<IN, OUT> configuration, string startingNonTerminal,
string i18n)
{

I18n = i18n;
Configuration = configuration;
StartingNonTerminal = startingNonTerminal;
Expand All @@ -24,6 +25,11 @@ public partial class RecursiveDescentSyntaxParser<IN, OUT> where IN : struct
#region parsing

public SyntaxParseResult<IN> Parse(IList<Token<IN>> tokens, string startingNonTerminal = null)
{
return SafeParse(tokens, new SyntaxParsingContext<IN>(), startingNonTerminal);
}

public SyntaxParseResult<IN> SafeParse(IList<Token<IN>> tokens, SyntaxParsingContext<IN> parsingContext, string startingNonTerminal = null)
{
var start = startingNonTerminal ?? StartingNonTerminal;
var NonTerminals = Configuration.NonTerminals;
Expand All @@ -40,7 +46,7 @@ public SyntaxParseResult<IN> Parse(IList<Token<IN>> tokens, string startingNonTe
if (!tokens[0].IsEOS && rule.PossibleLeadingTokens.Any(x => x.Match(tokens[0])))
{
matchingRuleCount++;
var r = Parse(tokens, rule, 0, start);
var r = Parse(tokens, rule, 0, start, parsingContext);
rs.Add(r);
}
}
Expand Down Expand Up @@ -116,7 +122,7 @@ public SyntaxParseResult<IN> Parse(IList<Token<IN>> tokens, string startingNonTe


public virtual SyntaxParseResult<IN> Parse(IList<Token<IN>> tokens, Rule<IN> rule, int position,
string nonTerminalName)
string nonTerminalName, SyntaxParsingContext<IN> parsingContext)
{
var currentPosition = position;
var errors = new List<UnexpectedTokenSyntaxError<IN>>();
Expand All @@ -132,7 +138,7 @@ public SyntaxParseResult<IN> Parse(IList<Token<IN>> tokens, string startingNonTe
{
case TerminalClause<IN> terminalClause:
{
var termRes = ParseTerminal(tokens, terminalClause, currentPosition);
var termRes = ParseTerminal(tokens, terminalClause, currentPosition, parsingContext);
if (!termRes.IsError)
{
children.Add(termRes.Root);
Expand All @@ -151,7 +157,7 @@ public SyntaxParseResult<IN> Parse(IList<Token<IN>> tokens, string startingNonTe
case NonTerminalClause<IN> terminalClause:
{
var nonTerminalResult =
ParseNonTerminal(tokens, terminalClause, currentPosition);
ParseNonTerminal(tokens, terminalClause, currentPosition, parsingContext);
if (!nonTerminalResult.IsError)
{
children.Add(nonTerminalResult.Root);
Expand Down Expand Up @@ -191,7 +197,6 @@ public SyntaxParseResult<IN> Parse(IList<Token<IN>> tokens, string startingNonTe
result.IsEnded = tokens[result.EndingPosition].IsEOS;
}


return result;
}

Expand Down Expand Up @@ -244,8 +249,13 @@ protected SyntaxNode<IN> ManageExpressionRules(Rule<IN> rule, SyntaxNode<IN> nod
return node;
}

public SyntaxParseResult<IN> ParseTerminal(IList<Token<IN>> tokens, TerminalClause<IN> terminal, int position)
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;
Expand All @@ -260,20 +270,28 @@ public SyntaxParseResult<IN> ParseTerminal(IList<Token<IN>> tokens, TerminalClau
new UnexpectedTokenSyntaxError<IN>(token, LexemeLabels, I18n, terminal.ExpectedToken));
result.AddExpecting(terminal.ExpectedToken);
}

parsingContext.Memoize(terminal,position,result);
return result;
}



public SyntaxParseResult<IN> ParseNonTerminal(IList<Token<IN>> tokens, NonTerminalClause<IN> nonTermClause,
int currentPosition)
int currentPosition, SyntaxParsingContext<IN> parsingContext)
{
return ParseNonTerminal(tokens, nonTermClause.NonTerminalName, currentPosition);
var result = ParseNonTerminal(tokens, nonTermClause.NonTerminalName, currentPosition, parsingContext);
return result;
}



public SyntaxParseResult<IN> ParseNonTerminal(IList<Token<IN>> tokens, string nonTerminalName,
int currentPosition)
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>>();
Expand All @@ -290,7 +308,7 @@ public SyntaxParseResult<IN> ParseTerminal(IList<Token<IN>> tokens, TerminalClau
if (startPosition < tokens.Count && !tokens[startPosition].IsEOS &&
innerrule.PossibleLeadingTokens.Any(x => x.Match(tokens[startPosition])) || innerrule.MayBeEmpty)
{
var innerRuleRes = Parse(tokens, innerrule, startPosition, nonTerminalName);
var innerRuleRes = Parse(tokens, innerrule, startPosition, nonTerminalName, parsingContext);
rulesResults.Add(innerRuleRes);

var other = greaterIndex == 0 && innerRuleRes.EndingPosition == 0;
Expand All @@ -317,7 +335,10 @@ public SyntaxParseResult<IN> ParseTerminal(IList<Token<IN>> tokens, TerminalClau
allAcceptableTokens.AddRange(r.PossibleLeadingTokens);
});
// allAcceptableTokens = allAcceptableTokens.ToList();
return NoMatchingRuleError(tokens, currentPosition, allAcceptableTokens);

var noMatching = NoMatchingRuleError(tokens, currentPosition, allAcceptableTokens);
parsingContext.Memoize(new NonTerminalClause<IN>(nonTerminalName),currentPosition,noMatching);
return noMatching;
}

errors.AddRange(innerRuleErrors);
Expand Down Expand Up @@ -379,7 +400,7 @@ public SyntaxParseResult<IN> ParseTerminal(IList<Token<IN>> tokens, TerminalClau
}
}
}

parsingContext.Memoize(new NonTerminalClause<IN>(nonTerminalName),currentPosition,result);
return result;
}

Expand Down Expand Up @@ -410,6 +431,9 @@ public SyntaxParseResult<IN> ParseTerminal(IList<Token<IN>> tokens, TerminalClau
return error;
}




public virtual void Init(ParserConfiguration<IN, OUT> configuration, string root)
{
if (root != null) StartingNonTerminal = root;
Expand Down
39 changes: 39 additions & 0 deletions src/sly/parser/syntax/grammar/ChoiceClause.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,44 @@ public string Dump()
{
return ToString();
}

public bool Equals(IClause<T> clause)
{
if (clause is ChoiceClause<T> other)
{
return Equals(other);
}

return false;
}

protected bool Equals(ChoiceClause<T> other)
{
if (other.Choices.Count != Choices.Count)
{
return false;
}

if (other.IsTerminalChoice != IsTerminalChoice)
{
return false;
}

return other.Choices.All(x => Choices.Exists(y => y.Equals(x)));
}

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ChoiceClause<T>)obj);
}

public override int GetHashCode()
{
return Dump().GetHashCode();
}

}
}
4 changes: 3 additions & 1 deletion src/sly/parser/syntax/grammar/Clause.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;

namespace sly.parser.syntax.grammar
{
/// <summary>
/// a clause within a grammar rule
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IClause<T> : GrammarNode<T>
public interface IClause<T> : GrammarNode<T>, IEquatable<IClause<T>>
{
bool MayBeEmpty();
string Dump();
Expand Down
24 changes: 24 additions & 0 deletions src/sly/parser/syntax/grammar/ClauseSequence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,29 @@ public string Dump()
{
return Clauses.Select<IClause<T>, string>(c => c.Dump()).Aggregate<string>((d1, d2) => d1 + " " + d2);
}

public bool Equals(IClause<T> other)
{
if (other != null)
{
if (other is ClauseSequence<T> sequence)
{
if (sequence.Clauses.Count == Clauses.Count)
{
for (int i = 0; i < Clauses.Count; i++)
{
if (!Clauses[i].Equals(sequence.Clauses[i]))
{
return false;
}
}

return true;
}
}
}

return false;
}
}
}
26 changes: 25 additions & 1 deletion src/sly/parser/syntax/grammar/GroupClause.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,31 @@ public string Dump()
return dump.ToString();
}



public bool Equals(IClause<T> other)
{
if (other != null)
{
if (other is GroupClause<T> group)
{
if (group.Clauses.Count == Clauses.Count)
{
for (int i = 0; i < Clauses.Count; i++)
{
if (!Clauses[i].Equals(group.Clauses[i]))
{
return false;
}
}

return true;
}
}
}

return false;
}

[ExcludeFromCodeCoverage]
public override string ToString()
{
Expand Down
27 changes: 26 additions & 1 deletion src/sly/parser/syntax/grammar/LeadingToken.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using System;
using System.Diagnostics.CodeAnalysis;
using sly.lexer;

namespace sly.parser.syntax.grammar
{
public class LeadingToken<IN> where IN:struct
public class LeadingToken<IN> : IEquatable<LeadingToken<IN>> where IN:struct
{
public IN TokenId { get; set; }

Expand Down Expand Up @@ -48,5 +49,29 @@ public override string ToString()
return TokenId.ToString();
}
}

public bool Equals(LeadingToken<IN> other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if (IsExplicitToken)
{
return other.IsExplicitToken && ExplicitToken == other.ExplicitToken;
}
return TokenId.Equals(other.TokenId);
}

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((LeadingToken<IN>)obj);
}

public override int GetHashCode()
{
return IsExplicitToken ? this.ExplicitToken.GetHashCode() : TokenId.GetHashCode();
}
}
}
1 change: 1 addition & 0 deletions src/sly/parser/syntax/grammar/ManyClause.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ public abstract class ManyClause<T> : IClause<T>
public abstract bool MayBeEmpty();

public abstract string Dump();
public abstract bool Equals(IClause<T> other);
}
}

0 comments on commit 7924b6b

Please sign in to comment.