From 9cae339546b01f0fcfccbfd1e2e6cc71d473426f Mon Sep 17 00:00:00 2001 From: James Shubin Date: Tue, 22 May 2018 20:02:50 -0400 Subject: [PATCH] lang: Error parser if SetType fails to avoid a panic Turns out we can actually cause the parser to error instead of needing to panic. It definitely seems to work, and is better than the panic. The only awkward thing is how this plumbing works in yacc world. If anyone knows why this is wrong, please let me know. Reading the generated code seems to imply that this is correct. --- lang/lexparse.go | 1 + lang/lexparse_test.go | 24 ++++++++++++++++++++++++ lang/parser.y | 5 ++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lang/lexparse.go b/lang/lexparse.go index a3e689ec..c3e5d71c 100644 --- a/lang/lexparse.go +++ b/lang/lexparse.go @@ -31,6 +31,7 @@ const ( ErrLexerIntegerOverflow = interfaces.Error("integer: overflow") ErrLexerFloatOverflow = interfaces.Error("float: overflow") ErrParseError = interfaces.Error("parser") + ErrParseSetType = interfaces.Error("can't set return type in parser") ErrParseAdditionalEquals = interfaces.Error(errstrParseAdditionalEquals) ErrParseExpectingComma = interfaces.Error(errstrParseExpectingComma) ) diff --git a/lang/lexparse_test.go b/lang/lexparse_test.go index 5a062f8d..75152b1c 100644 --- a/lang/lexparse_test.go +++ b/lang/lexparse_test.go @@ -835,6 +835,30 @@ func TestLexParse0(t *testing.T) { exp: exp, }) } + { + values = append(values, test{ + name: "parser set type incompatibility str", + code: ` + $x int = "hello" # type should be str to work + test "t1" { + str => $x, + } + `, + fail: true, + }) + } + { + values = append(values, test{ + name: "parser set type incompatibility int", + code: ` + $x int = "hello" # value should be int to work + test "t1" { + int => $x, + } + `, + fail: true, + }) + } for index, test := range values { // run all the tests name, code, fail, exp := test.name, test.code, test.fail, test.exp diff --git a/lang/parser.y b/lang/parser.y index 34729e56..18c3e581 100644 --- a/lang/parser.y +++ b/lang/parser.y @@ -637,7 +637,8 @@ bind: posLast(yylex, yyDollar) // our pos var expr interfaces.Expr = $4.expr if err := expr.SetType($2.typ); err != nil { - panic(fmt.Sprintf("can't set type in parser: %+v", err)) + // this will ultimately cause a parser error to occur... + yylex.Error(fmt.Sprintf("%s: %+v", ErrParseSetType, err)) } $$.stmt = &StmtBind{ Ident: $1.str, @@ -926,6 +927,8 @@ func (yylex *Lexer) Error(str string) { err = ErrParseAdditionalEquals } else if strings.HasSuffix(str, ErrParseExpectingComma.Error()) { err = ErrParseExpectingComma + } else if strings.HasPrefix(str, ErrParseSetType.Error()) { + err = ErrParseSetType } lp.parseErr = &LexParseErr{ Err: err,