static EbnfExpression _ParseExpression(EbnfDocument doc, ParseContext pc) { EbnfExpression current = null; EbnfExpression e; long position; int line; int column; pc.TrySkipCCommentsAndWhiteSpace(); position = pc.Position; line = pc.Line; column = pc.Column; while (-1 != pc.Current && ']' != pc.Current && ')' != pc.Current && '}' != pc.Current && ';' != pc.Current) { pc.TrySkipCCommentsAndWhiteSpace(); position = pc.Position; line = pc.Line; column = pc.Column; switch (pc.Current) { case '|': pc.Advance(); current = new EbnfOrExpression(current, _ParseExpression(doc, pc)); current.SetLocationInfo(line, column, position); break; case '(': pc.Advance(); e = _ParseExpression(doc, pc); current.SetLocationInfo(line, column, position); pc.Expecting(')'); pc.Advance(); e.SetLocationInfo(line, column, position); if (null == current) { current = e; } else { current = new EbnfConcatExpression(current, e); } break; case '[': pc.Advance(); e = new EbnfOptionalExpression(_ParseExpression(doc, pc)); e.SetLocationInfo(line, column, position); pc.TrySkipCCommentsAndWhiteSpace(); pc.Expecting(']'); pc.Advance(); if (null == current) { current = e; } else { current = new EbnfConcatExpression(current, e); } break; case '{': pc.Advance(); e = new EbnfRepeatExpression(_ParseExpression(doc, pc)); e.SetLocationInfo(line, column, position); pc.TrySkipCCommentsAndWhiteSpace(); pc.Expecting('}'); pc.Advance(); if ('+' == pc.Current) { pc.Advance(); ((EbnfRepeatExpression)e).IsOptional = false; } if (null == current) { current = e; } else { current = new EbnfConcatExpression(current, e); } break; case '\"': e = new EbnfLiteralExpression(pc.ParseJsonString()); if (null == current) { current = e; } else { current = new EbnfConcatExpression(current, e); } e.SetLocationInfo(line, column, position); break; case '\'': pc.Advance(); pc.ClearCapture(); pc.TryReadUntil('\'', '\\', false); pc.Expecting('\''); pc.Advance(); e = new EbnfRegexExpression(pc.Capture); if (null == current) { current = e; } else { current = new EbnfConcatExpression(current, e); } e.SetLocationInfo(line, column, position); break; case ';': case ']': case ')': case '}': return(current); default: e = new EbnfRefExpression(_ParseIdentifier(pc)); if (null == current) { current = e; } else { current = new EbnfConcatExpression(current, e); } e.SetLocationInfo(line, column, position); break; } } pc.TrySkipCCommentsAndWhiteSpace(); return(current); }
static IList <EbnfMessage> _TryParseExpression(ParseNode pn, out EbnfExpression result) { result = null; Debug.Assert(EbnfParser.expression == pn.SymbolId, "Not positioned on expression"); var msgs = new List <EbnfMessage>(); if (1 == pn.Children.Count) { var c = pn.Children[0]; if (EbnfParser.symbol == c.SymbolId) { ParseContext pc; var cc = c.Children[0]; //TODO: parse the regular expressions and literals to make sure they're valid. switch (cc.SymbolId) { case EbnfParser.identifier: result = new EbnfRefExpression(cc.Value); return(msgs); case EbnfParser.regex: pc = ParseContext.Create(cc.Value); pc.EnsureStarted(); pc.Advance(); pc.TryReadUntil('\'', '\\', false); result = new EbnfRegexExpression(pc.GetCapture()); return(msgs); case EbnfParser.literal: pc = ParseContext.Create(cc.Value); pc.EnsureStarted(); pc.Advance(); pc.TryReadUntil('\"', '\\', false); result = new EbnfLiteralExpression(pc.GetCapture()); return(msgs); case EbnfParser.lbrace: msgs.AddRange(_TryParseExpressions(c, 1, out result)); result = new EbnfRepeatExpression(result); if (EbnfParser.rbracePlus == c.Children[c.Children.Count - 1].SymbolId) { ((EbnfRepeatExpression)result).IsOptional = false; } return(msgs); case EbnfParser.lbracket: msgs.AddRange(_TryParseExpressions(c, 1, out result)); result = new EbnfOptionalExpression(result); return(msgs); case EbnfParser.lparen: msgs.AddRange(_TryParseExpressions(c, 1, out result)); return(msgs); default: break; } } } return(msgs); }