Commit c88ca590 authored by Andrew Balholm's avatar Andrew Balholm Committed by Nigel Tao

exp/html: add parseImpliedToken method to parser

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
parent e03dd509
...@@ -295,23 +295,12 @@ func (p *parser) reconstructActiveFormattingElements() { ...@@ -295,23 +295,12 @@ func (p *parser) reconstructActiveFormattingElements() {
} }
} }
// read reads the next token. This is usually from the tokenizer, but it may // read reads the next token from the tokenizer.
// be the synthesized end tag implied by a self-closing tag.
func (p *parser) read() error { 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.tokenizer.Next()
p.tok = p.tokenizer.Token() p.tok = p.tokenizer.Token()
switch p.tok.Type { if p.tok.Type == ErrorToken {
case ErrorToken:
return p.tokenizer.Err() return p.tokenizer.Err()
case SelfClosingTagToken:
p.hasSelfClosingToken = true
p.tok.Type = StartTagToken
} }
return nil return nil
} }
...@@ -426,7 +415,8 @@ func beforeHTMLIM(p *parser) bool { ...@@ -426,7 +415,8 @@ func beforeHTMLIM(p *parser) bool {
case EndTagToken: case EndTagToken:
switch p.tok.Data { switch p.tok.Data {
case "head", "body", "html", "br": case "head", "body", "html", "br":
// Drop down to creating an implied <html> tag. p.parseImpliedToken(StartTagToken, "html", nil)
return false
default: default:
// Ignore the token. // Ignore the token.
return true return true
...@@ -438,9 +428,7 @@ func beforeHTMLIM(p *parser) bool { ...@@ -438,9 +428,7 @@ func beforeHTMLIM(p *parser) bool {
}) })
return true return true
} }
// Create an implied <html> tag. p.parseImpliedToken(StartTagToken, "html", nil)
p.addElement("html", nil)
p.im = beforeHeadIM
return false return false
} }
...@@ -466,7 +454,8 @@ func beforeHeadIM(p *parser) bool { ...@@ -466,7 +454,8 @@ func beforeHeadIM(p *parser) bool {
case EndTagToken: case EndTagToken:
switch p.tok.Data { switch p.tok.Data {
case "head", "body", "html", "br": case "head", "body", "html", "br":
// Drop down to adding an implied <head> tag. p.parseImpliedToken(StartTagToken, "head", nil)
return false
default: default:
// Ignore the token. // Ignore the token.
return true return true
...@@ -482,9 +471,7 @@ func beforeHeadIM(p *parser) bool { ...@@ -482,9 +471,7 @@ func beforeHeadIM(p *parser) bool {
return true return true
} }
p.addElement("head", nil) p.parseImpliedToken(StartTagToken, "head", nil)
p.head = p.top()
p.im = inHeadIM
return false return false
} }
...@@ -1767,29 +1754,52 @@ func (p *parser) inForeignContent() bool { ...@@ -1767,29 +1754,52 @@ func (p *parser) inForeignContent() bool {
return true return true
} }
func (p *parser) parse() error { // parseImpliedToken parses a token as though it had appeared in the parser's
// Iterate until EOF. Any other error will cause an early return. // input.
consumed := true func (p *parser) parseImpliedToken(t TokenType, data string, attr []Attribute) {
for { realToken, selfClosing := p.tok, p.hasSelfClosingToken
if consumed { p.tok = Token{
if err := p.read(); err != nil { Type: t,
if err == io.EOF { Data: data,
break Attr: attr,
} }
return err 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() { if p.inForeignContent() {
consumed = parseForeignContent(p) consumed = parseForeignContent(p)
} else { } else {
consumed = p.im(p) consumed = p.im(p)
} }
} }
// Loop until the final token (the ErrorToken signifying EOF) is consumed.
for { if p.hasSelfClosingToken {
if consumed = p.im(p); consumed { p.hasSelfClosingToken = false
break 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 return nil
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment