Skip to content

Commit

Permalink
fix non terminal alternate option clause.
Browse files Browse the repository at this point in the history
  • Loading branch information
b3b00 committed Oct 11, 2024
1 parent be74c8d commit 3ce30f0
Show file tree
Hide file tree
Showing 16 changed files with 99 additions and 55 deletions.
2 changes: 1 addition & 1 deletion src/samples/indented/IndentedParser2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public Ast integer(Token<IndentedLangLexer2> tok)
[Production("statement: [set|ifthenelse]? EOL[d]")]
public Ast Statement(ValueOption<Ast> stat)
{
return stat.Match(
return stat.Match<Ast>(
x => x as Statement,
() => new EmptyLine()
);
Expand Down
4 changes: 0 additions & 4 deletions src/sly/parser/generator/visitor/ConcreteSyntaxTreeWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ public OUT Visit(ISyntaxNode<IN> n)
return Visit(node);
case SyntaxNode<IN> node:
return Visit(node);
case SyntaxEpsilon<IN> epsilon:
{
return Visitor.VisitEpsilon();
}
default:
return Visitor.VisitLeaf(new Token<IN>() {TokenID = default(IN),SpanValue="NULL".ToCharArray()});
}
Expand Down
8 changes: 0 additions & 8 deletions src/sly/parser/generator/visitor/EBNFSyntaxTreeVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ protected override SyntaxVisitorResult<IN, OUT> Visit(ISyntaxNode<IN> n, object
return Visit(node, context);
case SyntaxNode<IN> node:
return Visit(node, context);
case SyntaxEpsilon<IN> epsilon:
return SyntaxVisitorResult<IN, OUT>.Epsilon();
default:
return null;
}
Expand Down Expand Up @@ -74,8 +72,6 @@ private SyntaxVisitorResult<IN, OUT> Visit(OptionSyntaxNode<IN> node, object con
var innerResult = Visit(child, context);
switch (child)
{
case SyntaxEpsilon<IN> epsilon:
return SyntaxVisitorResult<IN, OUT>.NewOptionNone();
case SyntaxLeaf<IN> leaf:
return SyntaxVisitorResult<IN, OUT>.NewToken(leaf.Token);
case GroupSyntaxNode<IN> group:
Expand Down Expand Up @@ -131,10 +127,6 @@ private SyntaxVisitorResult<IN, OUT> Visit(SyntaxNode<IN> node, object context =
{
args.Add(v.GroupListResult);
}
else if (v.IsEpsilon)
{
args.Add(default(OUT));
}
}

if (node.IsByPassNode)
Expand Down
6 changes: 0 additions & 6 deletions src/sly/parser/generator/visitor/SyntaxTreeVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,6 @@ public static SyntaxVisitorResult<IN, OUT> NoneResult()
return res;
}

public static SyntaxVisitorResult<IN, OUT> Epsilon()
{
var res = new SyntaxVisitorResult<IN, OUT>();
res.IsEpsilon = true;
return res;
}
}

public class SyntaxTreeVisitor<IN, OUT> where IN : struct
Expand Down
2 changes: 1 addition & 1 deletion src/sly/parser/parser/ValueOption.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public ValueOption(T value)
public bool IsNone { get; }
public bool IsSome => !IsNone;

public T Match(Func<T, T> some, Func<T> none)
public X Match<X>(Func<T, X> some, Func<X> none)
{
if (IsSome)
return some(Value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,13 @@ public SyntaxParseResult<IN> ParseOption(IList<Token<IN>> tokens, OptionClause<I
}
else if (choiceClause.IsNonTerminalChoice)
{
result = new SyntaxParseResult<IN>();
result.IsError = false;
result.Root = new SyntaxEpsilon<IN>();
result.EndingPosition = position;
result = new SyntaxParseResult<IN>
{
IsError = false,
Root = new OptionSyntaxNode<IN>(rule.NonTerminalName, new List<ISyntaxNode<IN>>(),
rule.GetVisitor()),
EndingPosition = position
};
}

break;
Expand Down
6 changes: 5 additions & 1 deletion src/sly/parser/syntax/grammar/ChoiceClause.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public string Dump()
return ToString();
}

[ExcludeFromCodeCoverage]
public bool Equals(IClause<T> clause)
{
if (clause is ChoiceClause<T> other)
Expand All @@ -55,7 +56,8 @@ public bool Equals(IClause<T> clause)

return false;
}


[ExcludeFromCodeCoverage]
private bool Equals(ChoiceClause<T> other)
{
if (other.Choices.Count != Choices.Count)
Expand All @@ -71,6 +73,7 @@ private bool Equals(ChoiceClause<T> other)
return other.Choices.TrueForAll(x => Choices.Exists(y => y.Equals(x)));
}

[ExcludeFromCodeCoverage]
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
Expand All @@ -79,6 +82,7 @@ public override bool Equals(object obj)
return Equals((ChoiceClause<T>)obj);
}

[ExcludeFromCodeCoverage]
public override int GetHashCode()
{
return Dump().GetHashCode();
Expand Down
1 change: 1 addition & 0 deletions src/sly/parser/syntax/grammar/ClauseSequence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public string Dump()
return Clauses.Select(c => c.Dump()).Aggregate((d1, d2) => d1 + " " + d2);
}

[ExcludeFromCodeCoverage]
public bool Equals(IClause<T> other)
{
if (other is ClauseSequence<T> sequence && sequence.Clauses.Count == Clauses.Count)
Expand Down
1 change: 1 addition & 0 deletions src/sly/parser/syntax/grammar/GroupClause.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public string Dump()
}


[ExcludeFromCodeCoverage]
public bool Equals(IClause<T> other)
{
if (other is GroupClause<T> group && group.Clauses.Count == Clauses.Count)
Expand Down
4 changes: 4 additions & 0 deletions src/sly/parser/syntax/grammar/NonTerminalClause.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public string Dump()
return $"{NonTerminalName}(NT)";
}

[ExcludeFromCodeCoverage]
public bool Equals(IClause<T> clause)
{
if (clause is NonTerminalClause<T> other)
Expand All @@ -42,11 +43,13 @@ public bool Equals(IClause<T> clause)
return false;
}

[ExcludeFromCodeCoverage]
private bool Equals(NonTerminalClause<T> other)
{
return NonTerminalName == other.NonTerminalName && IsGroup == other.IsGroup;
}

[ExcludeFromCodeCoverage]
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
Expand All @@ -55,6 +58,7 @@ public override bool Equals(object obj)
return Equals((NonTerminalClause<T>)obj);
}

