寫一個整數四則運算的解析器——詞法分析部分

寫一個簡單的詞法、語法分析器,來最終分析出整數四則運算表達式的結果。函數

爲了簡化詞語法分析咱們只容許出現0~9,+,-,*,/,空格,\r, \n這幾個字符spa

詞法分析:code

方法1. 狀態機blog

咱們先準備3個判斷方法:token

// 是不是數字
function isNum(letter) {
    return letter === '0' || letter === '1' || letter === '2' || letter === '3' || letter === '4' || letter === '5' || letter === '0' || letter === '6' || letter === '7' || letter === '8' || letter === '9'
}
// 是不是運算符
function isOperater(letter) {
    return letter === '+' || letter === '-' || letter === '*' || letter === '/'
}
// 是不是間隔符
function isEmptyLetter(letter) {
    return letter === ' ' || letter === '\r' || letter === '\n'
}

定義生成token的函數:字符串

const tokenList = []
function generateToken(type, token) {
    console.log("生成token: " + token);
    tokenList.push({type, token});
}

定義狀態轉移函數:it

let token = []
function startToken(letter) {
    if (isNum(letter)) {
        // 若是是數字,則進入inNumber狀態
        token.push(letter)
        return inNumber
    } else if (isOperater(letter)) {
        // 若是是+-*/, 就立刻生成一個token
        generateToken('operator', letter)
        return startToken
    } else if (isEmptyLetter(letter)) {
        // 若是是空白字符,則跳過
        return startToken
    } else {
        // 若是是其餘字符則報錯
        throw new Error('出現意外字符')
    }
}

function inNumber(letter) {
    if (isNum(letter)) {
        token.push(letter)
        return inNumber
    } else {
        // 直到遇到非數字, 把前面push的數字生成一個數字token, 而後清空token
        generateToken('number', token.join(''))
        token = []
        // 最後讓新的letter立刻執行一次startToken
        return startToken(letter)
    }
}

開始詞法分析:io

// 要詞法分析的字符串
const str = '123* 656 - 644 + 3131'
// 分割成一個個字母
let strArr = str.split('');
// 定義狀態機
let state = startToken
// 遍歷字母,不停地更新狀態機
for(let letter of strArr) {
    state = state(letter)
}

 得出結果:console

方法2. 正則分析function

 

// 要詞法分析的字符串
let str = '123* 656 - 644 + 3131'
// 過濾間隔符
str = str.replace(/[\r\n ]/g, '')

const operatorRegExp = /[+\-*/]/g
// 獲取運算的數字token
let numList = str.split(operatorRegExp)
// 獲取運算符token
let operatorList = str.match(operatorRegExp)

const tokenList = []
numList.forEach((item, idx) => {
    tokenList.push({type: 'number', token: item})
    if (idx !== numList.length - 1) {
        tokenList.push({type: 'operator', token: operatorList[idx]})
    }
})

console.log(tokenList)

得出結果:

到這裏詞法分析就已經完成了。

相關文章
相關標籤/搜索