aboutsummaryrefslogblamecommitdiffstats
path: root/vendor/github.com/robertkrimen/otto/cmpl_parse.go
blob: dc5baa12a83f196cdbe7bc6677933b476407e7f0 (plain) (tree)
1
2
3
4
5
6
7
8






                                          
                                           




                                                            
                                                 

                                           

                                                                           


                          
                                

                               

                                                                      
                 

                                                                  
                 
                          


                                              


                                                                 



                                              



                                                                   


                                 
                             





                                               


                                                                


                                 


                                                                                    
                 

                                                                         
                 
                          


                                                   


                                                                        



                                           


                                                                  

                 


                                  

                                  

                                           
                 
                                             
                                     


                                                             
                 


                                                                     
                                                    
                                                                 

                         
                                                          

                                                      
                                                                                                                                         

                                                                  
                                                                                     




                                                                                                         
                          


                                        

                                      


                                


                                                                                    
                 

                                                                         
                 
                          





                                     
                                                 


                                

                                                                    
                 

                                                     

                                                  
                                                                         

                         
                          


                                           

                                            


                                     

                                                                            
                 

                                                                     
                 
                          


                                     
                                                        






                                             


                                                                   



                                                


                                                                          



                 
                                                                          

 

                                                                        


                          
                                

                                 

                                                                   
                 

                                                                
                 
                          

                                  

                                             
                 

                                                 
                 
                          




                                                

                                                            
                 
                                                    
                                                                 
                                             
                        
                                                         
                 
                          





                                                 
                                                                        


                                 


                                                                
                 
                                                    
                                                                 
                                             
                        
                                                         
                 
                          

                               



                                                                          
                 
                                                    
                                                                 
                                             
                        
                                                         
                 
                          
 


                                     

                                         


                                                                       



                                               

                                                                     



                                             
                                                                    


                                  








                                                                                           
                         

                                                                                      
                         
                 
                          


                                            
                                                                    


                               







                                                                              

                         
                          

                                    

                                                                    
                 

                                                                 
                 
                          

                                 

                                                            
                 
                                                    
                                                                 
                                             
                        
                                                         
                 
                          


                                           

                                                                



                 
                                                                         

 


                                                
         






                                                              
         



                                                        

                                              
                                                                                                                                 

                                                          
                                                                             

                         
                                                                                                          

                 
                  








                                            

                       

































                                          
                               















                                              
                                   










                                                     
                                        


                                
                             









































                                              
                                    
















































































































































                                                       
package otto

import (
    "fmt"
    "regexp"

    "github.com/robertkrimen/otto/ast"
    "github.com/robertkrimen/otto/file"
    "github.com/robertkrimen/otto/token"
)

var trueLiteral = &_nodeLiteral{value: toValue_bool(true)}
var falseLiteral = &_nodeLiteral{value: toValue_bool(false)}
var nullLiteral = &_nodeLiteral{value: nullValue}
var emptyStatement = &_nodeEmptyStatement{}

func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression {
    if in == nil {
        return nil
    }

    switch in := in.(type) {

    case *ast.ArrayLiteral:
        out := &_nodeArrayLiteral{
            value: make([]_nodeExpression, len(in.Value)),
        }
        for i, value := range in.Value {
            out.value[i] = cmpl.parseExpression(value)
        }
        return out

    case *ast.AssignExpression:
        return &_nodeAssignExpression{
            operator: in.Operator,
            left:     cmpl.parseExpression(in.Left),
            right:    cmpl.parseExpression(in.Right),
        }

    case *ast.BinaryExpression:
        return &_nodeBinaryExpression{
            operator:   in.Operator,
            left:       cmpl.parseExpression(in.Left),
            right:      cmpl.parseExpression(in.Right),
            comparison: in.Comparison,
        }

    case *ast.BooleanLiteral:
        if in.Value {
            return trueLiteral
        }
        return falseLiteral

    case *ast.BracketExpression:
        return &_nodeBracketExpression{
            idx:    in.Left.Idx0(),
            left:   cmpl.parseExpression(in.Left),
            member: cmpl.parseExpression(in.Member),
        }

    case *ast.CallExpression:
        out := &_nodeCallExpression{
            callee:       cmpl.parseExpression(in.Callee),
            argumentList: make([]_nodeExpression, len(in.ArgumentList)),
        }
        for i, value := range in.ArgumentList {
            out.argumentList[i] = cmpl.parseExpression(value)
        }
        return out

    case *ast.ConditionalExpression:
        return &_nodeConditionalExpression{
            test:       cmpl.parseExpression(in.Test),
            consequent: cmpl.parseExpression(in.Consequent),
            alternate:  cmpl.parseExpression(in.Alternate),
        }

    case *ast.DotExpression:
        return &_nodeDotExpression{
            idx:        in.Left.Idx0(),
            left:       cmpl.parseExpression(in.Left),
            identifier: in.Identifier.Name,
        }

    case *ast.EmptyExpression:
        return nil

    case *ast.FunctionLiteral:
        name := ""
        if in.Name != nil {
            name = in.Name.Name
        }
        out := &_nodeFunctionLiteral{
            name:   name,
            body:   cmpl.parseStatement(in.Body),
            source: in.Source,
            file:   cmpl.file,
        }
        if in.ParameterList != nil {
            list := in.ParameterList.List
            out.parameterList = make([]string, len(list))
            for i, value := range list {
                out.parameterList[i] = value.Name
            }
        }
        for _, value := range in.DeclarationList {
            switch value := value.(type) {
            case *ast.FunctionDeclaration:
                out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*_nodeFunctionLiteral))
            case *ast.VariableDeclaration:
                for _, value := range value.List {
                    out.varList = append(out.varList, value.Name)
                }
            default:
                panic(fmt.Errorf("Here be dragons: parseProgram.declaration(%T)", value))
            }
        }
        return out

    case *ast.Identifier:
        return &_nodeIdentifier{
            idx:  in.Idx,
            name: in.Name,
        }

    case *ast.NewExpression:
        out := &_nodeNewExpression{
            callee:       cmpl.parseExpression(in.Callee),
            argumentList: make([]_nodeExpression, len(in.ArgumentList)),
        }
        for i, value := range in.ArgumentList {
            out.argumentList[i] = cmpl.parseExpression(value)
        }
        return out

    case *ast.NullLiteral:
        return nullLiteral

    case *ast.NumberLiteral:
        return &_nodeLiteral{
            value: toValue(in.Value),
        }

    case *ast.ObjectLiteral:
        out := &_nodeObjectLiteral{
            value: make([]_nodeProperty, len(in.Value)),
        }
        for i, value := range in.Value {
            out.value[i] = _nodeProperty{
                key:   value.Key,
                kind:  value.Kind,
                value: cmpl.parseExpression(value.Value),
            }
        }
        return out

    case *ast.RegExpLiteral:
        return &_nodeRegExpLiteral{
            flags:   in.Flags,
            pattern: in.Pattern,
        }

    case *ast.SequenceExpression:
        out := &_nodeSequenceExpression{
            sequence: make([]_nodeExpression, len(in.Sequence)),
        }
        for i, value := range in.Sequence {
            out.sequence[i] = cmpl.parseExpression(value)
        }
        return out

    case *ast.StringLiteral:
        return &_nodeLiteral{
            value: toValue_string(in.Value),
        }

    case *ast.ThisExpression:
        return &_nodeThisExpression{}

    case *ast.UnaryExpression:
        return &_nodeUnaryExpression{
            operator: in.Operator,
            operand:  cmpl.parseExpression(in.Operand),
            postfix:  in.Postfix,
        }

    case *ast.VariableExpression:
        return &_nodeVariableExpression{
            idx:         in.Idx0(),
            name:        in.Name,
            initializer: cmpl.parseExpression(in.Initializer),
        }

    }

    panic(fmt.Errorf("Here be dragons: cmpl.parseExpression(%T)", in))
}

