编译原理之Lexical Analysis(js实现)

// 实验存档

效果图:

代码:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>Lexical_Analysis</title>
        <link href="https://fonts.googleapis.com/css?family=Noto+Serif+SC" rel="stylesheet">
        <style>
            main {
                /*对子元素开启弹性布局*/
                display: flex;
                /*弹性元素在必要的时候换行*/
                flex-wrap: wrap;
                /*将弹性元素居中*/
                justify-content: center;
            }

            textarea,
            button {
                font-family: ‘Noto Serif SC‘, STFangSong, serif;
                font-size: 17px;
            }
        </style>
    </head>

    <body>
        <main>
            <textarea name="input" rows="20" cols="40"></textarea>
            <textarea name="output" rows="20" cols="40"></textarea>
            <button name="compile">Lexical Analysis</button>
        </main>s

        <script>
            let inputBox = document.querySelector("textarea[name=input]");
            let outputBox = document.querySelector("textarea[name=output]");
            let btnCompile = document.querySelector("button[name=compile]");
            btnCompile.addEventListener("click", event => {
                let inputCode = inputBox.value;
                outputBox.value = JSON.stringify(Lexical_Analysis(inputCode));
            });
            /*
             * 规则:
            识别保留字:if、int、for、while、do、return、break、continue;
            单词种别码为1。
            其他的都识别为标识符;单词种别码为2。
            常数为无符号整形数;单词种别码为3。
            运算符包括:+、-、*、/、=、>、<、>=、<=、!= ;单词种别码为4。
            分隔符包括:,、;、{、}、(、); 单词种别码为5。
             */
            const reservedWords = [‘if‘, ‘int‘, ‘for‘, ‘while‘, ‘do‘, ‘return‘, ‘break‘, ‘continue‘];
            const operators = [‘+‘, ‘-‘, ‘*‘, ‘/‘, ‘=‘, ‘<‘, ‘>‘, ‘!‘, ‘>=‘, ‘<=‘, ‘!=‘];
            const separators = [‘,‘, ‘;‘, ‘{‘, ‘}‘, ‘(‘, ‘)‘];

            function Lexical_Analysis(str) {
                /**
                 * current用于标识当前字符位置,
                 * str[cur]即为当前字符
                 */
                let cur = 0;
                /**
                 * tokens存储词法分析的最终结果
                 */
                let tokens = [];

                while(cur < str.length) {

                    if(/\s/.test(str[cur])) { // 跳过空格
                        cur++;
                    } else if(/[a-z]/i.test(str[cur])) { // 读单词
                        debugger;
                        let word = "" + str[cur++];
                        // 测试下一位字符,如果不是字母直接进入下一次循环(此时cur已经右移)
                        // 如果是则继续读字母,并将cur向右移动
                        while(cur < str.length && /[a-z]/i.test(str[cur])) {
                            // cur < str.length防止越界
                            word += str[cur++];
                        }
                        if(reservedWords.includes(word)) {
                            tokens.push({
                                type: 1,
                                value: word,
                            }); // 存储保留字(关键字)
                        } else {
                            tokens.push({
                                type: 2,
                                value: word,
                            }); // 存储普通单词
                        }
                    } else if(separators.includes(str[cur])) {
                        tokens.push({
                            type: 5,
                            value: str[cur++],
                        }); // 存储分隔符并将cur向右移动
                    } else if(operators.includes(str[cur])) {
                        let operator = "" + str[cur++];
                        if([‘>‘, ‘<‘, ‘!‘].includes(operator)) {
                            // 如果下一个字符是=就添加到operator并再次向右移动cur
                            if(str[cur] = ‘=‘) {
                                operator += str[cur++];
                            }
                        }
                        tokens.push({
                            type: 4,
                            value: operator,
                        }); // 存储运算符
                    } else if(/[0-9]/.test(str[cur])) {
                        let val = "" + str[cur++];
                        // cur < str.length防止越界
                        while(cur < str.length && /[0-9]/.test(str[cur])) {
                            val += str[cur++];
                        }
                        tokens.push({
                            type: 3,
                            value: val,
                        }); // 存储整数数字
                    } else {
                        return "包含非法字符:" + str[cur];
                    }

                }
                return tokens;
            }
        </script>
    </body>
</html>

原文地址:https://www.cnblogs.com/xkxf/p/10538719.html

时间: 2024-07-30 19:27:47

编译原理之Lexical Analysis(js实现)的相关文章

前端与编译原理 用js去运行js代码 js2run

# 前端与编译原理 用js去运行js代码 js2run 前端与编译原理似乎相隔甚远,各种热门的框架都学不过来,那能顾及到这么多底层呢,前端开发者们似乎对编译原理的影响仅仅是"抽象语法树",但这只是个开头而已,我们的目的是利用js直接运行js代码 项目地址 安装及使用方法 写这个干嘛,有现成的eval不香么 接触过微信小程序开发的同学或许知道,小程序为运行环境禁止new Function,eval,setTimeout等方法的使用,限制了我们执行字符串形式的动态代码,其他小程序平台对此也