[ExcludeFromCodeCoverage]
public override int GetHashCode()
{
return Dump().GetHashCode();
Expand Down
1 change: 1 addition & 0 deletions src/sly/parser/syntax/grammar/OneOrMoreClause.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public override string Dump()
return Clause.Dump()+"+";
}

[ExcludeFromCodeCoverage]
public override bool Equals(IClause<T> other)
{
if (other is OneOrMoreClause<T> otherOneOrMore)
Expand Down
6 changes: 5 additions & 1 deletion src/sly/parser/syntax/grammar/OptionClause.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public string Dump()
return $"{Clause}?";
}

[ExcludeFromCodeCoverage]
public bool Equals(IClause<T> clause)
{
if (clause is OptionClause<T> other)
Expand All @@ -39,12 +40,14 @@ public bool Equals(IClause<T> clause)
}
return false;
}


[ExcludeFromCodeCoverage]
private bool Equals(OptionClause<T> other)
{
return Equals(Clause, other.Clause);
}

[ExcludeFromCodeCoverage]
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
Expand All @@ -53,6 +56,7 @@ public override bool Equals(object obj)
return Equals((OptionClause<T>)obj);
}

[ExcludeFromCodeCoverage]
public override int GetHashCode()
{
return (Clause != null ? Clause.GetHashCode() : 0);
Expand Down
1 change: 1 addition & 0 deletions src/sly/parser/syntax/grammar/ZeroOrMoreClause.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public override string Dump()
return t;
}