func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement {
    if in == nil {
        return nil
    }

    switch in := in.(type) {

    case *ast.BlockStatement:
        out := &_nodeBlockStatement{
            list: make([]_nodeStatement, len(in.List)),
        }
        for i, value := range in.List {
            out.list[i] = cmpl.parseStatement(value)
        }
        return out

    case *ast.BranchStatement:
        out := &_nodeBranchStatement{
            branch: in.Token,
        }
        if in.Label != nil {
            out.label = in.Label.Name
        }
        return out

    case *ast.DebuggerStatement:
        return &_nodeDebuggerStatement{}

    case *ast.DoWhileStatement:
        out := &_nodeDoWhileStatement{
            test: cmpl.parseExpression(in.Test),
        }
        body := cmpl.parseStatement(in.Body)
        if block, ok := body.(*_nodeBlockStatement); ok {
            out.body = block.list
        } else {
            out.body = append(out.body, body)
        }
        return out

    case *ast.EmptyStatement:
        return emptyStatement

    case *ast.ExpressionStatement:
        return &_nodeExpressionStatement{
            expression: cmpl.parseExpression(in.Expression),
        }

    case *ast.ForInStatement:
        out := &_nodeForInStatement{
            into:   cmpl.parseExpression(in.Into),
            source: cmpl.parseExpression(in.Source),
        }
        body := cmpl.parseStatement(in.Body)
        if block, ok := body.(*_nodeBlockStatement); ok {
            out.body = block.list
        } else {
            out.body = append(out.body, body)
        }
        return out

    case *ast.ForStatement:
        out := &_nodeForStatement{
            initializer: cmpl.parseExpression(in.Initializer),
            update:      cmpl.parseExpression(in.Update),
            test:        cmpl.parseExpression(in.Test),
        }
        body := cmpl.parseStatement(in.Body)
        if block, ok := body.(*_nodeBlockStatement); ok {
            out.body = block.list
        } else {
            out.body = append(out.body, body)
        }
        return out

    case *ast.FunctionStatement:
        return emptyStatement

    case *ast.IfStatement:
        return &_nodeIfStatement{
            test:       cmpl.parseExpression(in.Test),
            consequent: cmpl.parseStatement(in.Consequent),
            alternate:  cmpl.parseStatement(in.Alternate),
        }

    case *ast.LabelledStatement:
        return &_nodeLabelledStatement{
            label:     in.Label.Name,
            statement: cmpl.parseStatement(in.Statement),
        }

    case *ast.ReturnStatement:
        return &_nodeReturnStatement{
            argument: cmpl.parseExpression(in.Argument),
        }

    case *ast.SwitchStatement:
        out := &_nodeSwitchStatement{
            discriminant: cmpl.parseExpression(in.Discriminant),
            default_:     in.Default,
            body:         make([]*_nodeCaseStatement, len(in.Body)),
        }
        for i, clause := range in.Body {
            out.body[i] = &_nodeCaseStatement{
                test:       cmpl.parseExpression(clause.Test),
                consequent: make([]_nodeStatement, len(clause.Consequent)),
            }
            for j, value := range clause.Consequent {
                out.body[i].consequent[j] = cmpl.parseStatement(value)
            }
        }
        return out

    case *ast.ThrowStatement:
        return &_nodeThrowStatement{
            argument: cmpl.parseExpression(in.Argument),
        }

    case *ast.TryStatement:
        out := &_nodeTryStatement{
            body:    cmpl.parseStatement(in.Body),
            finally: cmpl.parseStatement(in.Finally),
        }
        if in.Catch != nil {
            out.catch = &_nodeCatchStatement{
                parameter: in.Catch.Parameter.Name,
                body:      cmpl.parseStatement(in.Catch.Body),
            }
        }
        return out

    case *ast.VariableStatement:
        out := &_nodeVariableStatement{
            list: make([]_nodeExpression, len(in.List)),
        }
        for i, value := range in.List {
            out.list[i] = cmpl.parseExpression(value)
        }
        return out

    case *ast.WhileStatement:
        out := &_nodeWhileStatement{
            test: cmpl.parseExpression(in.Test),
        }
        body := cmpl.parseStatement(in.Body)
        if block, ok := body.(*_nodeBlockStatement); ok {
            out.body = block.list
        } else {
            out.body = append(out.body, body)
        }
        return out

    case *ast.WithStatement:
        return &_nodeWithStatement{
            object: cmpl.parseExpression(in.Object),
            body:   cmpl.parseStatement(in.Body),
        }

    }

    panic(fmt.Errorf("Here be dragons: cmpl.parseStatement(%T)", in))
}

