写一个整数四则运算的解析器——词法分析部分
分析 一个 部分 整数 解析器 词法 四则运算
2023-09-14 09:00:17 时间
写一个简单的词法、语法分析器,来最终分析出整数四则运算表达式的结果。
为了简化词语法分析我们只允许出现0~9,+,-,*,/,空格,\r, \n这几个字符
词法分析:
方法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 === '\r' || letter === '\n' }
定义生成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(/[\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: operatorList[idx], token: operatorList[idx]}) } }) // 结束 tokenList.push({type: 'EOF', token: 'EOF'}) console.log(tokenList)
得出结果:
到这里词法分析就已经完成了。
相关文章
- [代码质量] 推荐一个vs自带工具分析代码的复杂度
- 从一个OutOfMemoryError 学会了分析Java内存泄漏问题
- 【数据运营】在运营中,为什么文本分析远比数值型分析重要?一个实际案例,五点分析(下)
- MongoDB Secondary同步慢问题分析
- MySQL · BUG分析 · Rename table 死锁分析
- 一个典型的加了 SAP 注解的 OData 服务明细分析
- 一个SAP UI5 TreeTable控件的错误分析
- 分析一个BO上创建的extension field detail
- 用户和天猫精灵通过语音交互的一个典型流程分析
- 利用Chrome开发者工具memory comparison分析一个时间段内的JavaScript代码内存占用率
- OBS架构分析
- JVM源码分析之一个Java进程究竟能创建多少线程
- Android多线程分析之中的一个:使用Thread异步下载图像
- 【SQL开发实战技巧】系列(二十七):数仓报表场景☞通过对移动范围进行聚集来详解分析函数开窗原理以及如何一个SQL打印九九乘法表
- 性能测试分析工具: jps、jstack、jmap、jhat、jstat、hprof 使用详解
- python开发岗位需求分析,来看看它是什么一个情况吧
- Mybatis源码分析之(一)搭建一个mybatis框架(写一个mybatis的Demo)
- (18)Blender源码分析之闪屏窗口的菜单python代码属性识别
- (4)Blender源码分析之闪屏窗口显示流程
- 谷歌浏览器的源码分析(9)