编译原理实验代码(词法分析,语法分析,中间代码生成)

花了一天写出的程序没有顾及很多层面,但对于理解基本的实验道理和交上实验还是有点帮助的.代码实现了基于有限自动机的词法分析,采用递归下降分析法和EBNF文法实现语法分析并生成中间代码. lexAnalysis.h /* * lexAnalysis.h * * Created on: 2014-12-2 * Author: liuqiushan */ #ifndef LEXANALYSIS_H_ #define LEXANALYSIS_H_ #include <stdio.h> #include

wex5 教程 前端UI编译原理与记事本编辑

一 前言 wex5页面,与html页面有何差异?两者之前的关系是什么?是如何完成转译的? 能否像编辑html那样用记事本来修改w页面? wex5前端UI在云部署后能否在云端进行二次编辑,而不需要在wex5编辑器里修改后再次上传?? 带着这些问题,重新认识wex5的UI设计与编译原理,有助于我们分离前端开发. 二 页面结构分析: wex5页面由w.js,css三个页面构成,具体功能与对应关系如下: 三 编译后页面结构 1 在公有云部署时,要将wex5页面进行编译,得到部署需要的Native下的ww

大三开学第一天--编译原理和人工智能的初步入门

开学的第一天,学的都是入门,所以知识比较少,但是我还是会整理出来.因为是开学第一天,事情比较忙,知识没有得到很好的消化和了解,所以今天只作初步了解,过几天会找时间重新整理,具体化. 编译原理第一课: 编译器:编译器是一种语言处理器,可以将“一种语言(通常为高级语言)”翻译为“另一种语言(通常为低级语言)”.通俗的讲,就是我们目前所使用的高级语言,如C++,java,都是易于人们理解和编写的.但是对于机器来说,只能看懂机器语言(即汇编语言,属于低级语言).所以,人们用高级语言写出来的代码,首先要经

编译原理——引论

语言处理器 编译器(compiler):阅读以某一种语言(源语言)编写的程序,并把该程序翻译成为一个等价的.用另一种语言(目标语言)编写的程序.编译器的重要任务之一是报告它在翻译过程中发现的源程序中的错误. 解释器(interpreter):另一种常见的语言处理器.它并不通过翻译的方式生成目标程序.从用户的角度看,解释器直接利用用户提供的输入执行源程序中指定的操作. 在把用户输入映射成输出的过程中,由一个编译器产生的机器语言目标程序通常比一个解释器快很多.然而,解释器的错误诊断效果通常比编译器好

MYSQL 源代码 编译原理 AST和解析树 代码语法解析

MYSQL 源代码 编译原理 AST和解析树 代码语法解析 http://blog.csdn.net/wfp458113181wfp/article/details/17082355 使用AST树 分类:             antlr              2013-12-02 22:39     255人阅读     评论(0)     收藏     举报 目录(?)[+] 第五章使用AST树中间结果来计算表达式值 创建ASTS 第五章.使用AST树中间结果来计算表达式值 现在我们已

编译原理-如何使用flex和yacc工具构造一个高级计算器

Flex工具的使用方法 Lex 是一种生成扫描器的工具. Lex是Unix环境下非常著名的工具,主要功能是生成一个扫描器(Scanner)的C源码. 扫描器是一种识别文本中的词汇模式的程序. 这些词汇模式(或者常规表达式)在一种特殊的句子结构中定义.一种匹配的常规表达式可能会包含相关的动作.这一动作可能还包括返回一个标记. 当 Lex 接收到文件或文本形式的输入时,它试图将文本与常规表达式进行匹配. 它一次读入一个输入字符,直到找到一个匹配的模式. 如果能够找到一个匹配的模式,Lex 就执行相关

编译原理大作业(用java编写小型GCC 编译器)

以前只用编译器编译程序,现在学完编译原理这门课以后,通过编译大作业,我对编译器的工作原理有了比较清晰的认识 编译器的工作原理 编译器 (Compiler) 是一种将由一种语言编写的程序转换为另一种编程语言的可执行程序. 现代软件对于编译器的需求远甚从前, 究其原因很简单: 作为中间层, 编译器是构建更高层抽象的基础设施. 编译器意欲将人类可阅读的高阶代码, 翻译为机器能运行的低阶代码. 现代编译器的主要工作流程为: 源代码(source code)→ 预处理器(preprocessor)→ 编译

哈工大软件学院编译原理实验1——词法分析

这次实验被"过来人"们定位非常easy,实验内容例如以下: ----------------------------------------------------------------------------------- 对例如以下工作进行展开描写叙述 (1) 给出语言的词法规则描写叙述 · 标识符.keyword.整常数.字符常数.浮点常数 · 单界符:+,-,×,;,- · 双界符:/*,:=,>=,<=,!=,- · 凝视 (2) 针对这样的单词的状态转换图和程