mirror of
https://github.com/google/go-jsonnet.git
synced 2025-09-28 17:01:02 +02:00
Add ParseParameter. Also fell down the rabbithole improving content and consistency of parse errors
This commit is contained in:
parent
ce07c7fb8b
commit
5476fefb25
@ -69,7 +69,7 @@ func (ef *termErrorFormatter) Format(err error) string {
|
|||||||
case RuntimeError:
|
case RuntimeError:
|
||||||
return ef.formatRuntime(&err)
|
return ef.formatRuntime(&err)
|
||||||
case errors.StaticError:
|
case errors.StaticError:
|
||||||
return ef.formatStatic(&err)
|
return ef.formatStatic(err)
|
||||||
default:
|
default:
|
||||||
return ef.formatInternal(err)
|
return ef.formatInternal(err)
|
||||||
}
|
}
|
||||||
@ -79,10 +79,10 @@ func (ef *termErrorFormatter) formatRuntime(err *RuntimeError) string {
|
|||||||
return err.Error() + "\n" + ef.buildStackTrace(err.StackTrace)
|
return err.Error() + "\n" + ef.buildStackTrace(err.StackTrace)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ef *termErrorFormatter) formatStatic(err *errors.StaticError) string {
|
func (ef *termErrorFormatter) formatStatic(err errors.StaticError) string {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
buf.WriteString(err.Error() + "\n")
|
buf.WriteString(err.Error() + "\n")
|
||||||
ef.showCode(&buf, err.Loc)
|
ef.showCode(&buf, err.Loc())
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,26 +27,45 @@ import (
|
|||||||
|
|
||||||
// StaticError represents an error during parsing/lexing or static analysis.
|
// StaticError represents an error during parsing/lexing or static analysis.
|
||||||
// TODO(sbarzowski) Make it possible to have multiple static errors and warnings
|
// TODO(sbarzowski) Make it possible to have multiple static errors and warnings
|
||||||
type StaticError struct {
|
type StaticError interface {
|
||||||
Loc ast.LocationRange
|
// WithContext returns a new StaticError with additional context before the error message.
|
||||||
Msg string
|
WithContext(string) StaticError
|
||||||
|
// Error returns the string representation of a StaticError.
|
||||||
|
Error() string
|
||||||
|
// Loc returns the place in the source code that triggerred the error.
|
||||||
|
Loc() ast.LocationRange
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeStaticErrorMsg returns a StaticError with a message.
|
type staticError struct {
|
||||||
|
loc ast.LocationRange
|
||||||
|
msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err staticError) WithContext(context string) StaticError {
|
||||||
|
return staticError{
|
||||||
|
loc: err.loc,
|
||||||
|
msg: fmt.Sprintf("%v while %s", err.msg, context),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err staticError) Error() string {
|
||||||
|
loc := ""
|
||||||
|
if err.loc.IsSet() {
|
||||||
|
loc = err.loc.String()
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%v %v", loc, err.msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err staticError) Loc() ast.LocationRange {
|
||||||
|
return err.loc
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeStaticErrorMsg returns a staticError with a message.
|
||||||
func MakeStaticErrorMsg(msg string) StaticError {
|
func MakeStaticErrorMsg(msg string) StaticError {
|
||||||
return StaticError{Msg: msg}
|
return staticError{msg: msg}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeStaticError returns a StaticError with a message and a LocationRange.
|
// MakeStaticError returns a StaticError with a message and a LocationRange.
|
||||||
func MakeStaticError(msg string, lr ast.LocationRange) StaticError {
|
func MakeStaticError(msg string, lr ast.LocationRange) StaticError {
|
||||||
return StaticError{Msg: msg, Loc: lr}
|
return staticError{msg: msg, loc: lr}
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns the string representation of a StaticError.
|
|
||||||
func (err StaticError) Error() string {
|
|
||||||
loc := ""
|
|
||||||
if err.Loc.IsSet() {
|
|
||||||
loc = err.Loc.String()
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%v %v", loc, err.Msg)
|
|
||||||
}
|
}
|
||||||
|
@ -126,6 +126,17 @@ var tokenKindStrings = []string{
|
|||||||
tokenEndOfFile: "end of file",
|
tokenEndOfFile: "end of file",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tokenHasContent = map[tokenKind]bool{
|
||||||
|
tokenIdentifier: true,
|
||||||
|
tokenNumber: true,
|
||||||
|
tokenOperator: true,
|
||||||
|
tokenStringBlock: true,
|
||||||
|
tokenStringDouble: true,
|
||||||
|
tokenStringSingle: true,
|
||||||
|
tokenVerbatimStringDouble: true,
|
||||||
|
tokenVerbatimStringSingle: true,
|
||||||
|
}
|
||||||
|
|
||||||
func (tk tokenKind) String() string {
|
func (tk tokenKind) String() string {
|
||||||
if tk < 0 || int(tk) >= len(tokenKindStrings) {
|
if tk < 0 || int(tk) >= len(tokenKindStrings) {
|
||||||
panic(fmt.Sprintf("INTERNAL ERROR: Unknown token kind:: %d", tk))
|
panic(fmt.Sprintf("INTERNAL ERROR: Unknown token kind:: %d", tk))
|
||||||
@ -151,10 +162,10 @@ type Tokens []token
|
|||||||
func (t *token) String() string {
|
func (t *token) String() string {
|
||||||
if t.data == "" {
|
if t.data == "" {
|
||||||
return t.kind.String()
|
return t.kind.String()
|
||||||
} else if t.kind == tokenOperator {
|
} else if tokenHasContent[t.kind] {
|
||||||
return fmt.Sprintf("\"%v\"", t.data)
|
|
||||||
} else {
|
|
||||||
return fmt.Sprintf("(%v, \"%v\")", t.kind, t.data)
|
return fmt.Sprintf("(%v, \"%v\")", t.kind, t.data)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("\"%v\"", t.data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +382,7 @@ func (l *lexer) emitFullToken(kind tokenKind, data, stringBlockIndent, stringBlo
|
|||||||
data: data,
|
data: data,
|
||||||
stringBlockIndent: stringBlockIndent,
|
stringBlockIndent: stringBlockIndent,
|
||||||
stringBlockTermIndent: stringBlockTermIndent,
|
stringBlockTermIndent: stringBlockTermIndent,
|
||||||
loc: ast.MakeLocationRange(l.fileName, l.source, l.tokenStartLoc, l.location()),
|
loc: ast.MakeLocationRange(l.fileName, l.source, l.tokenStartLoc, l.location()),
|
||||||
})
|
})
|
||||||
l.fodder = ast.Fodder{}
|
l.fodder = ast.Fodder{}
|
||||||
}
|
}
|
||||||
@ -387,7 +398,7 @@ func (l *lexer) addFodder(kind ast.FodderKind, blanks int, indent int, comment [
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *lexer) makeStaticErrorPoint(msg string, loc ast.Location) errors.StaticError {
|
func (l *lexer) makeStaticErrorPoint(msg string, loc ast.Location) errors.StaticError {
|
||||||
return errors.StaticError{Msg: msg, Loc: ast.MakeLocationRange(l.fileName, l.source, loc, loc)}
|
return errors.MakeStaticError(msg, ast.MakeLocationRange(l.fileName, l.source, loc, loc))
|
||||||
}
|
}
|
||||||
|
|
||||||
// lexWhitespace consumes all whitespace and returns the number of \n and number of
|
// lexWhitespace consumes all whitespace and returns the number of \n and number of
|
||||||
|
@ -56,9 +56,9 @@ var bopPrecedence = map[ast.BinaryOp]precedence{
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
func makeUnexpectedError(t *token, while string) error {
|
func makeUnexpectedError(t *token, while string) errors.StaticError {
|
||||||
return errors.MakeStaticError(
|
return errors.MakeStaticError(
|
||||||
fmt.Sprintf("Unexpected: %v while %v", t, while), t.loc)
|
fmt.Sprintf("Unexpected: %v", t), t.loc).WithContext(while)
|
||||||
}
|
}
|
||||||
|
|
||||||
func locFromTokens(begin, end *token) ast.LocationRange {
|
func locFromTokens(begin, end *token) ast.LocationRange {
|
||||||
@ -88,14 +88,14 @@ func (p *parser) pop() *token {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) unexpectedTokenError(tk tokenKind, t *token) error {
|
func (p *parser) unexpectedTokenError(tk tokenKind, t *token) errors.StaticError {
|
||||||
if tk == t.kind {
|
if tk == t.kind {
|
||||||
panic("Unexpectedly expected token kind.")
|
panic("Unexpectedly expected token kind")
|
||||||
}
|
}
|
||||||
return errors.MakeStaticError(fmt.Sprintf("Expected token %v but got %v", tk, t), t.loc)
|
return errors.MakeStaticError(fmt.Sprintf("Expected token %v but got %v", tk, t), t.loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) popExpect(tk tokenKind) (*token, error) {
|
func (p *parser) popExpect(tk tokenKind) (*token, errors.StaticError) {
|
||||||
t := p.pop()
|
t := p.pop()
|
||||||
if t.kind != tk {
|
if t.kind != tk {
|
||||||
return nil, p.unexpectedTokenError(tk, t)
|
return nil, p.unexpectedTokenError(tk, t)
|
||||||
@ -103,7 +103,7 @@ func (p *parser) popExpect(tk tokenKind) (*token, error) {
|
|||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) popExpectOp(op string) (*token, error) {
|
func (p *parser) popExpectOp(op string) (*token, errors.StaticError) {
|
||||||
t := p.pop()
|
t := p.pop()
|
||||||
if t.kind != tokenOperator || t.data != op {
|
if t.kind != tokenOperator || t.data != op {
|
||||||
return nil, errors.MakeStaticError(
|
return nil, errors.MakeStaticError(
|
||||||
@ -133,7 +133,7 @@ func astVarToIdentifier(node ast.Node) (ast.Fodder, *ast.Identifier, bool) {
|
|||||||
// parseArgument parses either <f1> id <f2> = expr or just expr.
|
// parseArgument parses either <f1> id <f2> = expr or just expr.
|
||||||
// It returns either (<f1>, id, <f2>, expr) or (nil, nil, nil, expr)
|
// It returns either (<f1>, id, <f2>, expr) or (nil, nil, nil, expr)
|
||||||
// respectively.
|
// respectively.
|
||||||
func (p *parser) parseArgument() (ast.Fodder, *ast.Identifier, ast.Fodder, ast.Node, error) {
|
func (p *parser) parseArgument() (ast.Fodder, *ast.Identifier, ast.Fodder, ast.Node, errors.StaticError) {
|
||||||
var idFodder ast.Fodder
|
var idFodder ast.Fodder
|
||||||
var id *ast.Identifier
|
var id *ast.Identifier
|
||||||
var eqFodder ast.Fodder
|
var eqFodder ast.Fodder
|
||||||
@ -153,7 +153,7 @@ func (p *parser) parseArgument() (ast.Fodder, *ast.Identifier, ast.Fodder, ast.N
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(sbarzowski) - this returned bool is weird
|
// TODO(sbarzowski) - this returned bool is weird
|
||||||
func (p *parser) parseArguments(elementKind string) (*token, *ast.Arguments, bool, error) {
|
func (p *parser) parseArguments(elementKind string) (*token, *ast.Arguments, bool, errors.StaticError) {
|
||||||
args := &ast.Arguments{}
|
args := &ast.Arguments{}
|
||||||
gotComma := false
|
gotComma := false
|
||||||
commaFodder := ast.Fodder{}
|
commaFodder := ast.Fodder{}
|
||||||
@ -168,7 +168,7 @@ func (p *parser) parseArguments(elementKind string) (*token, *ast.Arguments, boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !first && !gotComma {
|
if !first && !gotComma {
|
||||||
return nil, nil, false, errors.MakeStaticError(fmt.Sprintf("Expected a comma before next %s, got %s.", elementKind, next), next.loc)
|
return nil, nil, false, errors.MakeStaticError(fmt.Sprintf("Expected a comma before next %s, got %s", elementKind, next), next.loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
idFodder, id, eqFodder, expr, err := p.parseArgument()
|
idFodder, id, eqFodder, expr, err := p.parseArgument()
|
||||||
@ -208,8 +208,34 @@ func (p *parser) parseArguments(elementKind string) (*token, *ast.Arguments, boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseParameter parses either <f1> id <f2> = expr or just <f1> id.
|
||||||
|
// It returns either (<f1>, id, <f2>, expr) or (<f1>, id, nil, nil)
|
||||||
|
// respectively.
|
||||||
|
func (p *parser) parseParameter() (ast.Fodder, *ast.Identifier, ast.Fodder, ast.Node, errors.StaticError) {
|
||||||
|
var idFodder ast.Fodder
|
||||||
|
var id *ast.Identifier
|
||||||
|
var eqFodder ast.Fodder
|
||||||
|
ident, err := p.popExpect(tokenIdentifier)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, nil, err.WithContext("parsing parameter")
|
||||||
|
}
|
||||||
|
var tmpID = ast.Identifier(ident.data)
|
||||||
|
id = &tmpID
|
||||||
|
idFodder = ident.fodder
|
||||||
|
if p.peek().kind == tokenOperator && p.peek().data == "=" {
|
||||||
|
eq := p.pop()
|
||||||
|
eqFodder = eq.fodder
|
||||||
|
expr, err := p.parse(maxPrecedence)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, nil, err
|
||||||
|
}
|
||||||
|
return idFodder, id, eqFodder, expr, nil
|
||||||
|
}
|
||||||
|
return idFodder, id, nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(sbarzowski) - this returned bool is weird
|
// TODO(sbarzowski) - this returned bool is weird
|
||||||
func (p *parser) parseParameters(elementKind string) (*token, []ast.Parameter, bool, error) {
|
func (p *parser) parseParameters(elementKind string) (*token, []ast.Parameter, bool, errors.StaticError) {
|
||||||
|
|
||||||
var parenR *token
|
var parenR *token
|
||||||
var params []ast.Parameter
|
var params []ast.Parameter
|
||||||
@ -226,10 +252,10 @@ func (p *parser) parseParameters(elementKind string) (*token, []ast.Parameter, b
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !first && !gotComma {
|
if !first && !gotComma {
|
||||||
return nil, nil, false, errors.MakeStaticError(fmt.Sprintf("Expected a comma before next %s, got %s.", elementKind, next), next.loc)
|
return nil, nil, false, errors.MakeStaticError(fmt.Sprintf("Expected a comma before next %s, got %s", elementKind, next), next.loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
idFodder, id, eqFodder, expr, err := p.parseArgument()
|
idFodder, id, eqFodder, expr, err := p.parseParameter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, false, err
|
return nil, nil, false, err
|
||||||
}
|
}
|
||||||
@ -242,15 +268,11 @@ func (p *parser) parseParameters(elementKind string) (*token, []ast.Parameter, b
|
|||||||
gotComma = false
|
gotComma = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if id == nil {
|
if expr == nil {
|
||||||
// Param has no default, is just 'id2'
|
// Param has no default
|
||||||
idFodder2, id2, ok := astVarToIdentifier(expr)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, false, errors.MakeStaticError(fmt.Sprintf("Expected simple identifier but got a complex expression."), *expr.Loc())
|
|
||||||
}
|
|
||||||
param := ast.Parameter{
|
param := ast.Parameter{
|
||||||
NameFodder: idFodder2,
|
NameFodder: idFodder,
|
||||||
Name: *id2,
|
Name: *id,
|
||||||
}
|
}
|
||||||
if gotComma {
|
if gotComma {
|
||||||
param.CommaFodder = commaFodder
|
param.CommaFodder = commaFodder
|
||||||
@ -274,10 +296,10 @@ func (p *parser) parseParameters(elementKind string) (*token, []ast.Parameter, b
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(sbarzowski) add location to all individual binds
|
// TODO(sbarzowski) add location to all individual binds
|
||||||
func (p *parser) parseBind(binds *ast.LocalBinds) (*token, error) {
|
func (p *parser) parseBind(binds *ast.LocalBinds) (*token, errors.StaticError) {
|
||||||
varID, err := p.popExpect(tokenIdentifier)
|
varID, popErr := p.popExpect(tokenIdentifier)
|
||||||
if err != nil {
|
if popErr != nil {
|
||||||
return nil, err
|
return nil, popErr
|
||||||
}
|
}
|
||||||
for _, b := range *binds {
|
for _, b := range *binds {
|
||||||
if b.Variable == ast.Identifier(varID.data) {
|
if b.Variable == ast.Identifier(varID.data) {
|
||||||
@ -301,9 +323,9 @@ func (p *parser) parseBind(binds *ast.LocalBinds) (*token, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eqToken, err := p.popExpectOp("=")
|
eqToken, popErr := p.popExpectOp("=")
|
||||||
if err != nil {
|
if popErr != nil {
|
||||||
return nil, err
|
return nil, popErr
|
||||||
}
|
}
|
||||||
body, err := p.parse(maxPrecedence)
|
body, err := p.parse(maxPrecedence)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -339,7 +361,7 @@ func (p *parser) parseBind(binds *ast.LocalBinds) (*token, error) {
|
|||||||
return delim, nil
|
return delim, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) parseObjectAssignmentOp() (opFodder ast.Fodder, plusSugar bool, hide ast.ObjectFieldHide, err error) {
|
func (p *parser) parseObjectAssignmentOp() (opFodder ast.Fodder, plusSugar bool, hide ast.ObjectFieldHide, err errors.StaticError) {
|
||||||
op, err := p.popExpect(tokenOperator)
|
op, err := p.popExpect(tokenOperator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -382,7 +404,7 @@ func (p *parser) parseObjectAssignmentOp() (opFodder ast.Fodder, plusSugar bool,
|
|||||||
// +gen set
|
// +gen set
|
||||||
type LiteralField string
|
type LiteralField string
|
||||||
|
|
||||||
func (p *parser) parseObjectRemainderComp(fields ast.ObjectFields, gotComma bool, tok *token, next *token) (ast.Node, *token, error) {
|
func (p *parser) parseObjectRemainderComp(fields ast.ObjectFields, gotComma bool, tok *token, next *token) (ast.Node, *token, errors.StaticError) {
|
||||||
numFields := 0
|
numFields := 0
|
||||||
numAsserts := 0
|
numAsserts := 0
|
||||||
var field ast.ObjectField
|
var field ast.ObjectField
|
||||||
@ -399,16 +421,16 @@ func (p *parser) parseObjectRemainderComp(fields ast.ObjectFields, gotComma bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
if numAsserts > 0 {
|
if numAsserts > 0 {
|
||||||
return nil, nil, errors.MakeStaticError("Object comprehension cannot have asserts.", next.loc)
|
return nil, nil, errors.MakeStaticError("Object comprehension cannot have asserts", next.loc)
|
||||||
}
|
}
|
||||||
if numFields != 1 {
|
if numFields != 1 {
|
||||||
return nil, nil, errors.MakeStaticError("Object comprehension can only have one field.", next.loc)
|
return nil, nil, errors.MakeStaticError("Object comprehension can only have one field", next.loc)
|
||||||
}
|
}
|
||||||
if field.Hide != ast.ObjectFieldInherit {
|
if field.Hide != ast.ObjectFieldInherit {
|
||||||
return nil, nil, errors.MakeStaticError("Object comprehensions cannot have hidden fields.", next.loc)
|
return nil, nil, errors.MakeStaticError("Object comprehensions cannot have hidden fields", next.loc)
|
||||||
}
|
}
|
||||||
if field.Kind != ast.ObjectFieldExpr {
|
if field.Kind != ast.ObjectFieldExpr {
|
||||||
return nil, nil, errors.MakeStaticError("Object comprehensions can only have [e] fields.", next.loc)
|
return nil, nil, errors.MakeStaticError("Object comprehensions can only have [e] fields", next.loc)
|
||||||
}
|
}
|
||||||
spec, last, err := p.parseComprehensionSpecs(next, tokenBraceR)
|
spec, last, err := p.parseComprehensionSpecs(next, tokenBraceR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -423,7 +445,7 @@ func (p *parser) parseObjectRemainderComp(fields ast.ObjectFields, gotComma bool
|
|||||||
}, last, nil
|
}, last, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) parseObjectRemainderField(literalFields *LiteralFieldSet, tok *token, next *token) (*ast.ObjectField, error) {
|
func (p *parser) parseObjectRemainderField(literalFields *LiteralFieldSet, tok *token, next *token) (*ast.ObjectField, errors.StaticError) {
|
||||||
var kind ast.ObjectFieldKind
|
var kind ast.ObjectFieldKind
|
||||||
var fodder1 ast.Fodder
|
var fodder1 ast.Fodder
|
||||||
var expr1 ast.Node
|
var expr1 ast.Node
|
||||||
@ -441,7 +463,7 @@ func (p *parser) parseObjectRemainderField(literalFields *LiteralFieldSet, tok *
|
|||||||
default:
|
default:
|
||||||
fodder1 = next.fodder
|
fodder1 = next.fodder
|
||||||
kind = ast.ObjectFieldExpr
|
kind = ast.ObjectFieldExpr
|
||||||
var err error
|
var err errors.StaticError
|
||||||
expr1, err = p.parse(maxPrecedence)
|
expr1, err = p.parse(maxPrecedence)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -460,7 +482,7 @@ func (p *parser) parseObjectRemainderField(literalFields *LiteralFieldSet, tok *
|
|||||||
var params []ast.Parameter
|
var params []ast.Parameter
|
||||||
if p.peek().kind == tokenParenL {
|
if p.peek().kind == tokenParenL {
|
||||||
parenL = p.pop()
|
parenL = p.pop()
|
||||||
var err error
|
var err errors.StaticError
|
||||||
parenR, params, methComma, err = p.parseParameters("method parameter")
|
parenR, params, methComma, err = p.parseParameters("method parameter")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -521,10 +543,10 @@ func (p *parser) parseObjectRemainderField(literalFields *LiteralFieldSet, tok *
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) parseObjectRemainderLocal(binds *ast.IdentifierSet, tok *token, next *token) (*ast.ObjectField, error) {
|
func (p *parser) parseObjectRemainderLocal(binds *ast.IdentifierSet, tok *token, next *token) (*ast.ObjectField, errors.StaticError) {
|
||||||
varID, err := p.popExpect(tokenIdentifier)
|
varID, popErr := p.popExpect(tokenIdentifier)
|
||||||
if err != nil {
|
if popErr != nil {
|
||||||
return nil, err
|
return nil, popErr
|
||||||
}
|
}
|
||||||
|
|
||||||
id := ast.Identifier(varID.data)
|
id := ast.Identifier(varID.data)
|
||||||
@ -543,14 +565,15 @@ func (p *parser) parseObjectRemainderLocal(binds *ast.IdentifierSet, tok *token,
|
|||||||
if p.peek().kind == tokenParenL {
|
if p.peek().kind == tokenParenL {
|
||||||
parenL = p.pop()
|
parenL = p.pop()
|
||||||
isMethod = true
|
isMethod = true
|
||||||
|
var err errors.StaticError
|
||||||
parenR, params, funcComma, err = p.parseParameters("function parameter")
|
parenR, params, funcComma, err = p.parseParameters("function parameter")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opToken, err := p.popExpectOp("=")
|
opToken, popErr := p.popExpectOp("=")
|
||||||
if err != nil {
|
if popErr != nil {
|
||||||
return nil, err
|
return nil, popErr
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := p.parse(maxPrecedence)
|
body, err := p.parse(maxPrecedence)
|
||||||
@ -590,7 +613,7 @@ func (p *parser) parseObjectRemainderLocal(binds *ast.IdentifierSet, tok *token,
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) parseObjectRemainderAssert(tok *token, next *token) (*ast.ObjectField, error) {
|
func (p *parser) parseObjectRemainderAssert(tok *token, next *token) (*ast.ObjectField, errors.StaticError) {
|
||||||
cond, err := p.parse(maxPrecedence)
|
cond, err := p.parse(maxPrecedence)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -623,7 +646,7 @@ func (p *parser) parseObjectRemainderAssert(tok *token, next *token) (*ast.Objec
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse object or object comprehension without leading brace
|
// Parse object or object comprehension without leading brace
|
||||||
func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, errors.StaticError) {
|
||||||
var fields ast.ObjectFields
|
var fields ast.ObjectFields
|
||||||
literalFields := make(LiteralFieldSet)
|
literalFields := make(LiteralFieldSet)
|
||||||
binds := make(ast.IdentifierSet)
|
binds := make(ast.IdentifierSet)
|
||||||
@ -650,11 +673,11 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !gotComma && !first {
|
if !gotComma && !first {
|
||||||
return nil, nil, errors.MakeStaticError("Expected a comma before next field.", next.loc)
|
return nil, nil, errors.MakeStaticError("Expected a comma before next field", next.loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
var field *ast.ObjectField
|
var field *ast.ObjectField
|
||||||
var err error
|
var err errors.StaticError
|
||||||
switch next.kind {
|
switch next.kind {
|
||||||
case tokenBracketL, tokenIdentifier, tokenStringDouble, tokenStringSingle,
|
case tokenBracketL, tokenIdentifier, tokenStringDouble, tokenStringSingle,
|
||||||
tokenStringBlock, tokenVerbatimStringDouble, tokenVerbatimStringSingle:
|
tokenStringBlock, tokenVerbatimStringDouble, tokenVerbatimStringSingle:
|
||||||
@ -693,14 +716,14 @@ func (p *parser) parseObjectRemainder(tok *token) (ast.Node, *token, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* parses for x in expr for y in expr if expr for z in expr ... */
|
/* parses for x in expr for y in expr if expr for z in expr ... */
|
||||||
func (p *parser) parseComprehensionSpecs(forToken *token, end tokenKind) (*ast.ForSpec, *token, error) {
|
func (p *parser) parseComprehensionSpecs(forToken *token, end tokenKind) (*ast.ForSpec, *token, errors.StaticError) {
|
||||||
var parseComprehensionSpecsHelper func(forToken *token, outer *ast.ForSpec) (*ast.ForSpec, *token, error)
|
var parseComprehensionSpecsHelper func(forToken *token, outer *ast.ForSpec) (*ast.ForSpec, *token, errors.StaticError)
|
||||||
parseComprehensionSpecsHelper = func(forToken *token, outer *ast.ForSpec) (*ast.ForSpec, *token, error) {
|
parseComprehensionSpecsHelper = func(forToken *token, outer *ast.ForSpec) (*ast.ForSpec, *token, errors.StaticError) {
|
||||||
var ifSpecs []ast.IfSpec
|
var ifSpecs []ast.IfSpec
|
||||||
|
|
||||||
varID, err := p.popExpect(tokenIdentifier)
|
varID, popErr := p.popExpect(tokenIdentifier)
|
||||||
if err != nil {
|
if popErr != nil {
|
||||||
return nil, nil, err
|
return nil, nil, popErr
|
||||||
}
|
}
|
||||||
id := ast.Identifier(varID.data)
|
id := ast.Identifier(varID.data)
|
||||||
inToken, err := p.popExpect(tokenIn)
|
inToken, err := p.popExpect(tokenIn)
|
||||||
@ -748,7 +771,7 @@ func (p *parser) parseComprehensionSpecs(forToken *token, end tokenKind) (*ast.F
|
|||||||
|
|
||||||
// Assumes that the leading '[' has already been consumed and passed as tok.
|
// Assumes that the leading '[' has already been consumed and passed as tok.
|
||||||
// Should read up to and consume the trailing ']'
|
// Should read up to and consume the trailing ']'
|
||||||
func (p *parser) parseArray(tok *token) (ast.Node, error) {
|
func (p *parser) parseArray(tok *token) (ast.Node, errors.StaticError) {
|
||||||
if p.peek().kind == tokenBracketR {
|
if p.peek().kind == tokenBracketR {
|
||||||
bracketR := p.pop()
|
bracketR := p.pop()
|
||||||
return &ast.Array{
|
return &ast.Array{
|
||||||
@ -801,7 +824,7 @@ func (p *parser) parseArray(tok *token) (ast.Node, error) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if !gotComma {
|
if !gotComma {
|
||||||
return nil, errors.MakeStaticError("Expected a comma before next array element.", next.loc)
|
return nil, errors.MakeStaticError("Expected a comma before next array element", next.loc)
|
||||||
}
|
}
|
||||||
nextElem, err := p.parse(maxPrecedence)
|
nextElem, err := p.parse(maxPrecedence)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -868,7 +891,7 @@ func tokenStringToAst(tok *token) *ast.LiteralString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) parseTerminal() (ast.Node, error) {
|
func (p *parser) parseTerminal() (ast.Node, errors.StaticError) {
|
||||||
tok := p.pop()
|
tok := p.pop()
|
||||||
switch tok.kind {
|
switch tok.kind {
|
||||||
case tokenAssert, tokenBraceR, tokenBracketR, tokenComma, tokenDot, tokenElse,
|
case tokenAssert, tokenBraceR, tokenBracketR, tokenComma, tokenDot, tokenElse,
|
||||||
@ -877,7 +900,7 @@ func (p *parser) parseTerminal() (ast.Node, error) {
|
|||||||
return nil, makeUnexpectedError(tok, "parsing terminal")
|
return nil, makeUnexpectedError(tok, "parsing terminal")
|
||||||
|
|
||||||
case tokenEndOfFile:
|
case tokenEndOfFile:
|
||||||
return nil, errors.MakeStaticError("Unexpected end of file.", tok.loc)
|
return nil, errors.MakeStaticError("Unexpected end of file", tok.loc)
|
||||||
|
|
||||||
case tokenBraceL:
|
case tokenBraceL:
|
||||||
obj, _, err := p.parseObjectRemainder(tok)
|
obj, _, err := p.parseObjectRemainder(tok)
|
||||||
@ -953,7 +976,7 @@ func (p *parser) parseTerminal() (ast.Node, error) {
|
|||||||
idFodder = fieldID.fodder
|
idFodder = fieldID.fodder
|
||||||
id = (*ast.Identifier)(&fieldID.data)
|
id = (*ast.Identifier)(&fieldID.data)
|
||||||
case tokenBracketL:
|
case tokenBracketL:
|
||||||
var err error
|
var err errors.StaticError
|
||||||
index, err = p.parse(maxPrecedence)
|
index, err = p.parse(maxPrecedence)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -964,7 +987,7 @@ func (p *parser) parseTerminal() (ast.Node, error) {
|
|||||||
}
|
}
|
||||||
idFodder = bracketR.fodder
|
idFodder = bracketR.fodder
|
||||||
default:
|
default:
|
||||||
return nil, errors.MakeStaticError("Expected . or [ after super.", tok.loc)
|
return nil, errors.MakeStaticError("Expected . or [ after super", tok.loc)
|
||||||
}
|
}
|
||||||
return &ast.SuperIndex{
|
return &ast.SuperIndex{
|
||||||
NodeBase: ast.NewNodeBaseLoc(tok.loc, tok.fodder),
|
NodeBase: ast.NewNodeBaseLoc(tok.loc, tok.fodder),
|
||||||
@ -978,11 +1001,11 @@ func (p *parser) parseTerminal() (ast.Node, error) {
|
|||||||
return nil, errors.MakeStaticError(fmt.Sprintf("INTERNAL ERROR: Unknown tok kind: %v", tok.kind), tok.loc)
|
return nil, errors.MakeStaticError(fmt.Sprintf("INTERNAL ERROR: Unknown tok kind: %v", tok.kind), tok.loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) parsingFailure(msg string, tok *token) (ast.Node, error) {
|
func (p *parser) parsingFailure(msg string, tok *token) (ast.Node, errors.StaticError) {
|
||||||
return nil, errors.MakeStaticError(msg, tok.loc)
|
return nil, errors.MakeStaticError(msg, tok.loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) parse(prec precedence) (ast.Node, error) {
|
func (p *parser) parse(prec precedence) (ast.Node, errors.StaticError) {
|
||||||
begin := p.peek()
|
begin := p.peek()
|
||||||
|
|
||||||
switch begin.kind {
|
switch begin.kind {
|
||||||
@ -1365,7 +1388,7 @@ func (p *parser) parse(prec precedence) (ast.Node, error) {
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Parse parses a slice of tokens into a parse tree.
|
// Parse parses a slice of tokens into a parse tree.
|
||||||
func Parse(t Tokens) (ast.Node, error) {
|
func Parse(t Tokens) (ast.Node, errors.StaticError) {
|
||||||
p := makeParser(t)
|
p := makeParser(t)
|
||||||
expr, err := p.parse(maxPrecedence)
|
expr, err := p.parse(maxPrecedence)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -146,74 +146,74 @@ type testError struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var errorTests = []testError{
|
var errorTests = []testError{
|
||||||
{`,`, `test:1:1-2 Unexpected: (",", ",") while parsing terminal`},
|
{`,`, `test:1:1-2 Unexpected: "," while parsing terminal`},
|
||||||
{`function(a, b c)`, `test:1:15-16 Expected a comma before next function parameter, got (IDENTIFIER, "c").`},
|
{`function(a, b c)`, `test:1:15-16 Expected a comma before next function parameter, got (IDENTIFIER, "c")`},
|
||||||
{`function(a, 1)`, `test:1:13-14 Expected simple identifier but got a complex expression.`},
|
{`function(a, 1)`, `test:1:13-14 Expected token IDENTIFIER but got (NUMBER, "1") while parsing parameter`},
|
||||||
{`function(,)`, `test:1:10-11 Unexpected: (",", ",") while parsing terminal`},
|
{`function(,)`, `test:1:10-11 Expected token IDENTIFIER but got "," while parsing parameter`},
|
||||||
{`function(a=)`, `test:1:12-13 Unexpected: (")", ")") while parsing terminal`},
|
{`function(a=)`, `test:1:12-13 Unexpected: ")" while parsing terminal`},
|
||||||
{`function(a=,)`, `test:1:12-13 Unexpected: (",", ",") while parsing terminal`},
|
{`function(a=,)`, `test:1:12-13 Unexpected: "," while parsing terminal`},
|
||||||
{`a b`, `test:1:3-4 Did not expect: (IDENTIFIER, "b")`},
|
{`a b`, `test:1:3-4 Did not expect: (IDENTIFIER, "b")`},
|
||||||
{`foo(a, bar(a b))`, `test:1:14-15 Expected a comma before next function argument, got (IDENTIFIER, "b").`},
|
{`foo(a, bar(a b))`, `test:1:14-15 Expected a comma before next function argument, got (IDENTIFIER, "b")`},
|
||||||
|
|
||||||
{`local`, `test:1:6 Expected token IDENTIFIER but got end of file`},
|
{`local`, `test:1:6 Expected token IDENTIFIER but got end of file`},
|
||||||
{`local foo = 1, foo = 2; true`, `test:1:16-19 Duplicate local var: foo`},
|
{`local foo = 1, foo = 2; true`, `test:1:16-19 Duplicate local var: foo`},
|
||||||
{`local foo(a b) = a; true`, `test:1:13-14 Expected a comma before next function parameter, got (IDENTIFIER, "b").`},
|
{`local foo(a b) = a; true`, `test:1:13-14 Expected a comma before next function parameter, got (IDENTIFIER, "b")`},
|
||||||
{`local foo(a): a; true`, `test:1:13-14 Expected operator = but got ":"`},
|
{`local foo(a): a; true`, `test:1:13-14 Expected operator = but got (OPERATOR, ":")`},
|
||||||
{`local foo(a) = bar(a b); true`, `test:1:22-23 Expected a comma before next function argument, got (IDENTIFIER, "b").`},
|
{`local foo(a) = bar(a b); true`, `test:1:22-23 Expected a comma before next function argument, got (IDENTIFIER, "b")`},
|
||||||
{`local foo: 1; true`, `test:1:10-11 Expected operator = but got ":"`},
|
{`local foo: 1; true`, `test:1:10-11 Expected operator = but got (OPERATOR, ":")`},
|
||||||
{`local foo = bar(a b); true`, `test:1:19-20 Expected a comma before next function argument, got (IDENTIFIER, "b").`},
|
{`local foo = bar(a b); true`, `test:1:19-20 Expected a comma before next function argument, got (IDENTIFIER, "b")`},
|
||||||
|
|
||||||
{`{a b}`, `test:1:4-5 Expected token OPERATOR but got (IDENTIFIER, "b")`},
|
{`{a b}`, `test:1:4-5 Expected token OPERATOR but got (IDENTIFIER, "b")`},
|
||||||
{`{a = b}`, `test:1:4-5 Expected one of :, ::, :::, +:, +::, +:::, got: =`},
|
{`{a = b}`, `test:1:4-5 Expected one of :, ::, :::, +:, +::, +:::, got: =`},
|
||||||
{`{a :::: b}`, `test:1:4-8 Expected one of :, ::, :::, +:, +::, +:::, got: ::::`},
|
{`{a :::: b}`, `test:1:4-8 Expected one of :, ::, :::, +:, +::, +:::, got: ::::`},
|
||||||
|
|
||||||
{`{assert x for x in [1, 2, 3]}`, `test:1:11-14 Object comprehension cannot have asserts.`},
|
{`{assert x for x in [1, 2, 3]}`, `test:1:11-14 Object comprehension cannot have asserts`},
|
||||||
{`{['foo' + x]: true, [x]: x for x in [1, 2, 3]}`, `test:1:28-31 Object comprehension can only have one field.`},
|
{`{['foo' + x]: true, [x]: x for x in [1, 2, 3]}`, `test:1:28-31 Object comprehension can only have one field`},
|
||||||
{`{foo: x for x in [1, 2, 3]}`, `test:1:9-12 Object comprehensions can only have [e] fields.`},
|
{`{foo: x for x in [1, 2, 3]}`, `test:1:9-12 Object comprehensions can only have [e] fields`},
|
||||||
{`{[x]:: true for x in [1, 2, 3]}`, `test:1:13-16 Object comprehensions cannot have hidden fields.`},
|
{`{[x]:: true for x in [1, 2, 3]}`, `test:1:13-16 Object comprehensions cannot have hidden fields`},
|
||||||
{`{[x]: true for 1 in [1, 2, 3]}`, `test:1:16-17 Expected token IDENTIFIER but got (NUMBER, "1")`},
|
{`{[x]: true for 1 in [1, 2, 3]}`, `test:1:16-17 Expected token IDENTIFIER but got (NUMBER, "1")`},
|
||||||
{`{[x]: true for x at [1, 2, 3]}`, `test:1:18-20 Expected token in but got (IDENTIFIER, "at")`},
|
{`{[x]: true for x at [1, 2, 3]}`, `test:1:18-20 Expected token in but got (IDENTIFIER, "at")`},
|
||||||
{`{[x]: true for x in [1, 2 3]}`, `test:1:27-28 Expected a comma before next array element.`},
|
{`{[x]: true for x in [1, 2 3]}`, `test:1:27-28 Expected a comma before next array element`},
|
||||||
{`{[x]: true for x in [1, 2, 3] if (a b)}`, `test:1:37-38 Expected token ")" but got (IDENTIFIER, "b")`},
|
{`{[x]: true for x in [1, 2, 3] if (a b)}`, `test:1:37-38 Expected token ")" but got (IDENTIFIER, "b")`},
|
||||||
{`{[x]: true for x in [1, 2, 3] if a b}`, `test:1:36-37 Expected for, if or "}" after for clause, got: (IDENTIFIER, "b")`},
|
{`{[x]: true for x in [1, 2, 3] if a b}`, `test:1:36-37 Expected for, if or "}" after for clause, got: (IDENTIFIER, "b")`},
|
||||||
|
|
||||||
{`{a: b c:d}`, `test:1:7-8 Expected a comma before next field.`},
|
{`{a: b c:d}`, `test:1:7-8 Expected a comma before next field`},
|
||||||
|
|
||||||
{`{[(x y)]: z}`, `test:1:6-7 Expected token ")" but got (IDENTIFIER, "y")`},
|
{`{[(x y)]: z}`, `test:1:6-7 Expected token ")" but got (IDENTIFIER, "y")`},
|
||||||
{`{[x y]: z}`, `test:1:5-6 Expected token "]" but got (IDENTIFIER, "y")`},
|
{`{[x y]: z}`, `test:1:5-6 Expected token "]" but got (IDENTIFIER, "y")`},
|
||||||
|
|
||||||
{`{foo(x y): z}`, `test:1:8-9 Expected a comma before next method parameter, got (IDENTIFIER, "y").`},
|
{`{foo(x y): z}`, `test:1:8-9 Expected a comma before next method parameter, got (IDENTIFIER, "y")`},
|
||||||
{`{foo(x)+: z}`, `test:1:2-5 Cannot use +: syntax sugar in a method: foo`},
|
{`{foo(x)+: z}`, `test:1:2-5 Cannot use +: syntax sugar in a method: foo`},
|
||||||
{`{foo: 1, foo: 2}`, `test:1:10-13 Duplicate field: foo`},
|
{`{foo: 1, foo: 2}`, `test:1:10-13 Duplicate field: foo`},
|
||||||
{`{foo: (1 2)}`, `test:1:10-11 Expected token ")" but got (NUMBER, "2")`},
|
{`{foo: (1 2)}`, `test:1:10-11 Expected token ")" but got (NUMBER, "2")`},
|
||||||
|
|
||||||
{`{local 1 = 3, true}`, `test:1:8-9 Expected token IDENTIFIER but got (NUMBER, "1")`},
|
{`{local 1 = 3, true}`, `test:1:8-9 Expected token IDENTIFIER but got (NUMBER, "1")`},
|
||||||
{`{local foo = 1, local foo = 2, true}`, `test:1:23-26 Duplicate local var: foo`},
|
{`{local foo = 1, local foo = 2, true}`, `test:1:23-26 Duplicate local var: foo`},
|
||||||
{`{local foo(a b) = 1, a: true}`, `test:1:14-15 Expected a comma before next function parameter, got (IDENTIFIER, "b").`},
|
{`{local foo(a b) = 1, a: true}`, `test:1:14-15 Expected a comma before next function parameter, got (IDENTIFIER, "b")`},
|
||||||
{`{local foo(a): 1, a: true}`, `test:1:14-15 Expected operator = but got ":"`},
|
{`{local foo(a): 1, a: true}`, `test:1:14-15 Expected operator = but got (OPERATOR, ":")`},
|
||||||
{`{local foo(a) = (a b), a: true}`, `test:1:20-21 Expected token ")" but got (IDENTIFIER, "b")`},
|
{`{local foo(a) = (a b), a: true}`, `test:1:20-21 Expected token ")" but got (IDENTIFIER, "b")`},
|
||||||
|
|
||||||
{`{assert (a b), a: true}`, `test:1:12-13 Expected token ")" but got (IDENTIFIER, "b")`},
|
{`{assert (a b), a: true}`, `test:1:12-13 Expected token ")" but got (IDENTIFIER, "b")`},
|
||||||
{`{assert a: (a b), a: true}`, `test:1:15-16 Expected token ")" but got (IDENTIFIER, "b")`},
|
{`{assert a: (a b), a: true}`, `test:1:15-16 Expected token ")" but got (IDENTIFIER, "b")`},
|
||||||
|
|
||||||
{`{function(a, b) a+b: true}`, `test:1:2-10 Unexpected: (function, "function") while parsing field definition`},
|
{`{function(a, b) a+b: true}`, `test:1:2-10 Unexpected: "function" while parsing field definition`},
|
||||||
|
|
||||||
{`[(a b), 2, 3]`, `test:1:5-6 Expected token ")" but got (IDENTIFIER, "b")`},
|
{`[(a b), 2, 3]`, `test:1:5-6 Expected token ")" but got (IDENTIFIER, "b")`},
|
||||||
{`[1, (a b), 2, 3]`, `test:1:8-9 Expected token ")" but got (IDENTIFIER, "b")`},
|
{`[1, (a b), 2, 3]`, `test:1:8-9 Expected token ")" but got (IDENTIFIER, "b")`},
|
||||||
{`[a for b in [1 2 3]]`, `test:1:16-17 Expected a comma before next array element.`},
|
{`[a for b in [1 2 3]]`, `test:1:16-17 Expected a comma before next array element`},
|
||||||
|
|
||||||
{`for`, `test:1:1-4 Unexpected: (for, "for") while parsing terminal`},
|
{`for`, `test:1:1-4 Unexpected: "for" while parsing terminal`},
|
||||||
{``, `test:1:1 Unexpected end of file.`},
|
{``, `test:1:1 Unexpected end of file`},
|
||||||
{`((a b))`, `test:1:5-6 Expected token ")" but got (IDENTIFIER, "b")`},
|
{`((a b))`, `test:1:5-6 Expected token ")" but got (IDENTIFIER, "b")`},
|
||||||
{`a.1`, `test:1:3-4 Expected token IDENTIFIER but got (NUMBER, "1")`},
|
{`a.1`, `test:1:3-4 Expected token IDENTIFIER but got (NUMBER, "1")`},
|
||||||
{`super.1`, `test:1:7-8 Expected token IDENTIFIER but got (NUMBER, "1")`},
|
{`super.1`, `test:1:7-8 Expected token IDENTIFIER but got (NUMBER, "1")`},
|
||||||
{`super[(a b)]`, `test:1:10-11 Expected token ")" but got (IDENTIFIER, "b")`},
|
{`super[(a b)]`, `test:1:10-11 Expected token ")" but got (IDENTIFIER, "b")`},
|
||||||
{`super[a b]`, `test:1:9-10 Expected token "]" but got (IDENTIFIER, "b")`},
|
{`super[a b]`, `test:1:9-10 Expected token "]" but got (IDENTIFIER, "b")`},
|
||||||
{`super`, `test:1:1-6 Expected . or [ after super.`},
|
{`super`, `test:1:1-6 Expected . or [ after super`},
|
||||||
|
|
||||||
{`assert (a b); true`, `test:1:11-12 Expected token ")" but got (IDENTIFIER, "b")`},
|
{`assert (a b); true`, `test:1:11-12 Expected token ")" but got (IDENTIFIER, "b")`},
|
||||||
{`assert a: (a b); true`, `test:1:14-15 Expected token ")" but got (IDENTIFIER, "b")`},
|
{`assert a: (a b); true`, `test:1:14-15 Expected token ")" but got (IDENTIFIER, "b")`},
|
||||||
{`assert a: 'foo', true`, `test:1:16-17 Expected token ";" but got (",", ",")`},
|
{`assert a: 'foo', true`, `test:1:16-17 Expected token ";" but got ","`},
|
||||||
{`assert a: 'foo'; (a b)`, `test:1:21-22 Expected token ")" but got (IDENTIFIER, "b")`},
|
{`assert a: 'foo'; (a b)`, `test:1:21-22 Expected token ")" but got (IDENTIFIER, "b")`},
|
||||||
|
|
||||||
{`error (a b)`, `test:1:10-11 Expected token ")" but got (IDENTIFIER, "b")`},
|
{`error (a b)`, `test:1:10-11 Expected token ")" but got (IDENTIFIER, "b")`},
|
||||||
|
@ -137,10 +137,10 @@ func runInternalJsonnet(i jsonnetInput) jsonnetResult {
|
|||||||
vm.NativeFunction(jsonToString)
|
vm.NativeFunction(jsonToString)
|
||||||
vm.NativeFunction(nativeError)
|
vm.NativeFunction(nativeError)
|
||||||
|
|
||||||
rawAST, err := parser.SnippetToRawAST(i.name, string(i.input))
|
rawAST, staticErr := parser.SnippetToRawAST(i.name, string(i.input))
|
||||||
if err != nil {
|
if staticErr != nil {
|
||||||
return jsonnetResult{
|
return jsonnetResult{
|
||||||
output: errFormatter.Format(err) + "\n",
|
output: errFormatter.Format(staticErr) + "\n",
|
||||||
isError: true,
|
isError: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
testdata/extvar_static_error.golden
vendored
2
testdata/extvar_static_error.golden
vendored
@ -1,4 +1,4 @@
|
|||||||
<extvar:staticErrorVar>:1:1-2 Unexpected: (")", ")") while parsing terminal
|
<extvar:staticErrorVar>:1:1-2 Unexpected: ")" while parsing terminal
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
2
testdata/object_comp_assert.golden
vendored
2
testdata/object_comp_assert.golden
vendored
@ -1,4 +1,4 @@
|
|||||||
testdata/object_comp_assert:1:32-35 Object comprehension cannot have asserts.
|
testdata/object_comp_assert:1:32-35 Object comprehension cannot have asserts
|
||||||
|
|
||||||
{ assert self.x == 5, ["x"]: 5 for i in [42] }
|
{ assert self.x == 5, ["x"]: 5 for i in [42] }
|
||||||
|
|
||||||
|
2
testdata/object_comp_bad_field.golden
vendored
2
testdata/object_comp_bad_field.golden
vendored
@ -1,4 +1,4 @@
|
|||||||
testdata/object_comp_bad_field:1:9-12 Object comprehensions can only have [e] fields.
|
testdata/object_comp_bad_field:1:9-12 Object comprehensions can only have [e] fields
|
||||||
|
|
||||||
{ x: 42 for _ in [1] }
|
{ x: 42 for _ in [1] }
|
||||||
|
|
||||||
|
2
testdata/object_comp_bad_field2.golden
vendored
2
testdata/object_comp_bad_field2.golden
vendored
@ -1,4 +1,4 @@
|
|||||||
testdata/object_comp_bad_field2:1:11-14 Object comprehensions can only have [e] fields.
|
testdata/object_comp_bad_field2:1:11-14 Object comprehensions can only have [e] fields
|
||||||
|
|
||||||
{ "x": 42 for _ in [1] }
|
{ "x": 42 for _ in [1] }
|
||||||
|
|
||||||
|
2
testdata/object_comp_illegal.golden
vendored
2
testdata/object_comp_illegal.golden
vendored
@ -1,4 +1,4 @@
|
|||||||
testdata/object_comp_illegal:1:15-18 Object comprehension can only have one field.
|
testdata/object_comp_illegal:1:15-18 Object comprehension can only have one field
|
||||||
|
|
||||||
{ local x = 5 for y in [1, 2, 3] }
|
{ local x = 5 for y in [1, 2, 3] }
|
||||||
|
|
||||||
|
2
testdata/unfinished_args.golden
vendored
2
testdata/unfinished_args.golden
vendored
@ -1,4 +1,4 @@
|
|||||||
testdata/unfinished_args:2:1 Expected a comma before next function argument, got end of file.
|
testdata/unfinished_args:2:1 Expected a comma before next function argument, got end of file
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user