static void _VisitUnreferenced(XbnfDocument doc, XbnfExpression expr, HashSet <string> result) { var r = expr as XbnfRefExpression; if (null != r) { if (!doc.Productions.Contains(r.Symbol)) { result.Add(r.Symbol); } return; } var u = expr as XbnfUnaryExpression; if (null != u) { _VisitUnreferenced(doc, u.Expression, result); return; } var b = expr as XbnfBinaryExpression; if (null != b) { _VisitUnreferenced(doc, b.Left, result); _VisitUnreferenced(doc, b.Right, result); return; } }
static XbnfExpression _FindNonTerminal(XbnfExpression expr) { var re = expr as XbnfRefExpression; if (null != re) { return(re); } var bo = expr as XbnfBinaryExpression; if (bo != null) { var res = _FindNonTerminal(bo.Left); if (null != res) { return(res); } res = _FindNonTerminal(bo.Right); if (null != res) { return(res); } } var ue = expr as XbnfUnaryExpression; if (null != ue) { return(_FindNonTerminal(ue.Expression)); } return(null); }
static void _ParseIncludes(LexContext pc, IList <string> result) { pc.TrySkipCCommentsAndWhiteSpace(); while ('@' == pc.Current) { pc.Advance(); var s = XbnfNode.ParseIdentifier(pc); if ("include" == s) { pc.TrySkipCCommentsAndWhiteSpace(); var lit = XbnfExpression.Parse(pc) as XbnfLiteralExpression; if (!result.Contains(lit.Value)) { result.Add(lit.Value); } pc.TryReadCCommentsAndWhitespace(); pc.Advance(); pc.TryReadCCommentsAndWhitespace(); } else { while (-1 != pc.Current && ';' != pc.Current) { pc.Advance(); } if (';' == pc.Current) { pc.Advance(); } pc.TrySkipCCommentsAndWhiteSpace(); } } }
static XbnfImport _ParseIncludePart(XbnfDocument doc, LexContext pc) { pc.TrySkipCCommentsAndWhiteSpace(); var l = pc.Line; var c = pc.Column; var p = pc.Position; pc.Expecting('\"'); // borrow the parsing from XbnfExpression for this. var le = XbnfExpression.Parse(pc) as XbnfLiteralExpression; if (null == le) { throw new ExpectingException("Expecting string literal include argument", l, c, p, pc.FileOrUrl, "string literal"); } var res = le.Value; pc.TrySkipCCommentsAndWhiteSpace(); pc.Expecting(';'); pc.Advance(); var cmp = res.ToLowerInvariant(); var result = new XbnfImport(); if (-1 < cmp.IndexOf("://")) { result.Document = XbnfDocument.ReadFromUrl(cmp); } else { string mdir = null; if (null != doc && !string.IsNullOrEmpty(doc.FileOrUrl)) { mdir = doc.FileOrUrl; if (!Path.IsPathRooted(mdir)) { mdir = Path.GetFullPath(mdir); } mdir = Path.GetDirectoryName(mdir); } var path = res; if (!Path.IsPathRooted(path)) { if (null != mdir) { path = Path.Combine(mdir, path); } else { path = Path.GetFullPath(path); } } result.Document = XbnfDocument.ReadFrom(path); } result.SetLocation(l, c, p); return(result); }
public XbnfProduction GetProductionForExpression(XbnfExpression expr) { for (int ic = Productions.Count, i = 0; i < ic; ++i) { var prod = Productions[i]; if (Equals(expr, prod.Expression)) { return(prod); } } return(null); }
public XbnfConcatExpression(XbnfExpression left, params XbnfExpression[] right) { Left = left; for (int i = 0; i < right.Length; i++) { var r = right[i]; if (null == Right) { Right = r; } var c = new XbnfConcatExpression(); c.Left = Left; c.Right = Right; Right = null; Left = c; } }
public XbnfOrExpression(XbnfExpression left, params XbnfExpression[] right) { Right = null; Left = left; for (int i = 0; i < right.Length; i++) { if (null == Right) { Right = right[i]; } else { var or = new XbnfOrExpression(); or.Left = Left; or.Right = Right; Left = or; Right = right[i]; } } }
static void _VisitFetchTerminals(XbnfExpression expr, HashSet <XbnfExpression> terms) { var l = expr as XbnfLiteralExpression; if (null != l) { if (!terms.Contains(l)) { terms.Add(l); } return; } var r = expr as XbnfRegexExpression; if (null != r) { if (!terms.Contains(r)) { terms.Add(r); } return; } var u = expr as XbnfUnaryExpression; if (null != u) { _VisitFetchTerminals(u.Expression, terms); return; } var b = expr as XbnfBinaryExpression; if (null != b) { _VisitFetchTerminals(b.Left, terms); _VisitFetchTerminals(b.Right, terms); return; } }
public XbnfOptionalExpression(XbnfExpression expression) { Expression = expression; }
static IList <IList <string> > _GetDysjunctions( XbnfDocument d, ICollection <string> syms, IDictionary <XbnfExpression, string> tmap, IDictionary <string, XbnfAttributeList> attrs, IList <KeyValuePair <string, IList <string> > > rules, XbnfProduction p, XbnfExpression e ) { var le = e as XbnfLiteralExpression; if (null != le) { var res = new List <IList <string> >(); var l = new List <string>(); l.Add(tmap[le]); res.Add(l); return(res); } var rxe = e as XbnfRegexExpression; if (null != rxe) { var res = new List <IList <string> >(); var l = new List <string>(); l.Add(tmap[rxe]); res.Add(l); return(res); } var rfe = e as XbnfRefExpression; if (null != rfe) { var res = new List <IList <string> >(); var l = new List <string>(); l.Add(rfe.Symbol); res.Add(l); return(res); } var ce = e as XbnfConcatExpression; if (null != ce) { return(_GetDysConcat(d, syms, tmap, attrs, rules, p, ce)); } var oe = e as XbnfOrExpression; if (null != oe) { return(_GetDysOr(d, syms, tmap, attrs, rules, p, oe)); } var ope = e as XbnfOptionalExpression; if (null != ope) { return(_GetDysOptional(d, syms, tmap, attrs, rules, p, ope)); } var re = e as XbnfRepeatExpression; if (null != re) { return(_GetDysRepeat(d, syms, tmap, attrs, rules, p, re)); } throw new NotSupportedException("The specified expression type is not supported."); }
static string _ToRegex(XbnfDocument d, XbnfExpression e, bool first, bool gplex = false) { var le = e as XbnfLiteralExpression; if (null != le) { var s = _EscapeLiteral(XbnfNode.Escape(le.Value), !gplex); if (gplex) { s = string.Concat("\"", s, "\""); } return(s); } var rxe = e as XbnfRegexExpression; if (null != rxe) { var r = rxe.Value; if (gplex) { r = r.Replace("\"", "\\\""); } return(first ? r : string.Concat("(", r, ")")); } var rfe = e as XbnfRefExpression; if (null != rfe) { _ToRegex(d, d.Productions[rfe.Symbol].Expression, first, gplex); } var re = e as XbnfRepeatExpression; if (null != re) { if (re.IsOptional) { return(string.Concat("(", _ToRegex(d, re.Expression, true, gplex), ")*")); } else { return(string.Concat("(", _ToRegex(d, re.Expression, true, gplex), ")+")); } } var oe = e as XbnfOrExpression; if (null != oe) { if (!first) { return(string.Concat("(", _ToRegex(d, oe.Left, false, gplex), "|", _ToRegex(d, oe.Right, false, gplex), ")")); } else { return(string.Concat(_ToRegex(d, oe.Left, false, gplex), "|", _ToRegex(d, oe.Right, false, gplex))); } } var oc = e as XbnfConcatExpression; if (null != oc) { return(string.Concat(_ToRegex(d, oc.Left, false, gplex), _ToRegex(d, oc.Right, false, gplex))); } var ope = e as XbnfOptionalExpression; if (null != ope) { return(string.Concat("(", _ToRegex(d, ope.Expression, true, gplex), ")?")); } return(""); }
public static string ToRolexSpec(XbnfGenerationInfo genInfo) { var termStart = 0; var stbl = GetSymbolTable(genInfo, out termStart); var stbli = new List <KeyValuePair <string, int> >(); var id = 0; // assign temp ids foreach (var se in stbl) { if (id >= termStart) { stbli.Add(new KeyValuePair <string, int>(se, id)); } ++id; } stbli.Sort(new _TermPriorityComparer(genInfo.Cfg)); var sb = new StringBuilder(); for (int ic = stbli.Count, i = 0; i < ic; ++i) { var sym = stbli[i].Key; if ("#EOS" == sym || "#ERROR" == sym) { continue; } XbnfExpression e = null; foreach (var k in genInfo.TerminalMap) { if (k.Value == sym) { e = k.Key; break; } } //var te = genInfo.TerminalMap[i]; //var sym = te.Value; //var id = stbli.IndexOf(new KeyValuePair<string, XbnfDocument>(sym, d)); id = stbli[i].Value; if (-1 < id) // some terminals might never be used. { // implicit terminals do not have productions and therefore attributes var pi = genInfo.Xbnf.Productions.IndexOf(sym); if (-1 < pi) { // explicit var prod = genInfo.Xbnf.Productions[pi]; sb.Append(sym); sb.Append("<id="); sb.Append(id); foreach (var attr in prod.Attributes) { sb.Append(", "); sb.Append(attr.ToString()); } sb.Append(">"); } else { // implicit sb.Append(sym); sb.Append(string.Concat("<id=", id, ">")); } sb.AppendLine(string.Concat("= \'", _ToRegex(genInfo.Xbnf, e, true), "\'")); } } return(sb.ToString()); }
public XbnfProduction(string name, XbnfExpression expression = null) { Name = name; Expression = expression; }
void _ValidateExpression(XbnfExpression expr, IDictionary <string, int> refCounts, IList <XbnfMessage> messages) { var l = expr as XbnfLiteralExpression; if (null != l) { string id = null; for (int ic = Productions.Count, i = 0; i < ic; ++i) { var ll = Productions[i].Expression as XbnfLiteralExpression; if (ll == l) { id = Productions[i].Name; break; } } // don't count itself. only things just like itself if (!string.IsNullOrEmpty(id) && !ReferenceEquals(Productions[id].Expression, l)) { refCounts[id] += 1; } } var r = expr as XbnfRefExpression; if (null != r) { int rc; if (null == r.Symbol) { messages.Add( new XbnfMessage( ErrorLevel.Error, -1, "Null reference expression", expr.Line, expr.Column, expr.Position, FileOrUrl)); return; } if (!refCounts.TryGetValue(r.Symbol, out rc)) { messages.Add( new XbnfMessage( ErrorLevel.Error, -1, string.Concat( "Reference to undefined symbol \"", r.Symbol, "\""), expr.Line, expr.Column, expr.Position, FileOrUrl)); return; } refCounts[r.Symbol] = rc + 1; return; } var b = expr as XbnfBinaryExpression; if (null != b) { if (null == b.Left && null == b.Right) { messages.Add( new XbnfMessage( ErrorLevel.Warning, -1, "Nil expression", expr.Line, expr.Column, expr.Position, FileOrUrl)); return; } _ValidateExpression(b.Left, refCounts, messages); _ValidateExpression(b.Right, refCounts, messages); return; } var u = expr as XbnfUnaryExpression; if (null != u) { if (null == u.Expression) { messages.Add( new XbnfMessage( ErrorLevel.Warning, -1, "Nil expression", expr.Line, expr.Column, expr.Position, FileOrUrl)); return; } _ValidateExpression(u.Expression, refCounts, messages); } }
public XbnfRepeatExpression(XbnfExpression expression, bool isOptional = true) { Expression = expression; IsOptional = isOptional; }
internal static XbnfExpression Parse(LexContext pc) { XbnfExpression current = null; XbnfExpression 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.Current) { pc.TrySkipCCommentsAndWhiteSpace(); position = pc.Position; line = pc.Line; column = pc.Column; switch (pc.Current) { case '|': pc.Advance(); position = pc.Position; line = pc.Line; column = pc.Column; current = new XbnfOrExpression(current, Parse(pc)); current.SetLocation(line, column, position); break; case '(': pc.Advance(); position = pc.Position; line = pc.Line; column = pc.Column; e = Parse(pc); if (null != current) { current.SetLocation(line, column, position); } pc.Expecting(')'); pc.Advance(); e.SetLocation(line, column, position); if (null == current) { current = e; } else { current = new XbnfConcatExpression(current, e); } break; case '[': pc.Advance(); e = new XbnfOptionalExpression(Parse(pc)); e.SetLocation(line, column, position); pc.TrySkipCCommentsAndWhiteSpace(); pc.Expecting(']'); pc.Advance(); if (null == current) { current = e; } else { current = new XbnfConcatExpression(current, e); } break; case '{': pc.Advance(); e = new XbnfRepeatExpression(Parse(pc)); e.SetLocation(line, column, position); pc.TrySkipCCommentsAndWhiteSpace(); pc.Expecting('}'); pc.Advance(); if ('+' == pc.Current) { pc.Advance(); ((XbnfRepeatExpression)e).IsOptional = false; } if (null == current) { current = e; } else { current = new XbnfConcatExpression(current, e); } break; case '\"': e = new XbnfLiteralExpression(pc.ParseJsonString()); if (null == current) { current = e; } else { current = new XbnfConcatExpression(current, e); } e.SetLocation(line, column, position); break; case '\'': pc.Advance(); pc.ClearCapture(); pc.TryReadUntil('\'', '\\', false); pc.Expecting('\''); pc.Advance(); e = new XbnfRegexExpression(pc.GetCapture()); if (null == current) { current = e; } else { current = new XbnfConcatExpression(current, e); } e.SetLocation(line, column, position); break; case ';': case ']': case ')': case '}': case '=': case ':': return(current); default: e = new XbnfRefExpression(ParseIdentifier(pc)); if (null == current) { current = e; } else { current = new XbnfConcatExpression(current, e); } e.SetLocation(line, column, position); break; } } pc.TrySkipCCommentsAndWhiteSpace(); return(current); }
internal static XbnfProduction Parse(LexContext pc) { var result = new XbnfProduction(); pc.TrySkipCCommentsAndWhiteSpace(); var l = pc.Line; var c = pc.Column; var p = pc.Position; // read identifier result.Name = ParseIdentifier(pc); // read attributes if ('<' == pc.Current) { pc.Advance(); while (-1 != pc.Current && '>' != pc.Current) { result.Attributes.Add(XbnfAttribute.Parse(pc)); pc.TrySkipCCommentsAndWhiteSpace(); pc.Expecting('>', ','); if (',' == pc.Current) { pc.Advance(); } } pc.Expecting('>'); pc.Advance(); } pc.TrySkipCCommentsAndWhiteSpace(); pc.Expecting('='); pc.Advance(); result.Expression = XbnfExpression.Parse(pc); pc.Expecting(';', '='); result.SetLocation(l, c, p); if (';' == pc.Current) { pc.Advance(); return(result); } if ('=' == pc.Current) { pc.Advance(); pc.Expecting('>'); pc.Advance(); pc.TrySkipCCommentsAndWhiteSpace(); pc.Expecting('{'); pc.Advance(); l = pc.Line; c = pc.Column; p = pc.Position; var s = XbnfDocument.ReadCode(pc); pc.Expecting('}'); pc.Advance(); result.Action = new XbnfCode(s); result.SetLocation(l, c, p); } return(result); }