Fix panic in parser when first token is invalid
newParser was calling p.next(), which could trigger a scanner error that results in a panic. Move the first p.next() into parse(p), which correctly converts the paanic into a reportable error. Bug: 254831383 Test: TestParserError Change-Id: I2a427010379bb8dd5087550c7f159499cbb84066
This commit is contained in:
parent
c5e959b244
commit
31c10a12c8
2 changed files with 33 additions and 3 deletions
|
@ -70,6 +70,7 @@ func parse(p *parser) (file *File, errs []error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
p.next()
|
||||||
defs := p.parseDefinitions()
|
defs := p.parseDefinitions()
|
||||||
p.accept(scanner.EOF)
|
p.accept(scanner.EOF)
|
||||||
errs = p.errors
|
errs = p.errors
|
||||||
|
@ -100,6 +101,7 @@ func Parse(filename string, r io.Reader, scope *Scope) (file *File, errs []error
|
||||||
|
|
||||||
func ParseExpression(r io.Reader) (value Expression, errs []error) {
|
func ParseExpression(r io.Reader) (value Expression, errs []error) {
|
||||||
p := newParser(r, NewScope(nil))
|
p := newParser(r, NewScope(nil))
|
||||||
|
p.next()
|
||||||
value = p.parseExpression()
|
value = p.parseExpression()
|
||||||
p.accept(scanner.EOF)
|
p.accept(scanner.EOF)
|
||||||
errs = p.errors
|
errs = p.errors
|
||||||
|
@ -124,7 +126,6 @@ func newParser(r io.Reader, scope *Scope) *parser {
|
||||||
}
|
}
|
||||||
p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanStrings |
|
p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanStrings |
|
||||||
scanner.ScanRawStrings | scanner.ScanComments
|
scanner.ScanRawStrings | scanner.ScanComments
|
||||||
p.next()
|
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1139,7 +1139,7 @@ var validParseTestCases = []struct {
|
||||||
Comments: []*Comment{
|
Comments: []*Comment{
|
||||||
&Comment{
|
&Comment{
|
||||||
Comment: []string{"/* comment3", " comment4 */"},
|
Comment: []string{"/* comment3", " comment4 */"},
|
||||||
Slash: mkpos(32, 5, 3),
|
Slash: mkpos(32, 5, 3),
|
||||||
},
|
},
|
||||||
&Comment{
|
&Comment{
|
||||||
Comment: []string{"// comment5"},
|
Comment: []string{"// comment5"},
|
||||||
|
@ -1214,7 +1214,36 @@ func TestParseValidInput(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Test error strings
|
func TestParserError(t *testing.T) {
|
||||||
|
testcases := []struct {
|
||||||
|
name string
|
||||||
|
input string
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "invalid first token",
|
||||||
|
input: "\x00",
|
||||||
|
err: "invalid character NUL",
|
||||||
|
},
|
||||||
|
// TODO: test more parser errors
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range testcases {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
r := bytes.NewBufferString(tt.input)
|
||||||
|
_, errs := ParseAndEval("", r, NewScope(nil))
|
||||||
|
if len(errs) == 0 {
|
||||||
|
t.Fatalf("missing expected error")
|
||||||
|
}
|
||||||
|
if g, w := errs[0], tt.err; !strings.Contains(g.Error(), w) {
|
||||||
|
t.Errorf("expected error %q, got %q", w, g)
|
||||||
|
}
|
||||||
|
for _, err := range errs[1:] {
|
||||||
|
t.Errorf("got unexpected extra error %q", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestParserEndPos(t *testing.T) {
|
func TestParserEndPos(t *testing.T) {
|
||||||
in := `
|
in := `
|
||||||
|
|
Loading…
Reference in a new issue