Skip to content

Commit

Permalink
Merge pull request #196 from b3b00/bugfix/#194
Browse files Browse the repository at this point in the history
Bugfix/#194
  • Loading branch information
b3b00 authored Aug 24, 2020
2 parents 996405d + 39f47c8 commit 6b13b43
Show file tree
Hide file tree
Showing 7 changed files with 528 additions and 27 deletions.
10 changes: 5 additions & 5 deletions ParserTests/EBNFTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,9 @@ public string Choice(Token<OptionTestToken> c)
}

[Production("D : [ E | C] [d]")]
public string D(Token<OptionTestToken> d)
public string D()
{
return d.Value;
return "nothing here";
}

[Production("E : e")]
Expand Down Expand Up @@ -351,20 +351,20 @@ public string A(Token<OptionTestToken> t)
public class Bugfix104Test
{
[Production("testNonTerm : sub (COMMA[d] unreachable)? ")]
public int TestNonTerminal(List<int> options, Token<GroupTestToken> token)
public int TestNonTerminal(int sub, ValueOption<Group<GroupTestToken,int>> group)
{
return 1;
}

[Production("sub : A")]
public int sub(Token<GroupTestToken> token)
public int Sub(Token<GroupTestToken> token)
{
return 1;
}


[Production("unreachable : A")]
public int unreachable(Token<GroupTestToken> token)
public int Unreachable(Token<GroupTestToken> token)
{
return 1;
}
Expand Down
232 changes: 232 additions & 0 deletions ParserTests/ParserConfigurationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using sly.buildresult;
using sly.lexer;
using sly.parser.generator;
using sly.parser.parser;
using Xunit;

namespace ParserTests
Expand All @@ -15,6 +16,121 @@ public enum BadTokens
MissingLexeme = 3
}

public enum BadVisitorTokens
{
[Lexeme("a")] A = 1,
[Lexeme("b")] B = 2,
[Lexeme("c")] C = 3,
}


public interface BadVisitor
{

}

public interface SubBadVisitor : BadVisitor
{

}

public class BadVisitorReturnParser {

[Production("badreturn : A B")]
public string BadReturn(Token<BadVisitorTokens> a, Token<BadVisitorTokens> b)
{
return "toto";
}
}

public class BadTerminalArgParser
{
[Production("badtermarg : A B")]
public SubBadVisitor BarTermArg(string aArg, Token<BadVisitorTokens> bArg)
{
return null;
}
}

public class BadNonTerminalArgParser
{
[Production("badnontermarg : a B")]
public SubBadVisitor BadNonTermArg(string aArg, Token<BadVisitorTokens> bArg)
{
return null;
}

[Production("a : A")]
public BadVisitor noTerm(Token<BadVisitorTokens> a)
{
return null;
}
}

public class BadManyArgParser
{
[Production("badmanyarg : a* B* ( a B )+ [a|b]+")]
public SubBadVisitor BadNonTermArg(string aArg, string bArg, string cArg, string dArg )
{
return null;
}

[Production("a : A")]
public BadVisitor noTerm(Token<BadVisitorTokens> a)
{
return null;
}
}

public class BadGroupArgParser
{
[Production("badgrouparg : ( a B )")]
public SubBadVisitor BadNonTermArg(string aArg )
{
return null;
}

[Production("a : A")]
public BadVisitor noTerm(Token<BadVisitorTokens> a)
{
return null;
}
}

public class BadArgNumberParser
{
[Production("badargnumber : A B ")]
public SubBadVisitor BadNonTermArg(Token<BadVisitorTokens> a, Token<BadVisitorTokens> b, object somethingThatCouldBeAContext, BadVisitor extraneousArg)
{
return null;
}

[Production("badargnumber2 : A B ")]
public SubBadVisitor BadNonTermArg(Token<BadVisitorTokens> a)
{
return null;
}


}

public class BadOptionArgParser
{
[Production("badoptionarg : a? B? (A B)? [A|B]?")]
public SubBadVisitor BadOptionArg(BadVisitor a, ValueOption<Token<BadVisitorTokens>> b, Group<BadVisitor,BadVisitorTokens> c, string d)
{
return null;
}

[Production("a : A ")]
public SubBadVisitor BadNonTermArg(Token<BadVisitorTokens> a)
{
return null;
}


}

public class ParserConfigurationTests
{
[Production("R : R1 R2")]
Expand Down Expand Up @@ -69,5 +185,121 @@ public void TestLexerBuildErrors()
Assert.True(warnMessage.Contains(BadTokens.MissingLexeme.ToString()) &&
warnMessage.Contains("not have Lexeme"));
}

[Fact]
public void TestBadVisitorReturn()
{
var instance = new BadVisitorReturnParser();
ParserBuilder<BadVisitorTokens,BadVisitor> builder = new ParserBuilder<BadVisitorTokens, BadVisitor>();
var result = builder.BuildParser(instance, ParserType.LL_RECURSIVE_DESCENT, "badreturn");
Assert.True(result.IsError);
Assert.Single(result.Errors);
Assert.Contains("incorrect return type", result.Errors.First().Message);
Assert.Contains("visitor BadReturn", result.Errors.First().Message);

result = builder.BuildParser(instance, ParserType.EBNF_LL_RECURSIVE_DESCENT, "badreturn");
Assert.True(result.IsError);
Assert.Single(result.Errors);
Assert.Contains("incorrect return type", result.Errors.First().Message);
Assert.Contains("visitor BadReturn", result.Errors.First().Message);
;
}

[Fact]
public void TestBadVisitorTerminalArgument()
{
var instance = new BadTerminalArgParser();
ParserBuilder<BadVisitorTokens,BadVisitor> builder = new ParserBuilder<BadVisitorTokens, BadVisitor>();
var result = builder.BuildParser(instance, ParserType.LL_RECURSIVE_DESCENT, "badtermarg");
Assert.True(result.IsError);
Assert.Single(result.Errors);
//"visitor BadReturn for rule badtermarg : A B ; parameter a has incorrect type : expected sly.lexer.Token`1[ParserTests.BadVisitorTokens], found SubBadVisitor"
Assert.Contains("parameter aArg has incorrect type", result.Errors.First().Message);

result = builder.BuildParser(instance, ParserType.EBNF_LL_RECURSIVE_DESCENT, "badtermarg");
Assert.True(result.IsError);
Assert.Single(result.Errors);
//"visitor BadReturn for rule badtermarg : A B ; parameter a has incorrect type : expected sly.lexer.Token`1[ParserTests.BadVisitorTokens], found SubBadVisitor"
Assert.Contains("parameter aArg has incorrect type", result.Errors.First().Message);



}


[Fact]
public void TestBadVisitorNonTerminalArgument()
{
var instance = new BadNonTerminalArgParser();
ParserBuilder<BadVisitorTokens,BadVisitor> builder = new ParserBuilder<BadVisitorTokens, BadVisitor>();
var result = builder.BuildParser(instance, ParserType.LL_RECURSIVE_DESCENT, "badnontermarg");
Assert.True(result.IsError);
Assert.Single(result.Errors);
//"visitor BadReturn for rule badtermarg : A B ; parameter a has incorrect type : expected sly.lexer.Token`1[ParserTests.BadVisitorTokens], found SubBadVisitor"
Assert.Contains("parameter aArg has incorrect type", result.Errors.First().Message);

result = builder.BuildParser(instance, ParserType.EBNF_LL_RECURSIVE_DESCENT, "badnontermarg");
Assert.True(result.IsError);
Assert.Single(result.Errors);
//"visitor BadReturn for rule badtermarg : A B ; parameter a has incorrect type : expected sly.lexer.Token`1[ParserTests.BadVisitorTokens], found SubBadVisitor"
Assert.Contains("parameter aArg has incorrect type", result.Errors.First().Message);



}

[Fact]
public void TestBadManyArgument()
{
var instance = new BadManyArgParser();
ParserBuilder<BadVisitorTokens,BadVisitor> builder = new ParserBuilder<BadVisitorTokens, BadVisitor>();
var result = builder.BuildParser(instance, ParserType.EBNF_LL_RECURSIVE_DESCENT, "badmanyarg");
Assert.True(result.IsError);
Assert.Equal(4,result.Errors.Count);

//"visitor BadReturn for rule badtermarg : A B ; parameter a has incorrect type : expected sly.lexer.Token`1[ParserTests.BadVisitorTokens], found SubBadVisitor"
Assert.True(result.Errors.Exists(x => x.Message.Contains("parameter aArg has incorrect type")));
Assert.True(result.Errors.Exists(x => x.Message.Contains("parameter bArg has incorrect type")));
Assert.True(result.Errors.Exists(x => x.Message.Contains("parameter cArg has incorrect type")));
Assert.True(result.Errors.Exists(x => x.Message.Contains("parameter dArg has incorrect type")));

}

[Fact]
public void TestBadGroupArgument()
{
var instance = new BadGroupArgParser();
ParserBuilder<BadVisitorTokens,BadVisitor> builder = new ParserBuilder<BadVisitorTokens, BadVisitor>();
var result = builder.BuildParser(instance, ParserType.EBNF_LL_RECURSIVE_DESCENT, "badgrouparg");
Assert.True(result.IsError);
Assert.Single(result.Errors);
Assert.Contains("parameter aArg has incorrect type",result.Errors.First().Message);
}

[Fact]
public void TestBadArgumentNumber()
{
var instance = new BadArgNumberParser();
ParserBuilder<BadVisitorTokens,BadVisitor> builder = new ParserBuilder<BadVisitorTokens, BadVisitor>();
var result = builder.BuildParser(instance, ParserType.EBNF_LL_RECURSIVE_DESCENT, "badargnumber");
Assert.True(result.IsError);
Assert.Equal(3, result.Errors.Count);
Assert.True(result.Errors.Exists(x => x.Message.Contains("visitor BadNonTermArg for rule badargnumber : A B has incorrect argument number : expected 2, found 4")));
Assert.True(result.Errors.Exists(x => x.Message.Contains("visitor BadNonTermArg for rule badargnumber2 : A B has incorrect argument number : expected 2, found 1")));
}

