mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.inline] cmd/compile/internal/syntax: simplified position code
Reviewed in and cherry-picked from https://go-review.googlesource.com/#/c/33805/. Change-Id: I859d9bd5f2256ca78f7b24b330290f7ae600854d Reviewed-on: https://go-review.googlesource.com/34234 Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
32bf2829a1
commit
e97c8a592f
4 changed files with 53 additions and 66 deletions
|
|
@ -6,10 +6,11 @@
|
||||||
|
|
||||||
package syntax
|
package syntax
|
||||||
|
|
||||||
import "fmt"
|
import "strconv"
|
||||||
|
|
||||||
// A Pos encodes a source position consisting of a (line, column) number pair
|
// A Pos encodes a source position consisting of a (line, column) number pair
|
||||||
// and a position base.
|
// and a position base. A zero Pos is a ready to use "unknown" position (empty
|
||||||
|
// filename, and unknown line and column number).
|
||||||
//
|
//
|
||||||
// The (line, column) values refer to a position in a file independent of any
|
// The (line, column) values refer to a position in a file independent of any
|
||||||
// position base ("absolute" position). They start at 1, and they are unknown
|
// position base ("absolute" position). They start at 1, and they are unknown
|
||||||
|
|
@ -33,47 +34,36 @@ func MakePos(base *PosBase, line, col uint) Pos {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filename returns the name of the actual file containing this position.
|
// Filename returns the name of the actual file containing this position.
|
||||||
func (p *Pos) Filename() string {
|
func (p *Pos) Filename() string { return p.base.Pos().RelFilename() }
|
||||||
if b := p.base; b != nil {
|
|
||||||
return b.pos.RelFilename()
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base returns the position base.
|
// Base returns the position base.
|
||||||
func (p *Pos) Base() *PosBase { return p.base }
|
func (p *Pos) Base() *PosBase { return p.base }
|
||||||
|
|
||||||
// RelFilename returns the filename recorded with the position's base.
|
// RelFilename returns the filename recorded with the position's base.
|
||||||
func (p *Pos) RelFilename() string {
|
func (p *Pos) RelFilename() string { return p.base.Filename() }
|
||||||
if b := p.base; b != nil {
|
|
||||||
return b.filename
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// RelLine returns the line number relative to the positions's base.
|
// RelLine returns the line number relative to the positions's base.
|
||||||
func (p *Pos) RelLine() uint {
|
func (p *Pos) RelLine() uint { b := p.base; return b.Line() + p.Line() - b.Pos().Line() }
|
||||||
var line0 uint
|
|
||||||
if b := p.base; b != nil {
|
|
||||||
line0 = b.line - p.base.pos.Line()
|
|
||||||
}
|
|
||||||
return line0 + p.Line()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pos) String() string {
|
func (p *Pos) String() string {
|
||||||
b := p.base
|
b := p.base
|
||||||
|
|
||||||
if b == nil {
|
if b == b.Pos().base {
|
||||||
return p.lico.String()
|
// base is file base (incl. nil)
|
||||||
}
|
return posString(b.Filename(), p.Line(), p.Col())
|
||||||
|
|
||||||
if b == b.pos.base {
|
|
||||||
// base is file base
|
|
||||||
return fmt.Sprintf("%s:%s", b.filename, p.lico.String())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// base is relative
|
// base is relative
|
||||||
return fmt.Sprintf("%s:%s[%s]", b.filename, licoString(p.RelLine(), p.Col()), b.pos.String())
|
return posString(b.Filename(), p.RelLine(), p.Col()) + "[" + b.Pos().String() + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
// posString formats a (filename, line, col) tuple as a printable position.
|
||||||
|
func posString(filename string, line, col uint) string {
|
||||||
|
s := filename + ":" + strconv.FormatUint(uint64(line), 10)
|
||||||
|
if col != 0 {
|
||||||
|
s += ":" + strconv.FormatUint(uint64(col), 10)
|
||||||
|
}
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
@ -91,10 +81,13 @@ type PosBase struct {
|
||||||
|
|
||||||
// NewFileBase returns a new *PosBase for a file with the given filename.
|
// NewFileBase returns a new *PosBase for a file with the given filename.
|
||||||
func NewFileBase(filename string) *PosBase {
|
func NewFileBase(filename string) *PosBase {
|
||||||
|
if filename != "" {
|
||||||
base := &PosBase{filename: filename}
|
base := &PosBase{filename: filename}
|
||||||
base.pos = MakePos(base, 0, 0)
|
base.pos = MakePos(base, 0, 0)
|
||||||
return base
|
return base
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewLinePragmaBase returns a new *PosBase for a line pragma of the form
|
// NewLinePragmaBase returns a new *PosBase for a line pragma of the form
|
||||||
// //line filename:line
|
// //line filename:line
|
||||||
|
|
@ -106,7 +99,7 @@ func NewLinePragmaBase(pos Pos, filename string, line uint) *PosBase {
|
||||||
var noPos Pos
|
var noPos Pos
|
||||||
|
|
||||||
// Pos returns the position at which base is located.
|
// Pos returns the position at which base is located.
|
||||||
// If b == nil, the result is the empty position.
|
// If b == nil, the result is the zero position.
|
||||||
func (b *PosBase) Pos() *Pos {
|
func (b *PosBase) Pos() *Pos {
|
||||||
if b != nil {
|
if b != nil {
|
||||||
return &b.pos
|
return &b.pos
|
||||||
|
|
@ -144,29 +137,21 @@ type lico uint32
|
||||||
// information as line numbers grow bigger; similar to what gcc
|
// information as line numbers grow bigger; similar to what gcc
|
||||||
// does.)
|
// does.)
|
||||||
const (
|
const (
|
||||||
lineW, lineM = 24, 1<<lineW - 1
|
lineBits, lineMax = 24, 1<<lineBits - 1
|
||||||
colW, colM = 32 - lineW, 1<<colW - 1
|
colBits, colMax = 32 - lineBits, 1<<colBits - 1
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeLico(line, col uint) lico {
|
func makeLico(line, col uint) lico {
|
||||||
if line > lineM {
|
if line > lineMax {
|
||||||
// cannot represent line, use max. line so we have some information
|
// cannot represent line, use max. line so we have some information
|
||||||
line = lineM
|
line = lineMax
|
||||||
}
|
}
|
||||||
if col > colM {
|
if col > colMax {
|
||||||
// cannot represent column, use 0 to indicate unknown column
|
// cannot represent column, use 0 to indicate unknown column
|
||||||
col = 0
|
col = 0
|
||||||
}
|
}
|
||||||
return lico(line<<colW | col)
|
return lico(line<<colBits | col)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x lico) Line() uint { return uint(x) >> colW }
|
func (x lico) Line() uint { return uint(x) >> colBits }
|
||||||
func (x lico) Col() uint { return uint(x) & colM }
|
func (x lico) Col() uint { return uint(x) & colMax }
|
||||||
func (x lico) String() string { return licoString(x.Line(), x.Col()) }
|
|
||||||
|
|
||||||
func licoString(line, col uint) string {
|
|
||||||
if col == 0 {
|
|
||||||
return fmt.Sprintf("%d", line)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%d:%d", line, col)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPos(t *testing.T) {
|
func TestPos(t *testing.T) {
|
||||||
|
f0 := NewFileBase("")
|
||||||
f1 := NewFileBase("f1")
|
f1 := NewFileBase("f1")
|
||||||
f2 := NewLinePragmaBase(Pos{}, "f2", 10)
|
f2 := NewLinePragmaBase(Pos{}, "f2", 10)
|
||||||
f3 := NewLinePragmaBase(MakePos(f1, 10, 1), "f3", 100)
|
f3 := NewLinePragmaBase(MakePos(f1, 10, 1), "f3", 100)
|
||||||
|
|
@ -27,10 +28,11 @@ func TestPos(t *testing.T) {
|
||||||
relFilename string
|
relFilename string
|
||||||
relLine uint
|
relLine uint
|
||||||
}{
|
}{
|
||||||
{Pos{}, "0", "", 0, 0, "", 0},
|
{Pos{}, ":0", "", 0, 0, "", 0},
|
||||||
{MakePos(nil, 2, 3), "2:3", "", 2, 3, "", 2},
|
{MakePos(nil, 2, 3), ":2:3", "", 2, 3, "", 2},
|
||||||
|
{MakePos(f0, 2, 3), ":2:3", "", 2, 3, "", 2},
|
||||||
{MakePos(f1, 1, 1), "f1:1:1", "f1", 1, 1, "f1", 1},
|
{MakePos(f1, 1, 1), "f1:1:1", "f1", 1, 1, "f1", 1},
|
||||||
{MakePos(f2, 7, 10), "f2:16:10[0]", "", 7, 10, "f2", 16},
|
{MakePos(f2, 7, 10), "f2:16:10[:0]", "", 7, 10, "f2", 16},
|
||||||
{MakePos(f3, 12, 7), "f3:101:7[f1:10:1]", "f1", 12, 7, "f3", 101},
|
{MakePos(f3, 12, 7), "f3:101:7[f1:10:1]", "f1", 12, 7, "f3", 101},
|
||||||
{MakePos(f4, 25, 1), "f4:114:1[f3:99:1[f1:10:1]]", "f3", 25, 1, "f4", 114}, // doesn't occur in Go code
|
{MakePos(f4, 25, 1), "f4:114:1[f3:99:1[f1:10:1]]", "f3", 25, 1, "f4", 114}, // doesn't occur in Go code
|
||||||
} {
|
} {
|
||||||
|
|
@ -66,20 +68,20 @@ func TestLico(t *testing.T) {
|
||||||
string string
|
string string
|
||||||
line, col uint
|
line, col uint
|
||||||
}{
|
}{
|
||||||
{0, "0", 0, 0},
|
{0, ":0", 0, 0},
|
||||||
{makeLico(0, 0), "0", 0, 0},
|
{makeLico(0, 0), ":0", 0, 0},
|
||||||
{makeLico(0, 1), "0:1", 0, 1},
|
{makeLico(0, 1), ":0:1", 0, 1},
|
||||||
{makeLico(1, 0), "1", 1, 0},
|
{makeLico(1, 0), ":1", 1, 0},
|
||||||
{makeLico(1, 1), "1:1", 1, 1},
|
{makeLico(1, 1), ":1:1", 1, 1},
|
||||||
{makeLico(2, 3), "2:3", 2, 3},
|
{makeLico(2, 3), ":2:3", 2, 3},
|
||||||
{makeLico(lineM, 1), fmt.Sprintf("%d:1", lineM), lineM, 1},
|
{makeLico(lineMax, 1), fmt.Sprintf(":%d:1", lineMax), lineMax, 1},
|
||||||
{makeLico(lineM+1, 1), fmt.Sprintf("%d:1", lineM), lineM, 1}, // line too large, stick with max. line
|
{makeLico(lineMax+1, 1), fmt.Sprintf(":%d:1", lineMax), lineMax, 1}, // line too large, stick with max. line
|
||||||
{makeLico(1, colM), fmt.Sprintf("1:%d", colM), 1, colM},
|
{makeLico(1, colMax), fmt.Sprintf(":1:%d", colMax), 1, colMax},
|
||||||
{makeLico(1, colM+1), "1", 1, 0}, // column too large
|
{makeLico(1, colMax+1), ":1", 1, 0}, // column too large
|
||||||
{makeLico(lineM+1, colM+1), fmt.Sprintf("%d", lineM), lineM, 0},
|
{makeLico(lineMax+1, colMax+1), fmt.Sprintf(":%d", lineMax), lineMax, 0},
|
||||||
} {
|
} {
|
||||||
x := test.x
|
x := test.x
|
||||||
if got := x.String(); got != test.string {
|
if got := posString("", x.Line(), x.Col()); got != test.string {
|
||||||
t.Errorf("%s: got %q", test.string, got)
|
t.Errorf("%s: got %q", test.string, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -577,7 +577,7 @@ func (s *scanner) lineComment() {
|
||||||
}
|
}
|
||||||
nstr := text[i+1:]
|
nstr := text[i+1:]
|
||||||
n, err := strconv.Atoi(nstr)
|
n, err := strconv.Atoi(nstr)
|
||||||
if err != nil || n <= 0 || n > lineM {
|
if err != nil || n <= 0 || n > lineMax {
|
||||||
s.error_at(s.line0, s.col0-uint(len(nstr)), "invalid line number: "+nstr)
|
s.error_at(s.line0, s.col0-uint(len(nstr)), "invalid line number: "+nstr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -323,7 +323,7 @@ func TestScanErrors(t *testing.T) {
|
||||||
{`//line foo:123abc`, "invalid line number: 123abc", 1, 12},
|
{`//line foo:123abc`, "invalid line number: 123abc", 1, 12},
|
||||||
{`/**///line foo:x`, "invalid line number: x", 1, 16},
|
{`/**///line foo:x`, "invalid line number: x", 1, 16},
|
||||||
{`//line foo:0`, "invalid line number: 0", 1, 12},
|
{`//line foo:0`, "invalid line number: 0", 1, 12},
|
||||||
{fmt.Sprintf(`//line foo:%d`, lineM+1), fmt.Sprintf("invalid line number: %d", lineM+1), 1, 12},
|
{fmt.Sprintf(`//line foo:%d`, lineMax+1), fmt.Sprintf("invalid line number: %d", lineMax+1), 1, 12},
|
||||||
|
|
||||||
// former problem cases
|
// former problem cases
|
||||||
{"package p\n\n\xef", "invalid UTF-8 encoding", 3, 1},
|
{"package p\n\n\xef", "invalid UTF-8 encoding", 3, 1},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue