lineComment *ast.CommentGroup // last line comment
// Next token
- pos token.Pos // token position
- tok token.Token // one token look-ahead
- lit []byte // token literal
+ pos token.Pos // token position
+ tok token.Token // one token look-ahead
+ lit_ []byte // token literal (slice into original source, don't hold on to it)
// Non-syntactic parser control
exprLev int // < 0: in control clause, >= 0: in expression
}
+func (p *parser) lit() []byte {
+ // make a copy of p.lit_ so that we don't hold on to
+ // a copy of the entire source indirectly in the AST
+ t := make([]byte, len(p.lit_))
+ copy(t, p.lit_)
+ return t
+}
+
+
// ----------------------------------------------------------------------------
// Scoping support
s := p.tok.String()
switch {
case p.tok.IsLiteral():
- p.printTrace(s, string(p.lit))
+ p.printTrace(s, string(p.lit_))
case p.tok.IsOperator(), p.tok.IsKeyword():
p.printTrace("\"" + s + "\"")
default:
}
}
- p.pos, p.tok, p.lit = p.scanner.Scan()
+ p.pos, p.tok, p.lit_ = p.scanner.Scan()
}
// Consume a comment and return it and the line on which it ends.
// /*-style comments may end on a different line than where they start.
// Scan the comment for '\n' chars and adjust endline accordingly.
endline = p.file.Line(p.pos)
- if p.lit[1] == '*' {
- for _, b := range p.lit {
+ if p.lit_[1] == '*' {
+ for _, b := range p.lit_ {
if b == '\n' {
endline++
}
}
}
- comment = &ast.Comment{p.pos, p.lit}
+ comment = &ast.Comment{p.pos, p.lit()}
p.next0()
return
if pos == p.pos {
// the error happened at the current position;
// make the error message more specific
- if p.tok == token.SEMICOLON && p.lit[0] == '\n' {
+ if p.tok == token.SEMICOLON && p.lit_[0] == '\n' {
msg += ", found newline"
} else {
msg += ", found '" + p.tok.String() + "'"
if p.tok.IsLiteral() {
- msg += " " + string(p.lit)
+ msg += " " + string(p.lit_)
}
}
}
pos := p.pos
name := "_"
if p.tok == token.IDENT {
- name = string(p.lit)
+ name = string(p.lit_)
p.next()
} else {
p.expect(token.IDENT) // use expect() error handling
// optional tag
var tag *ast.BasicLit
if p.tok == token.STRING {
- tag = &ast.BasicLit{p.pos, p.tok, p.lit}
+ tag = &ast.BasicLit{p.pos, p.tok, p.lit()}
p.next()
}
return ident
case token.INT, token.FLOAT, token.IMAG, token.CHAR, token.STRING:
- x := &ast.BasicLit{p.pos, p.tok, p.lit}
+ x := &ast.BasicLit{p.pos, p.tok, p.lit()}
p.next()
return x
var path *ast.BasicLit
if p.tok == token.STRING {
- path = &ast.BasicLit{p.pos, p.tok, p.lit}
+ path = &ast.BasicLit{p.pos, p.tok, p.lit()}
p.next()
} else {
p.expect(token.STRING) // use expect() error handling