Пример #1
0
		void SetLine()
		{
			if (line != null)
				lineSeq = line & new RepeatParser().Until(Terminals.Eol);
			else
				lineSeq = null;
		}
Пример #2
0
		void SetBlock()
		{
			if (start != null && end != null)
				blockSeq = start & new RepeatParser().Until(end, true);
			else
				blockSeq = null;
		}
Пример #3
0
		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;
			}
		}
Пример #4
0
		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();
		}
Пример #5
0
		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;
			};
		}
Пример #6
0
		protected SequenceParser(SequenceParser other, ParserCloneArgs chain)
			: base(other, chain)
		{
			Separator = chain.Clone(other.Separator);
		}