Skip to content

Commit 58365b3

Browse files
committed
cmd/compile/internal/syntax: allow more than one rune "unread"
Make it possible to "unread" more than one byte before the most recently read rune. Use a better name than ungetr2 and make it slightly more efficient. R=Go1.13 Change-Id: I45d5dfa11e508259a972ca6560d1f78d7a51fe15 Reviewed-on: https://go-review.googlesource.com/c/158957 Reviewed-by: Russ Cox <rsc@golang.org>
1 parent 701f6a2 commit 58365b3

File tree

2 files changed

+32
-23
lines changed

2 files changed

+32
-23
lines changed

src/cmd/compile/internal/syntax/scanner.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ redo:
150150
case '.':
151151
c = s.getr()
152152
if isDigit(c) {
153-
s.ungetr2()
153+
s.unread(1)
154154
s.number('.')
155155
break
156156
}
@@ -160,7 +160,7 @@ redo:
160160
s.tok = _DotDotDot
161161
break
162162
}
163-
s.ungetr2()
163+
s.unread(1)
164164
}
165165
s.ungetr()
166166
s.tok = _Dot

src/cmd/compile/internal/syntax/source.go

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ import (
2222
const linebase = 1
2323
const colbase = 1
2424

25+
// max. number of bytes to unread
26+
const maxunread = 10
27+
2528
// buf [...read...|...|...unread...|s|...free...]
2629
// ^ ^ ^ ^
2730
// | | | |
@@ -59,20 +62,21 @@ func (s *source) init(src io.Reader, errh func(line, pos uint, msg string)) {
5962
s.suf = -1
6063
}
6164

62-
// ungetr ungets the most recently read rune.
65+
// ungetr sets the reading position to a previous reading
66+
// position, usually the one of the most recently read
67+
// rune, but possibly earlier (see unread below).
6368
func (s *source) ungetr() {
6469
s.r, s.line, s.col = s.r0, s.line0, s.col0
6570
}
6671

67-
// ungetr2 is like ungetr but enables a 2nd ungetr.
68-
// It must not be called if one of the runes seen
69-
// was a newline or had a UTF-8 encoding longer than
70-
// 1 byte.
71-
func (s *source) ungetr2() {
72-
s.ungetr()
73-
// line must not have changed
74-
s.r0--
75-
s.col0--
72+
// unread moves the previous reading position to a position
73+
// that is n bytes earlier in the source. The next ungetr
74+
// call will set the reading position to that moved position.
75+
// The "unread" runes must be single byte and not contain any
76+
// newlines; and 0 <= n <= maxunread must hold.
77+
func (s *source) unread(n int) {
78+
s.r0 -= n
79+
s.col0 -= uint(n)
7680
}
7781

7882
func (s *source) error(msg string) {
@@ -142,7 +146,7 @@ redo:
142146
// BOM's are only allowed as the first character in a file
143147
const BOM = 0xfeff
144148
if r == BOM {
145-
if s.r0 > 0 { // s.r0 is always > 0 after 1st character (fill will set it to 1)
149+
if s.r0 > 0 { // s.r0 is always > 0 after 1st character (fill will set it to maxunread)
146150
s.error("invalid BOM in the middle of the file")
147151
}
148152
goto redo
@@ -153,20 +157,25 @@ redo:
153157

154158
func (s *source) fill() {
155159
// Slide unread bytes to beginning but preserve last read char
156-
// (for one ungetr call) plus one extra byte (for a 2nd ungetr
157-
// call, only for ".." character sequence and float literals
158-
// starting with ".").
159-
if s.r0 > 1 {
160+
// (for one ungetr call) plus maxunread extra bytes (for one
161+
// unread call).
162+
if s.r0 > maxunread {
163+
n := s.r0 - maxunread // number of bytes to slide down
160164
// save literal prefix, if any
161-
// (We see at most one ungetr call while reading
162-
// a literal, so make sure s.r0 remains in buf.)
165+
// (make sure we keep maxunread bytes and the last
166+
// read char in the buffer)
163167
if s.suf >= 0 {
164-
s.lit = append(s.lit, s.buf[s.suf:s.r0]...)
165-
s.suf = 1 // == s.r0 after slide below
168+
// we have a literal
169+
if s.suf < n {
170+
// save literal prefix
171+
s.lit = append(s.lit, s.buf[s.suf:n]...)
172+
s.suf = 0
173+
} else {
174+
s.suf -= n
175+
}
166176
}
167-
n := s.r0 - 1
168177
copy(s.buf[:], s.buf[n:s.w])
169-
s.r0 = 1 // eqv: s.r0 -= n
178+
s.r0 = maxunread // eqv: s.r0 -= n
170179
s.r -= n
171180
s.w -= n
172181
}

0 commit comments

Comments
 (0)