1
1
package parser
2
2
3
- // FIXME need to implement end of line continuations with \
4
- // If find \ at end of line, read next line then skip indent calcs
5
-
6
3
// FIXME need to implement formfeed
7
4
5
+ // Lexer should count line numbers too!
6
+
8
7
import (
9
8
"bufio"
10
9
"bytes"
@@ -58,14 +57,16 @@ func NewLex(r io.Reader) *yyLex {
58
57
func (x * yyLex ) refill () {
59
58
var err error
60
59
x .line , err = x .reader .ReadString ('\n' )
61
- fmt .Printf ("line = %q, err = %v\n " , x .line , err )
60
+ if yyDebug >= 2 {
61
+ fmt .Printf ("line = %q, err = %v\n " , x .line , err )
62
+ }
62
63
switch err {
63
64
case nil :
64
65
case io .EOF :
65
66
x .eof = true
66
67
default :
67
68
x .eof = true
68
- x .Error ( fmt . Sprintf ( "Error reading input: %v" , err ) )
69
+ x .Errorf ( "Error reading input: %v" , err )
69
70
}
70
71
}
71
72
@@ -238,16 +239,18 @@ const (
238
239
// The parser calls this method to get each new token. This
239
240
// implementation returns operators and NUM.
240
241
func (x * yyLex ) Lex (yylval * yySymType ) (ret int ) {
241
- defer func () {
242
- name := tokenToString [ret ]
243
- if ret == NAME {
244
- fmt .Printf ("LEX> %q (%d) = %q\n " , name , ret , yylval .str )
245
- } else if ret == STRING || ret == NUMBER {
246
- fmt .Printf ("LEX> %q (%d) = %T{%v}\n " , name , ret , yylval .obj , yylval .obj )
247
- } else {
248
- fmt .Printf ("LEX> %q (%d) \n " , name , ret )
249
- }
250
- }()
242
+ if yyDebug >= 2 {
243
+ defer func () {
244
+ name := tokenToString [ret ]
245
+ if ret == NAME {
246
+ fmt .Printf ("LEX> %q (%d) = %q\n " , name , ret , yylval .str )
247
+ } else if ret == STRING || ret == NUMBER {
248
+ fmt .Printf ("LEX> %q (%d) = %T{%v}\n " , name , ret , yylval .obj , yylval .obj )
249
+ } else {
250
+ fmt .Printf ("LEX> %q (%d) \n " , name , ret )
251
+ }
252
+ }()
253
+ }
251
254
252
255
for {
253
256
switch x .state {
@@ -323,6 +326,16 @@ func (x *yyLex) Lex(yylval *yySymType) (ret int) {
323
326
return NEWLINE
324
327
}
325
328
329
+ // Check if continuation character
330
+ if x .line [0 ] == '\\' && (len (x .line ) <= 1 || x .line [1 ] == '\n' ) {
331
+ if x .eof {
332
+ return eof
333
+ }
334
+ x .refill ()
335
+ x .state = parseTokens
336
+ continue
337
+ }
338
+
326
339
// Read a number if available
327
340
token , value := x .readNumber ()
328
341
if token != eof {
@@ -646,6 +659,11 @@ found:
646
659
escape := false
647
660
for i , c := range x .line {
648
661
if escape {
662
+ // Continuation line - remove \ then continue
663
+ if c == '\n' {
664
+ buf .Truncate (buf .Len () - 1 )
665
+ goto readMore
666
+ }
649
667
buf .WriteRune (c )
650
668
escape = false
651
669
} else {
@@ -663,11 +681,12 @@ found:
663
681
}
664
682
}
665
683
if ! multiLineString {
666
- x .Error ("Unterminated single quoted string" )
684
+ x .Errorf ("Unterminated %sx%s string" , stringEnd , stringEnd )
667
685
return eofError , nil
668
686
}
687
+ readMore:
669
688
if x .eof {
670
- x .Error ("Unterminated triple quoted string" )
689
+ x .Errorf ("Unterminated %sx%s string" , stringEnd , stringEnd )
671
690
return eofError , nil
672
691
}
673
692
x .refill ()
@@ -685,9 +704,16 @@ foundEndOfString:
685
704
// The parser calls this method on a parse error.
686
705
func (x * yyLex ) Error (s string ) {
687
706
x .error = true
688
- log .Printf ("Parse error: %s" , s )
689
- log .Printf ("Parse buffer %q" , x .line )
690
- log .Printf ("State %#v" , x )
707
+ if yyDebug >= 1 {
708
+ log .Printf ("Parse error: %s" , s )
709
+ log .Printf ("Parse buffer %q" , x .line )
710
+ log .Printf ("State %#v" , x )
711
+ }
712
+ }
713
+
714
+ // Call this to write formatted errors
715
+ func (x * yyLex ) Errorf (format string , a ... interface {}) {
716
+ x .Error (fmt .Sprintf (format , a ... ))
691
717
}
692
718
693
719
// Set the debug level 0 = off, 4 = max
0 commit comments