mirror of
https://github.com/golang/go
synced 2024-11-19 15:44:44 -07:00
cmd/compile/internal/syntax: cleanups around parser tracing
These changes affect the parser only when the internal trace constant is set. - factored our printing code used for tracing - streamlined advance function and added trace output The parser's trace output now more clearly prints what tokens are skipped and which is the next token in case of an error. Example trace: 4: . . . . . . . . . . call ( 4: . . . . . . . . . . . expr ( 4: . . . . . . . . . . . . unaryExpr ( 4: . . . . . . . . . . . . . pexpr ( 4: . . . . . . . . . . . . . . operand name ( 4: . . . . . . . . . . . . . . ) 4: . . . . . . . . . . . . . . call ( 4: . . . . . . . . . . . . . . ) 4: . . . . . . . . . . . . . ) 4: . . . . . . . . . . . . ) 4: . . . . . . . . . . . ) 4: . . . . . . . . . . . syntax error: expecting comma or ) 4: . . . . . . . . . . . skip ; 6: . . . . . . . . . . . skip name 6: . . . . . . . . . . . skip := 6: . . . . . . . . . . . skip literal 6: . . . . . . . . . . . skip ; 7: . . . . . . . . . . . skip } 7: . . . . . . . . . . . skip ; 9: . . . . . . . . . . . skip func 9: . . . . . . . . . . . skip name 9: . . . . . . . . . . . skip ( 9: . . . . . . . . . . . next ) 9: . . . . . . . . . . ) For #22164. Change-Id: I4a233696b1f989ee3287472172afaf92cf424565 Reviewed-on: https://go-review.googlesource.com/70490 Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
5ddd3d588c
commit
4b7325c7e3
@ -614,6 +614,7 @@ var knownFormats = map[string]string{
|
||||
"[]cmd/compile/internal/ssa.Edge %v": "",
|
||||
"[]cmd/compile/internal/ssa.ID %v": "",
|
||||
"[]cmd/compile/internal/ssa.VarLocList %v": "",
|
||||
"[]cmd/compile/internal/syntax.token %s": "",
|
||||
"[]string %v": "",
|
||||
"bool %v": "",
|
||||
"byte %08b": "",
|
||||
@ -683,9 +684,9 @@ var knownFormats = map[string]string{
|
||||
"int32 %d": "",
|
||||
"int32 %v": "",
|
||||
"int32 %x": "",
|
||||
"int64 %.5d": "",
|
||||
"int64 %+d": "",
|
||||
"int64 %-10d": "",
|
||||
"int64 %.5d": "",
|
||||
"int64 %X": "",
|
||||
"int64 %d": "",
|
||||
"int64 %v": "",
|
||||
|
@ -97,7 +97,7 @@ func (p *parser) got(tok token) bool {
|
||||
|
||||
func (p *parser) want(tok token) {
|
||||
if !p.got(tok) {
|
||||
p.syntax_error("expecting " + tok.String())
|
||||
p.syntax_error("expecting " + tokstring(tok))
|
||||
p.advance()
|
||||
}
|
||||
}
|
||||
@ -126,7 +126,7 @@ func (p *parser) error_at(pos src.Pos, msg string) {
|
||||
// syntax_error_at reports a syntax error at the given position.
|
||||
func (p *parser) syntax_error_at(pos src.Pos, msg string) {
|
||||
if trace {
|
||||
defer p.trace("syntax_error (" + msg + ")")()
|
||||
p.print("syntax error: " + msg)
|
||||
}
|
||||
|
||||
if p.tok == _EOF && p.first != nil {
|
||||
@ -168,6 +168,18 @@ func (p *parser) syntax_error_at(pos src.Pos, msg string) {
|
||||
p.error_at(pos, "syntax error: unexpected "+tok+msg)
|
||||
}
|
||||
|
||||
// tokstring returns the English word for selected punctuation tokens
|
||||
// for more readable error messages.
|
||||
func tokstring(tok token) string {
|
||||
switch tok {
|
||||
case _Comma:
|
||||
return "comma"
|
||||
case _Semi:
|
||||
return "semicolon"
|
||||
}
|
||||
return tok.String()
|
||||
}
|
||||
|
||||
// Convenience methods using the current token position.
|
||||
func (p *parser) pos() src.Pos { return p.pos_at(p.line, p.col) }
|
||||
func (p *parser) error(msg string) { p.error_at(p.pos(), msg) }
|
||||
@ -194,40 +206,42 @@ const stopset uint64 = 1<<_Break |
|
||||
// Advance consumes tokens until it finds a token of the stopset or followlist.
|
||||
// The stopset is only considered if we are inside a function (p.fnest > 0).
|
||||
// The followlist is the list of valid tokens that can follow a production;
|
||||
// if it is empty, exactly one token is consumed to ensure progress.
|
||||
// if it is empty, exactly one (non-EOF) token is consumed to ensure progress.
|
||||
func (p *parser) advance(followlist ...token) {
|
||||
if len(followlist) == 0 {
|
||||
p.next()
|
||||
return
|
||||
if trace {
|
||||
p.print(fmt.Sprintf("advance %s", followlist))
|
||||
}
|
||||
|
||||
// compute follow set
|
||||
// (not speed critical, advance is only called in error situations)
|
||||
var followset uint64 = 1 << _EOF // never skip over EOF
|
||||
for _, tok := range followlist {
|
||||
followset |= 1 << tok
|
||||
var followset uint64 = 1 << _EOF // don't skip over EOF
|
||||
if len(followlist) > 0 {
|
||||
if p.fnest > 0 {
|
||||
followset |= stopset
|
||||
}
|
||||
for _, tok := range followlist {
|
||||
followset |= 1 << tok
|
||||
}
|
||||
}
|
||||
|
||||
for !(contains(followset, p.tok) || p.fnest > 0 && contains(stopset, p.tok)) {
|
||||
for !contains(followset, p.tok) {
|
||||
if trace {
|
||||
p.print("skip " + p.tok.String())
|
||||
}
|
||||
p.next()
|
||||
if len(followlist) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func tokstring(tok token) string {
|
||||
switch tok {
|
||||
case _EOF:
|
||||
return "EOF"
|
||||
case _Comma:
|
||||
return "comma"
|
||||
case _Semi:
|
||||
return "semicolon"
|
||||
if trace {
|
||||
p.print("next " + p.tok.String())
|
||||
}
|
||||
return tok.String()
|
||||
}
|
||||
|
||||
// usage: defer p.trace(msg)()
|
||||
func (p *parser) trace(msg string) func() {
|
||||
fmt.Printf("%5d: %s%s (\n", p.line, p.indent, msg)
|
||||
p.print(msg + " (")
|
||||
const tab = ". "
|
||||
p.indent = append(p.indent, tab...)
|
||||
return func() {
|
||||
@ -235,10 +249,14 @@ func (p *parser) trace(msg string) func() {
|
||||
if x := recover(); x != nil {
|
||||
panic(x) // skip print_trace
|
||||
}
|
||||
fmt.Printf("%5d: %s)\n", p.line, p.indent)
|
||||
p.print(")")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parser) print(msg string) {
|
||||
fmt.Printf("%5d: %s%s\n", p.line, p.indent, msg)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Package files
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user