private static Grammar MakeParser() { // Literals var ws = Terminals.WhiteSpace.Repeat(0); var comma = ws.Then(Terminals.Set(','), ws); var subExpressionAccess = ws.Then(Terminals.Set('.'), ws); var number = new NumberParser { AllowDecimal = true, AllowExponent = true, AllowSign = true, ValueType = typeof(float) }; var identifier = Terminals.Letter.Or(Terminals.Set(_identifierAllowedCharacters)) .Then(Terminals.LetterOrDigit.Or(Terminals.Set(_identifierAllowedCharacters)).Repeat(0)); // Expressions var expression = new UnaryParser(); var subExpression = expression.Named(ElementAST.SubExpressionRoot) .Then(subExpressionAccess, identifier.Named(ElementAST.SubExpressionName)); var arguments = expression.Named(ElementAST.CallArgument).Repeat(0).SeparatedBy(comma); var call = expression.Named(ElementAST.Callee) .Then(ws, Terminals.Set('('), ws, arguments.Named(ElementAST.CallArguments), ws, Terminals.Set(')')); expression.Inner = new AlternativeParser( number.Named(ElementAST.NumberExpression), identifier.Named(ElementAST.VariableExpression), subExpression.Named(ElementAST.SubExpression), call.Named(ElementAST.CallExpression) ); // Functions var portType = ws.Then(Terminals.Literal(":"), ws, identifier.Named(ElementAST.PortType)).Optional(); var port = identifier.Named(ElementAST.PortName).Then(portType).Named(ElementAST.Port); var ports = port.Repeat(0).SeparatedBy(comma); var fnInputs = Terminals.Set('(') .Then(ws, ports.Named(ElementAST.FunctionInputs), ws, Terminals.Set(')')).Optional(); var fnOutputs = Terminals.Literal("->").Then(ws, ports.Named(ElementAST.FunctionOutputs)).Or(portType); var fnSignature = identifier.Named(ElementAST.FunctionName).Then(ws, fnInputs, ws, fnOutputs, ws); // Statements var statement = new UnaryParser(); var body = Terminals.Set('{').Then(ws, statement.Then(ws).Repeat(0).Named(ElementAST.FunctionBody), ws, Terminals.Set('}')); var assign = Terminals.Set('=').Then(ws, expression.Named(ElementAST.AssignmentStatement), ws, Terminals.Set(';')); statement.Inner = fnSignature .Then(body.Or(assign).Or(Terminals.Set(';').Named(ElementAST.TypeStatement))) .Named(ElementAST.Statement); var start = ws.Then(statement, ws).Repeat(0); start.Until = Terminals.End; return(new Grammar(start)); }
public EbnfGrammar() : base("ebnf") { DefineCommonNonTerminals = true; GenerateSpecialSequences(); // terminals AlternativeParser terminal_string = ("'" & (+Terminals.AnyChar).Until("'").WithName("value") & "'") | ("\"" & (+Terminals.AnyChar).Until("\"").WithName("value") & "\"") | ("’" & (+Terminals.AnyChar).Until("’").WithName("value") & "’"); SequenceParser special_sequence = ("?" & (+Terminals.AnyChar).Until("?").WithName("name") & "?").WithName("special sequence"); SequenceParser meta_identifier_terminal = Terminals.Letter & -(Terminals.LetterOrDigit | '_'); var integer = new NumberParser(); Parser old = DefaultSeparator; DefaultSeparator = cws; // nonterminals var definition_list = new UnaryParser("definition list"); var single_definition = new UnaryParser("single definition"); var term = new UnaryParser("term"); var primary = new UnaryParser("primary"); var exception = new UnaryParser("exception"); var factor = new UnaryParser("factor"); var meta_identifier = new UnaryParser("meta identifier"); var syntax_rule = new UnaryParser("syntax rule"); var rule_equals = new UnaryParser("equals"); SequenceParser optional_sequence = ("[" & definition_list & "]").WithName("optional sequence"); SequenceParser repeated_sequence = ("{" & definition_list & "}").WithName("repeated sequence"); SequenceParser grouped_sequence = ("(" & definition_list & ")").WithName("grouped sequence"); // rules meta_identifier.Inner = (+meta_identifier_terminal).SeparatedBy(ws); primary.Inner = optional_sequence | repeated_sequence | special_sequence | grouped_sequence | meta_identifier | terminal_string.Named("terminal string") | null; factor.Inner = ~(integer.Named("integer") & "*") & primary; term.Inner = factor & ~("-" & exception); exception.Inner = term; single_definition.Inner = term & -("," & term); definition_list.Inner = single_definition & -("|" & single_definition); rule_equals.Inner = (Parser)"=" | ":="; syntax_rule.Inner = meta_identifier & rule_equals & definition_list & ";"; Inner = cws & +syntax_rule & cws; DefaultSeparator = old; AttachEvents(); }
public void TestInt32Values() { var sample = "123,+123,-123"; var grammar = new Grammar(); var num = new NumberParser { AllowSign = true, AllowDecimal = true, ValueType = typeof(int) }; grammar.Inner = (+num.Named("str")).SeparatedBy(","); var match = grammar.Match(sample); Assert.True(match.Success, match.ErrorMessage); Assert.Equal(new Int32[] { 123, 123, -123 }, match.Find("str").Select(m => (int)m.Value)); }
public void TestExponent() { var sample = "123E-02,123E+10,123.4567E+5,1234E2"; var grammar = new Grammar(); var num = new NumberParser { AllowDecimal = true, AllowExponent = true }; grammar.Inner = (+num.Named("str")).SeparatedBy(","); var match = grammar.Match(sample); Assert.True(match.Success, match.ErrorMessage); Assert.Equal(new object[] { 123E-2M, 123E+10M, 123.4567E+5M, 1234E+2M }, match.Find("str").Select(m => num.GetValue(m))); }
public void TestSign() { var sample = "123.4567,+123.4567,-123.4567"; var grammar = new Grammar(); var num = new NumberParser { AllowSign = true, AllowDecimal = true }; grammar.Inner = (+num.Named("str")).SeparatedBy(","); var match = grammar.Match(sample); Assert.True(match.Success, match.ErrorMessage); Assert.Equal(new object[] { 123.4567M, 123.4567M, -123.4567M }, match.Find("str").Select(m => num.GetValue(m))); }
public void TestDecimalValues() { var sample = "123.4567,+123.4567,-123.4567"; var grammar = new Grammar(); var num = new NumberParser { AllowSign = true, AllowDecimal = true, ValueType = typeof(decimal) }; grammar.Inner = (+num.Named("str")).SeparatedBy(","); var match = grammar.Match(sample); Assert.IsTrue(match.Success, match.ErrorMessage); CollectionAssert.AreEquivalent(new Decimal[] { 123.4567M, 123.4567M, -123.4567M }, match.Find("str").Select(m => (decimal)m.Value)); }