@@ -22,6 +22,9 @@ import (
2222const linebase = 1
2323const 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).
6368func (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
7882func (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
154158func (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