当前位置: 首页 > news >正文

js实现简单计算器词法解析语法解析解释器,带可视化界面

代码

Lexer是词法解析器

Parser是语法解析器

Interpreter 是ast解释器

可视化页面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Lexer, Parser, and Interpreter Visualization</title><style>body {font-family: Arial, sans-serif;}#input-container {margin-bottom: 20px;}#lexer-output, #parser-output, #interpreter-output {border: 1px solid #ccc;padding: 10px;margin-bottom: 20px;}#lexer-output h2, #parser-output h2, #interpreter-output h2 {margin-top: 0;}#lexer-tokens, #parser-ast {list-style-type: none;padding: 0;}#lexer-tokens li {margin-bottom: 5px;}#parser-ast ul {padding-left: 20px;}</style>
</head>
<body><h1>Lexer, Parser, and Interpreter Visualization</h1><div id="input-container"><label for="input">Input Expression:</label><input type="text" id="input" placeholder="Enter expression..."><button onclick="processInput()">Process</button></div><div id="lexer-output"><h2>Lexer Output:</h2><ul id="lexer-tokens"></ul></div><div id="parser-output"><h2>Parser Output (Abstract Syntax Tree):</h2><pre id="parser-ast"></pre></div><div id="interpreter-output"><h2>Interpreter Output (Result):</h2><div id="interpreter-result"></div></div><script>function processInput() {const input = document.getElementById('input').value;// Lexerconst lexer = new Lexer(input);const lexerTokens = [];let token;while ((token = lexer.nextToken()) !== null) {lexerTokens.push(token);}displayLexerOutput(lexerTokens);// Parserconst parser = new Parser(new Lexer(input));const ast = parser.parse();displayParserOutput(ast);// Interpreterconst interpreter = new Interpreter();const result = interpreter.interpret(ast);displayInterpreterOutput(result);}function displayLexerOutput(tokens) {const lexerTokensList = document.getElementById('lexer-tokens');lexerTokensList.innerHTML = '';tokens.forEach(token => {const li = document.createElement('li');li.textContent = `${token.type}: ${token.value}`;lexerTokensList.appendChild(li);});}function displayParserOutput(ast) {const parserAST = document.getElementById('parser-ast');parserAST.textContent = JSON.stringify(ast, null, 2);}function displayInterpreterOutput(result) {const interpreterResult = document.getElementById('interpreter-result');interpreterResult.textContent = `Result: ${result}`;}class Lexer {constructor(input) {this.input = input;this.position = 0;}nextToken() {while (this.position < this.input.length && /\s/.test(this.input[this.position])) {this.position++;}if (this.position >= this.input.length) {return null;}let currentChar = this.input[this.position];if (/\d/.test(currentChar)) {let number = '';while (/\d/.test(currentChar) && this.position < this.input.length) {number += currentChar;this.position++;currentChar = this.input[this.position];}return { type: 'NUMBER', value: number };}if (currentChar === '+') {this.position++;return { type: 'PLUS', value: '+' };}if (currentChar === '-') {this.position++;return { type: 'MINUS', value: '-' };}if (currentChar === '*') {this.position++;return { type: 'STAR', value: '*' };}if (currentChar === '/') {this.position++;return { type: 'SLASH', value: '/' };}if (currentChar === '(') {this.position++;return { type: 'LPAREN', value: '(' };}if (currentChar === ')') {this.position++;return { type: 'RPAREN', value: ')' };}throw new Error(`Unknown character: ${currentChar}`);}}class Parser {constructor(lexer) {this.lexer = lexer;this.currentToken = this.lexer.nextToken();}eat(tokenType) {if (this.currentToken && this.currentToken.type === tokenType) {this.currentToken = this.lexer.nextToken();} else {throw new Error(`Expected token type ${tokenType} but got ${this.currentToken ? this.currentToken.type : 'null'}`);}}factor() {let token = this.currentToken;if (token.type === 'NUMBER') {this.eat('NUMBER');return { type: 'Literal', value: parseInt(token.value, 10) };} else if (token.type === 'LPAREN') {this.eat('LPAREN');let node = this.expr();this.eat('RPAREN');return node;} else {throw new Error(`Unexpected token: ${token.type}`);}}term() {let node = this.factor();while (this.currentToken && (this.currentToken.type === 'STAR' || this.currentToken.type === 'SLASH')) {let token = this.currentToken;if (token.type === 'STAR') {this.eat('STAR');} else if (token.type === 'SLASH') {this.eat('SLASH');}node = { type: 'BinaryExpression', operator: token.value, left: node, right: this.factor() };}return node;}expr() {let node = this.term();while (this.currentToken && (this.currentToken.type === 'PLUS' || this.currentToken.type === 'MINUS')) {let token = this.currentToken;if (token.type === 'PLUS') {this.eat('PLUS');} else if (token.type === 'MINUS') {this.eat('MINUS');}node = { type: 'BinaryExpression', operator: token.value, left: node,right: this.term() };}return node;}parse() {return this.expr();}}class Interpreter {interpret(node) {if (node.type === 'Literal') {return node.value;} else if (node.type === 'BinaryExpression') {const leftValue = this.interpret(node.left);const rightValue = this.interpret(node.right);switch (node.operator) {case '+':return leftValue + rightValue;case '-':return leftValue - rightValue;case '*':return leftValue * rightValue;case '/':if (rightValue === 0) {throw new Error('Division by zero');}return leftValue / rightValue;default:throw new Error(`Unknown operator: ${node.operator}`);}} else {throw new Error(`Unknown node type: ${node.type}`);}}}</script>
</body>
</html>

相关文章:

  • 租用服务器提供服务
  • Docker 安装gitLab
  • web前端语言框架:探索现代前端开发的核心架构
  • Adobe Illustrator 基础学习
  • Java从放弃到继续放弃
  • Web前端商品详情:深入解析与技巧实践
  • 「前端+鸿蒙」鸿蒙应用开发-TS接口-特殊用途
  • LabVIEW进行负载测试
  • HALCON-从入门到入门-阈值分割定位算子综合运用
  • SD文生图超详参数使用技巧和方法-看这一篇就懂了!!!
  • 水质在线监测站:提高水质应急处理能力
  • AI办公自动化:用Kimi批量在Excel文件名中加入日期
  • 33 _ 跨站脚本攻击(XSS):为什么Cookie中有HttpOnly属性?
  • 【保姆级教程】教你手把手搭建一个OPCDA/UA服务器
  • 超全AI大模型微调产品经理面试题
  • AHK 中 = 和 == 等比较运算符的用法
  • CSS实用技巧
  • Javascript弹出层-初探
  • Linux下的乱码问题
  • Mocha测试初探
  • Odoo domain写法及运用
  • OSS Web直传 (文件图片)
  • python 学习笔记 - Queue Pipes,进程间通讯
  • React Native移动开发实战-3-实现页面间的数据传递
  • WebSocket使用
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 算法---两个栈实现一个队列
  • 小程序开发之路(一)
  • 学习Vue.js的五个小例子
  • 硬币翻转问题,区间操作
  • 用Visual Studio开发以太坊智能合约
  • ​​​​​​​STM32通过SPI硬件读写W25Q64
  • ​14:00面试,14:06就出来了,问的问题有点变态。。。
  • #include<初见C语言之指针(5)>
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (LeetCode 49)Anagrams
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (附源码)python旅游推荐系统 毕业设计 250623
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (十)Flink Table API 和 SQL 基本概念
  • (十六)视图变换 正交投影 透视投影
  • (十七)Flink 容错机制
  • (四)事件系统
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战
  • (限时免费)震惊!流落人间的haproxy宝典被找到了!一切玄妙尽在此处!
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • *2 echo、printf、mkdir命令的应用
  • .dat文件写入byte类型数组_用Python从Abaqus导出txt、dat数据
  • .describe() python_Python-Win32com-Excel
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .Net 6.0 Windows平台如何判断当前电脑是否联网