public DirectiveNode (ILocation location, string name, TagAttributes attributes) : base (location) { this.name = name; this.attributes = attributes; //FIXME: workaround for weird parser MasterPage bug if (string.IsNullOrEmpty(name)) foreach (string key in attributes.Keys) if (key.ToLower() == "master") this.name = "Master"; }
public DirectiveNode(ILocation location, string name, TagAttributes attributes) : base(location) { this.name = name; this.attributes = attributes; //FIXME: workaround for weird parser MasterPage bug if (string.IsNullOrEmpty(name)) { foreach (string key in attributes.Keys) { if (key.ToLower() == "master") { this.name = "Master"; } } } }
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 OnTagParsed (TagType tagtype, string id, TagAttributes attributes) { TagParsedHandler eh = events [tagParsedEvent] as TagParsedHandler; if (eh != null) eh (this, tagtype, id, attributes); }
void GetServerTag (out TagType tagtype, out string id, out TagAttributes attributes) { string inside_tags; bool old = tokenizer.ExpectAttrValue; tokenizer.ExpectAttrValue = false; if (Eat ('@')){ tokenizer.ExpectAttrValue = old; tagtype = TagType.Directive; id = ""; if (Eat (Token.DIRECTIVE)) id = tokenizer.Value; attributes = GetAttributes (); if (!Eat ('%') || !Eat ('>')) OnError ("expecting '%>'"); return; } if (Eat (Token.DOUBLEDASH)) { tokenizer.ExpectAttrValue = old; tokenizer.Verbatim = true; inside_tags = GetVerbatim (tokenizer.get_token (), "--%>"); tokenizer.Verbatim = false; id = null; attributes = null; tagtype = TagType.ServerComment; return; } tokenizer.ExpectAttrValue = old; bool varname; bool databinding; varname = Eat ('='); databinding = !varname && Eat ('#'); tokenizer.Verbatim = true; inside_tags = GetVerbatim (tokenizer.get_token (), "%>"); tokenizer.Verbatim = false; id = inside_tags; attributes = null; tagtype = (databinding ? TagType.DataBinding : (varname ? TagType.CodeRenderExpression : TagType.CodeRender)); }
TagAttributes GetAttributes () { int token; TagAttributes attributes; string id; bool wellFormedForServer = true; attributes = new TagAttributes (); while ((token = tokenizer.get_token ()) != Token.EOF){ if (token == '<' && Eat ('%')) { tokenizer.Verbatim = true; attributes.Add ("", "<%" + GetVerbatim (tokenizer.get_token (), "%>") + "%>"); tokenizer.Verbatim = false; tokenizer.InTag = true; continue; } if (token != Token.IDENTIFIER) break; id = tokenizer.Value; if (Eat ('=')){ if (Eat (Token.ATTVALUE)){ attributes.Add (id, tokenizer.Value); wellFormedForServer &= tokenizer.AlternatingQuotes; } else if (Eat ('<') && Eat ('%')) { tokenizer.Verbatim = true; attributes.Add (id, "<%" + GetVerbatim (tokenizer.get_token (), "%>") + "%>"); tokenizer.Verbatim = false; tokenizer.InTag = true; } else { OnError ("expected ATTVALUE"); return null; } } else { attributes.Add (id, null); } } tokenizer.put_back (); if (attributes.IsRunAtServer () && !wellFormedForServer) { OnError ("The server tag is not well formed."); return null; } return attributes; }
void GetTag (out TagType tagtype, out string id, out TagAttributes attributes) { int token = tokenizer.get_token (); tagtype = TagType.ServerComment; id = null; attributes = null; switch (token){ case '%': GetServerTag (out tagtype, out id, out attributes); break; case '/': if (!Eat (Token.IDENTIFIER)) OnError ("expecting TAGNAME"); id = tokenizer.Value; if (!Eat ('>')) OnError ("expecting '>'. Got '" + id + "'"); tagtype = TagType.Close; break; case '!': bool double_dash = Eat (Token.DOUBLEDASH); if (double_dash) tokenizer.put_back (); tokenizer.Verbatim = true; string end = double_dash ? "-->" : ">"; string comment = GetVerbatim (tokenizer.get_token (), end); tokenizer.Verbatim = false; if (comment == null) OnError ("Unfinished HTML comment/DTD"); string pathType, filename; if (double_dash && GetInclude (comment, out pathType, out filename)) { tagtype = TagType.Include; attributes = new TagAttributes (); attributes.Add (pathType, filename); } else { tagtype = TagType.Text; id = "<!" + comment + end; } break; case Token.IDENTIFIER: if (this.filename == "@@inner_string@@") { // Actually not tag but "xxx < yyy" stuff in inner_string! tagtype = TagType.Text; tokenizer.InTag = false; id = "<" + tokenizer.Odds + tokenizer.Value; } else { id = tokenizer.Value; try { attributes = GetAttributes (); } catch (Exception e) { OnError (e.Message); break; } tagtype = TagType.Tag; if (Eat ('/') && Eat ('>')) { tagtype = TagType.SelfClosing; } else if (!Eat ('>')) { if (attributes.IsRunAtServer ()) { OnError ("The server tag is not well formed."); break; } tokenizer.Verbatim = true; attributes.Add ("", GetVerbatim (tokenizer.get_token (), ">") + ">"); tokenizer.Verbatim = false; } } break; default: tagtype = TagType.Text; tokenizer.InTag = false; id = "<" + tokenizer.Value; break; } }
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); } }
internal TagNode(ILocation location, string name, TagAttributes attributes) : base(location) { this.tagName = name; this.attributes = attributes; }
internal TagNode (ILocation location, string name, TagAttributes attributes) : base (location) { this.tagName = name; this.attributes = attributes; }