]> Cypherpunks repositories - gostls13.git/commitdiff
exp/html: add parseImpliedToken method to parser
authorAndrew Balholm <andybalholm@gmail.com>
Thu, 19 Apr 2012 01:48:17 +0000 (11:48 +1000)
committerNigel Tao <nigeltao@golang.org>
Thu, 19 Apr 2012 01:48:17 +0000 (11:48 +1000)
This method will allow us to be explicit about what we're doing when
we insert an implied token, and avoid repeating the logic involved in
multiple places.

R=nigeltao
CC=golang-dev
https://golang.org/cl/6060048

src/pkg/exp/html/parse.go

index 1a6bc2eebde4516d9126bf2e8923e51dd1da7201..42d9d553c4c4375cce32ee44a577ff198b75c589 100644 (file)
@@ -295,23 +295,12 @@ func (p *parser) reconstructActiveFormattingElements() {
        }
 }
 
-// read reads the next token. This is usually from the tokenizer, but it may
-// be the synthesized end tag implied by a self-closing tag.
+// read reads the next token from the tokenizer.
 func (p *parser) read() error {
-       if p.hasSelfClosingToken {
-               p.hasSelfClosingToken = false
-               p.tok.Type = EndTagToken
-               p.tok.Attr = nil
-               return nil
-       }
        p.tokenizer.Next()
        p.tok = p.tokenizer.Token()
-       switch p.tok.Type {
-       case ErrorToken:
+       if p.tok.Type == ErrorToken {
                return p.tokenizer.Err()
-       case SelfClosingTagToken:
-               p.hasSelfClosingToken = true
-               p.tok.Type = StartTagToken
        }
        return nil
 }
@@ -426,7 +415,8 @@ func beforeHTMLIM(p *parser) bool {
        case EndTagToken:
                switch p.tok.Data {
                case "head", "body", "html", "br":
-                       // Drop down to creating an implied <html> tag.
+                       p.parseImpliedToken(StartTagToken, "html", nil)
+                       return false
                default:
                        // Ignore the token.
                        return true
@@ -438,9 +428,7 @@ func beforeHTMLIM(p *parser) bool {
                })
                return true
        }
-       // Create an implied <html> tag.
-       p.addElement("html", nil)
-       p.im = beforeHeadIM
+       p.parseImpliedToken(StartTagToken, "html", nil)
        return false
 }
 
@@ -466,7 +454,8 @@ func beforeHeadIM(p *parser) bool {
        case EndTagToken:
                switch p.tok.Data {
                case "head", "body", "html", "br":
-                       // Drop down to adding an implied <head> tag.
+                       p.parseImpliedToken(StartTagToken, "head", nil)
+                       return false
                default:
                        // Ignore the token.
                        return true
@@ -482,9 +471,7 @@ func beforeHeadIM(p *parser) bool {
                return true
        }
 
-       p.addElement("head", nil)
-       p.head = p.top()
-       p.im = inHeadIM
+       p.parseImpliedToken(StartTagToken, "head", nil)
        return false
 }
 
@@ -1767,29 +1754,52 @@ func (p *parser) inForeignContent() bool {
        return true
 }
 
-func (p *parser) parse() error {
-       // Iterate until EOF. Any other error will cause an early return.
-       consumed := true
-       for {
-               if consumed {
-                       if err := p.read(); err != nil {
-                               if err == io.EOF {
-                                       break
-                               }
-                               return err
-                       }
-               }
+// parseImpliedToken parses a token as though it had appeared in the parser's
+// input.
+func (p *parser) parseImpliedToken(t TokenType, data string, attr []Attribute) {
+       realToken, selfClosing := p.tok, p.hasSelfClosingToken
+       p.tok = Token{
+               Type: t,
+               Data: data,
+               Attr: attr,
+       }
+       p.hasSelfClosingToken = false
+       p.parseCurrentToken()
+       p.tok, p.hasSelfClosingToken = realToken, selfClosing
+}
+
+// parseCurrentToken runs the current token through the parsing routines
+// until it is consumed.
+func (p *parser) parseCurrentToken() {
+       if p.tok.Type == SelfClosingTagToken {
+               p.hasSelfClosingToken = true
+               p.tok.Type = StartTagToken
+       }
+
+       consumed := false
+       for !consumed {
                if p.inForeignContent() {
                        consumed = parseForeignContent(p)
                } else {
                        consumed = p.im(p)
                }
        }
-       // Loop until the final token (the ErrorToken signifying EOF) is consumed.
-       for {
-               if consumed = p.im(p); consumed {
-                       break
+
+       if p.hasSelfClosingToken {
+               p.hasSelfClosingToken = false
+               p.parseImpliedToken(EndTagToken, p.tok.Data, nil)
+       }
+}
+
+func (p *parser) parse() error {
+       // Iterate until EOF. Any other error will cause an early return.
+       var err error
+       for err != io.EOF {
+               err = p.read()
+               if err != nil && err != io.EOF {
+                       return err
                }
+               p.parseCurrentToken()
        }
        return nil
 }