问题描述
假设你有这样的系统:
const input = [0,[1,2,[3,4,[8,9],6,7],4],[5,3,7,[1],9]
const output = parse(input)
console.log(output.join('-'))
function parse(input) {
const output = []
iterate(input,value => {
check(() => isArray(value),() => { // yes array
const children = parse(value)
output.push(...children)
},() => { // not array
check(() => isEven(value),() => {
output.push(value)
})
})
})
return output
}
function isArray(value) {
return Array.isArray(value)
}
function isEven(value) {
return value % 2 == 0
}
function check(condition,success,failure) {
if (condition()) success()
else if (failure) failure()
}
function iterate(array,block) {
array.forEach(block)
}
本质上这就像一个树语法:
parse =
iterate input,value =>
check isArray(value)
call parse(value)
check isNumber(value)
check isEven(value)
push(value)
你可以把它想象成 JSON:
{
type: 'function',name: 'parse',children: [
{
type: 'iterate',children: [
{
type: 'check',checker: 'isArray',children: [
{
type: 'call',function: 'parse'
}
]
},{
type: 'check',checker: 'isNumber',children: [
{
type: 'check',checker: 'isEven',children: [
{
type: 'push',}
]
}
]
}
]
}
]
}
基本上我真正的问题是我在自定义编程语言中有这样的 JSON,我想将它转换为状态机,而不是我们在这篇文章中开始的嵌套/递归函数调用。
所以我的问题是,你如何重写本文开头的递归函数系统,使其使用状态机?你不必一路走来从 JSON 生成状态机(在这个例子中是不完整的,因为我没有一个很好的例子来简化)。相反,如果您能展示如何从本文开头将这个递归或嵌套函数系统重写为状态机,那就足够了。
我的想象是这样的:
let transitions = [
function1,function2,...
]
let transition = transitions[0] // the start function in theory
let currentInput = input
let someStack = []
while (transition) {
[currentInput,transition] = transition(someStack,currentInput)
}
但是我很快就会迷失在如何跟踪我们在输入中所处的位置,以及如何处理诸如迭代(如iterator
)或“if 语句”(如check
)。
function iterate(input) {
// you can't do the recursive call here,// as the original while loop should handle this.
// but,we should return some reference to the current input,// as well as the next transition.
}
如果必须选择一种语言,那么在 JavaScript 中执行此操作将是最简单的。但它甚至可以用伪代码来完成,以大致展示它是如何完成的。
解决方法
这是不可能的。 state machine 无法识别/解析 language with a recursive grammar,只能识别/解析 regular language。您需要一个 stack machine。