Skip to content

ast.js #1

@wuyuedefeng

Description

@wuyuedefeng
// https://ericsmekens.github.io/jsep
import {parse} from '@/utils/expression-eval'
class Ast {
	static transToAstArray(ast) {
		const tags = []
		let layer = ast
		console.log('layer', layer)
		while(layer) {
			switch(layer.type) {
				case 'MemberExpression': {
					const operator = layer.computed ? '[]' : '.'
					const right = Ast.transToAstArray(layer.property)
					tags.push({operator: operator, left: '', right, type: layer.type })
					layer = layer.object
					break
				}
				case 'CallExpression': {
					// tags.push(this.ViewModel.find(layer.arguments[0].value).name)
					let operator = '.'
					let right = ''
					const calleeType = layer.callee.type
					if (calleeType === 'CallExpression') {
						operator = ''
						right = Ast.transToAstArray(layer.callee)
					} else if (calleeType === 'MemberExpression') {
						operator = layer.callee?.computed ? '[]' : '.'
						right = Ast.transToAstArray(layer.callee.property)
					} else { // FIXME, 未测试,还不确定其他情况, 暂时用MemberExpression的值
						right = Ast.transToAstArray(layer.callee.property)
					}
					tags.push({ operator, left: '', right, args: layer.arguments.map(arg => Ast.transToAstArray(arg)), type: layer.type })
					layer = layer.callee.object
					break
				}
				case 'Identifier':
					tags.push({ operator: '', left: '', right: layer.name, type: layer.type })
					layer = layer.object
					break
				case 'BinaryExpression':
				case 'LogicalExpression':
					tags.push({ operator: layer.operator, left: Ast.transToAstArray(layer.left), right: Ast.transToAstArray(layer.right), type: layer.type })
					layer = layer.object
					break
				// !a, a++, ++a, a--, --a
				case 'UnaryExpression':
					tags.push({
						operator: layer.operator,
						left: '',
						right: layer.argument ? Ast.transToAstArray(layer.argument) : '',
						type: layer.type
					})
					layer = layer.object
					break
				case 'Literal':
					tags.push({
						operator: '',
						left: '',
						right: typeof layer.value === 'string' ? `'${ layer.value }'` : layer.value,
						type: layer.type
					})
					layer = layer.object
					break
				default:
					layer = null
			}
		}
		return tags.reverse()
	}
	static transToExpression(astArray, isEntry = true) {
		let expression = ''
		for(const cLayer of astArray) {
			switch (cLayer.type) {
				// + - * /
				case 'BinaryExpression':
				//	a[0]
				case 'LogicalExpression': {
					const leftExpression = this.transToExpression(cLayer.left, false)
					const rightExpression = this.transToExpression(cLayer.right, false)
					expression = cLayer.operator === '[]' ? `${leftExpression}[${rightExpression}]` : `${leftExpression}${cLayer.operator}${rightExpression}`
					if (!isEntry) {
						expression = `(${expression})`
					}
					break
				}
				// ! ++ --
				case 'UnaryExpression': {
					let leftExpression = this.transToExpression(cLayer.left, false)
					let rightExpression = this.transToExpression(cLayer.right, false)
					expression = cLayer.operator === '[]' ? `${leftExpression}[${rightExpression}]` : `${leftExpression}${cLayer.operator}${rightExpression}`
					break
				}
				case 'MemberExpression': {
					const rightExpression = this.transToExpression(cLayer.right, false)
					expression = cLayer.operator === '[]' ? `${expression}${cLayer.left}[${rightExpression}]` : `${expression}${cLayer.left}${cLayer.operator}${rightExpression}`
					break
				}
				// 函数
				case 'CallExpression':
					// 函数参数
					const rightExpression = this.transToExpression(cLayer.right, false)
					const args = cLayer.args.map(argument => this.transToExpression(argument, true))
					expression = cLayer.operator === '[]' ? `${expression}${cLayer.left}[${rightExpression}](${args.join(',')})` : `${expression}${cLayer.left}${cLayer.operator}${rightExpression}(${args.join(',')})`
					break
				default:
					expression = cLayer.operator === '[]' ? `${expression}${cLayer.left}[${cLayer.right}]` : `${expression}${cLayer.left}${cLayer.operator}${cLayer.right}`
			}
		}
		return expression
	}
	constructor() {
		// 最后一次正确的解析表达式
		this.expression = ''
		// 当前表达式
		this._expression = ''
		this._error = null
	}
	get ast() {
		return this._ast
	}
	set ast(val) {
		this._ast = val
		this._astArray = Ast.transToAstArray(val)
		this._astExpression = Ast.transToExpression(this._astArray)
	}
	update(expression) {
		try {
			// parse expression
			const ast = parse(expression)
			this.expression = expression
			this.ast = ast
			this._expression = expression
			this._error = null
		} catch (err) {
			console.error('expression parse error:', err)
			this._expression = expression
			this._error = err
		}
		return this
	}

}

export default Ast

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions