有限状态机
每个状态都是一个机器,每个机器都可以输入和输出。机器本身没有状态,每一个机器都可以根据输入决定下一个状态。
上一篇文章我们研究了如何生成AST语法树,然后如何根据语法树来生成状态。现在我们来研究下,状态机是如何实现的。
假设我有一段字符串。我们要判断这个字符串中数字有多少个,然后运算符号有多少个,我们就需要用到状态机。
示例代码:
/**
* 分词
* 状态机
*/
let NUMBER=/[0-9]/
let tokens=[]
let currentToken
// 要确定一个新的token了
function emit(token){
currentToken={type: '',value: ''}
tokens.push(token)
}
function start(char){
if(NUMBER.test(char)){
currentToken={type:'Numeric',value:''}
}
return number(char)
}
function number(char){
if(NUMBER.test(char)){
currentToken.value+=char
}else if(char==='+'||char=='-'){
emit(currentToken)
emit({type:'Punctuator',value: char})
currentToken={type:'Numeric',value: ''}
return number
}
return number
}
function tokenizer(input){
// 刚开始的时候是start的状态
let state=start
for(let char of input){
state=state(char)
}
if(currentToken.value.length>0){
emit(currentToken)
}
}
tokenizer("10+20+30-10")
console.log(tokens)
- 首先我们传入字符串
- 字符串进行解析,从第一个字符算开始状态。每遍历一个字符我们就改变其状态
function start(char){
if(NUMBER.test(char)){
currentToken={type:'Numeric',value:''}
}
return number(char)
}
- 其中状态改变的方法叫做Numeric。碰到运算符号我们保存Punctuator
function number(char){
if(NUMBER.test(char)){
currentToken.value+=char
}else if(char==='+'||char=='-'){
emit(currentToken)
emit({type:'Punctuator',value: char})
currentToken={type:'Numeric',value: ''}
return number
}
return number
}
- 每保存一次状态我们就将currentToken给他改变清空掉。最后我们将每一位的状态保存到一个数组里面去。
我正在参加「创意开发 投稿大赛」详情请看:掘金创意开发大赛来了!