zoukankan      html  css  js  c++  java
  • 写一个整数四则运算的解析器——词法分析部分

    写一个简单的词法、语法分析器,来最终分析出整数四则运算表达式的结果。

    为了简化词语法分析我们只允许出现0~9,+,-,*,/,空格, , 这几个字符

    词法分析:

    方法1. 状态机

    我们先准备3个判断方法:

    // 是否是数字
    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 === '
    ' || letter === '
    '
    }

    定义生成token的函数:

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

    定义状态转移函数:

    let token = []
    function startToken(letter) {
        if (isNum(letter)) {
            // 如果是数字,则进入inNumber状态
            token.push(letter)
            return inNumber
        } else if (isOperater(letter)) {
            // 如果是+-*/, 就马上生成一个token
            generateToken(letter, 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)
        }
    }

    开始词法分析:

    // 要词法分析的字符串
    const str = '123* 656 - 644 + 3131'
    // 分割成一个个字母
    let strArr = str.split('');
    // 定义状态机
    let state = startToken
    // 遍历字母,不停地更新状态机
    for(let letter of strArr) {
        state = state(letter)
    }
    // 结束
    state(Symbol('EOF'))
    generateToken('EOF', 'EOF')

     得出结果:

    方法2. 正则分析

    // 要词法分析的字符串
    let str = '123* 656 - 644 + 3131'
    // 过滤间隔符
    str = str.replace(/[
     ]/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: operatorList[idx], token: operatorList[idx]})
        }
    })
    // 结束
    tokenList.push({type: 'EOF', token: 'EOF'})
    console.log(tokenList)

    得出结果:

    到这里词法分析就已经完成了。

  • 相关阅读:
    pycharm的集成vim
    几款在线脑图制作工具
    编辑器vim简介
    常用服务器ftp、ssh
    56. Merge Intervals
    58. Length of Last Word
    55. Jump Game
    53. Maximum Subarray
    52. N-Queens II
    51. N-Queens
  • 原文地址:https://www.cnblogs.com/amiezhang/p/11061605.html
Copyright © 2011-2022 走看看