func cmpl_parse(in *ast.Program) *_nodeProgram {
    cmpl := _compiler{
        program: in,
    }
    return cmpl.parse()
}

func (cmpl *_compiler) _parse(in *ast.Program) *_nodeProgram {
    out := &_nodeProgram{
        body: make([]_nodeStatement, len(in.Body)),
        file: in.File,
    }
    for i, value := range in.Body {
        out.body[i] = cmpl.parseStatement(value)
    }
    for _, value := range in.DeclarationList {
        switch value := value.(type) {
        case *ast.FunctionDeclaration:
            out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*_nodeFunctionLiteral))
        case *ast.VariableDeclaration:
            for _, value := range value.List {
                out.varList = append(out.varList, value.Name)
            }
        default:
            panic(fmt.Errorf("Here be dragons: cmpl.parseProgram.DeclarationList(%T)", value))
        }
    }
    return out
}

type _nodeProgram struct {
    body []_nodeStatement

    varList      []string
    functionList []*_nodeFunctionLiteral

    variableList []_nodeDeclaration

    file *file.File
}

type _nodeDeclaration struct {
    name       string
    definition _node
}

type _node interface {
}

type (
    _nodeExpression interface {
        _node
        _expressionNode()
    }

    _nodeArrayLiteral struct {
        value []_nodeExpression
    }

    _nodeAssignExpression struct {
        operator token.Token
        left     _nodeExpression
        right    _nodeExpression
    }

    _nodeBinaryExpression struct {
        operator   token.Token
        left       _nodeExpression
        right      _nodeExpression
        comparison bool
    }

    _nodeBracketExpression struct {
        idx    file.Idx
        left   _nodeExpression
        member _nodeExpression
    }

    _nodeCallExpression struct {
        callee       _nodeExpression
        argumentList []_nodeExpression
    }

    _nodeConditionalExpression struct {
        test       _nodeExpression
        consequent _nodeExpression
        alternate  _nodeExpression
    }

    _nodeDotExpression struct {
        idx        file.Idx
        left       _nodeExpression
        identifier string
    }

    _nodeFunctionLiteral struct {
        name          string
        body          _nodeStatement
        source        string
        parameterList []string
        varList       []string
        functionList  []*_nodeFunctionLiteral
        file          *file.File
    }

    _nodeIdentifier struct {
        idx  file.Idx
        name string
    }

    _nodeLiteral struct {
        value Value
    }

    _nodeNewExpression struct {
        callee       _nodeExpression
        argumentList []_nodeExpression
    }

    _nodeObjectLiteral struct {
        value []_nodeProperty
    }

    _nodeProperty struct {
        key   string
        kind  string
        value _nodeExpression
    }

    _nodeRegExpLiteral struct {
        flags   string
        pattern string // Value?
        regexp  *regexp.Regexp
    }

    _nodeSequenceExpression struct {
        sequence []_nodeExpression
    }

    _nodeThisExpression struct {
    }

    _nodeUnaryExpression struct {
        operator token.Token
        operand  _nodeExpression
        postfix  bool
    }

    _nodeVariableExpression struct {
        idx         file.Idx
        name        string
        initializer _nodeExpression
    }
)

