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)) }
// formatExpression formats an ES expression. func (sf *sourceFormatter) formatExpression(expression ast.Expression) { // Add the mapping for the expression. sf.addMapping(expression.Idx0()) switch e := expression.(type) { // ArrayLiteral case *ast.ArrayLiteral: sf.append("[") sf.formatExpressionList(e.Value) sf.append("]") // AssignExpression case *ast.AssignExpression: sf.formatExpression(e.Left) sf.append(" ") sf.append(e.Operator.String()) sf.append(" ") sf.formatExpression(e.Right) // BinaryExpression case *ast.BinaryExpression: sf.appendOptionalOpenParen(e.Left) sf.formatExpression(e.Left) sf.appendOptionalCloseParen(e.Left) sf.append(" ") sf.append(e.Operator.String()) sf.append(" ") sf.appendOptionalOpenParen(e.Right) sf.formatExpression(e.Right) sf.appendOptionalCloseParen(e.Right) // BooleanLiteral case *ast.BooleanLiteral: sf.append(e.Literal) // BracketExpression case *ast.BracketExpression: sf.formatExpression(e.Left) sf.append("[") sf.formatExpression(e.Member) sf.append("]") // CallExpression case *ast.CallExpression: sf.formatExpression(e.Callee) sf.append("(") sf.formatExpressionList(e.ArgumentList) sf.append(")") // ConditionalExpression case *ast.ConditionalExpression: sf.formatExpression(e.Test) sf.append(" ? ") sf.formatExpression(e.Consequent) sf.append(" : ") sf.formatExpression(e.Alternate) // DotExpression case *ast.DotExpression: sf.appendOptionalOpenParen(e.Left) sf.formatExpression(e.Left) sf.appendOptionalCloseParen(e.Left) sf.append(".") sf.append(e.Identifier.Name) // FunctionLiteral case *ast.FunctionLiteral: sf.append("function") if e.Name != nil { sf.append(" ") sf.append(e.Name.Name) } sf.append(" (") sf.formatIdentifierList(e.ParameterList.List) sf.append(") ") sf.formatStatement(e.Body) // Identifer case *ast.Identifier: sf.append(e.Name) // NewExpression case *ast.NewExpression: sf.append("new ") sf.formatExpression(e.Callee) sf.append("(") sf.formatExpressionList(e.ArgumentList) sf.append(")") // NullLiteral case *ast.NullLiteral: sf.append("null") // NumberLiteral case *ast.NumberLiteral: sf.append(e.Literal) // ObjectLiteral case *ast.ObjectLiteral: sf.append("{") sf.appendLine() sf.indent() for _, value := range e.Value { noQuoting, _ := regexp.MatchString("^[$a-zA-Z0-9]+$", value.Key) if !noQuoting { sf.append("\"") } sf.append(value.Key) if !noQuoting { sf.append("\"") } sf.append(": ") sf.formatExpression(value.Value) sf.append(",") sf.appendLine() } sf.dedent() sf.append("}") // RegExpLiteral case *ast.RegExpLiteral: sf.append(e.Literal) // StringLiteral case *ast.StringLiteral: sf.append(e.Literal) // ThisExpression case *ast.ThisExpression: sf.append("this") // SequenceExpression: case *ast.SequenceExpression: if len(e.Sequence) > 1 { sf.append("(") } sf.formatExpressionList(e.Sequence) if len(e.Sequence) > 1 { sf.append(")") } // UnaryExpression case *ast.UnaryExpression: if e.Postfix { sf.formatExpression(e.Operand) sf.appendOptionalOpenParen(e.Operand) sf.append(e.Operator.String()) sf.appendOptionalCloseParen(e.Operand) } else { if e.Operator.String() == "delete" || e.Operator.String() == "typeof" { sf.append(e.Operator.String()) sf.append(" ") sf.formatExpression(e.Operand) } else { sf.append(e.Operator.String()) sf.appendOptionalOpenParen(e.Operand) sf.formatExpression(e.Operand) sf.appendOptionalCloseParen(e.Operand) } } // VariableExpression case *ast.VariableExpression: sf.append("var ") sf.append(e.Name) if e.Initializer != nil { sf.append(" = ") sf.formatExpression(e.Initializer) } default: panic(fmt.Sprintf("Unknown expression AST node: %T", e)) } }