Skip to content

Commit f9aaac9

Browse files
committed
fluent : sub node names
1 parent dcacb3f commit f9aaac9

File tree

4 files changed

+129
-0
lines changed

4 files changed

+129
-0
lines changed

src/sly/parser/fluent/FluentEBNFParserBuilder.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,4 +368,13 @@ public IFluentEbnfParserBuilder<IN, OUT> Named(string name)
368368
}
369369
return this;
370370
}
371+
372+
public IFluentEbnfParserBuilder<IN, OUT> WithSubNodeNamed(params string[] subNodeNames)
373+
{
374+
if (_currentRule != null)
375+
{
376+
_currentRule.SubNodeNames = subNodeNames;
377+
}
378+
return this;
379+
}
371380
}

src/sly/parser/fluent/IFluentEbnfParserBuilder.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ namespace sly.parser.generator;
77
public interface IFluentEbnfRuleBuilder<IN, OUT> : IFluentEbnfParserBuilder<IN, OUT> where IN : struct
88
{
99
public IFluentEbnfParserBuilder<IN, OUT> Named(string name);
10+
11+
public IFluentEbnfParserBuilder<IN, OUT> WithSubNodeNamed(params string[] subNodeNames);
1012
}
1113

1214
public interface IFluentEbnfParserBuilder<IN,OUT> where IN : struct

tests/ParserTests/ExpressionGeneratorTests.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using sly.parser.generator;
99
using Xunit;
1010
using ParserTests.Issue184;
11+
using sly.lexer.fluent;
1112
using sly.parser.generator.visitor;
1213
using sly.parser.syntax.tree;
1314
using ExpressionToken = expressionparser.ExpressionToken;
@@ -469,6 +470,69 @@ public void TestPrefix()
469470
Check.That(buildResult).IsOk();
470471
var parser = buildResult.Result;
471472

473+
var result = parser.Parse("## 42");
474+
Check.That(result).IsOkParsing();
475+
Check.That(result.Result).IsEqualTo("##::42");
476+
var tree = result.SyntaxTree;
477+
var syntaxTree = tree as SyntaxNode<SimpleExpressionToken, string>;
478+
Check.That(syntaxTree).IsNotNull();
479+
Check.That(syntaxTree.Children).CountIs(1);
480+
Check.That(syntaxTree.Name).IsEqualTo($"{nameof(PrefixOperation)}_expressions");
481+
var child = syntaxTree.Children[0] as SyntaxNode<SimpleExpressionToken, string>;
482+
Check.That(child).IsNotNull();
483+
Check.That(child.Name).IsEqualTo("hash-hash");
484+
Check.That(child.Children).CountIs(2);
485+
486+
result = parser.Parse("@@ 42");
487+
Check.That(result).IsOkParsing();
488+
Check.That(result.Result).IsEqualTo("@@::42");
489+
tree = result.SyntaxTree;
490+
syntaxTree = tree as SyntaxNode<SimpleExpressionToken, string>;
491+
Check.That(syntaxTree).IsNotNull();
492+
Check.That(syntaxTree.Children).CountIs(1);
493+
Check.That(syntaxTree.Name).IsEqualTo($"{nameof(PrefixOperation)}_expressions");
494+
child = syntaxTree.Children[0] as SyntaxNode<SimpleExpressionToken, string>;
495+
Check.That(child).IsNotNull();
496+
Check.That(child.Name).IsEqualTo("at-at");
497+
Check.That(child.Children).CountIs(2);
498+
}
499+
500+
[Fact]
501+
public void TestPrefixFluent()
502+
{
503+
StartingRule = $"{nameof(PrefixOperation)}_expressions";
504+
505+
var lexer = FluentLexerBuilder<SimpleExpressionToken>.NewBuilder()
506+
.IgnoreEol(true)
507+
.IgnoreWhiteSpace(true)
508+
.IgnoreKeywordCase(true)
509+
.Int(SimpleExpressionToken.INT);
510+
511+
var build = FluentEBNFParserBuilder<SimpleExpressionToken, string>.NewBuilder(new PrefixOperation(),
512+
$"{nameof(PrefixOperation)}_expressions", "en")
513+
.Operand("testOperand: INT", (args =>
514+
{
515+
return (args[0] as Token<SimpleExpressionToken>)?.Value;
516+
}))
517+
.Prefix("'##'", 10, args =>
518+
{
519+
var token = args[0] as Token<SimpleExpressionToken>;
520+
var operand = args[1] as string;
521+
return $"{token?.Value}::{operand}";
522+
}).Named("hash-hash")
523+
.Prefix("'@@'", 10, args =>
524+
{
525+
var token = args[0] as Token<SimpleExpressionToken>;
526+
var operand = args[1] as string;
527+
return $"{token?.Value}::{operand}";
528+
}).Named("at-at")
529+
.WithLexerbuilder(lexer)
530+
.BuildParser();
531+
532+
Check.That(build).IsOk();
533+
var parser = build.Result;
534+
535+
472536
var result = parser.Parse("## 42");
473537
Check.That(result).IsOkParsing();
474538
Check.That(result.Result).IsEqualTo("##::42");

tests/ParserTests/FluentTests.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
using sly.lexer.fluent;
88
using sly.lexer.fsm;
99
using sly.parser.generator;
10+
using sly.parser.parser;
11+
using sly.parser.syntax.tree;
1012
using Xunit;
1113

1214
namespace ParserTests;
@@ -256,6 +258,8 @@ public void TestFluentParser()
256258
Check.That(r).IsOkParsing();
257259
Check.That(r.Result).IsEqualTo(@"hello(hello, olivier) - world(world, 1977-03-30)");
258260
}
261+
262+
259263

