123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992 |
- package parser
- import (
- "regexp"
- "github.com/robertkrimen/otto/ast"
- "github.com/robertkrimen/otto/file"
- "github.com/robertkrimen/otto/token"
- )
- func (p *parser) parseIdentifier() *ast.Identifier {
- literal := p.literal
- idx := p.idx
- if p.mode&StoreComments != 0 {
- p.comments.MarkComments(ast.LEADING)
- }
- p.next()
- exp := &ast.Identifier{
- Name: literal,
- Idx: idx,
- }
- if p.mode&StoreComments != 0 {
- p.comments.SetExpression(exp)
- }
- return exp
- }
- func (p *parser) parsePrimaryExpression() ast.Expression {
- literal := p.literal
- idx := p.idx
- switch p.token {
- case token.IDENTIFIER:
- p.next()
- if len(literal) > 1 {
- tkn, strict := token.IsKeyword(literal)
- if tkn == token.KEYWORD {
- if !strict {
- p.error(idx, "Unexpected reserved word")
- }
- }
- }
- return &ast.Identifier{
- Name: literal,
- Idx: idx,
- }
- case token.NULL:
- p.next()
- return &ast.NullLiteral{
- Idx: idx,
- Literal: literal,
- }
- case token.BOOLEAN:
- p.next()
- value := false
- switch literal {
- case "true":
- value = true
- case "false":
- value = false
- default:
- p.error(idx, "Illegal boolean literal")
- }
- return &ast.BooleanLiteral{
- Idx: idx,
- Literal: literal,
- Value: value,
- }
- case token.STRING:
- p.next()
- value, err := parseStringLiteral(literal[1 : len(literal)-1])
- if err != nil {
- p.error(idx, err.Error())
- }
- return &ast.StringLiteral{
- Idx: idx,
- Literal: literal,
- Value: value,
- }
- case token.NUMBER:
- p.next()
- value, err := parseNumberLiteral(literal)
- if err != nil {
- p.error(idx, err.Error())
- value = 0
- }
- return &ast.NumberLiteral{
- Idx: idx,
- Literal: literal,
- Value: value,
- }
- case token.SLASH, token.QUOTIENT_ASSIGN:
- return p.parseRegExpLiteral()
- case token.LEFT_BRACE:
- return p.parseObjectLiteral()
- case token.LEFT_BRACKET:
- return p.parseArrayLiteral()
- case token.LEFT_PARENTHESIS:
- p.expect(token.LEFT_PARENTHESIS)
- expression := p.parseExpression()
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.expect(token.RIGHT_PARENTHESIS)
- return expression
- case token.THIS:
- p.next()
- return &ast.ThisExpression{
- Idx: idx,
- }
- case token.FUNCTION:
- return p.parseFunction(false)
- }
- p.errorUnexpectedToken(p.token)
- p.nextStatement()
- return &ast.BadExpression{From: idx, To: p.idx}
- }
- func (p *parser) parseRegExpLiteral() *ast.RegExpLiteral {
- offset := p.chrOffset - 1 // Opening slash already gotten
- if p.token == token.QUOTIENT_ASSIGN {
- offset-- // =
- }
- idx := p.idxOf(offset)
- pattern, err := p.scanString(offset)
- endOffset := p.chrOffset
- p.next()
- if err == nil {
- pattern = pattern[1 : len(pattern)-1]
- }
- flags := ""
- if p.token == token.IDENTIFIER { // gim
- flags = p.literal
- endOffset = p.chrOffset
- p.next()
- }
- var value string
- // TODO 15.10
- // Test during parsing that this is a valid regular expression
- // Sorry, (?=) and (?!) are invalid (for now)
- pat, err := TransformRegExp(pattern)
- if err != nil {
- if pat == "" || p.mode&IgnoreRegExpErrors == 0 {
- p.error(idx, "Invalid regular expression: %s", err.Error())
- }
- } else {
- _, err = regexp.Compile(pat)
- if err != nil {
- // We should not get here, ParseRegExp should catch any errors
- p.error(idx, "Invalid regular expression: %s", err.Error()[22:]) // Skip redundant "parse regexp error"
- } else {
- value = pat
- }
- }
- literal := p.str[offset:endOffset]
- return &ast.RegExpLiteral{
- Idx: idx,
- Literal: literal,
- Pattern: pattern,
- Flags: flags,
- Value: value,
- }
- }
- func (p *parser) parseVariableDeclaration(declarationList *[]*ast.VariableExpression) ast.Expression {
- if p.token != token.IDENTIFIER {
- idx := p.expect(token.IDENTIFIER)
- p.nextStatement()
- return &ast.BadExpression{From: idx, To: p.idx}
- }
- literal := p.literal
- idx := p.idx
- p.next()
- node := &ast.VariableExpression{
- Name: literal,
- Idx: idx,
- }
- if p.mode&StoreComments != 0 {
- p.comments.SetExpression(node)
- }
- if declarationList != nil {
- *declarationList = append(*declarationList, node)
- }
- if p.token == token.ASSIGN {
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- node.Initializer = p.parseAssignmentExpression()
- }
- return node
- }
- func (p *parser) parseVariableDeclarationList(idx file.Idx) []ast.Expression {
- var declarationList []*ast.VariableExpression // Avoid bad expressions
- var list []ast.Expression
- for {
- if p.mode&StoreComments != 0 {
- p.comments.MarkComments(ast.LEADING)
- }
- decl := p.parseVariableDeclaration(&declarationList)
- list = append(list, decl)
- if p.token != token.COMMA {
- break
- }
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- }
- p.scope.declare(&ast.VariableDeclaration{
- Var: idx,
- List: declarationList,
- })
- return list
- }
- func (p *parser) parseObjectPropertyKey() (string, string) {
- idx, tkn, literal := p.idx, p.token, p.literal
- value := ""
- if p.mode&StoreComments != 0 {
- p.comments.MarkComments(ast.KEY)
- }
- p.next()
- switch tkn {
- case token.IDENTIFIER:
- value = literal
- case token.NUMBER:
- var err error
- _, err = parseNumberLiteral(literal)
- if err != nil {
- p.error(idx, err.Error())
- } else {
- value = literal
- }
- case token.STRING:
- var err error
- value, err = parseStringLiteral(literal[1 : len(literal)-1])
- if err != nil {
- p.error(idx, err.Error())
- }
- default:
- // null, false, class, etc.
- if matchIdentifier.MatchString(literal) {
- value = literal
- }
- }
- return literal, value
- }
- func (p *parser) parseObjectProperty() ast.Property {
- literal, value := p.parseObjectPropertyKey()
- if literal == "get" && p.token != token.COLON {
- idx := p.idx
- _, value = p.parseObjectPropertyKey()
- parameterList := p.parseFunctionParameterList()
- node := &ast.FunctionLiteral{
- Function: idx,
- ParameterList: parameterList,
- }
- p.parseFunctionBlock(node)
- return ast.Property{
- Key: value,
- Kind: "get",
- Value: node,
- }
- } else if literal == "set" && p.token != token.COLON {
- idx := p.idx
- _, value = p.parseObjectPropertyKey()
- parameterList := p.parseFunctionParameterList()
- node := &ast.FunctionLiteral{
- Function: idx,
- ParameterList: parameterList,
- }
- p.parseFunctionBlock(node)
- return ast.Property{
- Key: value,
- Kind: "set",
- Value: node,
- }
- }
- if p.mode&StoreComments != 0 {
- p.comments.MarkComments(ast.COLON)
- }
- p.expect(token.COLON)
- exp := ast.Property{
- Key: value,
- Kind: "value",
- Value: p.parseAssignmentExpression(),
- }
- if p.mode&StoreComments != 0 {
- p.comments.SetExpression(exp.Value)
- }
- return exp
- }
- func (p *parser) parseObjectLiteral() ast.Expression {
- var value []ast.Property
- idx0 := p.expect(token.LEFT_BRACE)
- for p.token != token.RIGHT_BRACE && p.token != token.EOF {
- value = append(value, p.parseObjectProperty())
- if p.token == token.COMMA {
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- continue
- }
- }
- if p.mode&StoreComments != 0 {
- p.comments.MarkComments(ast.FINAL)
- }
- idx1 := p.expect(token.RIGHT_BRACE)
- return &ast.ObjectLiteral{
- LeftBrace: idx0,
- RightBrace: idx1,
- Value: value,
- }
- }
- func (p *parser) parseArrayLiteral() ast.Expression {
- idx0 := p.expect(token.LEFT_BRACKET)
- var value []ast.Expression
- for p.token != token.RIGHT_BRACKET && p.token != token.EOF {
- if p.token == token.COMMA {
- // This kind of comment requires a special empty expression node.
- empty := &ast.EmptyExpression{Begin: p.idx, End: p.idx}
- if p.mode&StoreComments != 0 {
- p.comments.SetExpression(empty)
- p.comments.Unset()
- }
- value = append(value, empty)
- p.next()
- continue
- }
- exp := p.parseAssignmentExpression()
- value = append(value, exp)
- if p.token != token.RIGHT_BRACKET {
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.expect(token.COMMA)
- }
- }
- if p.mode&StoreComments != 0 {
- p.comments.MarkComments(ast.FINAL)
- }
- idx1 := p.expect(token.RIGHT_BRACKET)
- return &ast.ArrayLiteral{
- LeftBracket: idx0,
- RightBracket: idx1,
- Value: value,
- }
- }
- func (p *parser) parseArgumentList() (argumentList []ast.Expression, idx0, idx1 file.Idx) { //nolint:nonamedreturns
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- idx0 = p.expect(token.LEFT_PARENTHESIS)
- for p.token != token.RIGHT_PARENTHESIS {
- exp := p.parseAssignmentExpression()
- if p.mode&StoreComments != 0 {
- p.comments.SetExpression(exp)
- }
- argumentList = append(argumentList, exp)
- if p.token != token.COMMA {
- break
- }
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- }
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- idx1 = p.expect(token.RIGHT_PARENTHESIS)
- return
- }
- func (p *parser) parseCallExpression(left ast.Expression) ast.Expression {
- argumentList, idx0, idx1 := p.parseArgumentList()
- exp := &ast.CallExpression{
- Callee: left,
- LeftParenthesis: idx0,
- ArgumentList: argumentList,
- RightParenthesis: idx1,
- }
- if p.mode&StoreComments != 0 {
- p.comments.SetExpression(exp)
- }
- return exp
- }
- func (p *parser) parseDotMember(left ast.Expression) ast.Expression {
- period := p.expect(token.PERIOD)
- literal := p.literal
- idx := p.idx
- if !matchIdentifier.MatchString(literal) {
- p.expect(token.IDENTIFIER)
- p.nextStatement()
- return &ast.BadExpression{From: period, To: p.idx}
- }
- p.next()
- return &ast.DotExpression{
- Left: left,
- Identifier: &ast.Identifier{
- Idx: idx,
- Name: literal,
- },
- }
- }
- func (p *parser) parseBracketMember(left ast.Expression) ast.Expression {
- idx0 := p.expect(token.LEFT_BRACKET)
- member := p.parseExpression()
- idx1 := p.expect(token.RIGHT_BRACKET)
- return &ast.BracketExpression{
- LeftBracket: idx0,
- Left: left,
- Member: member,
- RightBracket: idx1,
- }
- }
- func (p *parser) parseNewExpression() ast.Expression {
- idx := p.expect(token.NEW)
- callee := p.parseLeftHandSideExpression()
- node := &ast.NewExpression{
- New: idx,
- Callee: callee,
- }
- if p.token == token.LEFT_PARENTHESIS {
- argumentList, idx0, idx1 := p.parseArgumentList()
- node.ArgumentList = argumentList
- node.LeftParenthesis = idx0
- node.RightParenthesis = idx1
- }
- if p.mode&StoreComments != 0 {
- p.comments.SetExpression(node)
- }
- return node
- }
- func (p *parser) parseLeftHandSideExpression() ast.Expression {
- var left ast.Expression
- if p.token == token.NEW {
- left = p.parseNewExpression()
- } else {
- if p.mode&StoreComments != 0 {
- p.comments.MarkComments(ast.LEADING)
- p.comments.MarkPrimary()
- }
- left = p.parsePrimaryExpression()
- }
- if p.mode&StoreComments != 0 {
- p.comments.SetExpression(left)
- }
- for {
- switch p.token {
- case token.PERIOD:
- left = p.parseDotMember(left)
- case token.LEFT_BRACKET:
- left = p.parseBracketMember(left)
- default:
- return left
- }
- }
- }
- func (p *parser) parseLeftHandSideExpressionAllowCall() ast.Expression {
- allowIn := p.scope.allowIn
- p.scope.allowIn = true
- defer func() {
- p.scope.allowIn = allowIn
- }()
- var left ast.Expression
- if p.token == token.NEW {
- var newComments []*ast.Comment
- if p.mode&StoreComments != 0 {
- newComments = p.comments.FetchAll()
- p.comments.MarkComments(ast.LEADING)
- p.comments.MarkPrimary()
- }
- left = p.parseNewExpression()
- if p.mode&StoreComments != 0 {
- p.comments.CommentMap.AddComments(left, newComments, ast.LEADING)
- }
- } else {
- if p.mode&StoreComments != 0 {
- p.comments.MarkComments(ast.LEADING)
- p.comments.MarkPrimary()
- }
- left = p.parsePrimaryExpression()
- }
- if p.mode&StoreComments != 0 {
- p.comments.SetExpression(left)
- }
- for {
- switch p.token {
- case token.PERIOD:
- left = p.parseDotMember(left)
- case token.LEFT_BRACKET:
- left = p.parseBracketMember(left)
- case token.LEFT_PARENTHESIS:
- left = p.parseCallExpression(left)
- default:
- return left
- }
- }
- }
- func (p *parser) parsePostfixExpression() ast.Expression {
- operand := p.parseLeftHandSideExpressionAllowCall()
- switch p.token {
- case token.INCREMENT, token.DECREMENT:
- // Make sure there is no line terminator here
- if p.implicitSemicolon {
- break
- }
- tkn := p.token
- idx := p.idx
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- switch operand.(type) {
- case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression:
- default:
- p.error(idx, "invalid left-hand side in assignment")
- p.nextStatement()
- return &ast.BadExpression{From: idx, To: p.idx}
- }
- exp := &ast.UnaryExpression{
- Operator: tkn,
- Idx: idx,
- Operand: operand,
- Postfix: true,
- }
- if p.mode&StoreComments != 0 {
- p.comments.SetExpression(exp)
- }
- return exp
- }
- return operand
- }
- func (p *parser) parseUnaryExpression() ast.Expression {
- switch p.token {
- case token.PLUS, token.MINUS, token.NOT, token.BITWISE_NOT:
- fallthrough
- case token.DELETE, token.VOID, token.TYPEOF:
- tkn := p.token
- idx := p.idx
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- return &ast.UnaryExpression{
- Operator: tkn,
- Idx: idx,
- Operand: p.parseUnaryExpression(),
- }
- case token.INCREMENT, token.DECREMENT:
- tkn := p.token
- idx := p.idx
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- operand := p.parseUnaryExpression()
- switch operand.(type) {
- case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression:
- default:
- p.error(idx, "invalid left-hand side in assignment")
- p.nextStatement()
- return &ast.BadExpression{From: idx, To: p.idx}
- }
- return &ast.UnaryExpression{
- Operator: tkn,
- Idx: idx,
- Operand: operand,
- }
- }
- return p.parsePostfixExpression()
- }
- func (p *parser) parseMultiplicativeExpression() ast.Expression {
- next := p.parseUnaryExpression
- left := next()
- for p.token == token.MULTIPLY || p.token == token.SLASH ||
- p.token == token.REMAINDER {
- tkn := p.token
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- left = &ast.BinaryExpression{
- Operator: tkn,
- Left: left,
- Right: next(),
- }
- }
- return left
- }
- func (p *parser) parseAdditiveExpression() ast.Expression {
- next := p.parseMultiplicativeExpression
- left := next()
- for p.token == token.PLUS || p.token == token.MINUS {
- tkn := p.token
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- left = &ast.BinaryExpression{
- Operator: tkn,
- Left: left,
- Right: next(),
- }
- }
- return left
- }
- func (p *parser) parseShiftExpression() ast.Expression {
- next := p.parseAdditiveExpression
- left := next()
- for p.token == token.SHIFT_LEFT || p.token == token.SHIFT_RIGHT ||
- p.token == token.UNSIGNED_SHIFT_RIGHT {
- tkn := p.token
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- left = &ast.BinaryExpression{
- Operator: tkn,
- Left: left,
- Right: next(),
- }
- }
- return left
- }
- func (p *parser) parseRelationalExpression() ast.Expression {
- next := p.parseShiftExpression
- left := next()
- allowIn := p.scope.allowIn
- p.scope.allowIn = true
- defer func() {
- p.scope.allowIn = allowIn
- }()
- switch p.token {
- case token.LESS, token.LESS_OR_EQUAL, token.GREATER, token.GREATER_OR_EQUAL:
- tkn := p.token
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- exp := &ast.BinaryExpression{
- Operator: tkn,
- Left: left,
- Right: p.parseRelationalExpression(),
- Comparison: true,
- }
- return exp
- case token.INSTANCEOF:
- tkn := p.token
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- exp := &ast.BinaryExpression{
- Operator: tkn,
- Left: left,
- Right: p.parseRelationalExpression(),
- }
- return exp
- case token.IN:
- if !allowIn {
- return left
- }
- tkn := p.token
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- exp := &ast.BinaryExpression{
- Operator: tkn,
- Left: left,
- Right: p.parseRelationalExpression(),
- }
- return exp
- }
- return left
- }
- func (p *parser) parseEqualityExpression() ast.Expression {
- next := p.parseRelationalExpression
- left := next()
- for p.token == token.EQUAL || p.token == token.NOT_EQUAL ||
- p.token == token.STRICT_EQUAL || p.token == token.STRICT_NOT_EQUAL {
- tkn := p.token
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- left = &ast.BinaryExpression{
- Operator: tkn,
- Left: left,
- Right: next(),
- Comparison: true,
- }
- }
- return left
- }
- func (p *parser) parseBitwiseAndExpression() ast.Expression {
- next := p.parseEqualityExpression
- left := next()
- for p.token == token.AND {
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- tkn := p.token
- p.next()
- left = &ast.BinaryExpression{
- Operator: tkn,
- Left: left,
- Right: next(),
- }
- }
- return left
- }
- func (p *parser) parseBitwiseExclusiveOrExpression() ast.Expression {
- next := p.parseBitwiseAndExpression
- left := next()
- for p.token == token.EXCLUSIVE_OR {
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- tkn := p.token
- p.next()
- left = &ast.BinaryExpression{
- Operator: tkn,
- Left: left,
- Right: next(),
- }
- }
- return left
- }
- func (p *parser) parseBitwiseOrExpression() ast.Expression {
- next := p.parseBitwiseExclusiveOrExpression
- left := next()
- for p.token == token.OR {
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- tkn := p.token
- p.next()
- left = &ast.BinaryExpression{
- Operator: tkn,
- Left: left,
- Right: next(),
- }
- }
- return left
- }
- func (p *parser) parseLogicalAndExpression() ast.Expression {
- next := p.parseBitwiseOrExpression
- left := next()
- for p.token == token.LOGICAL_AND {
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- tkn := p.token
- p.next()
- left = &ast.BinaryExpression{
- Operator: tkn,
- Left: left,
- Right: next(),
- }
- }
- return left
- }
- func (p *parser) parseLogicalOrExpression() ast.Expression {
- next := p.parseLogicalAndExpression
- left := next()
- for p.token == token.LOGICAL_OR {
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- tkn := p.token
- p.next()
- left = &ast.BinaryExpression{
- Operator: tkn,
- Left: left,
- Right: next(),
- }
- }
- return left
- }
- func (p *parser) parseConditionalExpression() ast.Expression {
- left := p.parseLogicalOrExpression()
- if p.token == token.QUESTION_MARK {
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- consequent := p.parseAssignmentExpression()
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.expect(token.COLON)
- exp := &ast.ConditionalExpression{
- Test: left,
- Consequent: consequent,
- Alternate: p.parseAssignmentExpression(),
- }
- return exp
- }
- return left
- }
- func (p *parser) parseAssignmentExpression() ast.Expression {
- left := p.parseConditionalExpression()
- var operator token.Token
- switch p.token {
- case token.ASSIGN:
- operator = p.token
- case token.ADD_ASSIGN:
- operator = token.PLUS
- case token.SUBTRACT_ASSIGN:
- operator = token.MINUS
- case token.MULTIPLY_ASSIGN:
- operator = token.MULTIPLY
- case token.QUOTIENT_ASSIGN:
- operator = token.SLASH
- case token.REMAINDER_ASSIGN:
- operator = token.REMAINDER
- case token.AND_ASSIGN:
- operator = token.AND
- case token.AND_NOT_ASSIGN:
- operator = token.AND_NOT
- case token.OR_ASSIGN:
- operator = token.OR
- case token.EXCLUSIVE_OR_ASSIGN:
- operator = token.EXCLUSIVE_OR
- case token.SHIFT_LEFT_ASSIGN:
- operator = token.SHIFT_LEFT
- case token.SHIFT_RIGHT_ASSIGN:
- operator = token.SHIFT_RIGHT
- case token.UNSIGNED_SHIFT_RIGHT_ASSIGN:
- operator = token.UNSIGNED_SHIFT_RIGHT
- }
- if operator != 0 {
- idx := p.idx
- if p.mode&StoreComments != 0 {
- p.comments.Unset()
- }
- p.next()
- switch left.(type) {
- case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression:
- default:
- p.error(left.Idx0(), "invalid left-hand side in assignment")
- p.nextStatement()
- return &ast.BadExpression{From: idx, To: p.idx}
- }
- exp := &ast.AssignExpression{
- Left: left,
- Operator: operator,
- Right: p.parseAssignmentExpression(),
- }
- if p.mode&StoreComments != 0 {
- p.comments.SetExpression(exp)
- }
- return exp
- }
- return left
- }
- func (p *parser) parseExpression() ast.Expression {
- next := p.parseAssignmentExpression
- left := next()
- if p.token == token.COMMA {
- sequence := []ast.Expression{left}
- for {
- if p.token != token.COMMA {
- break
- }
- p.next()
- sequence = append(sequence, next())
- }
- return &ast.SequenceExpression{
- Sequence: sequence,
- }
- }
- return left
- }
|