| 242 | } |
| 243 | |
| 244 | func skipWhitespace(buf []byte, start pos) ([]byte, pos) { |
| 245 | var i int |
| 246 | p := start |
| 247 | Byte: |
| 248 | for i = 0; i < len(buf); i++ { |
| 249 | switch buf[i] { |
| 250 | case ' ': |
| 251 | p.Pos.Byte++ |
| 252 | p.Pos.Column++ |
| 253 | case '\n': |
| 254 | p.Pos.Byte++ |
| 255 | p.Pos.Column = 1 |
| 256 | p.Pos.Line++ |
| 257 | case '\r': |
| 258 | // For the purpose of line/column counting we consider a |
| 259 | // carriage return to take up no space, assuming that it will |
| 260 | // be paired up with a newline (on Windows, for example) that |
| 261 | // will account for both of them. |
| 262 | p.Pos.Byte++ |
| 263 | case '\t': |
| 264 | // We arbitrarily count a tab as if it were two spaces, because |
| 265 | // we need to choose _some_ number here. This means any system |
| 266 | // that renders code on-screen with markers must itself treat |
| 267 | // tabs as a pair of spaces for rendering purposes, or instead |
| 268 | // use the byte offset and back into its own column position. |
| 269 | p.Pos.Byte++ |
| 270 | p.Pos.Column += 2 |
| 271 | default: |
| 272 | break Byte |
| 273 | } |
| 274 | } |
| 275 | return buf[i:], p |
| 276 | } |
| 277 | |
| 278 | type pos struct { |
| 279 | Filename string |