aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/syntax/source.go
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2016-11-29 16:13:09 -0800
committerRobert Griesemer <gri@golang.org>2016-12-09 00:42:42 +0000
commit8d20b25779d4ce32e8eaeb52374fba1e74f7df57 (patch)
tree1dd10782d5b321986850604da0bc743789ee31b8 /src/cmd/compile/internal/syntax/source.go
parenteaca0e0529b780f4c862a97aa47008aa1b403adf (diff)
downloadgo-8d20b25779d4ce32e8eaeb52374fba1e74f7df57.tar.gz
go-8d20b25779d4ce32e8eaeb52374fba1e74f7df57.zip
[dev.inline] cmd/compile/internal/syntax: introduce general position info for nodes
Reviewed in and cherry-picked from https://go-review.googlesource.com/#/c/33758/. Minor adjustments in noder.go to fix merge. Change-Id: Ibe429e327c7f8554f8ac205c61ce3738013aed98 Reviewed-on: https://go-review.googlesource.com/34231 Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/syntax/source.go')
-rw-r--r--src/cmd/compile/internal/syntax/source.go37
1 files changed, 27 insertions, 10 deletions
diff --git a/src/cmd/compile/internal/syntax/source.go b/src/cmd/compile/internal/syntax/source.go
index 05a11960c6..db161166ed 100644
--- a/src/cmd/compile/internal/syntax/source.go
+++ b/src/cmd/compile/internal/syntax/source.go
@@ -2,6 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// This file implements source, a buffered rune reader
+// which is specialized for the needs of the Go scanner:
+// Contiguous sequences of runes (literals) are extracted
+// directly as []byte without the need to re-encode the
+// runes in UTF-8 (as would be necessary with bufio.Reader).
+
package syntax
import (
@@ -23,7 +29,8 @@ type source struct {
buf [4 << 10]byte
offs int // source offset of buf
r0, r, w int // previous/current read and write buf positions, excluding sentinel
- line0, line int // previous/current line
+ line0, line uint // previous/current line
+ col0, col uint // previous/current column
err error // pending io error
// literal buffer
@@ -40,6 +47,7 @@ func (s *source) init(src io.Reader, errh ErrorHandler) {
s.offs = 0
s.r0, s.r, s.w = 0, 0, 0
s.line0, s.line = 1, 1
+ s.col0, s.col = 1, 1
s.err = nil
s.lit = s.lit[:0]
@@ -47,11 +55,11 @@ func (s *source) init(src io.Reader, errh ErrorHandler) {
}
func (s *source) error(msg string) {
- s.error_at(s.pos0(), s.line0, msg)
+ s.error_at(s.line0, s.col0, msg)
}
-func (s *source) error_at(pos, line int, msg string) {
- err := Error{pos, line, msg}
+func (s *source) error_at(line, col uint, msg string) {
+ err := Error{line, col, msg}
if s.first == nil {
s.first = err
}
@@ -61,18 +69,24 @@ func (s *source) error_at(pos, line int, msg string) {
s.errh(err)
}
-// pos0 returns the byte position of the last character read.
-func (s *source) pos0() int {
- return s.offs + s.r0
+// ungetr ungets the most recently read rune.
+func (s *source) ungetr() {
+ s.r, s.line, s.col = s.r0, s.line0, s.col0
}
-func (s *source) ungetr() {
- s.r, s.line = s.r0, s.line0
+// ungetr2 is like ungetr but enables a 2nd ungetr.
+// It must not be called if one of the runes seen
+// was a newline.
+func (s *source) ungetr2() {
+ s.ungetr()
+ // line must not have changed
+ s.r0--
+ s.col0--
}
func (s *source) getr() rune {
redo:
- s.r0, s.line0 = s.r, s.line
+ s.r0, s.line0, s.col0 = s.r, s.line, s.col
// We could avoid at least one test that is always taken in the
// for loop below by duplicating the common case code (ASCII)
@@ -88,12 +102,14 @@ redo:
// (invariant: s.buf[s.w] == utf8.RuneSelf)
if b := s.buf[s.r]; b < utf8.RuneSelf {
s.r++
+ s.col++
if b == 0 {
s.error("invalid NUL character")
goto redo
}
if b == '\n' {
s.line++
+ s.col = 1
}
return rune(b)
}
@@ -109,6 +125,7 @@ redo:
// uncommon case: not ASCII
r, w := utf8.DecodeRune(s.buf[s.r:s.w])
s.r += w
+ s.col++
if r == utf8.RuneError && w == 1 {
s.error("invalid UTF-8 encoding")