aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/syntax/scanner_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/syntax/scanner_test.go')
-rw-r--r--src/cmd/compile/internal/syntax/scanner_test.go108
1 files changed, 80 insertions, 28 deletions
diff --git a/src/cmd/compile/internal/syntax/scanner_test.go b/src/cmd/compile/internal/syntax/scanner_test.go
index 89ba04022e..297b61428a 100644
--- a/src/cmd/compile/internal/syntax/scanner_test.go
+++ b/src/cmd/compile/internal/syntax/scanner_test.go
@@ -255,44 +255,96 @@ var sampleTokens = [...]struct {
func TestScanErrors(t *testing.T) {
for _, test := range []struct {
- src, msg string
+ src, msg string
+ pos, line int
}{
+ // Note: Positions for lexical errors are the earliest position
+ // where the error is apparent, not the beginning of the respective
+ // token.
+
// rune-level errors
- {"fo\x00o", "invalid NUL character"},
- {"fo\ufeffo", "invalid BOM in the middle of the file"},
- {"\xff", "invalid UTF-8 encoding"},
+ {"fo\x00o", "invalid NUL character", 2, 1},
+ {"foo\n\ufeff bar", "invalid BOM in the middle of the file", 4, 2},
+ {"foo\n\n\xff ", "invalid UTF-8 encoding", 5, 3},
// token-level errors
- {"~", "bitwise complement operator is ^"},
- {"$", "invalid rune '$'"},
- {"0xyz", "malformed hex constant"},
- {"08", "malformed octal constant"},
- {"1.0e+x", "malformed floating-point constant exponent"},
- {`"foo`, "string not terminated"},
- {"`foo", "string not terminated"},
- {"/* foo", "comment not terminated"},
- {`"foo\z"`, "unknown escape sequence"},
- // {`"\x`, "escape sequence not terminated"},
- {`"\x"`, "illegal character U+0022 '\"' in escape sequence"},
- {`"\Uffffffff"`, "escape sequence is invalid Unicode code point"},
+ {"x + ~y", "bitwise complement operator is ^", 4, 1},
+ {"foo$bar = 0", "invalid rune '$'", 3, 1},
+ {"const x = 0xyz", "malformed hex constant", 12, 1},
+ {"0123456789", "malformed octal constant", 10, 1},
+ {"0123456789. /*", "comment not terminated", 14, 1}, // valid float constant
+ {"0123456789e0 /*", "comment not terminated", 15, 1}, // valid float constant
+ {"var a, b = 08, 07\n", "malformed octal constant", 13, 1},
+ {"(x + 1.0e+x)", "malformed floating-point constant exponent", 10, 1},
+
+ {`''`, "empty character literal", 1, 1},
+ {`'\`, "missing '", 2, 1},
+ {`'\'`, "missing '", 3, 1},
+ {`'\x`, "missing '", 3, 1},
+ {`'\x'`, "escape sequence incomplete", 3, 1},
+ {`'\y'`, "unknown escape sequence", 2, 1},
+ {`'\x0'`, "escape sequence incomplete", 4, 1},
+ {`'\00'`, "escape sequence incomplete", 4, 1},
+ {`'\377' /*`, "comment not terminated", 9, 1}, // valid octal escape
+ {`'\378`, "illegal character U+0038 '8' in escape sequence", 4, 1},
+ {`'\400'`, "octal escape value > 255: 256", 5, 1},
+ {`'xx`, "missing '", 2, 1},
+
+ {`"`, "string not terminated", 1, 1},
+ {`"foo`, "string not terminated", 4, 1},
+ {"`", "string not terminated", 1, 1},
+ {"`foo", "string not terminated", 4, 1},
+ {"/*/", "comment not terminated", 3, 1},
+ {"/*\n\nfoo", "comment not terminated", 7, 3},
+ {`"\`, "string not terminated", 2, 1},
+ {`"\"`, "string not terminated", 3, 1},
+ {`"\x`, "string not terminated", 3, 1},
+ {`"\x"`, "escape sequence incomplete", 3, 1},
+ {`"\y"`, "unknown escape sequence", 2, 1},
+ {`"\x0"`, "escape sequence incomplete", 4, 1},
+ {`"\00"`, "escape sequence incomplete", 4, 1},
+ {`"\377" /*`, "comment not terminated", 9, 1}, // valid octal escape
+ {`"\378"`, "illegal character U+0038 '8' in escape sequence", 4, 1},
+ {`"\400"`, "octal escape value > 255: 256", 5, 1},
+
+ {`s := "foo\z"`, "unknown escape sequence", 10, 1},
+ {`s := "foo\z00\nbar"`, "unknown escape sequence", 10, 1},
+ {`"\x`, "string not terminated", 3, 1},
+ {`"\x"`, "escape sequence incomplete", 3, 1},
+ {`var s string = "\x"`, "escape sequence incomplete", 18, 1},
+ {`return "\Uffffffff"`, "escape sequence is invalid Unicode code point", 18, 1},
// former problem cases
- {"\xef", "invalid UTF-8 encoding"},
+ {"package p\n\n\xef", "invalid UTF-8 encoding", 11, 3},
} {
var s scanner
- hasError := false
- s.init(&bytesReader{[]byte(test.src)}, func(_, line int, msg string) {
- hasError = true
- // TODO(gri) test exact position as well
- if line != 1 {
- t.Errorf("got line = %d; want 1", line)
- }
- if msg != test.msg {
- t.Errorf("got msg = %q; want %q", msg, test.msg)
+ nerrors := 0
+ s.init(&bytesReader{[]byte(test.src)}, func(pos, line int, msg string) {
+ nerrors++
+ // only check the first error
+ if nerrors == 1 {
+ if msg != test.msg {
+ t.Errorf("%q: got msg = %q; want %q", test.src, msg, test.msg)
+ }
+ if pos != test.pos {
+ t.Errorf("%q: got pos = %d; want %d", test.src, pos, test.pos)
+ }
+ if line != test.line {
+ t.Errorf("%q: got line = %d; want %d", test.src, line, test.line)
+ }
+ } else if nerrors > 1 {
+ t.Errorf("%q: got unexpected %q at pos = %d, line = %d", test.src, msg, pos, line)
}
})
- s.next()
- if !hasError {
+
+ for {
+ s.next()
+ if s.tok == _EOF {
+ break
+ }
+ }
+
+ if nerrors == 0 {
t.Errorf("%q: got no error; want %q", test.src, test.msg)
}
}