Skip to content

Instantly share code, notes, and snippets.

@erukiti
Created September 11, 2017 12:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erukiti/8eb040fce47ee37203912263bf549206 to your computer and use it in GitHub Desktop.
Save erukiti/8eb040fce47ee37203912263bf549206 to your computer and use it in GitHub Desktop.
AST使った計算機 (引数に"1 * 3"みたいに式を指定)
const babylon = require('babylon')
const parse = (source) => {
try {
const ast = babylon.parse(source)
delete ast.tokens
return {ast}
} catch (err) {
return {error: err}
}
}
if (process.argv.length <= 2) {
console.error('引数に計算式かいてください')
process.exit(1)
}
const {ast} = parse(process.argv[2])
const replacer = (key, value) => {
if (!key) {
return value
}
if (/^[0-9]+$/.test(key)) {
return value
}
return (['type', 'program', 'body', 'expression','left', 'right']).indexOf(key) === -1 ? undefined : value
}
// console.log(JSON.stringify(ast, replacer, ' '))
const walker = (node, warkers) => {
if (!(node.type in walkers)) {
throw new Error('対応してないtype', node.type)
}
return walkers[node.type](node)
}
const walkers = {
'File': node => walker(node.program),
'Program': node => {
node.body.forEach(value => console.log(walker(value)))
return null
},
'ExpressionStatement': node => walker(node.expression),
'BinaryExpression': node => {
const left = walker(node.left)
const right = walker(node.right)
switch (node.operator) {
case '+': return left + right
case '*': return left * right
case '-': return left - right
case '/': return left / right
case '%': return left % right
default: throw new Error('対応してない二項演算子')
}
},
'NumericLiteral': node => node.value
}
walker(ast, walkers)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment