void Add (ErrorType type, Node node, string message, params object[] args) { errors.Add (new Error (type, node.Location.BeginLine, node.Location.BeginColumn, string.Format (message, args))); }
public void Parse (string fileName, TextReader textStream) { var parser = new AspParser (fileName, textStream); this.fileName = fileName; parser.Error += ParseError; parser.TagParsed += TagParsed; parser.TextParsed += TextParsed; currentNode = this; parser.Parse (); }
void TagParsed (ILocation location, TagType tagtype, string tagId, TagAttributes attributes) { switch (tagtype) { case TagType.Close: TagNode tn = currentNode as TagNode; if (tn == null) { errors.Add (new ParseException (location, "Closing tag '" + tagId +"' does not match an opening tag.")); } else { if (tn.TagName == tagId) { tn.EndLocation = location; currentNode = currentNode.Parent; tn.Close (); } else { errors.Add (new ParseException (location, "Closing tag '" + tagId +"' does not match opening tag '" + tn.TagName + "'.")); currentNode = currentNode.Parent; TagParsed (location, TagType.Close, tagId, null); } } break; case TagType.CodeRender: case TagType.CodeRenderExpression: case TagType.DataBinding: try { AddtoCurrent (location, new ExpressionNode (location, tagId, tagtype == TagType.CodeRenderExpression)); } catch (ParseException ex) { errors.Add (ex); } break; case TagType.Directive: try { AddtoCurrent (location, new DirectiveNode (location, tagId, attributes)); } catch (ParseException ex) { errors.Add (ex); } break; case TagType.Include: throw new NotImplementedException ("Server-side includes have not yet been implemented: " + location.PlainText); case TagType.ServerComment: //FIXME: the parser doesn't actually return these throw new NotImplementedException ("Server comments have not yet been implemented: " + location.PlainText); case TagType.SelfClosing: try { tn = new TagNode (location, tagId, attributes); AddtoCurrent (location, tn); tn.Close (); } catch (ParseException ex) { errors.Add (ex); } break; case TagType.Tag: try { //HACK: implicit close on block level in HTML4 TagNode prevTag = currentNode as TagNode; if (prevTag != null) { if (Array.IndexOf (implicitCloseOnBlock, prevTag.TagName.ToLowerInvariant ()) > -1 && Array.IndexOf (blockLevel, tagId.ToLowerInvariant ()) > -1) { errors.Add (new ParseException (location, "Unclosed " + prevTag.TagName + " tag. Assuming implicitly closed by block level tag.")); prevTag.Close (); currentNode = currentNode.Parent; } } //create and add the new tag TagNode child = new TagNode (location, tagId, attributes); AddtoCurrent (location, child); //HACK: implicitly closing tags in HTML4 if (Array.IndexOf (implicitSelfClosing, tagId.ToLowerInvariant ()) > -1) { errors.Add (new ParseException (location, "Unclosed " + tagId + " tag. Assuming implicitly closed.")); child.Close (); } else { currentNode = child; } } catch (ParseException ex) { errors.Add (ex); } break; case TagType.Text: //FIXME: the parser doesn't actually return these throw new NotImplementedException("Text tagtypes have not yet been implemented: " + location.PlainText); } }
void AddtoCurrent (ILocation location, Node n) { ParentNode pn = currentNode as ParentNode; if (pn == null) throw new ParseException (location, "Nodes of type " + n.GetType () + " must be inside other tags"); pn.AddChild (n); }