Пример #1
0
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))
}
Пример #2
0
// 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))
	}
}