type (
    _nodeStatement interface {
        _node
        _statementNode()
    }

    _nodeBlockStatement struct {
        list []_nodeStatement
    }

    _nodeBranchStatement struct {
        branch token.Token
        label  string
    }

    _nodeCaseStatement struct {
        test       _nodeExpression
        consequent []_nodeStatement
    }

    _nodeCatchStatement struct {
        parameter string
        body      _nodeStatement
    }

    _nodeDebuggerStatement struct {
    }

    _nodeDoWhileStatement struct {
        test _nodeExpression
        body []_nodeStatement
    }

    _nodeEmptyStatement struct {
    }

    _nodeExpressionStatement struct {
        expression _nodeExpression
    }

    _nodeForInStatement struct {
        into   _nodeExpression
        source _nodeExpression
        body   []_nodeStatement
    }

    _nodeForStatement struct {
        initializer _nodeExpression
        update      _nodeExpression
        test        _nodeExpression
        body        []_nodeStatement
    }

    _nodeIfStatement struct {
        test       _nodeExpression
        consequent _nodeStatement
        alternate  _nodeStatement
    }

    _nodeLabelledStatement struct {
        label     string
        statement _nodeStatement
    }

    _nodeReturnStatement struct {
        argument _nodeExpression
    }

    _nodeSwitchStatement struct {
        discriminant _nodeExpression
        default_     int
        body         []*_nodeCaseStatement
    }

    _nodeThrowStatement struct {
        argument _nodeExpression
    }

    _nodeTryStatement struct {
        body    _nodeStatement
        catch   *_nodeCatchStatement
        finally _nodeStatement
    }

    _nodeVariableStatement struct {
        list []_nodeExpression
    }

    _nodeWhileStatement struct {
        test _nodeExpression
        body []_nodeStatement
    }

    _nodeWithStatement struct {
        object _nodeExpression
        body   _nodeStatement
    }
)

// _expressionNode

func (*_nodeArrayLiteral) _expressionNode()          {}
func (*_nodeAssignExpression) _expressionNode()      {}
func (*_nodeBinaryExpression) _expressionNode()      {}
func (*_nodeBracketExpression) _expressionNode()     {}
func (*_nodeCallExpression) _expressionNode()        {}
func (*_nodeConditionalExpression) _expressionNode() {}
func (*_nodeDotExpression) _expressionNode()         {}
func (*_nodeFunctionLiteral) _expressionNode()       {}
func (*_nodeIdentifier) _expressionNode()            {}
func (*_nodeLiteral) _expressionNode()               {}
func (*_nodeNewExpression) _expressionNode()         {}
func (*_nodeObjectLiteral) _expressionNode()         {}
func (*_nodeRegExpLiteral) _expressionNode()         {}
func (*_nodeSequenceExpression) _expressionNode()    {}
func (*_nodeThisExpression) _expressionNode()        {}
func (*_nodeUnaryExpression) _expressionNode()       {}
func (*_nodeVariableExpression) _expressionNode()    {}

// _statementNode

func (*_nodeBlockStatement) _statementNode()      {}
func (*_nodeBranchStatement) _statementNode()     {}
func (*_nodeCaseStatement) _statementNode()       {}
func (*_nodeCatchStatement) _statementNode()      {}
func (*_nodeDebuggerStatement) _statementNode()   {}
func (*_nodeDoWhileStatement) _statementNode()    {}
func (*_nodeEmptyStatement) _statementNode()      {}
func (*_nodeExpressionStatement) _statementNode() {}
func (*_nodeForInStatement) _statementNode()      {}
func (*_nodeForStatement) _statementNode()        {}
func (*_nodeIfStatement) _statementNode()         {}
func (*_nodeLabelledStatement) _statementNode()   {}
func (*_nodeReturnStatement) _statementNode()     {}
func (*_nodeSwitchStatement) _statementNode()     {}
func (*_nodeThrowStatement) _statementNode()      {}
func (*_nodeTryStatement) _statementNode()        {}
func (*_nodeVariableStatement) _statementNode()   {}
func (*_nodeWhileStatement) _statementNode()      {}
func (*_nodeWithStatement) _statementNode()       {}