private void ParseLiteralElementOpeningTag(LiteralElement element, out bool expectClosingTag, ref SourceContext context){ SourceContext ctx = this.scanner.CurrentSourceContext; Identifier tag = element.Name = this.ParsePrefixedIdentifier(); if (tag.Prefix != null) { ctx = tag.Prefix.SourceContext; ctx.EndPos = this.scanner.endPos; } element.Type = new TypeExpression(element.Name); if (this.sink != null) this.sink.QualifyName(element.SourceContext, tag); while (Parser.IdentifierOrNonReservedKeyword[this.currentToken]){ element.AttributeNames.Add(this.ParsePrefixedIdentifier()); this.Skip(Token.Assign); switch(this.currentToken){ case Token.IntegerLiteral: element.AttributeValues.Add(this.ParseIntegerLiteral()); break; default: element.AttributeValues.Add(this.scanner.GetStringLiteral()); this.Skip(Token.StringLiteral); break; } } this.scanner.state = ScannerState.XML; element.SourceContext.EndPos = this.scanner.endPos; if (this.currentToken == Token.EndOfSimpleTag) expectClosingTag = false; else{ if (this.currentToken == Token.EndOfTag){ this.GetNextToken(); context = this.scanner.CurrentSourceContext; }else{ this.HandleError(Error.SyntaxError, ">"); context = this.scanner.CurrentSourceContext; } expectClosingTag = true; } }
private LiteralElement ParseLiteralElement(Identifier parentTagName, TokenSet followers, out bool parentMustExpectClosingTag){ Debug.Assert(this.currentToken == Token.StartOfTag); parentMustExpectClosingTag = true; this.scanner.state = ScannerState.Tag; LiteralElement result = new LiteralElement(); result.SourceContext = this.scanner.CurrentSourceContext; this.GetNextToken(); bool expectClosingTag; SourceContext sctx = this.scanner.CurrentSourceContext; ScannerState ss = this.scanner.state; this.ParseLiteralElementOpeningTag(result, out expectClosingTag, ref sctx); if (expectClosingTag){ Token tokenFollowingOpeningTag = this.currentToken; for(;;){ switch(this.currentToken){ case Token.LiteralContentString: case Token.LiteralComment: case Token.CharacterData: result.Contents.Add(this.scanner.GetStringLiteral()); result.ContentsType.Add((int)this.currentToken); if (this.scanner.state != ScannerState.Code) this.scanner.state = ScannerState.XML; this.GetNextToken(); break; case Token.ProcessingInstructions: result.Contents.Add(new Literal(this.scanner.CurrentSourceContext.SourceText)); result.ContentsType.Add((int)this.currentToken); this.scanner.state = ScannerState.XML; this.GetNextToken(); break; case Token.StartOfTag: bool nestedElementDidNotEndWithMyTag = true; LiteralElement xelem = this.ParseLiteralElement(result.Name, followers, out nestedElementDidNotEndWithMyTag); xelem.ParentLiteral = result; result.Contents.Add(xelem); result.ContentsType.Add((int)Token.StartOfTag); if (!nestedElementDidNotEndWithMyTag){ result.SourceContext.EndPos = xelem.SourceContext.EndPos; if (parentTagName == Identifier.Empty) this.scanner.state = ScannerState.Code; this.GetNextToken(); return result; }else if (this.currentToken == Token.EndOfFile && xelem.Name == Identifier.Empty) return result; break; default: goto checkForClosingTag; } } checkForClosingTag: if (this.currentToken != Token.StartOfClosingTag){ this.scanner.state = ScannerState.Code; Identifier tagId = result.Name; if (tokenFollowingOpeningTag == Token.LiteralContentString && parentTagName == Identifier.Empty && sctx.SourceText.Trim().Length != 0){ this.scanner.endPos = sctx.StartPos; this.scanner.state = ss; this.currentToken = Token.None; this.GetNextToken(); this.scanner.state = ScannerState.Code; Debug.Assert(this.currentToken != Token.ObjectLiteralStart); result = null; } if (tagId != null) this.HandleError(Error.SyntaxError, "</"+tagId.ToString()+">"); else this.HandleError(Error.SyntaxError, "<"); this.SkipTo(followers, Error.None); return result; } this.scanner.state = ScannerState.Tag; this.Skip(Token.StartOfClosingTag); Identifier closingId = this.ParsePrefixedIdentifier(); if (parentTagName == Identifier.Empty) this.scanner.state = ScannerState.Code; else this.scanner.state = ScannerState.XML; Identifier openingId = result.Name; bool matchesStartId = closingId.UniqueIdKey == openingId.UniqueIdKey && !(closingId.Prefix != null && (openingId.Prefix == null || closingId.Prefix.UniqueIdKey != openingId.Prefix.UniqueIdKey)); if (matchesStartId) this.Skip(Token.EndOfTag); else{ bool matchesParentId = closingId.UniqueIdKey == parentTagName.UniqueIdKey && !(closingId.Prefix != null && (parentTagName.Prefix == null || closingId.Prefix.UniqueIdKey != parentTagName.Prefix.UniqueIdKey)); if (matchesParentId){ parentMustExpectClosingTag = false; this.HandleError(closingId.SourceContext, Error.ClosingTagMismatch, result.Name.ToString()); }else{ this.Skip(Token.EndOfTag); this.HandleError(closingId.SourceContext, Error.ClosingTagMismatch, result.Name.ToString()); } } }else{ if (parentTagName == Identifier.Empty) this.scanner.state = ScannerState.Code; if (this.currentToken == Token.EndOfSimpleTag) this.GetNextToken(); } return result; }
private LiteralElement ParseObjectLiteral(TokenSet followers){ Token tok = this.currentToken; Debug.Assert(tok == Token.ObjectLiteralStart || tok == Token.MultiLineDocCommentStart || tok == Token.SingleLineDocCommentStart); Debug.Assert(this.scanner.state == ScannerState.XML); this.GetNextToken(); if (this.currentToken != Token.StartOfTag){ this.SkipTo(followers|Token.StartOfTag); if (this.currentToken != Token.StartOfTag) return null; } bool junk; LiteralElement result = this.ParseLiteralElement(Identifier.Empty, followers, out junk); if (result == null){ while (this.currentToken == Token.SingleLineDocCommentStart) this.GetNextToken(); return result; // error handling. } if (tok == Token.MultiLineDocCommentStart || tok == Token.SingleLineDocCommentStart || this.currentToken == Token.LessThan){ LiteralElement element = result; result = new LiteralElement(); result.SourceContext = element.SourceContext; result.Contents.Add(element); result.ContentsType.Add((int)Token.StartOfTag); for(;;){ switch(this.currentToken){ case Token.Multiply: this.GetNextToken(); continue; case Token.ObjectLiteralStart: case Token.SingleLineDocCommentStart: this.GetNextToken(); goto case Token.LessThan; case Token.LessThan: this.currentToken = Token.StartOfTag; LiteralElement xelem = this.ParseLiteralElement(Identifier.Empty, followers, out junk); result.Contents.Add(xelem); result.ContentsType.Add((int)Token.StartOfTag); break; default: goto done; } } } done: this.SkipTo(followers); return result; }
private XmlElement GetXmlElement(LiteralElement lit){ try { XmlElement result = null; result = this.module.Documentation.CreateElement(lit.Name.Name); IdentifierList attrNames = lit.AttributeNames; ExpressionList attrValues = lit.AttributeValues; for (int i = 0, n = attrNames == null ? 0 : attrNames.Count; i < n; i++){ Identifier attrName = attrNames[i]; if (attrName == null) continue; Expression attrValue = attrValues[i]; if (attrValue == null) continue; XmlAttribute attr = result.SetAttributeNode(attrName.Name, null); Literal attrLit = attrValue as Literal; if (attrLit != null && attrLit.Value is string) attr.Value = (string)attrLit.Value; else attr.Value = attrValue.SourceContext.SourceText; } ExpressionList contents = lit.Contents; Int32List contentsType = lit.ContentsType; for (int i = 0, n = contents == null ? 0 : contents.Count; i < n; i++){ Expression content = contents[i]; if (content == null) continue; switch ((Token)contentsType[i]){ case Token.StartOfTag: XmlElement childElement = this.GetXmlElement((LiteralElement)content); if (childElement == null) continue; result.AppendChild(childElement); break; case Token.LiteralContentString: result.AppendChild(result.OwnerDocument.CreateTextNode((string)((Literal)content).Value)); break; case Token.CharacterData: result.AppendChild(result.OwnerDocument.CreateCDataSection((string)((Literal)content).Value)); break; case Token.LiteralComment: result.AppendChild(result.OwnerDocument.CreateComment((string)((Literal)content).Value)); break; case Token.ProcessingInstructions: string piTagAndBody = (string)((Literal)content).Value; int len = piTagAndBody == null ? 0 : piTagAndBody.Length; int firstBlank = piTagAndBody.IndexOf(' '); if (firstBlank > 2 && firstBlank < len-3) result.AppendChild(result.OwnerDocument.CreateProcessingInstruction( piTagAndBody.Substring(2, firstBlank-2), piTagAndBody.Substring(firstBlank+1,len-3-firstBlank))); break; } } return result; } catch (Exception e) { this.HandleError(lit.SourceContext, Error.InternalCompilerError, e.Message); return null; } }
public ValidationState CheckElement(LiteralElement xElem) { if (this.validator != null) { validator.ValidateElement(xElem.Name, context); } return context; }
public void Start(LiteralElement element) { this.element = element; context.Name = element.Name; }