public void Add(BnfRule rule) { if (rules.ContainsKey(rule) == false) { rules.Add(rule, rule); } }
public void Add(BnfRule rule) { rules.Add(rule); var nt = rule.Nonterminal; if (NonTerminals.ContainsKey(nt.Name) == false) { NonTerminals.Add(nt.Name, nt); } nt.Add(rule); }
BnfGrammar Convert(EbnfGrammar EG) { Bnf = new BnfGrammar(); Footprint = new OperationFootprintGroup <EbnfGrammar, BnfGrammar> (EG, Bnf); foreach (var er in EG.Rules) { BnfRule br = Convert(er); } Footprint.Parts = ops.ToArray(); return(Bnf); }
private static IParser <AstNode> CreateParser(BnfRule rule, Dictionary <string, IParser <AstNode> > parsers) => CreateParser(rule.Symbol.Name, rule.Expression, parsers);
public BnfRule NextRule() { var streamPosition = (long)0; var symbol = ""; EatWhitespace(); if (EatSymbol(out symbol)) { if (symbol == "EOF") { // This is the marker for the end of the BNF data. We don't care what else there is, eat it ALL. Reader.ReadToEnd(); return(null); } EatWhitespace(); if (Reader.Peek() == -1) { return(null); } if ('=' != Reader.Read()) { throw new InvalidBnfFormatException(Reader, 1, "BNF parser expected '='."); } var production = ('=' == Reader.Peek()); if (production) { if ('=' != Reader.Read()) { throw new InvalidBnfFormatException(Reader, 2, "BNF parser expected '==>'."); } if ('>' != Reader.Read()) { throw new InvalidBnfFormatException(Reader, 3, "BNF parser expected '==>'."); } } var stackEx = new Stack <Operator>(); var stackOp = new Stack <char>(); Func <int> stackProcessOp = () => { var op = stackOp.Pop(); switch (op) { case ']': if (stackEx.Count < 1) { throw new InvalidBnfFormatException(Reader, 0, "BNF parser found unmatched '['."); } var right = stackEx.Pop(); stackEx.Push(new OptionalOperator(right)); break; case '}': if (stackEx.Count < 1) { throw new InvalidBnfFormatException(Reader, 0, "BNF parser found unmatched '{'."); } right = stackEx.Pop(); stackEx.Push(new RepeatOperator(right)); break; case '|': if (stackEx.Count < 2) { throw new InvalidBnfFormatException(Reader, 0, "BNF parser found unbalanced '|'."); } right = stackEx.Pop(); var left = stackEx.Pop(); stackEx.Push(new LogicalOrOperator(left, right)); break; case ' ': if (stackEx.Count < 2) { throw new InvalidBnfFormatException(Reader, 0, "BNF parser found unbalanced ' '."); } right = stackEx.Pop(); left = stackEx.Pop(); stackEx.Push(new LogicalAndOperator(left, right)); break; } return(0); }; while (true) { EatWhitespace(); while (new char[] { '[', '{' }.Contains <char>((char)Reader.Peek())) { if ('[' == Reader.Peek()) { Reader.Read(); stackOp.Push(']'); } else if ('{' == Reader.Peek()) { Reader.Read(); stackOp.Push('}'); } EatWhitespace(); } Operator ex = null; EatWhitespace(); if ('"' == Reader.Peek()) { var value = ""; streamPosition = Reader.BaseStream.Position; if (!EatString(out value)) { throw new InvalidBnfFormatException(Reader, Reader.BaseStream.Position - streamPosition, "BNF parser expected string."); } ex = new StringOperator(value); } else if ('.' == Reader.Peek()) { Reader.Read(); if ((stackOp.Count > 0) && (' ' == stackOp.Peek())) { stackOp.Pop(); } while (stackOp.Count > 0) { stackProcessOp(); } if (stackEx.Count > 1) { throw new InvalidBnfFormatException(Reader, 1, "BNF parser expected ']' and/or '}' but found '.'."); } Reader.ReadLine(); break; } else { if (':' != Reader.Read()) { throw new InvalidBnfFormatException(Reader, 1, "BNF parser expected ':'."); } var token = ""; streamPosition = Reader.BaseStream.Position; if (!EatSymbol(out token)) { throw new InvalidBnfFormatException(Reader, Reader.BaseStream.Position - streamPosition, "BNF parser expected token."); } ex = new ReferenceOperator(token); EatWhitespace(); if (',' == Reader.Peek()) { Reader.Read(); var tokenName = ""; EatWhitespace(); streamPosition = Reader.BaseStream.Position; if (!EatSymbol(out tokenName)) { throw new InvalidBnfFormatException(Reader, Reader.BaseStream.Position - streamPosition, "BNF parser expected token name."); } ex = new NamedReferenceOperator(tokenName, token); } } Debug.Assert(ex != null, "BNF parsed expression is null!"); stackEx.Push(ex); EatWhitespace(); while (new char[] { ']', '}' }.Contains <char>((char)Reader.Peek())) { var endOp = (char)Reader.Read(); while ((stackOp.Count > 0) && (stackOp.Peek() != endOp)) { stackProcessOp(); } if (stackOp.Count == 0) { throw new InvalidBnfFormatException(Reader, 0, "BNF parser found unmatched '" + endOp + "'."); } stackProcessOp(); EatWhitespace(); } EatWhitespace(); if ('|' == Reader.Peek()) { Reader.Read(); stackOp.Push('|'); } else { while ((stackOp.Count > 0) && ('|' == stackOp.Peek())) { stackProcessOp(); } stackOp.Push(' '); } } if (stackEx.Count == 0) { stackEx.Push(null); } BnfRule rule = null; if (production) { rule = new BnfProduction(File.Bnf, new ReferenceOperator(symbol), stackEx.Pop()); } else { rule = new BnfDefinition(File.Bnf, new ReferenceOperator(symbol), stackEx.Pop()); } return(rule); } return(null); }
BnfRule Convert(EbnfRule E) { BnfRule B = null; if (ruleConversions.ContainsKey(E)) { var footprint = ruleConversions [E]; B = footprint.After; } else { BnfNonterminal bn = Convert(E.Nonterminal); List <ISymbol> terms = new List <ISymbol> (); var p = E.RightPart; if (p is EbnfEnumeration) { foreach (var pp in ((EbnfEnumeration)p).Parts) { if (pp is EbnfNonterminal) { var name = (pp as EbnfNonterminal).Name; var node = Bnf.AddNonterminal(name); terms.Add(node); } else { if (pp is EbnfTerminal) { var node = (TerminalSymbol)pp; terms.Add(node); } else { throw new ApplicationException(); } } } } else { if (p is EbnfNonterminal) { var name = (p as EbnfNonterminal).Name; var node = Bnf.AddNonterminal(name); terms.Add(node); } else { if (p is EbnfTerminal) { var node = (TerminalSymbol)p; terms.Add(node); } else { throw new ApplicationException(); } } } B = new BnfRule(bn, terms.ToArray()); bn.Add(B); var footprint = new RuleConversionFootprint(E, B); ruleConversions.Add(E, footprint); ops.Add(footprint); } return(B); }