| |
| |
| |
|
|
| package syntax |
|
|
| import "fmt" |
|
|
| |
| |
| |
| |
| const PosMax = 1 << 30 |
|
|
| |
| |
| |
| |
| |
| type Pos struct { |
| base *PosBase |
| line, col uint32 |
| } |
|
|
| |
| func MakePos(base *PosBase, line, col uint) Pos { return Pos{base, sat32(line), sat32(col)} } |
|
|
| |
| |
|
|
| func (pos Pos) Pos() Pos { return pos } |
| func (pos Pos) IsKnown() bool { return pos.line > 0 } |
| func (pos Pos) Base() *PosBase { return pos.base } |
| func (pos Pos) Line() uint { return uint(pos.line) } |
| func (pos Pos) Col() uint { return uint(pos.col) } |
|
|
| |
| |
| |
| func (pos Pos) FileBase() *PosBase { |
| b := pos.base |
| for b != nil && b != b.pos.base { |
| b = b.pos.base |
| } |
| |
| return b |
| } |
|
|
| func (pos Pos) RelFilename() string { return pos.base.Filename() } |
|
|
| func (pos Pos) RelLine() uint { |
| b := pos.base |
| if b.Line() == 0 { |
| |
| return 0 |
| } |
| return b.Line() + (pos.Line() - b.Pos().Line()) |
| } |
|
|
| func (pos Pos) RelCol() uint { |
| b := pos.base |
| if b.Col() == 0 { |
| |
| |
| |
| |
| return 0 |
| } |
| if pos.Line() == b.Pos().Line() { |
| |
| return b.Col() + (pos.Col() - b.Pos().Col()) |
| } |
| return pos.Col() |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| func (p Pos) Cmp(q Pos) int { |
| pname := p.RelFilename() |
| qname := q.RelFilename() |
| switch { |
| case pname < qname: |
| return -1 |
| case pname > qname: |
| return +1 |
| } |
|
|
| pline := p.Line() |
| qline := q.Line() |
| switch { |
| case pline < qline: |
| return -1 |
| case pline > qline: |
| return +1 |
| } |
|
|
| pcol := p.Col() |
| qcol := q.Col() |
| switch { |
| case pcol < qcol: |
| return -1 |
| case pcol > qcol: |
| return +1 |
| } |
|
|
| return 0 |
| } |
|
|
| func (pos Pos) String() string { |
| rel := position_{pos.RelFilename(), pos.RelLine(), pos.RelCol()} |
| abs := position_{pos.Base().Pos().RelFilename(), pos.Line(), pos.Col()} |
| s := rel.String() |
| if rel != abs { |
| s += "[" + abs.String() + "]" |
| } |
| return s |
| } |
|
|
| |
| type position_ struct { |
| filename string |
| line, col uint |
| } |
|
|
| func (p position_) String() string { |
| if p.line == 0 { |
| if p.filename == "" { |
| return "<unknown position>" |
| } |
| return p.filename |
| } |
| if p.col == 0 { |
| return fmt.Sprintf("%s:%d", p.filename, p.line) |
| } |
| return fmt.Sprintf("%s:%d:%d", p.filename, p.line, p.col) |
| } |
|
|
| |
| |
| type PosBase struct { |
| pos Pos |
| filename string |
| line, col uint32 |
| trimmed bool |
| } |
|
|
| |
| |
| |
| func NewFileBase(filename string) *PosBase { |
| return NewTrimmedFileBase(filename, false) |
| } |
|
|
| |
| func NewTrimmedFileBase(filename string, trimmed bool) *PosBase { |
| base := &PosBase{MakePos(nil, linebase, colbase), filename, linebase, colbase, trimmed} |
| base.pos.base = base |
| return base |
| } |
|
|
| |
| |
| |
| |
| |
| func NewLineBase(pos Pos, filename string, trimmed bool, line, col uint) *PosBase { |
| return &PosBase{pos, filename, sat32(line), sat32(col), trimmed} |
| } |
|
|
| func (base *PosBase) IsFileBase() bool { |
| if base == nil { |
| return false |
| } |
| return base.pos.base == base |
| } |
|
|
| func (base *PosBase) Pos() (_ Pos) { |
| if base == nil { |
| return |
| } |
| return base.pos |
| } |
|
|
| func (base *PosBase) Filename() string { |
| if base == nil { |
| return "" |
| } |
| return base.filename |
| } |
|
|
| func (base *PosBase) Line() uint { |
| if base == nil { |
| return 0 |
| } |
| return uint(base.line) |
| } |
|
|
| func (base *PosBase) Col() uint { |
| if base == nil { |
| return 0 |
| } |
| return uint(base.col) |
| } |
|
|
| func (base *PosBase) Trimmed() bool { |
| if base == nil { |
| return false |
| } |
| return base.trimmed |
| } |
|
|
| func sat32(x uint) uint32 { |
| if x > PosMax { |
| return PosMax |
| } |
| return uint32(x) |
| } |
|
|