aboutsummaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/obscuren/otto/parser/statement.go
diff options
context:
space:
mode:
Diffstat (limited to 'Godeps/_workspace/src/github.com/obscuren/otto/parser/statement.go')
-rw-r--r--Godeps/_workspace/src/github.com/obscuren/otto/parser/statement.go662
1 files changed, 0 insertions, 662 deletions
diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/statement.go b/Godeps/_workspace/src/github.com/obscuren/otto/parser/statement.go
deleted file mode 100644
index 4c08b523c..000000000
--- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/statement.go
+++ /dev/null
@@ -1,662 +0,0 @@
-package parser
-
-import (
- "github.com/robertkrimen/otto/ast"
- "github.com/robertkrimen/otto/token"
-)
-
-func (self *_parser) parseBlockStatement() *ast.BlockStatement {
- node := &ast.BlockStatement{}
- node.LeftBrace = self.expect(token.LEFT_BRACE)
- node.List = self.parseStatementList()
- node.RightBrace = self.expect(token.RIGHT_BRACE)
-
- return node
-}
-
-func (self *_parser) parseEmptyStatement() ast.Statement {
- idx := self.expect(token.SEMICOLON)
- return &ast.EmptyStatement{Semicolon: idx}
-}
-
-func (self *_parser) parseStatementList() (list []ast.Statement) {
- for self.token != token.RIGHT_BRACE && self.token != token.EOF {
- list = append(list, self.parseStatement())
- }
-
- return
-}
-
-func (self *_parser) parseStatement() ast.Statement {
-
- if self.token == token.EOF {
- self.errorUnexpectedToken(self.token)
- return &ast.BadStatement{From: self.idx, To: self.idx + 1}
- }
-
- switch self.token {
- case token.SEMICOLON:
- return self.parseEmptyStatement()
- case token.LEFT_BRACE:
- return self.parseBlockStatement()
- case token.IF:
- return self.parseIfStatement()
- case token.DO:
- return self.parseDoWhileStatement()
- case token.WHILE:
- return self.parseWhileStatement()
- case token.FOR:
- return self.parseForOrForInStatement()
- case token.BREAK:
- return self.parseBreakStatement()
- case token.CONTINUE:
- return self.parseContinueStatement()
- case token.DEBUGGER:
- return self.parseDebuggerStatement()
- case token.WITH:
- return self.parseWithStatement()
- case token.VAR:
- return self.parseVariableStatement()
- case token.FUNCTION:
- self.parseFunction(true)
- // FIXME
- return &ast.EmptyStatement{}
- case token.SWITCH:
- return self.parseSwitchStatement()
- case token.RETURN:
- return self.parseReturnStatement()
- case token.THROW:
- return self.parseThrowStatement()
- case token.TRY:
- return self.parseTryStatement()
- }
-
- expression := self.parseExpression()
-
- if identifier, isIdentifier := expression.(*ast.Identifier); isIdentifier && self.token == token.COLON {
- // LabelledStatement
- colon := self.idx
- self.next() // :
- label := identifier.Name
- for _, value := range self.scope.labels {
- if label == value {
- self.error(identifier.Idx0(), "Label '%s' already exists", label)
- }
- }
- self.scope.labels = append(self.scope.labels, label) // Push the label
- statement := self.parseStatement()
- self.scope.labels = self.scope.labels[:len(self.scope.labels)-1] // Pop the label
- return &ast.LabelledStatement{
- Label: identifier,
- Colon: colon,
- Statement: statement,
- }
- }
-
- self.optionalSemicolon()
-
- return &ast.ExpressionStatement{
- Expression: expression,
- }
-}
-
-func (self *_parser) parseTryStatement() ast.Statement {
-
- node := &ast.TryStatement{
- Try: self.expect(token.TRY),
- Body: self.parseBlockStatement(),
- }
-
- if self.token == token.CATCH {
- catch := self.idx
- self.next()
- self.expect(token.LEFT_PARENTHESIS)
- if self.token != token.IDENTIFIER {
- self.expect(token.IDENTIFIER)
- self.nextStatement()
- return &ast.BadStatement{From: catch, To: self.idx}
- } else {
- identifier := self.parseIdentifier()
- self.expect(token.RIGHT_PARENTHESIS)
- node.Catch = &ast.CatchStatement{
- Catch: catch,
- Parameter: identifier,
- Body: self.parseBlockStatement(),
- }
- }
- }
-
- if self.token == token.FINALLY {
- self.next()
- node.Finally = self.parseBlockStatement()
- }
-
- if node.Catch == nil && node.Finally == nil {
- self.error(node.Try, "Missing catch or finally after try")
- return &ast.BadStatement{From: node.Try, To: node.Body.Idx1()}
- }
-
- return node
-}
-
-func (self *_parser) parseFunctionParameterList() *ast.ParameterList {
- opening := self.expect(token.LEFT_PARENTHESIS)
- var list []*ast.Identifier
- for self.token != token.RIGHT_PARENTHESIS && self.token != token.EOF {
- if self.token != token.IDENTIFIER {
- self.expect(token.IDENTIFIER)
- } else {
- list = append(list, self.parseIdentifier())
- }
- if self.token != token.RIGHT_PARENTHESIS {
- self.expect(token.COMMA)
- }
- }
- closing := self.expect(token.RIGHT_PARENTHESIS)
-
- return &ast.ParameterList{
- Opening: opening,
- List: list,
- Closing: closing,
- }
-}
-
-func (self *_parser) parseParameterList() (list []string) {
- for self.token != token.EOF {
- if self.token != token.IDENTIFIER {
- self.expect(token.IDENTIFIER)
- }
- list = append(list, self.literal)
- self.next()
- if self.token != token.EOF {
- self.expect(token.COMMA)
- }
- }
- return
-}
-
-func (self *_parser) parseFunction(declaration bool) *ast.FunctionLiteral {
-
- node := &ast.FunctionLiteral{
- Function: self.expect(token.FUNCTION),
- }
-
- var name *ast.Identifier
- if self.token == token.IDENTIFIER {
- name = self.parseIdentifier()
- if declaration {
- self.scope.declare(&ast.FunctionDeclaration{
- Function: node,
- })
- }
- } else if declaration {
- // Use expect error handling
- self.expect(token.IDENTIFIER)
- }
- node.Name = name
- node.ParameterList = self.parseFunctionParameterList()
- self.parseFunctionBlock(node)
- node.Source = self.slice(node.Idx0(), node.Idx1())
-
- return node
-}
-
-func (self *_parser) parseFunctionBlock(node *ast.FunctionLiteral) {
- {
- self.openScope()
- inFunction := self.scope.inFunction
- self.scope.inFunction = true
- defer func() {
- self.scope.inFunction = inFunction
- self.closeScope()
- }()
- node.Body = self.parseBlockStatement()
- node.DeclarationList = self.scope.declarationList
- }
-}
-
-func (self *_parser) parseDebuggerStatement() ast.Statement {
- idx := self.expect(token.DEBUGGER)
-
- node := &ast.DebuggerStatement{
- Debugger: idx,
- }
-
- self.semicolon()
-
- return node
-}
-
-func (self *_parser) parseReturnStatement() ast.Statement {
- idx := self.expect(token.RETURN)
-
- if !self.scope.inFunction {
- self.error(idx, "Illegal return statement")
- self.nextStatement()
- return &ast.BadStatement{From: idx, To: self.idx}
- }
-
- node := &ast.ReturnStatement{
- Return: idx,
- }
-
- if !self.implicitSemicolon && self.token != token.SEMICOLON && self.token != token.RIGHT_BRACE && self.token != token.EOF {
- node.Argument = self.parseExpression()
- }
-
- self.semicolon()
-
- return node
-}
-
-func (self *_parser) parseThrowStatement() ast.Statement {
- idx := self.expect(token.THROW)
-
- if self.implicitSemicolon {
- if self.chr == -1 { // Hackish
- self.error(idx, "Unexpected end of input")
- } else {
- self.error(idx, "Illegal newline after throw")
- }
- self.nextStatement()
- return &ast.BadStatement{From: idx, To: self.idx}
- }
-
- node := &ast.ThrowStatement{
- Argument: self.parseExpression(),
- }
-
- self.semicolon()
-
- return node
-}
-
-func (self *_parser) parseSwitchStatement() ast.Statement {
- self.expect(token.SWITCH)
- self.expect(token.LEFT_PARENTHESIS)
- node := &ast.SwitchStatement{
- Discriminant: self.parseExpression(),
- Default: -1,
- }
- self.expect(token.RIGHT_PARENTHESIS)
-
- self.expect(token.LEFT_BRACE)
-
- inSwitch := self.scope.inSwitch
- self.scope.inSwitch = true
- defer func() {
- self.scope.inSwitch = inSwitch
- }()
-
- for index := 0; self.token != token.EOF; index++ {
- if self.token == token.RIGHT_BRACE {
- self.next()
- break
- }
-
- clause := self.parseCaseStatement()
- if clause.Test == nil {
- if node.Default != -1 {
- self.error(clause.Case, "Already saw a default in switch")
- }
- node.Default = index
- }
- node.Body = append(node.Body, clause)
- }
-
- return node
-}
-
-func (self *_parser) parseWithStatement() ast.Statement {
- self.expect(token.WITH)
- self.expect(token.LEFT_PARENTHESIS)
- node := &ast.WithStatement{
- Object: self.parseExpression(),
- }
- self.expect(token.RIGHT_PARENTHESIS)
-
- node.Body = self.parseStatement()
-
- return node
-}
-
-func (self *_parser) parseCaseStatement() *ast.CaseStatement {
-
- node := &ast.CaseStatement{
- Case: self.idx,
- }
- if self.token == token.DEFAULT {
- self.next()
- } else {
- self.expect(token.CASE)
- node.Test = self.parseExpression()
- }
- self.expect(token.COLON)
-
- for {
- if self.token == token.EOF ||
- self.token == token.RIGHT_BRACE ||
- self.token == token.CASE ||
- self.token == token.DEFAULT {
- break
- }
- node.Consequent = append(node.Consequent, self.parseStatement())
-
- }
-
- return node
-}
-
-func (self *_parser) parseIterationStatement() ast.Statement {
- inIteration := self.scope.inIteration
- self.scope.inIteration = true
- defer func() {
- self.scope.inIteration = inIteration
- }()
- return self.parseStatement()
-}
-
-func (self *_parser) parseForIn(into ast.Expression) *ast.ForInStatement {
-
- // Already have consumed "<into> in"
-
- source := self.parseExpression()
- self.expect(token.RIGHT_PARENTHESIS)
-
- return &ast.ForInStatement{
- Into: into,
- Source: source,
- Body: self.parseIterationStatement(),
- }
-}
-
-func (self *_parser) parseFor(initializer ast.Expression) *ast.ForStatement {
-
- // Already have consumed "<initializer> ;"
-
- var test, update ast.Expression
-
- if self.token != token.SEMICOLON {
- test = self.parseExpression()
- }
- self.expect(token.SEMICOLON)
-
- if self.token != token.RIGHT_PARENTHESIS {
- update = self.parseExpression()
- }
- self.expect(token.RIGHT_PARENTHESIS)
-
- return &ast.ForStatement{
- Initializer: initializer,
- Test: test,
- Update: update,
- Body: self.parseIterationStatement(),
- }
-}
-
-func (self *_parser) parseForOrForInStatement() ast.Statement {
- idx := self.expect(token.FOR)
- self.expect(token.LEFT_PARENTHESIS)
-
- var left []ast.Expression
-
- forIn := false
- if self.token != token.SEMICOLON {
-
- allowIn := self.scope.allowIn
- self.scope.allowIn = false
- if self.token == token.VAR {
- var_ := self.idx
- self.next()
- list := self.parseVariableDeclarationList(var_)
- if len(list) == 1 && self.token == token.IN {
- self.next() // in
- forIn = true
- left = []ast.Expression{list[0]} // There is only one declaration
- } else {
- left = list
- }
- } else {
- left = append(left, self.parseExpression())
- if self.token == token.IN {
- self.next()
- forIn = true
- }
- }
- self.scope.allowIn = allowIn
- }
-
- if forIn {
- switch left[0].(type) {
- case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression, *ast.VariableExpression:
- // These are all acceptable
- default:
- self.error(idx, "Invalid left-hand side in for-in")
- self.nextStatement()
- return &ast.BadStatement{From: idx, To: self.idx}
- }
- return self.parseForIn(left[0])
- }
-
- self.expect(token.SEMICOLON)
- return self.parseFor(&ast.SequenceExpression{Sequence: left})
-}
-
-func (self *_parser) parseVariableStatement() *ast.VariableStatement {
-
- idx := self.expect(token.VAR)
-
- list := self.parseVariableDeclarationList(idx)
- self.semicolon()
-
- return &ast.VariableStatement{
- Var: idx,
- List: list,
- }
-}
-
-func (self *_parser) parseDoWhileStatement() ast.Statement {
- inIteration := self.scope.inIteration
- self.scope.inIteration = true
- defer func() {
- self.scope.inIteration = inIteration
- }()
-
- self.expect(token.DO)
- node := &ast.DoWhileStatement{}
- if self.token == token.LEFT_BRACE {
- node.Body = self.parseBlockStatement()
- } else {
- node.Body = self.parseStatement()
- }
-
- self.expect(token.WHILE)
- self.expect(token.LEFT_PARENTHESIS)
- node.Test = self.parseExpression()
- self.expect(token.RIGHT_PARENTHESIS)
-
- return node
-}
-
-func (self *_parser) parseWhileStatement() ast.Statement {
- self.expect(token.WHILE)
- self.expect(token.LEFT_PARENTHESIS)
- node := &ast.WhileStatement{
- Test: self.parseExpression(),
- }
- self.expect(token.RIGHT_PARENTHESIS)
- node.Body = self.parseIterationStatement()
-
- return node
-}
-
-func (self *_parser) parseIfStatement() ast.Statement {
- self.expect(token.IF)
- self.expect(token.LEFT_PARENTHESIS)
- node := &ast.IfStatement{
- Test: self.parseExpression(),
- }
- self.expect(token.RIGHT_PARENTHESIS)
-
- if self.token == token.LEFT_BRACE {
- node.Consequent = self.parseBlockStatement()
- } else {
- node.Consequent = self.parseStatement()
- }
-
- if self.token == token.ELSE {
- self.next()
- node.Alternate = self.parseStatement()
- }
-
- return node
-}
-
-func (self *_parser) parseSourceElement() ast.Statement {
- return self.parseStatement()
-}
-
-func (self *_parser) parseSourceElements() []ast.Statement {
- body := []ast.Statement(nil)
-
- for {
- if self.token != token.STRING {
- break
- }
-
- body = append(body, self.parseSourceElement())
- }
-
- for self.token != token.EOF {
- body = append(body, self.parseSourceElement())
- }
-
- return body
-}
-
-func (self *_parser) parseProgram() *ast.Program {
- self.openScope()
- defer self.closeScope()
- return &ast.Program{
- Body: self.parseSourceElements(),
- DeclarationList: self.scope.declarationList,
- }
-}
-
-func (self *_parser) parseBreakStatement() ast.Statement {
- idx := self.expect(token.BREAK)
- semicolon := self.implicitSemicolon
- if self.token == token.SEMICOLON {
- semicolon = true
- self.next()
- }
-
- if semicolon || self.token == token.RIGHT_BRACE {
- self.implicitSemicolon = false
- if !self.scope.inIteration && !self.scope.inSwitch {
- goto illegal
- }
- return &ast.BranchStatement{
- Idx: idx,
- Token: token.BREAK,
- }
- }
-
- if self.token == token.IDENTIFIER {
- identifier := self.parseIdentifier()
- if !self.scope.hasLabel(identifier.Name) {
- self.error(idx, "Undefined label '%s'", identifier.Name)
- return &ast.BadStatement{From: idx, To: identifier.Idx1()}
- }
- self.semicolon()
- return &ast.BranchStatement{
- Idx: idx,
- Token: token.BREAK,
- Label: identifier,
- }
- }
-
- self.expect(token.IDENTIFIER)
-
-illegal:
- self.error(idx, "Illegal break statement")
- self.nextStatement()
- return &ast.BadStatement{From: idx, To: self.idx}
-}
-
-func (self *_parser) parseContinueStatement() ast.Statement {
- idx := self.expect(token.CONTINUE)
- semicolon := self.implicitSemicolon
- if self.token == token.SEMICOLON {
- semicolon = true
- self.next()
- }
-
- if semicolon || self.token == token.RIGHT_BRACE {
- self.implicitSemicolon = false
- if !self.scope.inIteration {
- goto illegal
- }
- return &ast.BranchStatement{
- Idx: idx,
- Token: token.CONTINUE,
- }
- }
-
- if self.token == token.IDENTIFIER {
- identifier := self.parseIdentifier()
- if !self.scope.hasLabel(identifier.Name) {
- self.error(idx, "Undefined label '%s'", identifier.Name)
- return &ast.BadStatement{From: idx, To: identifier.Idx1()}
- }
- if !self.scope.inIteration {
- goto illegal
- }
- self.semicolon()
- return &ast.BranchStatement{
- Idx: idx,
- Token: token.CONTINUE,
- Label: identifier,
- }
- }
-
- self.expect(token.IDENTIFIER)
-
-illegal:
- self.error(idx, "Illegal continue statement")
- self.nextStatement()
- return &ast.BadStatement{From: idx, To: self.idx}
-}
-
-// Find the next statement after an error (recover)
-func (self *_parser) nextStatement() {
- for {
- switch self.token {
- case token.BREAK, token.CONTINUE,
- token.FOR, token.IF, token.RETURN, token.SWITCH,
- token.VAR, token.DO, token.TRY, token.WITH,
- token.WHILE, token.THROW, token.CATCH, token.FINALLY:
- // Return only if parser made some progress since last
- // sync or if it has not reached 10 next calls without
- // progress. Otherwise consume at least one token to
- // avoid an endless parser loop
- if self.idx == self.recover.idx && self.recover.count < 10 {
- self.recover.count++
- return
- }
- if self.idx > self.recover.idx {
- self.recover.idx = self.idx
- self.recover.count = 0
- return
- }
- // Reaching here indicates a parser bug, likely an
- // incorrect token list in this function, but it only
- // leads to skipping of possibly correct code if a
- // previous error is present, and thus is preferred
- // over a non-terminating parse.
- case token.EOF:
- return
- }
- self.next()
- }
-}