[Fact]
public void TestBadOptionArgument()
{
var instance = new BadOptionArgParser();
ParserBuilder<BadVisitorTokens,BadVisitor> builder = new ParserBuilder<BadVisitorTokens, BadVisitor>();
var result = builder.BuildParser(instance, ParserType.EBNF_LL_RECURSIVE_DESCENT, "badoptionarg");
Assert.True(result.IsError);
Assert.Equal(4,result.Errors.Count);
Assert.True(result.Errors.Exists(x => x.Message.Contains("parameter a has incorrect type")));
Assert.True(result.Errors.Exists(x => x.Message.Contains("parameter b has incorrect type")));
Assert.True(result.Errors.Exists(x => x.Message.Contains("parameter c has incorrect type")));
Assert.True(result.Errors.Exists(x => x.Message.Contains("parameter d has incorrect type")));
}
}
}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ SLY is highly inspired by the python lex yacc library ([PLY](http://www.dabeaz.c
A lexer - parser chain is fully described in only 2 C# files :
* [Lexer](#lexers) : an enum that lists all the lexems used (plus metadata to describe their patterns) ;
* [Parser](#parsers) : a class that lists production rules and their associated actions.

># ⚠️ CSLY is strictly typed, read carefully the [typing section](typing) to correctly write type your parser.
CSLY also has an additional feature that allow to write expression parsers(boolean or numeric expressions for instance) in a very compact and efficient way. (see [expression parser](#expressions-parser))




## Installation ##
Expand Down
34 changes: 17 additions & 17 deletions samples/jsonparser/EBNFJSONParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ public JSon StringValue(Token<JsonToken> stringToken)
}

[Production("value : INT")]
public object IntValue(Token<JsonToken> intToken)
public JSon IntValue(Token<JsonToken> intToken)
{
return new JValue(intToken.IntValue);
}

[Production("value : DOUBLE")]
public object DoubleValue(Token<JsonToken> doubleToken)
public JSon DoubleValue(Token<JsonToken> doubleToken)
{
var dbl = double.MinValue;
try
Expand All @@ -58,13 +58,13 @@ public object DoubleValue(Token<JsonToken> doubleToken)
}

[Production("value : BOOLEAN")]
public object BooleanValue(Token<JsonToken> boolToken)
public JSon BooleanValue(Token<JsonToken> boolToken)
{
return new JValue(bool.Parse(boolToken.Value));
}

[Production("value : NULL")]
public object NullValue(object forget)
[Production("value : NULL[d]")]
public JSon NullValue()
{
return new JNull();
}
Expand All @@ -85,14 +85,14 @@ public JSon ListValue(JList list)

#region OBJECT

[Production("object: ACCG ACCD")]
public JSon EmptyObjectValue(object accg, object accd)
[Production("object: ACCG[d] ACCD[d]")]
public JSon EmptyObjectValue()
{
return new JObject();
}

[Production("object: ACCG members ACCD")]
public JSon AttributesObjectValue(object accg, JObject members, object accd)
[Production("object: ACCG[d] members ACCD[d]")]
public JSon AttributesObjectValue(JObject members)
{
return members;
}
Expand All @@ -101,14 +101,14 @@ public JSon AttributesObjectValue(object accg, JObject members, object accd)

#region LIST

[Production("list: CROG CROD")]
public JSon EmptyList(object crog, object crod)
[Production("list: CROG[d] CROD[d]")]
public JSon EmptyList()
{
return new JList();
}

[Production("list: CROG listElements CROD")]
public JSon List(object crog, JList elements, object crod)
[Production("list: CROG[d] listElements CROD[d]")]
public JSon List(JList elements)
{
return elements;
}
Expand All @@ -133,7 +133,7 @@ public JSon ListElementsOne(Token<JsonToken> discardedComma, JSon value)
#region PROPERTIES

[Production("members: property additionalProperty*")]
public object Members(JObject head, List<JSon> tail)
public JObject Members(JObject head, List<JSon> tail)
{
var value = new JObject();
value.Merge(head);
Expand All @@ -142,13 +142,13 @@ public object Members(JObject head, List<JSon> tail)
}

[Production("additionalProperty : COMMA property")]
public object property(Token<JsonToken> comma, JObject property)
public JObject property(Token<JsonToken> comma, JObject property)
{
return property;
}

[Production("property: STRING COLON value")]
public object property(Token<JsonToken> key, object colon, JSon value)
[Production("property: STRING COLON[d] value")]
public JObject property(Token<JsonToken> key, JSon value)
{
return new JObject(key.StringWithoutQuotes, value);
}
Expand Down
Loading

0 comments on commit 6b13b43

Please sign in to comment.