public JsonGrammar() : base("json") { EnableMatchEvents = false; CaseSensitive = true; // terminals var jstring = new StringParser { AllowEscapeCharacters = true, Name = "string" }; var jnumber = new NumberParser { AllowExponent = true, AllowSign = true, AllowDecimal = true, Name = "number" }; var jboolean = new BooleanTerminal { Name = "bool", TrueValues = new string[] { "true" }, FalseValues = new string[] { "false" }, CaseSensitive = false }; var jname = new StringParser { AllowEscapeCharacters = true, Name = "name" }; var jnull = new LiteralTerminal { Value = "null", Name = "null", CaseSensitive = false }; var ws = new RepeatCharTerminal(char.IsWhiteSpace); var commaDelimiter = new RepeatCharTerminal(new RepeatCharItem(char.IsWhiteSpace), ',', new RepeatCharItem(char.IsWhiteSpace)); // nonterminals (things we're interested in getting back) var jobject = new SequenceParser { Name = "object" }; var jarray = new SequenceParser { Name = "array" }; var jprop = new SequenceParser { Name = "property" }; // rules var jvalue = jstring | jnumber | jobject | jarray | jboolean | jnull; jobject.Add("{", (-jprop).SeparatedBy(commaDelimiter), "}"); jprop.Add(jname, ":", jvalue); jarray.Add("[", (-jvalue).SeparatedBy(commaDelimiter), "]"); // separate sequence and repeating parsers by whitespace jvalue.SeparateChildrenBy(ws, false); // allow whitespace before and after the initial object or array this.Inner = ws & (jobject | jarray) & ws; }
protected NumberParser(NumberParser other, ParserCloneArgs chain) : base(other, chain) { AllowSign = other.AllowSign; AllowExponent = other.AllowExponent; DecimalSeparator = other.DecimalSeparator; ValueType = other.ValueType; }
public EbnfGrammar() : base("ebnf") { DefineCommonNonTerminals = true; GenerateSpecialSequences(); // terminals var terminal_string = ("'" & (+Terminals.AnyChar).Until("'").WithName("value") & "'") | ("\"" & (+Terminals.AnyChar).Until("\"").WithName("value") & "\"") | ("’" & (+Terminals.AnyChar).Until("’").WithName("value") & "’"); var special_sequence = ("?" & (+Terminals.AnyChar).Until("?").WithName("name") & "?").WithName("special sequence"); var meta_identifier_terminal = Terminals.Letter & -(Terminals.LetterOrDigit | '_'); var integer = new NumberParser(); var old = Parser.DefaultSeparator; Parser.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"); var optional_sequence = ("[" & definition_list & "]").WithName("optional sequence"); var repeated_sequence = ("{" & definition_list & "}").WithName("repeated sequence"); var 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 & ";"; this.Inner = cws & +syntax_rule & cws; Parser.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.IsTrue(match.Success, match.ErrorMessage); CollectionAssert.AreEquivalent(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.IsTrue(match.Success, match.ErrorMessage); CollectionAssert.AreEquivalent(new Decimal[] { 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.IsTrue(match.Success, match.ErrorMessage); CollectionAssert.AreEquivalent(new Decimal[] { 123.4567M, 123.4567M, -123.4567M }, match.Find("str").Select(m => num.GetValue(m))); }
public CarGrammar():base("procedure") { var writables = ((Parser)"[brake]" | "[throttle]").Named("telemetry"); var readables = (writables | "[velocity]").Named("telemetry"); var number = new Eto.Parse.Parsers.NumberParser { AllowDecimal = true, AllowExponent = true, AllowSign = false }; // (it sure would be nice to specify a range on that number) // - please file an enhancement request on github (; var writer = ((Parser)"set").Named("action") & WS & writables & WS & "at" & WS & number.Named("value") & ~WS & ~(Parser)"%"; var op = ((Parser)"<" | ">" | "=").Named("operator"); var unit = ((Parser)"m/s" | "kph" | "mph").Named("unit"); var reader = ((Parser)"until").Named("action") & WS & readables & WS & op & ~WS & ~unit; var row = (~(reader | writer) & Terminals.Eol).Named("row"); Inner = +row & ~row; // the optional at the end will never match, since it will be consumed by +row. // however, it will give us the expected results for the next line. }
public CarGrammar() : base("procedure") { var writables = ((Parser)"[brake]" | "[throttle]").Named("telemetry"); var readables = (writables | "[velocity]").Named("telemetry"); var number = new Eto.Parse.Parsers.NumberParser { AllowDecimal = true, AllowExponent = true, AllowSign = false }; // (it sure would be nice to specify a range on that number) // - please file an enhancement request on github (; var writer = ((Parser)"set").Named("action") & WS & writables & WS & "at" & WS & number.Named("value") & ~WS & ~(Parser)"%"; var op = ((Parser)"<" | ">" | "=").Named("operator"); var unit = ((Parser)"m/s" | "kph" | "mph").Named("unit"); var reader = ((Parser)"until").Named("action") & WS & readables & WS & op & ~WS & ~unit; var row = (~(reader | writer) & Terminals.Eol).Named("row"); Inner = +row & ~row; // the optional at the end will never match, since it will be consumed by +row. // however, it will give us the expected results for the next line. }
public EbnfGrammar(EbnfStyle style) : base("ebnf") { Style = style; DefineCommonNonTerminals = true; GenerateSpecialSequences(); // terminals var comment = style.HasFlag(EbnfStyle.BracketComments) ? new GroupParser("(*", "*)") : new GroupParser("/*", "*/"); var ows = -(Terminals.WhiteSpace | comment); var rws = +(Terminals.WhiteSpace | comment); var hex_character = ("#x" & +Terminals.HexDigit); var character = (("\\" & Terminals.AnyChar) | hex_character | Terminals.AnyChar.Except("]")).WithName("character"); var character_range = (character & "-" & character).WithName("character range"); var character_set = ("[" & ~(Parser)"^" & +(character_range | character) & "]").WithName("character set"); var terminal_string = new StringParser { QuoteCharacters = new [] { '\"', '\'', '’' }, Name = "terminal string" }; var special_sequence = ("?" & (+Terminals.AnyChar).Until("?").WithName("name") & "?").WithName("special sequence"); var meta_identifier_terminal = Terminals.Letter & -(Terminals.LetterOrDigit | '_'); var integer = new NumberParser().WithName("integer"); // nonterminals var definition_list = new RepeatParser(0).WithName("definition list"); var single_definition = new RepeatParser(1).WithName("single definition"); var term = new SequenceParser().WithName("term"); var primary = new AlternativeParser().WithName("primary"); var exception = new UnaryParser("exception"); var factor = new SequenceParser().WithName("factor"); var meta_identifier = new RepeatParser(1).WithName("meta identifier"); var syntax_rule = new SequenceParser().WithName("syntax rule"); var rule_equals = new AlternativeParser().WithName("equals"); Parser meta_reference = meta_identifier; Parser grouped_sequence = ("(" & ows & definition_list & ows & ")").WithName("grouped sequence"); if (style.HasFlag(EbnfStyle.SquareBracketAsOptional)) { primary.Add(("[" & ows & definition_list & ows & "]").WithName("optional sequence")); } if (!style.HasFlag(EbnfStyle.CardinalityFlags)) { var repeated_sequence = ("{" & ows & definition_list & ows & "}").WithName("repeated sequence"); primary.Add(repeated_sequence); } // rules meta_identifier.Inner = meta_identifier_terminal; meta_identifier.Separator = +(Terminals.SingleLineWhiteSpace); if (!style.HasFlag(EbnfStyle.CommaSeparator)) { // w3c identifiers must be a single word meta_identifier.Maximum = 1; meta_reference = meta_reference.NotFollowedBy(ows & rule_equals); } primary.Add(grouped_sequence, meta_reference, terminal_string, special_sequence); if (style.HasFlag(EbnfStyle.CharacterSets) && !style.HasFlag(EbnfStyle.SquareBracketAsOptional)) { // w3c supports character sets primary.Add(hex_character.Named("hex character")); primary.Add(character_set); } if (style.HasFlag(EbnfStyle.NumericCardinality)) factor.Add(~(integer & ows & "*" & ows)); factor.Add(primary); if (style.HasFlag(EbnfStyle.CardinalityFlags)) { // w3c defines cardinality at the end of a factor var flags = style.HasFlag(EbnfStyle.SquareBracketAsOptional) ? "*+" : "?*+"; factor.Add(~(ows & Terminals.Set(flags).WithName("cardinality"))); } term.Add(factor, ~(ows & "-" & ows & exception)); exception.Inner = term; single_definition.Inner = term; single_definition.Separator = style.HasFlag(EbnfStyle.CommaSeparator) ? (Parser)(ows & "," & ows) : ows; definition_list.Inner = single_definition; definition_list.Separator = ows & "|" & ows; rule_equals.Add(style.HasFlag(EbnfStyle.DoubleColonEquals) ? "::=" : "=", ":="); syntax_rule.Add(meta_identifier, ows, rule_equals, ows, definition_list); if (style.HasFlag(EbnfStyle.SemicolonTerminator)) syntax_rule.Add(ows, ";"); // iso rules are terminated by a semicolon var syntax_rules = +syntax_rule; syntax_rules.Separator = style.HasFlag(EbnfStyle.SemicolonTerminator) ? ows : rws; Inner = ows & syntax_rules & ows; AttachEvents(); }
public void TestErrorAtEnd() { var sample = "Num:"; var grammar = new Grammar(); var num = new NumberParser { }; grammar.Inner = "Num:" & num.WithName("num"); var match = grammar.Match(sample); Assert.IsFalse(match.Success, match.ErrorMessage); Assert.AreEqual(sample.Length, match.ErrorIndex, "Error index should be at the end"); Assert.AreEqual(sample.Length, match.ChildErrorIndex, "Child error index should be at the end"); }