aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/compile/internal/syntax/nodes_test.go4
-rw-r--r--src/cmd/compile/internal/syntax/parser_test.go28
-rw-r--r--src/cmd/compile/internal/syntax/scanner.go6
-rw-r--r--src/cmd/compile/internal/syntax/scanner_test.go122
-rw-r--r--src/cmd/compile/internal/syntax/source.go10
5 files changed, 87 insertions, 83 deletions
diff --git a/src/cmd/compile/internal/syntax/nodes_test.go b/src/cmd/compile/internal/syntax/nodes_test.go
index 6b4119c70b..47283bc4d2 100644
--- a/src/cmd/compile/internal/syntax/nodes_test.go
+++ b/src/cmd/compile/internal/syntax/nodes_test.go
@@ -297,8 +297,8 @@ func testPos(t *testing.T, list []test, prefix, suffix string, extract func(*Fil
}
// verify node position with expected position as indicated by @
- if col := int(node.Pos().Col()); col != index {
- t.Errorf("pos error: %s: col = %d, want %d", src, col, index)
+ if col := int(node.Pos().Col()); col != index+colbase {
+ t.Errorf("pos error: %s: col = %d, want %d", src, col, index+colbase)
continue
}
}
diff --git a/src/cmd/compile/internal/syntax/parser_test.go b/src/cmd/compile/internal/syntax/parser_test.go
index f7ada181dd..9028c41f37 100644
--- a/src/cmd/compile/internal/syntax/parser_test.go
+++ b/src/cmd/compile/internal/syntax/parser_test.go
@@ -188,20 +188,20 @@ func TestLineDirectives(t *testing.T) {
for _, test := range []struct {
src, msg string
filename string
- line, col uint
+ line, col uint // 0-based
}{
// test validity of //line directive
- {`//line :`, "invalid line number: ", "", 1, 8},
- {`//line :x`, "invalid line number: x", "", 1, 8},
- {`//line foo :`, "invalid line number: ", "", 1, 12},
- {`//line foo:123abc`, "invalid line number: 123abc", "", 1, 11},
- {`/**///line foo:x`, "syntax error: package statement must be first", "", 1, 16}, //line directive not at start of line - ignored
- {`//line foo:0`, "invalid line number: 0", "", 1, 11},
- {fmt.Sprintf(`//line foo:%d`, lineMax+1), fmt.Sprintf("invalid line number: %d", lineMax+1), "", 1, 11},
+ {`//line :`, "invalid line number: ", "", 0, 8},
+ {`//line :x`, "invalid line number: x", "", 0, 8},
+ {`//line foo :`, "invalid line number: ", "", 0, 12},
+ {`//line foo:123abc`, "invalid line number: 123abc", "", 0, 11},
+ {`/**///line foo:x`, "syntax error: package statement must be first", "", 0, 16}, //line directive not at start of line - ignored
+ {`//line foo:0`, "invalid line number: 0", "", 0, 11},
+ {fmt.Sprintf(`//line foo:%d`, lineMax+1), fmt.Sprintf("invalid line number: %d", lineMax+1), "", 0, 11},
// test effect of //line directive on (relative) position information
- {"//line foo:123\n foo", "syntax error: package statement must be first", "foo", 123, 3},
- {"//line foo:123\n//line bar:345\nfoo", "syntax error: package statement must be first", "bar", 345, 0},
+ {"//line foo:123\n foo", "syntax error: package statement must be first", "foo", 123 - linebase, 3},
+ {"//line foo:123\n//line bar:345\nfoo", "syntax error: package statement must be first", "bar", 345 - linebase, 0},
} {
_, err := ParseBytes(nil, []byte(test.src), nil, nil, 0)
if err == nil {
@@ -219,11 +219,11 @@ func TestLineDirectives(t *testing.T) {
if filename := perr.Pos.RelFilename(); filename != test.filename {
t.Errorf("%s: got filename = %q; want %q", test.src, filename, test.filename)
}
- if line := perr.Pos.RelLine(); line != test.line {
- t.Errorf("%s: got line = %d; want %d", test.src, line, test.line)
+ if line := perr.Pos.RelLine(); line != test.line+linebase {
+ t.Errorf("%s: got line = %d; want %d", test.src, line, test.line+linebase)
}
- if col := perr.Pos.Col(); col != test.col {
- t.Errorf("%s: got col = %d; want %d", test.src, col, test.col)
+ if col := perr.Pos.Col(); col != test.col+colbase {
+ t.Errorf("%s: got col = %d; want %d", test.src, col, test.col+colbase)
}
}
}
diff --git a/src/cmd/compile/internal/syntax/scanner.go b/src/cmd/compile/internal/syntax/scanner.go
index c2de9ce686..05391e5efb 100644
--- a/src/cmd/compile/internal/syntax/scanner.go
+++ b/src/cmd/compile/internal/syntax/scanner.go
@@ -577,12 +577,12 @@ func (s *scanner) skipLine(r rune) {
func (s *scanner) lineComment() {
r := s.getr()
- // directives must start at the beginning of the line (s.col == 0)
- if s.col != 0 || s.pragh == nil || (r != 'g' && r != 'l') {
+ // directives must start at the beginning of the line (s.col == colbase)
+ if s.col != colbase || s.pragh == nil || (r != 'g' && r != 'l') {
s.skipLine(r)
return
}
- // s.col == 0 && s.pragh != nil && (r == 'g' || r == 'l')
+ // s.col == colbase && s.pragh != nil && (r == 'g' || r == 'l')
// recognize directives
prefix := "go:"
diff --git a/src/cmd/compile/internal/syntax/scanner_test.go b/src/cmd/compile/internal/syntax/scanner_test.go
index 4d04e62875..e434db9a91 100644
--- a/src/cmd/compile/internal/syntax/scanner_test.go
+++ b/src/cmd/compile/internal/syntax/scanner_test.go
@@ -56,8 +56,8 @@ func TestTokens(t *testing.T) {
for i, want := range sampleTokens {
nlsemi := false
- if got.line != uint(i+1) {
- t.Errorf("got line %d; want %d", got.line, i+1)
+ if got.line != uint(i+linebase) {
+ t.Errorf("got line %d; want %d", got.line, i+linebase)
}
if got.tok != want.tok {
@@ -264,75 +264,75 @@ var sampleTokens = [...]struct {
func TestScanErrors(t *testing.T) {
for _, test := range []struct {
src, msg string
- line, col uint
+ line, col uint // 0-based
}{
// 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", 1, 2},
- {"foo\n\ufeff bar", "invalid BOM in the middle of the file", 2, 0},
- {"foo\n\n\xff ", "invalid UTF-8 encoding", 3, 0},
+ {"fo\x00o", "invalid NUL character", 0, 2},
+ {"foo\n\ufeff bar", "invalid BOM in the middle of the file", 1, 0},
+ {"foo\n\n\xff ", "invalid UTF-8 encoding", 2, 0},
// token-level errors
- {"\u00BD" /* ½ */, "invalid identifier character U+00BD '½'", 1, 0},
- {"\U0001d736\U0001d737\U0001d738_½" /* 𝜶𝜷𝜸_½ */, "invalid identifier character U+00BD '½'", 1, 13 /* byte offset */},
- {"\U0001d7d8" /* 𝟘 */, "identifier cannot begin with digit U+1D7D8 '𝟘'", 1, 0},
- {"foo\U0001d7d8_½" /* foo𝟘_½ */, "invalid identifier character U+00BD '½'", 1, 8 /* byte offset */},
+ {"\u00BD" /* ½ */, "invalid identifier character U+00BD '½'", 0, 0},
+ {"\U0001d736\U0001d737\U0001d738_½" /* 𝜶𝜷𝜸_½ */, "invalid identifier character U+00BD '½'", 0, 13 /* byte offset */},
+ {"\U0001d7d8" /* 𝟘 */, "identifier cannot begin with digit U+1D7D8 '𝟘'", 0, 0},
+ {"foo\U0001d7d8_½" /* foo𝟘_½ */, "invalid identifier character U+00BD '½'", 0, 8 /* byte offset */},
- {"x + ~y", "bitwise complement operator is ^", 1, 4},
- {"foo$bar = 0", "invalid character U+0024 '$'", 1, 3},
- {"const x = 0xyz", "malformed hex constant", 1, 12},
- {"0123456789", "malformed octal constant", 1, 10},
- {"0123456789. /* foobar", "comment not terminated", 1, 12}, // valid float constant
- {"0123456789e0 /*\nfoobar", "comment not terminated", 1, 13}, // valid float constant
- {"var a, b = 08, 07\n", "malformed octal constant", 1, 13},
- {"(x + 1.0e+x)", "malformed floating-point constant exponent", 1, 10},
+ {"x + ~y", "bitwise complement operator is ^", 0, 4},
+ {"foo$bar = 0", "invalid character U+0024 '$'", 0, 3},
+ {"const x = 0xyz", "malformed hex constant", 0, 12},
+ {"0123456789", "malformed octal constant", 0, 10},
+ {"0123456789. /* foobar", "comment not terminated", 0, 12}, // valid float constant
+ {"0123456789e0 /*\nfoobar", "comment not terminated", 0, 13}, // valid float constant
+ {"var a, b = 08, 07\n", "malformed octal constant", 0, 13},
+ {"(x + 1.0e+x)", "malformed floating-point constant exponent", 0, 10},
- {`''`, "empty character literal or unescaped ' in character literal", 1, 1},
- {"'\n", "newline in character literal", 1, 1},
- {`'\`, "invalid character literal (missing closing ')", 1, 0},
- {`'\'`, "invalid character literal (missing closing ')", 1, 0},
- {`'\x`, "invalid character literal (missing closing ')", 1, 0},
- {`'\x'`, "non-hex character in escape sequence: '", 1, 3},
- {`'\y'`, "unknown escape sequence", 1, 2},
- {`'\x0'`, "non-hex character in escape sequence: '", 1, 4},
- {`'\00'`, "non-octal character in escape sequence: '", 1, 4},
- {`'\377' /*`, "comment not terminated", 1, 7}, // valid octal escape
- {`'\378`, "non-octal character in escape sequence: 8", 1, 4},
- {`'\400'`, "octal escape value > 255: 256", 1, 5},
- {`'xx`, "invalid character literal (missing closing ')", 1, 0},
- {`'xx'`, "invalid character literal (more than one character)", 1, 0},
+ {`''`, "empty character literal or unescaped ' in character literal", 0, 1},
+ {"'\n", "newline in character literal", 0, 1},
+ {`'\`, "invalid character literal (missing closing ')", 0, 0},
+ {`'\'`, "invalid character literal (missing closing ')", 0, 0},
+ {`'\x`, "invalid character literal (missing closing ')", 0, 0},
+ {`'\x'`, "non-hex character in escape sequence: '", 0, 3},
+ {`'\y'`, "unknown escape sequence", 0, 2},
+ {`'\x0'`, "non-hex character in escape sequence: '", 0, 4},
+ {`'\00'`, "non-octal character in escape sequence: '", 0, 4},
+ {`'\377' /*`, "comment not terminated", 0, 7}, // valid octal escape
+ {`'\378`, "non-octal character in escape sequence: 8", 0, 4},
+ {`'\400'`, "octal escape value > 255: 256", 0, 5},
+ {`'xx`, "invalid character literal (missing closing ')", 0, 0},
+ {`'xx'`, "invalid character literal (more than one character)", 0, 0},
- {"\"\n", "newline in string", 1, 1},
- {`"`, "string not terminated", 1, 0},
- {`"foo`, "string not terminated", 1, 0},
- {"`", "string not terminated", 1, 0},
- {"`foo", "string not terminated", 1, 0},
- {"/*/", "comment not terminated", 1, 0},
- {"/*\n\nfoo", "comment not terminated", 1, 0},
- {"/*\n\nfoo", "comment not terminated", 1, 0},
- {`"\`, "string not terminated", 1, 0},
- {`"\"`, "string not terminated", 1, 0},
- {`"\x`, "string not terminated", 1, 0},
- {`"\x"`, "non-hex character in escape sequence: \"", 1, 3},
- {`"\y"`, "unknown escape sequence", 1, 2},
- {`"\x0"`, "non-hex character in escape sequence: \"", 1, 4},
- {`"\00"`, "non-octal character in escape sequence: \"", 1, 4},
- {`"\377" /*`, "comment not terminated", 1, 7}, // valid octal escape
- {`"\378"`, "non-octal character in escape sequence: 8", 1, 4},
- {`"\400"`, "octal escape value > 255: 256", 1, 5},
+ {"\"\n", "newline in string", 0, 1},
+ {`"`, "string not terminated", 0, 0},
+ {`"foo`, "string not terminated", 0, 0},
+ {"`", "string not terminated", 0, 0},
+ {"`foo", "string not terminated", 0, 0},
+ {"/*/", "comment not terminated", 0, 0},
+ {"/*\n\nfoo", "comment not terminated", 0, 0},
+ {"/*\n\nfoo", "comment not terminated", 0, 0},
+ {`"\`, "string not terminated", 0, 0},
+ {`"\"`, "string not terminated", 0, 0},
+ {`"\x`, "string not terminated", 0, 0},
+ {`"\x"`, "non-hex character in escape sequence: \"", 0, 3},
+ {`"\y"`, "unknown escape sequence", 0, 2},
+ {`"\x0"`, "non-hex character in escape sequence: \"", 0, 4},
+ {`"\00"`, "non-octal character in escape sequence: \"", 0, 4},
+ {`"\377" /*`, "comment not terminated", 0, 7}, // valid octal escape
+ {`"\378"`, "non-octal character in escape sequence: 8", 0, 4},
+ {`"\400"`, "octal escape value > 255: 256", 0, 5},
- {`s := "foo\z"`, "unknown escape sequence", 1, 10},
- {`s := "foo\z00\nbar"`, "unknown escape sequence", 1, 10},
- {`"\x`, "string not terminated", 1, 0},
- {`"\x"`, "non-hex character in escape sequence: \"", 1, 3},
- {`var s string = "\x"`, "non-hex character in escape sequence: \"", 1, 18},
- {`return "\Uffffffff"`, "escape sequence is invalid Unicode code point", 1, 18},
+ {`s := "foo\z"`, "unknown escape sequence", 0, 10},
+ {`s := "foo\z00\nbar"`, "unknown escape sequence", 0, 10},
+ {`"\x`, "string not terminated", 0, 0},
+ {`"\x"`, "non-hex character in escape sequence: \"", 0, 3},
+ {`var s string = "\x"`, "non-hex character in escape sequence: \"", 0, 18},
+ {`return "\Uffffffff"`, "escape sequence is invalid Unicode code point", 0, 18},
// former problem cases
- {"package p\n\n\xef", "invalid UTF-8 encoding", 3, 0},
+ {"package p\n\n\xef", "invalid UTF-8 encoding", 2, 0},
} {
var s scanner
nerrors := 0
@@ -343,11 +343,11 @@ func TestScanErrors(t *testing.T) {
if msg != test.msg {
t.Errorf("%q: got msg = %q; want %q", test.src, msg, test.msg)
}
- if line != test.line {
- t.Errorf("%q: got line = %d; want %d", test.src, line, test.line)
+ if line != test.line+linebase {
+ t.Errorf("%q: got line = %d; want %d", test.src, line, test.line+linebase)
}
- if col != test.col {
- t.Errorf("%q: got col = %d; want %d", test.src, col, test.col)
+ if col != test.col+colbase {
+ t.Errorf("%q: got col = %d; want %d", test.src, col, test.col+colbase)
}
} else if nerrors > 1 {
// TODO(gri) make this use position info
diff --git a/src/cmd/compile/internal/syntax/source.go b/src/cmd/compile/internal/syntax/source.go
index 4ce35a3615..93547213c0 100644
--- a/src/cmd/compile/internal/syntax/source.go
+++ b/src/cmd/compile/internal/syntax/source.go
@@ -18,6 +18,10 @@ import (
"unicode/utf8"
)
+// starting points for line and column numbers
+const linebase = 1
+const colbase = 1
+
// buf [...read...|...|...unread...|s|...free...]
// ^ ^ ^ ^
// | | | |
@@ -49,8 +53,8 @@ func (s *source) init(src io.Reader, errh func(line, pos uint, msg string)) {
s.buf[0] = utf8.RuneSelf // terminate with sentinel
s.offs = 0
s.r0, s.r, s.w = 0, 0, 0
- s.line0, s.line = 1, 1
- s.col0, s.col = 0, 0
+ s.line0, s.line = 0, linebase
+ s.col0, s.col = 0, colbase
s.ioerr = nil
s.lit = s.lit[:0]
@@ -112,7 +116,7 @@ redo:
}
if b == '\n' {
s.line++
- s.col = 0
+ s.col = colbase
}
return rune(b)
}