3 Star 1 Fork 0

Gitee 极速下载/otto

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
此仓库是为了提升国内下载速度的镜像仓库,每日同步一次。 原始仓库: https://github.com/robertkrimen/otto
克隆/下载
cmpl_parse.go 14.70 KB
一键复制 编辑 原始数据 按行查看 历史
Steven Hartland 提交于 2024-04-13 17:05 . chore: update ci versions (#519)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
package otto
import (
"fmt"
"github.com/robertkrimen/otto/ast"
"github.com/robertkrimen/otto/file"
"github.com/robertkrimen/otto/token"
)
var (
trueLiteral = &nodeLiteral{value: boolValue(true)}
falseLiteral = &nodeLiteral{value: boolValue(false)}
nullLiteral = &nodeLiteral{value: nullValue}
emptyStatement = &nodeEmptyStatement{}
)
func (cmpl *compiler) parseExpression(expr ast.Expression) nodeExpression {
if expr == nil {
return nil
}
switch expr := expr.(type) {
case *ast.ArrayLiteral:
out := &nodeArrayLiteral{
value: make([]nodeExpression, len(expr.Value)),
}
for i, value := range expr.Value {
out.value[i] = cmpl.parseExpression(value)
}
return out
case *ast.AssignExpression:
return &nodeAssignExpression{
operator: expr.Operator,
left: cmpl.parseExpression(expr.Left),
right: cmpl.parseExpression(expr.Right),
}
case *ast.BinaryExpression:
return &nodeBinaryExpression{
operator: expr.Operator,
left: cmpl.parseExpression(expr.Left),
right: cmpl.parseExpression(expr.Right),
comparison: expr.Comparison,
}
case *ast.BooleanLiteral:
if expr.Value {
return trueLiteral
}
return falseLiteral
case *ast.BracketExpression:
return &nodeBracketExpression{
idx: expr.Left.Idx0(),
left: cmpl.parseExpression(expr.Left),
member: cmpl.parseExpression(expr.Member),
}
case *ast.CallExpression:
out := &nodeCallExpression{
callee: cmpl.parseExpression(expr.Callee),
argumentList: make([]nodeExpression, len(expr.ArgumentList)),
}
for i, value := range expr.ArgumentList {
out.argumentList[i] = cmpl.parseExpression(value)
}
return out
case *ast.ConditionalExpression:
return &nodeConditionalExpression{
test: cmpl.parseExpression(expr.Test),
consequent: cmpl.parseExpression(expr.Consequent),
alternate: cmpl.parseExpression(expr.Alternate),
}
case *ast.DotExpression:
return &nodeDotExpression{
idx: expr.Left.Idx0(),
left: cmpl.parseExpression(expr.Left),
identifier: expr.Identifier.Name,
}
case *ast.EmptyExpression:
return nil
case *ast.FunctionLiteral:
name := ""
if expr.Name != nil {
name = expr.Name.Name
}
out := &nodeFunctionLiteral{
name: name,
body: cmpl.parseStatement(expr.Body),
source: expr.Source,
file: cmpl.file,
}
if expr.ParameterList != nil {
list := expr.ParameterList.List
out.parameterList = make([]string, len(list))
for i, value := range list {
out.parameterList[i] = value.Name
}
}
for _, value := range expr.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.Sprintf("parse expression unknown function declaration type %T", value))
}
}
return out
case *ast.Identifier:
return &nodeIdentifier{
idx: expr.Idx,
name: expr.Name,
}
case *ast.NewExpression:
out := &nodeNewExpression{
callee: cmpl.parseExpression(expr.Callee),
argumentList: make([]nodeExpression, len(expr.ArgumentList)),
}
for i, value := range expr.ArgumentList {
out.argumentList[i] = cmpl.parseExpression(value)
}
return out
case *ast.NullLiteral:
return nullLiteral
case *ast.NumberLiteral:
return &nodeLiteral{
value: toValue(expr.Value),
}
case *ast.ObjectLiteral:
out := &nodeObjectLiteral{
value: make([]nodeProperty, len(expr.Value)),
}
for i, value := range expr.Value {
out.value[i] = nodeProperty{
key: value.Key,
kind: value.Kind,
value: cmpl.parseExpression(value.Value),
}
}
return out
case *ast.RegExpLiteral:
return &nodeRegExpLiteral{
flags: expr.Flags,
pattern: expr.Pattern,
}
case *ast.SequenceExpression:
out := &nodeSequenceExpression{
sequence: make([]nodeExpression, len(expr.Sequence)),
}
for i, value := range expr.Sequence {
out.sequence[i] = cmpl.parseExpression(value)
}
return out
case *ast.StringLiteral:
return &nodeLiteral{
value: stringValue(expr.Value),
}
case *ast.ThisExpression:
return &nodeThisExpression{}
case *ast.UnaryExpression:
return &nodeUnaryExpression{
operator: expr.Operator,
operand: cmpl.parseExpression(expr.Operand),
postfix: expr.Postfix,
}
case *ast.VariableExpression:
return &nodeVariableExpression{
idx: expr.Idx0(),
name: expr.Name,
initializer: cmpl.parseExpression(expr.Initializer),
}
default:
panic(fmt.Errorf("parse expression unknown node type %T", expr))
}
}
func (cmpl *compiler) parseStatement(stmt ast.Statement) nodeStatement {
if stmt == nil {
return nil
}
switch stmt := stmt.(type) {
case *ast.BlockStatement:
out := &nodeBlockStatement{
list: make([]nodeStatement, len(stmt.List)),
}
for i, value := range stmt.List {
out.list[i] = cmpl.parseStatement(value)
}
return out
case *ast.BranchStatement:
out := &nodeBranchStatement{
branch: stmt.Token,
}
if stmt.Label != nil {
out.label = stmt.Label.Name
}
return out
case *ast.DebuggerStatement:
return &nodeDebuggerStatement{}
case *ast.DoWhileStatement:
out := &nodeDoWhileStatement{
test: cmpl.parseExpression(stmt.Test),
}
body := cmpl.parseStatement(stmt.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(stmt.Expression),
}
case *ast.ForInStatement:
out := &nodeForInStatement{
into: cmpl.parseExpression(stmt.Into),
source: cmpl.parseExpression(stmt.Source),
}
body := cmpl.parseStatement(stmt.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(stmt.Initializer),
update: cmpl.parseExpression(stmt.Update),
test: cmpl.parseExpression(stmt.Test),
}
body := cmpl.parseStatement(stmt.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(stmt.Test),
consequent: cmpl.parseStatement(stmt.Consequent),
alternate: cmpl.parseStatement(stmt.Alternate),
}
case *ast.LabelledStatement:
return &nodeLabelledStatement{
label: stmt.Label.Name,
statement: cmpl.parseStatement(stmt.Statement),
}
case *ast.ReturnStatement:
return &nodeReturnStatement{
argument: cmpl.parseExpression(stmt.Argument),
}
case *ast.SwitchStatement:
out := &nodeSwitchStatement{
discriminant: cmpl.parseExpression(stmt.Discriminant),
defaultIdx: stmt.Default,
body: make([]*nodeCaseStatement, len(stmt.Body)),
}
for i, clause := range stmt.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(stmt.Argument),
}
case *ast.TryStatement:
out := &nodeTryStatement{
body: cmpl.parseStatement(stmt.Body),
finally: cmpl.parseStatement(stmt.Finally),
}
if stmt.Catch != nil {
out.catch = &nodeCatchStatement{
parameter: stmt.Catch.Parameter.Name,
body: cmpl.parseStatement(stmt.Catch.Body),
}
}
return out
case *ast.VariableStatement:
out := &nodeVariableStatement{
list: make([]nodeExpression, len(stmt.List)),
}
for i, value := range stmt.List {
out.list[i] = cmpl.parseExpression(value)
}
return out
case *ast.WhileStatement:
out := &nodeWhileStatement{
test: cmpl.parseExpression(stmt.Test),
}
body := cmpl.parseStatement(stmt.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(stmt.Object),
body: cmpl.parseStatement(stmt.Body),
}
default:
panic(fmt.Sprintf("parse statement: unknown type %T", stmt))
}
}
func cmplParse(in *ast.Program) *nodeProgram {
cmpl := compiler{
program: in,
}
if cmpl.program != nil {
cmpl.file = cmpl.program.File
}
return cmpl.parse()
}
func (cmpl *compiler) parse() *nodeProgram {
out := &nodeProgram{
body: make([]nodeStatement, len(cmpl.program.Body)),
file: cmpl.program.File,
}
for i, value := range cmpl.program.Body {
out.body[i] = cmpl.parseStatement(value)
}
for _, value := range cmpl.program.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.Sprintf("Here be dragons: cmpl.parseProgram.DeclarationList(%T)", value))
}
}
return out
}
type nodeProgram struct {
file *file.File
body []nodeStatement
varList []string
functionList []*nodeFunctionLiteral
}
type node interface{}
type (
nodeExpression interface {
node
expressionNode()
}
nodeArrayLiteral struct {
value []nodeExpression
}
nodeAssignExpression struct {
left nodeExpression
right nodeExpression
operator token.Token
}
nodeBinaryExpression struct {
left nodeExpression
right nodeExpression
operator token.Token
comparison bool
}
nodeBracketExpression struct {
left nodeExpression
member nodeExpression
idx file.Idx
}
nodeCallExpression struct {
callee nodeExpression
argumentList []nodeExpression
}
nodeConditionalExpression struct {
test nodeExpression
consequent nodeExpression
alternate nodeExpression
}
nodeDotExpression struct {
left nodeExpression
identifier string
idx file.Idx
}
nodeFunctionLiteral struct {
body nodeStatement
file *file.File
name string
source string
parameterList []string
varList []string
functionList []*nodeFunctionLiteral
}
nodeIdentifier struct {
name string
idx file.Idx
}
nodeLiteral struct {
value Value
}
nodeNewExpression struct {
callee nodeExpression
argumentList []nodeExpression
}
nodeObjectLiteral struct {
value []nodeProperty
}
nodeProperty struct {
value nodeExpression
key string
kind string
}
nodeRegExpLiteral struct {
flags string
pattern string // Value?
}
nodeSequenceExpression struct {
sequence []nodeExpression
}
nodeThisExpression struct{}
nodeUnaryExpression struct {
operand nodeExpression
operator token.Token
postfix bool
}
nodeVariableExpression struct {
initializer nodeExpression
name string
idx file.Idx
}
)
type (
nodeStatement interface {
node
statementNode()
}
nodeBlockStatement struct {
list []nodeStatement
}
nodeBranchStatement struct {
label string
branch token.Token
}
nodeCaseStatement struct {
test nodeExpression
consequent []nodeStatement
}
nodeCatchStatement struct {
body nodeStatement
parameter string
}
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 {
statement nodeStatement
label string
}
nodeReturnStatement struct {
argument nodeExpression
}
nodeSwitchStatement struct {
discriminant nodeExpression
body []*nodeCaseStatement
defaultIdx int
}
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() {}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/mirrors/otto.git
git@gitee.com:mirrors/otto.git
mirrors
otto
otto
master

搜索帮助

0d507c66 1850385 C8b1a773 1850385