编译原理02-有限状态机

204 阅读1分钟

有限状态机

每个状态都是一个机器,每个机器都可以输入和输出。机器本身没有状态,每一个机器都可以根据输入决定下一个状态。

上一篇文章我们研究了如何生成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给他改变清空掉。最后我们将每一位的状态保存到一个数组里面去。

image.png

我正在参加「创意开发 投稿大赛」详情请看:掘金创意开发大赛来了!