260264
[Fact]
261265
public void TestFluentExpressionParser()
@@ -396,4 +400,54 @@ public void TestFluentExpressionParserWithExplicits()
396400
Check.That(result.Result).IsEqualTo(-1 + 2);
397401

398402
}
403+
404+
[Fact]
405+
public void TestFluentSubNodeNames()
406+
{
407+
var lexer = FluentLexerBuilder<FluentToken>.NewBuilder()
408+
.IgnoreEol(true)
409+
.IgnoreWhiteSpace(true)
410+
.IgnoreKeywordCase(true)
411+
.AlphaNumDashId(FluentToken.ID)
412+
.Date(FluentToken.DATE, DateFormat.YYYYMMDD, '-')
413+
.AlphaNumDashId(FluentToken.ID);
414+
415+
var build = FluentEBNFParserBuilder<FluentToken, string>.NewBuilder(new FluentTests(), "root", "en")
416+
.Production("root : (l 'SEP'[d] r)*", args =>
417+
{
418+
var items = args[0] as List<Group<FluentToken, string>>;
419+
var r = string.Join(",", items.Select(x => $"{x.Value(0)}|{x.Value(1)}"));
420+
return r;
421+
422+
}).WithSubNodeNamed("items")
423+
.Production("l : ID", args =>
424+
{
425+
return (args[0] as Token<FluentToken>)?.Value;
426+
}).Named("left")
427+
.Production("r : ID", args =>
428+
{
429+
return (args[0] as Token<FluentToken>)?.Value;
430+
}).Named("right")
431+
.WithLexerbuilder(lexer)
432+
.BuildParser();
433+
Check.That(build).IsOk();
434+
var parsed = build.Result.Parse("a SEP b c SEP d ");
435+
Check.That(parsed).IsOkParsing();
436+
Check.That(parsed.Result).IsEqualTo("a|b,c|d");
437+
var tree = parsed.SyntaxTree as SyntaxNode<FluentToken, string>;
438+
Check.That(tree).IsNotNull();
439+
Check.That(tree.Children).IsSingle();
440+
var child = tree.Children.FirstOrDefault();
441+
Check.That(child).IsNotNull();
442+
Check.That(child.Name).IsEqualTo("items");
443+
var childNode = child as SyntaxNode<FluentToken, string>;
444+
Check.That(childNode).IsNotNull();
445+
Check.That(childNode.Children).CountIs(2);
446+
var first = childNode.Children.FirstOrDefault() as SyntaxNode<FluentToken, string>;
447+
Check.That(first).IsNotNull();
448+
Check.That(first.Children).CountIs(3);
449+
var l = first.Children.FirstOrDefault() as SyntaxNode<FluentToken, string>;
450+
Check.That(l).IsNotNull();
451+
Check.That(l.Name).IsEqualTo("left");
452+
}
399453
}

0 commit comments

Comments
 (0)