[ExcludeFromCodeCoverage]
public override bool Equals(IClause<T> other)
{
if (other is OneOrMoreClause<T> otherOneOrMore)
Expand Down
2 changes: 1 addition & 1 deletion src/sly/parser/syntax/tree/OptionSyntaxNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace sly.parser.syntax.tree
public class OptionSyntaxNode<IN> : SyntaxNode<IN> where IN : struct
{
public bool IsGroupOption { get; set; } = false;

public OptionSyntaxNode(string name, List<ISyntaxNode<IN>> children = null, MethodInfo visitor = null) : base(
name, children, visitor)
{ }
Expand Down
26 changes: 0 additions & 26 deletions src/sly/parser/syntax/tree/SyntaxEpsilon.cs

This file was deleted.

73 changes: 71 additions & 2 deletions tests/ParserTests/EBNFTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -313,12 +313,12 @@ public string rootOption(Token<GroupTestToken> a, ValueOption<Group<GroupTestTok
{
var aToken = group.Token("A").Value;
builder.Append($";{aToken}");
return null;
return builder.ToString();
},
() =>
{
builder.Append($";<none>");
return null;
return builder.ToString();
});
builder.Append(")");
return builder.ToString();
Expand Down Expand Up @@ -413,6 +413,51 @@ public string Choice(Token<OptionTestToken> first, Token<OptionTestToken> next)
}
}


public class AlternateChoiceTestOptionNonTerminal
{
[Production("choice : [ A | B | C] [ B | C]? F?")]
public string Choice(string first, ValueOption<string> next, ValueOption<string> final)
{
StringBuilder builder = new StringBuilder();
builder.Append(first);


var v = next.Match(x => x,
() => "<none>");
builder.Append($",{v}");
v = final.Match(x => x,
() => "<none>");
builder.Append($",{v}");

return builder.ToString();
}

[Production("A : a")]
public string A(Token<OptionTestToken> a)
{
return a.Value;
}

[Production("B : b")]
public string B(Token<OptionTestToken> b)
{
return b.Value;
}

[Production("C : c")]
public string C(Token<OptionTestToken> c)
{
return c.Value;
}

[Production("F : f")]
public string F(Token<OptionTestToken> f)
{
return f.Value;
}
}

public class AlternateChoiceTestOptionDiscardedTerminal
{
[Production("choice : [ a | b | c] [ b | c] [d]")]
Expand Down Expand Up @@ -1209,6 +1254,30 @@ public void TestAlternateChoiceOptionTerminal()
Check.That(parseResult.Result).IsEqualTo("a,<none>");
}

[Fact]
public void TestAlternateChoiceOptionNonTerminal()
{
var startingRule = $"choice";
var parserInstance = new AlternateChoiceTestOptionNonTerminal();
var builder = new ParserBuilder<OptionTestToken, string>();
var builtParser = builder.BuildParser(parserInstance, ParserType.EBNF_LL_RECURSIVE_DESCENT, startingRule);
Check.That(builtParser.IsError).IsFalse();
Check.That(builtParser.Errors).IsEmpty();
var parseResult = builtParser.Result.Parse("a b f", "choice");
Check.That(parseResult.IsOk).IsTrue();
Check.That(parseResult.Result).IsEqualTo("a,b,f");
parseResult = builtParser.Result.Parse("a", "choice");
Check.That(parseResult.IsOk).IsTrue();
Check.That(parseResult.Result).IsEqualTo("a,<none>,<none>");
parseResult = builtParser.Result.Parse("a b ", "choice");
Check.That(parseResult.IsOk).IsTrue();
Check.That(parseResult.Result).IsEqualTo("a,b,<none>");
parseResult = builtParser.Result.Parse("a f", "choice");
Check.That(parseResult.IsOk).IsTrue();
Check.That(parseResult.Result).IsEqualTo("a,<none>,f");

}

[Fact]
public void TestAlternateChoiceOptionDiscardedTerminal()
{
Expand Down

0 comments on commit 3ce30f0

Please sign in to comment.