void SetLine() { if (line != null) lineSeq = line & new RepeatParser().Until(Terminals.Eol); else lineSeq = null; }
void SetBlock() { if (start != null && end != null) blockSeq = start & new RepeatParser().Until(end, true); else blockSeq = null; }
Parser SingleDefinition(Match match, bool isTerminal) { var terms = match.Find("term").ToArray(); if (terms.Length == 1) return Term(terms[0], isTerminal); else { var sequence = new SequenceParser(terms.Select(r => Term(r, isTerminal))); if (!isTerminal) sequence.Separator = separator; return sequence; } }
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(); }
void AttachEvents() { ruleName.Matched += m => { Parser parser; var name = m["name"].Text; if (!parserLookup.TryGetValue(name, out parser) && !baseLookup.TryGetValue(name, out parser)) { parser = Terminals.LetterOrDigit.Repeat(); parser.Name = name; } m.Tag = parser; }; literal.Matched += m => m.Tag = new LiteralTerminal(m["value"].Text); optionalRule.Matched += m => m.Tag = new OptionalParser((Parser)m["parser"].Tag); repeatRule.Matched += m => m.Tag = new RepeatParser((Parser)m["parser"].Tag, 0) { Separator = sws }; list.Matched += m => { if (m.Matches.Count > 1) { var parser = new SequenceParser(); foreach (var child in m.Matches) { if (child.Parser.Name == "ws") parser.Items.Add(sws); else if (child.Parser.Name == "term") parser.Items.Add((Parser)child["parser"].Tag); } m.Tag = parser; } else { m.Tag = m["term"]["parser"].Tag; } }; listRepeat.Matched += m => { // collapse alternatives to one alternative parser var parser = (Parser)m["expression"]["parser"].Tag; var alt = parser as AlternativeParser ?? new AlternativeParser(parser); alt.Items.Insert(0, (Parser)m["list"]["parser"].Tag); m.Tag = alt; }; rule.Matched += m => { var parser = (UnaryParser)m.Tag; parser.Inner = (Parser)m["parser"].Tag; m.Tag = parser; }; rule.PreMatch += m => { var name = m["ruleName"]["name"].Text; Parser parser; if (name == startParserName) parser = new Grammar(name); else parser = new UnaryParser(name); m.Tag = parser; parserLookup[parser.Name] = parser; }; }
protected SequenceParser(SequenceParser other, ParserCloneArgs chain) : base(other, chain) { Separator = chain.Clone(other.Separator); }