OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Package scanner implements a scanner for Go source text. | 5 // Package scanner implements a scanner for Go source text. |
6 // It takes a []byte as source which can then be tokenized | 6 // It takes a []byte as source which can then be tokenized |
7 // through repeated calls to the Scan method. | 7 // through repeated calls to the Scan method. |
8 // | 8 // |
9 package scanner | 9 package scanner |
10 | 10 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 // update scanner position | 150 // update scanner position |
151 s.file.AddLineInfo(s.lineOffset+len(text)+1, fil
ename, line) // +len(text)+1 since comment applies to next line | 151 s.file.AddLineInfo(s.lineOffset+len(text)+1, fil
ename, line) // +len(text)+1 since comment applies to next line |
152 } | 152 } |
153 } | 153 } |
154 } | 154 } |
155 } | 155 } |
156 | 156 |
157 func (s *Scanner) scanComment() string { | 157 func (s *Scanner) scanComment() string { |
158 // initial '/' already consumed; s.ch == '/' || s.ch == '*' | 158 // initial '/' already consumed; s.ch == '/' || s.ch == '*' |
159 offs := s.offset - 1 // position of initial '/' | 159 offs := s.offset - 1 // position of initial '/' |
| 160 hasCR := false |
160 | 161 |
161 if s.ch == '/' { | 162 if s.ch == '/' { |
162 //-style comment | 163 //-style comment |
163 s.next() | 164 s.next() |
164 for s.ch != '\n' && s.ch >= 0 { | 165 for s.ch != '\n' && s.ch >= 0 { |
| 166 if s.ch == '\r' { |
| 167 hasCR = true |
| 168 } |
165 s.next() | 169 s.next() |
166 } | 170 } |
167 if offs == s.lineOffset { | 171 if offs == s.lineOffset { |
168 // comment starts at the beginning of the current line | 172 // comment starts at the beginning of the current line |
169 s.interpretLineComment(s.src[offs:s.offset]) | 173 s.interpretLineComment(s.src[offs:s.offset]) |
170 } | 174 } |
171 goto exit | 175 goto exit |
172 } | 176 } |
173 | 177 |
174 /*-style comment */ | 178 /*-style comment */ |
175 s.next() | 179 s.next() |
176 for s.ch >= 0 { | 180 for s.ch >= 0 { |
177 ch := s.ch | 181 ch := s.ch |
| 182 if ch == '\r' { |
| 183 hasCR = true |
| 184 } |
178 s.next() | 185 s.next() |
179 if ch == '*' && s.ch == '/' { | 186 if ch == '*' && s.ch == '/' { |
180 s.next() | 187 s.next() |
181 goto exit | 188 goto exit |
182 } | 189 } |
183 } | 190 } |
184 | 191 |
185 s.error(offs, "comment not terminated") | 192 s.error(offs, "comment not terminated") |
186 | 193 |
187 exit: | 194 exit: |
188 » return string(s.src[offs:s.offset]) | 195 » lit := s.src[offs:s.offset] |
| 196 » if hasCR { |
| 197 » » lit = stripCR(lit) |
| 198 » } |
| 199 |
| 200 » return string(lit) |
189 } | 201 } |
190 | 202 |
191 func (s *Scanner) findLineEnd() bool { | 203 func (s *Scanner) findLineEnd() bool { |
192 // initial '/' already consumed | 204 // initial '/' already consumed |
193 | 205 |
194 defer func(offs int) { | 206 defer func(offs int) { |
195 // reset scanner state to where it was upon calling findLineEnd | 207 // reset scanner state to where it was upon calling findLineEnd |
196 s.ch = '/' | 208 s.ch = '/' |
197 s.offset = offs | 209 s.offset = offs |
198 s.rdOffset = offs + 1 | 210 s.rdOffset = offs + 1 |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 } | 532 } |
521 | 533 |
522 // Scan scans the next token and returns the token position, the token, | 534 // Scan scans the next token and returns the token position, the token, |
523 // and its literal string if applicable. The source end is indicated by | 535 // and its literal string if applicable. The source end is indicated by |
524 // token.EOF. | 536 // token.EOF. |
525 // | 537 // |
526 // If the returned token is a literal (token.IDENT, token.INT, token.FLOAT, | 538 // If the returned token is a literal (token.IDENT, token.INT, token.FLOAT, |
527 // token.IMAG, token.CHAR, token.STRING) or token.COMMENT, the literal string | 539 // token.IMAG, token.CHAR, token.STRING) or token.COMMENT, the literal string |
528 // has the corresponding value. | 540 // has the corresponding value. |
529 // | 541 // |
| 542 // If the returned token is a keyword, the literal string is the keyword. |
| 543 // |
530 // If the returned token is token.SEMICOLON, the corresponding | 544 // If the returned token is token.SEMICOLON, the corresponding |
531 // literal string is ";" if the semicolon was present in the source, | 545 // literal string is ";" if the semicolon was present in the source, |
532 // and "\n" if the semicolon was inserted because of a newline or | 546 // and "\n" if the semicolon was inserted because of a newline or |
533 // at EOF. | 547 // at EOF. |
534 // | 548 // |
535 // If the returned token is token.ILLEGAL, the literal string is the | 549 // If the returned token is token.ILLEGAL, the literal string is the |
536 // offending character. | 550 // offending character. |
537 // | 551 // |
538 // In all other cases, Scan returns an empty literal string. | 552 // In all other cases, Scan returns an empty literal string. |
539 // | 553 // |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
695 tok = token.ILLEGAL | 709 tok = token.ILLEGAL |
696 lit = string(ch) | 710 lit = string(ch) |
697 } | 711 } |
698 } | 712 } |
699 if s.mode&dontInsertSemis == 0 { | 713 if s.mode&dontInsertSemis == 0 { |
700 s.insertSemi = insertSemi | 714 s.insertSemi = insertSemi |
701 } | 715 } |
702 | 716 |
703 return | 717 return |
704 } | 718 } |
OLD | NEW |