├── src ├── Test │ ├── test.js │ ├── TestGrammar.ts │ ├── test.ts │ ├── generatelV_T.ts │ └── TestLexer.ts ├── Parser │ ├── DataStruct │ │ ├── HashFile.ts │ │ ├── Stack.ts │ │ ├── Closure.ts │ │ ├── TConstant.ts │ │ ├── FormItem.ts │ │ ├── Production.ts │ │ ├── V_T_Wrap.ts │ │ ├── Form.ts │ │ └── ASTNode.ts │ ├── AnalyzeGrammar │ │ ├── Index.ts │ │ └── BuildActionAndGoTo.ts │ ├── ParseModule.ts │ └── BuildAST │ │ └── Index.ts ├── main.ts ├── Cli │ ├── config.ts │ └── QScli.ts ├── QSLib │ ├── Index.ts │ └── Core.ts ├── Lexer │ ├── ScannerUtils.ts │ ├── PrintToken.ts │ ├── DataStruct │ │ ├── Token.ts │ │ └── V_T.ts │ └── Lexer.ts ├── Project │ └── Index.ts ├── Interpreter │ ├── DataStruct │ │ ├── Module.ts │ │ ├── Interpreter.ts │ │ ├── Reference.ts │ │ ├── Fun.ts │ │ ├── Complexus.ts │ │ ├── SymbolTable.ts │ │ └── Variable.ts │ └── Index.ts ├── Utils │ └── utils.ts └── Log │ └── Index.ts ├── QS ├── out │ ├── hash.value │ ├── FormError.txt │ ├── T.txt │ └── V.txt └── src │ ├── script │ ├── test │ │ └── test2.qs │ └── main.qs │ └── grammar │ └── grammar.txt ├── picture ├── image-20200408102859776.png ├── image-20200408104428888.png └── image-20200412215415982.png ├── tsconfig.json ├── webpack.config.js ├── package.json ├── LICENSE ├── 编译器和解释器各有什么特点与区别.md └── README.md /src/Test/test.js: -------------------------------------------------------------------------------- 1 | console.log(typeof 0) -------------------------------------------------------------------------------- /QS/out/hash.value: -------------------------------------------------------------------------------- 1 | {"hashValue":1566383174,"hashDate":2302417988} -------------------------------------------------------------------------------- /picture/image-20200408102859776.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yaser-wyx/QinScript/HEAD/picture/image-20200408102859776.png -------------------------------------------------------------------------------- /picture/image-20200408104428888.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yaser-wyx/QinScript/HEAD/picture/image-20200408104428888.png -------------------------------------------------------------------------------- /picture/image-20200412215415982.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yaser-wyx/QinScript/HEAD/picture/image-20200412215415982.png -------------------------------------------------------------------------------- /src/Test/TestGrammar.ts: -------------------------------------------------------------------------------- 1 | import { parseSingleModule} from "../Parser/ParseModule"; 2 | import {GRAMMAR_FILE, PROJECT_DIR} from "../Cli/config"; 3 | import {buildLRAnalyzeForm} from "../Parser/AnalyzeGrammar"; 4 | 5 | // parseModule(TEST_FILE,GRAMMAR_FILE);//测试分析表生成 6 | buildLRAnalyzeForm(GRAMMAR_FILE); -------------------------------------------------------------------------------- /src/Parser/DataStruct/HashFile.ts: -------------------------------------------------------------------------------- 1 | export class HashFile{ 2 | //hash文件的数据结构 3 | hashValue:number;//grammar文件内容的hash值 4 | hashDate:number;//grammar文件的修改日期hash值 5 | constructor(hashValue: number, hashDate: number) { 6 | this.hashValue = hashValue; 7 | this.hashDate = hashDate; 8 | } 9 | } -------------------------------------------------------------------------------- /src/Test/test.ts: -------------------------------------------------------------------------------- 1 | class node { 2 | left: node | null = null; 3 | value: number; 4 | right: node | null = null; 5 | 6 | constructor(value: number) { 7 | this.value = value; 8 | } 9 | } 10 | let root = new node(0); 11 | const depth = 100; 12 | for (let i = 0; i < depth; i++) { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "lib": ["es2017"], 5 | "module": "commonjs", 6 | "strictNullChecks": true, 7 | "strict": true, 8 | "alwaysStrict": true, 9 | "noImplicitAny": false, 10 | "sourceMap": true, 11 | "noImplicitThis": false 12 | }, 13 | "include": [ 14 | "src/**/*.ts" 15 | ] 16 | } -------------------------------------------------------------------------------- /QS/src/script/test/test2.qs: -------------------------------------------------------------------------------- 1 | @module:Test; 2 | export:res; 3 | export:test; 4 | export:reverseStr; 5 | let res=test("这是Test模块的res"); 6 | 7 | fun test(str){ 8 | 9 | return str; 10 | } 11 | 12 | fun reverseStr(str){ 13 | let temp = ""; 14 | let index = len(str)-1; 15 | while(index>=0){ 16 | temp = temp + str[index--]; 17 | } 18 | return temp; 19 | } -------------------------------------------------------------------------------- /QS/out/FormError.txt: -------------------------------------------------------------------------------- 1 | 打印时间:Sun Apr 12 2020 21:23:26 GMT+0800 (China Standard Time) 2 | 3 | ====================LR(1)分析表构造错误==================== 4 | Action表发生移进规约冲突; 5 | 在状态:751 展望字符:ELSE 上已有项目 6 | 旧项目内容: 7 | expected: ELSE reduceBy: Stmt-> IfStmt 8 | 新项目内容: 9 | expected: ELSE shiftTo: 574 10 | ==================================================== 11 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020. yaser. All rights reserved 3 | * Description: 主程序 4 | */ 5 | import {cli} from "./Cli/QScli"; 6 | import {buildLRAnalyzeForm} from "./Parser/AnalyzeGrammar"; 7 | import {GRAMMAR_FILE} from "./Cli/config"; 8 | import {printInfo} from "./Log"; 9 | export let grammarForms; 10 | buildLRAnalyzeForm(GRAMMAR_FILE).then(res => { 11 | grammarForms = res; 12 | printInfo("---------------------------------------------",false) 13 | cli(); 14 | }) 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Cli/config.ts: -------------------------------------------------------------------------------- 1 | export const GRAMMAR_FILE = "QS/src/grammar/grammar.txt"; 2 | export const PROJECT_DIR = "QS/src/script";//项目根目录 3 | export const FORM_ERROR_FILE = "QS/out/FormError.txt"; 4 | export const HASH_FILE = "QS/out/hash.value"; 5 | export const CACHE_FILE = "QS/out/FORM.CACHE"; 6 | export const TOKEN_OUT_DIR = "QS/out/"; 7 | export const V_FILE = "QS/out/V.txt"; 8 | export const T_FILE = "QS/out/T.txt"; 9 | export const ACTION_TABLE_FILE = "QS/out/Action.table.txt"; 10 | export const GOTO_TABLE_FILE = "QS/out/Goto.table.txt"; 11 | export const SUFFIX = ".qs"; 12 | -------------------------------------------------------------------------------- /src/QSLib/Index.ts: -------------------------------------------------------------------------------- 1 | import {VARIABLE_TYPE, VariableMeta} from "../Interpreter/DataStruct/Variable"; 2 | import {array, len, print, randomInteger} from "./Core"; 3 | 4 | export const QSFunMap = { 5 | print: print, 6 | len: len, 7 | randomInteger:randomInteger, 8 | array:array 9 | }; 10 | 11 | export function runLib(callee: Function, args: Array) { 12 | let transferredArgs: Array = []; 13 | args.forEach(arg => { 14 | //转换参数 15 | transferredArgs.push(arg.value) 16 | }); 17 | return callee(transferredArgs); 18 | } -------------------------------------------------------------------------------- /QS/out/T.txt: -------------------------------------------------------------------------------- 1 | AT, 2 | MODULE, 3 | COLON, 4 | ID, 5 | SEMI, 6 | IMPORT, 7 | EXPORT, 8 | E, 9 | STATIC, 10 | FUN, 11 | LEFT_PAREN, 12 | RIGHT_PAREN, 13 | COMMA, 14 | LEFT_BRACE, 15 | RIGHT_BRACE, 16 | LET, 17 | ASSIGN, 18 | IF, 19 | ELSE, 20 | WHILE, 21 | RETURN, 22 | LEFT_BRACKET, 23 | RIGHT_BRACKET, 24 | MODULE_SCOPE, 25 | DOT, 26 | LOGIC_OR, 27 | LOGIC_AND, 28 | BIT_AND, 29 | BIT_OR, 30 | LESS, 31 | LESS_EQUAL, 32 | EQUAL, 33 | NOT_EQUAL, 34 | GREATER, 35 | GREATER_EQUAL, 36 | ADD, 37 | SUB, 38 | MOD, 39 | DIV, 40 | MUL, 41 | BIT_NOT, 42 | NOT, 43 | ADD_ONE, 44 | SUB_ONE, 45 | NUMBER, 46 | STRING, 47 | TRUE, 48 | FALSE, 49 | NULL, 50 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | target: 'node', 3 | entry: { 4 | 'QS': './src/main.ts', 5 | 'testLexer':'./src/Test/TestLexer.ts', 6 | 'testGrammar':'./src/Test/TestGrammar.ts', 7 | 'test':'./src/Test/Test.ts' 8 | }, 9 | output: { 10 | filename: '[name].js', 11 | path: __dirname + '/out/', 12 | library: '[name]', 13 | libraryTarget: 'umd' 14 | }, 15 | devtool: 'source-map', 16 | resolve: { 17 | extensions: ['.ts', '.js', '.json'] 18 | }, 19 | module: { 20 | rules: [ 21 | { test: /\.tsx?$/, loader: 'awesome-typescript-loader' }, 22 | { enforce: 'pre', test: /\.js$/, loader: 'source-map-loader' } 23 | ] 24 | } 25 | }; -------------------------------------------------------------------------------- /QS/out/V.txt: -------------------------------------------------------------------------------- 1 | Start, 2 | Module, 3 | ModuleDefine, 4 | ModuleStmts, 5 | ModuleSelfDefine, 6 | ModuleImportDefineList, 7 | ModuleExportList, 8 | ModuleImportDefine, 9 | ModuleExport, 10 | VarDefStmt, 11 | FunDefStmt, 12 | FunDef, 13 | ParamList, 14 | BlockStmt, 15 | Stmts, 16 | Stmt, 17 | VariableDef, 18 | InnerFunDefStmt, 19 | IfStmt, 20 | WhileStmt, 21 | ReturnStmt, 22 | AssignStmt, 23 | Exp, 24 | VarDecStmt, 25 | ArrayMemberExp, 26 | ArrayExp, 27 | |ArrayMemberExp, 28 | CalExp, 29 | ArrayItems, 30 | ArrayItem, 31 | Literal, 32 | CallExp, 33 | ArraySub, 34 | ArgumentList, 35 | LogicOperator, 36 | LogicExp, 37 | BitOperator, 38 | BitExp, 39 | RelationalOperator, 40 | RelationExp, 41 | AdditiveOperator, 42 | AdditiveExp, 43 | FactorOperator, 44 | FactorExp, 45 | UnaryBeforeOperator, 46 | UnaryExp, 47 | UnaryAfterOperator, 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qin_script", 3 | "version": "1.0.0", 4 | "author": "yaser", 5 | "license": "copyright", 6 | "scripts": { 7 | "build": "./node_modules/.bin/webpack", 8 | "dev": "npm run build && node ./out/QS.js", 9 | "testLexer": "npm run build && node ./out/testLexer.js", 10 | "testGrammar": "npm run build && node ./out/testGrammar.js", 11 | "testGeneral": "npm run build && node ./out/test.js" 12 | }, 13 | "dependencies": { 14 | "@types/lodash": "^4.14.149", 15 | "@types/node": "^13.7.1", 16 | "awesome-typescript-loader": "^3.4.1", 17 | "colors": "^1.4.0", 18 | "fs": "^0.0.1-security", 19 | "source-map-loader": "^0.2.3", 20 | "tslint": "^5.9.1", 21 | "typescript": "^2.7.2", 22 | "uglifyjs-webpack-plugin": "^1.2.2", 23 | "webpack": "^3.11.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Test/generatelV_T.ts: -------------------------------------------------------------------------------- 1 | import {readFromFile, writeToFile} from "../Utils/utils"; 2 | import {GRAMMAR_FILE, T_FILE, V_FILE} from "../Cli/config"; 3 | 4 | let v = new Set(); 5 | let t = new Set(); 6 | 7 | async function read() { 8 | let grammar = await readFromFile(GRAMMAR_FILE); 9 | let str = grammar.split(/\s/); 10 | 11 | str.forEach(item => { 12 | if (!(item === "|" || item === "->" || item.length === 0)) { 13 | let testLow = /[a-z]/g; 14 | if (testLow.test(item)) { 15 | v.add(item); 16 | } else { 17 | t.add(item); 18 | } 19 | } 20 | }); 21 | let vData = ""; 22 | let tData = ""; 23 | v.forEach(item => { 24 | vData += item + ",\n"; 25 | }); 26 | t.forEach(item => { 27 | tData += item + ",\n"; 28 | }); 29 | await writeToFile(vData, V_FILE, false); 30 | await writeToFile(tData, T_FILE, false); 31 | } 32 | 33 | read(); -------------------------------------------------------------------------------- /src/Test/TestLexer.ts: -------------------------------------------------------------------------------- 1 | /* 2 | //测试词法分析器 3 | import {getNextToken, hasToken, initLexer} from "../Lexer/Lexer"; 4 | import {Token} from "../Lexer/DataStruct/Token"; 5 | import {T} from "../Lexer/DataStruct/V_T"; 6 | import {writeToFile} from "../Utils/utils"; 7 | import {PROJECT_DIR, TOKEN_OUT_FILE} from "../Cli/config"; 8 | 9 | 10 | function printToken(token: Token, index: number) { 11 | let data = ""; 12 | data += "====================第" + index + "个token====================\n"; 13 | data += "token.type: " + T[token.tokenType] + "\n"; 14 | data += "token.value: " + token.value + "\n"; 15 | data += "token.length: " + token.length + "\n"; 16 | data += "token.lineNo: " + token.lineNo + "\n"; 17 | data += "token.start: " + token.start + '\n'; 18 | return data; 19 | } 20 | 21 | async function lexer(filePath) { 22 | await initLexer(filePath); 23 | let index = 0; 24 | let str = ""; 25 | while (hasToken()) { 26 | index++; 27 | str += printToken(getNextToken(), index); 28 | } 29 | await writeToFile(str, TOKEN_OUT_FILE); 30 | } 31 | 32 | */ 33 | -------------------------------------------------------------------------------- /src/Lexer/ScannerUtils.ts: -------------------------------------------------------------------------------- 1 | import {keywordTable} from "./DataStruct/Token"; 2 | 3 | /**词法分析器工具包 4 | * 使用正则来判断读入的字符类别 5 | */ 6 | 7 | export function isNumberStart(char: string): boolean { 8 | let number = /[0-9]/; 9 | return number.test(char); 10 | } 11 | export function isNumber(char: string): boolean { 12 | let number = /[0-9.]/; 13 | return number.test(char); 14 | } 15 | 16 | export function isIDStart(char: string): boolean { 17 | //是否为标识符的开头 18 | let string = /[_A-Za-z]/; 19 | return string.test(char); 20 | } 21 | 22 | export function isID(char: string): boolean { 23 | //是否为标识符中间部分 24 | let string = /[_A-Za-z0-9]/; 25 | return string.test(char); 26 | } 27 | 28 | export function isSymbol(char: string): boolean { 29 | //是否是分隔符 30 | let separator = /[()\[\]{},:;.@=+\-*\/%!&|~<>]/; 31 | return separator.test(char); 32 | } 33 | 34 | export function isSpace(char: string): boolean { 35 | let space = /[ \f\r\t\v]/; 36 | return space.test(char); 37 | } 38 | 39 | export function isKeyword(char: string): boolean { 40 | let keyword = keywordTable[char]; 41 | return !!keyword; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /QS/src/script/main.qs: -------------------------------------------------------------------------------- 1 | @module:Main; 2 | import:Test; 3 | static fun Stack(len) { 4 | static let x = array(len,0); 5 | static let index = 0; 6 | @fun push(el){ 7 | @x[@index++] = el; 8 | } 9 | @fun pop(){ 10 | return @x[@index--]; 11 | } 12 | @fun getX(){ 13 | //只返回有值的部分 14 | let res = array(@index); 15 | let index = 0; 16 | while(index < @index){ 17 | res[index] = @x[index++]; 18 | } 19 | return res; 20 | } 21 | @fun getSize(){ 22 | return @index; 23 | } 24 | } 25 | 26 | fun main(){ 27 | //测试静态函数、多维数组 28 | let stack = Stack(100); 29 | let x= array(100,0); 30 | x[0]=[1,2,3]; 31 | x[1]=11; 32 | print(x[0][2],x[1]); 33 | stack.push("WYX"); 34 | stack.push("LOVE"); 35 | stack.push("QSN"); 36 | let len = 5; 37 | let index = 0; 38 | while(index++ = [];//存储所有的QS文件地址 7 | 8 | //读入项目 9 | export async function readProject(projectDir: string): Promise> { 10 | QSFiles = [];//清空。 11 | printInfo("开始解析项目路径。。。"); 12 | const projectPath = path.resolve(projectDir); 13 | await readFiles(projectPath); 14 | printInfo("项目路径解析完毕。。。"); 15 | return QSFiles; 16 | 17 | } 18 | 19 | //遍历当前根目录下的文件 20 | async function readFiles(curRoot: string) { 21 | let fileNameList = fs.readdirSync(curRoot); 22 | for (let i = 0; i < fileNameList.length; i++) { 23 | const fileName = fileNameList[i]; 24 | const filePath = path.join(curRoot, fileNameList[i]); 25 | const fileState = fs.statSync(filePath); 26 | if (fileState.isFile() && fileName.endsWith(SUFFIX)) { 27 | //如果是文件,同时是以指定后缀结尾,则加入到文件列表中 28 | QSFiles.push(filePath); 29 | } else if (fileState.isDirectory()) { 30 | //如果是目录,则递归遍历 31 | await readFiles(filePath); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/Lexer/PrintToken.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020. yaser. All rights reserved 3 | * Description: 4 | */ 5 | 6 | import {Token} from "./DataStruct/Token"; 7 | import {T} from "./DataStruct/V_T"; 8 | import * as path from "path"; 9 | import {TOKEN_OUT_DIR} from "../Cli/config"; 10 | import {printInfo} from "../Log"; 11 | import {writeToFile} from "../Utils/utils"; 12 | 13 | 14 | export function printTokens(tokens: ReadonlyArray, filePath: string) { 15 | let data = ""; 16 | for (let i = 0; i < tokens.length; i++) { 17 | const token = tokens[i]; 18 | data += `====================第${i + 1}个token====================\n`; 19 | data += "token.type: " + T[token.tokenType] + "\n"; 20 | data += "token.value: " + token.value + "\n"; 21 | data += "token.length: " + token.length + "\n"; 22 | data += "token.lineNo: " + token.lineNo + "\n"; 23 | data += "token.start: " + token.start + '\n'; 24 | } 25 | const endIndex = filePath.indexOf("."); 26 | const startIndex = filePath.lastIndexOf("\\") + 1; 27 | const outTokenFileName = filePath.substring(startIndex, endIndex) + '.out.tokens'; 28 | const tokenPath = path.join(TOKEN_OUT_DIR, outTokenFileName); 29 | writeToFile(data,tokenPath) 30 | } -------------------------------------------------------------------------------- /src/Parser/DataStruct/Stack.ts: -------------------------------------------------------------------------------- 1 | export class Stack { 2 | private elements: Array; 3 | 4 | constructor(initValue: T | null = null) { 5 | this.elements = new Array(); 6 | if (initValue!==null) { 7 | this.elements.push(initValue); 8 | } 9 | } 10 | 11 | push(element: T) { 12 | this.elements.push(element); 13 | } 14 | 15 | popX(x: number): T[] { 16 | let popList: T[] = []; 17 | if (x <= this.elements.length) { 18 | for (let i = 0; i < x; i++) { 19 | popList.push(this.elements.pop()); 20 | } 21 | } 22 | return popList.reverse(); 23 | } 24 | 25 | isEmpty(): boolean { 26 | return this.elements.length === 0; 27 | } 28 | 29 | pop(): T { 30 | return this.popX(1)[0]; 31 | } 32 | 33 | peek(): T | null { 34 | if (this.elements.length === 0) { 35 | return null; 36 | } else { 37 | return this.elements[this.elements.length - 1]; 38 | } 39 | } 40 | 41 | peekX(step: number): T | null { 42 | if (this.elements.length === 0) { 43 | return null; 44 | } else { 45 | return this.elements[this.elements.length - step]; 46 | } 47 | } 48 | 49 | get size(): number { 50 | return this.elements.length; 51 | } 52 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2020, Yaser 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /src/Parser/DataStruct/Closure.ts: -------------------------------------------------------------------------------- 1 | import {Production} from "./Production"; 2 | import {hashCode} from "../../Utils/utils"; 3 | 4 | export class Closure { 5 | name: string = ""; 6 | stateNum:number=0;//当前闭包的状态号 7 | innerSet: Array;//该闭包包含的产生式 8 | private _recognizeX: object = {};//一个映射表,表示识别了X后,到达的闭包 9 | flag: boolean = false;//标记,用于标记该closure是否被处理过 10 | value: string = ""; 11 | private hash: string = "";//closure的身份证,计算innerSet的值 12 | addClosureAfterRecognizeX(x: string, closure: Closure) { 13 | this._recognizeX[x] = closure; 14 | } 15 | 16 | getClosureAfterRecognizeX(x: string): Closure { 17 | return this._recognizeX[x]; 18 | } 19 | 20 | resetProductionFlag() { 21 | this.innerSet.forEach(Production => { 22 | Production.flag = false; 23 | }) 24 | } 25 | 26 | get recognizeX(): object { 27 | return this._recognizeX; 28 | } 29 | 30 | constructor(innerSet: Array) { 31 | this.innerSet = innerSet; 32 | } 33 | 34 | getHashCode(): string { 35 | if (this.hash.length === 0) { 36 | let str = ""; 37 | this.innerSet.forEach((production: Production) => { 38 | str += production.getValue() + "; "; 39 | }); 40 | this.value = str; 41 | this.hash = hashCode(str).toString(); 42 | } 43 | return this.hash 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /src/QSLib/Core.ts: -------------------------------------------------------------------------------- 1 | //QS核心库 2 | 3 | 4 | import {Complexus} from "../Interpreter/DataStruct/Complexus"; 5 | import {InnerFunDefStmt} from "../Parser/DataStruct/ASTNode"; 6 | 7 | export function print(args: Array) { 8 | let value = ""; 9 | const baseType = new Set(['string', 'number', 'boolean']); 10 | const replacer = (key, value) => { 11 | if (value instanceof InnerFunDefStmt) { 12 | value = "InnerFun"; 13 | } else if (value instanceof Complexus) { 14 | value = value.data; 15 | } 16 | 17 | return value; 18 | } 19 | args.forEach(datum => { 20 | if (baseType.has(typeof datum)) { 21 | value += datum + " "; 22 | } else { 23 | value += JSON.stringify(datum, replacer, 4) + " "; 24 | } 25 | }); 26 | console.log(value); 27 | } 28 | 29 | export function len(arg: Array) { 30 | return arg[0].length; 31 | } 32 | 33 | //两个参数,第一个为开始,第二个为结束 34 | export function randomInteger(args: Array) { 35 | let start = args[0]; 36 | let end = args[1]; 37 | return Math.round(Math.random() * (end - start) + start); 38 | 39 | } 40 | 41 | export function array(args: Array) { 42 | let len = args[0]; 43 | let initValue = args[1]; 44 | if (initValue === undefined) { 45 | initValue = 0; 46 | } 47 | let array = new Array(len); 48 | for (let i = 0; i < len; i++) { 49 | array[i] = initValue; 50 | } 51 | return array; 52 | } -------------------------------------------------------------------------------- /src/Parser/DataStruct/TConstant.ts: -------------------------------------------------------------------------------- 1 | //终结符常量表 2 | export const ID = "ID"; 3 | export const ELSE = "ELSE"; 4 | export const STATIC = "STATIC"; 5 | export const DOT = "DOT"; 6 | export const AT = "AT"; 7 | export const MODULE_SCOPE = "MODULE_SCOPE"; 8 | export const EXP = "Exp"; 9 | export const UNARY_BEFORE_OPERATOR = "UnaryBeforeOperator"; 10 | export const UNARY_AFTER_OPERATOR = "UnaryAfterOperator"; 11 | export const ARRAY_SUB = "ArraySub"; 12 | export const VARIABLE_EXP = "VariableExp"; 13 | export const COMMA = "COMMA"; 14 | export const NUMBER = "NUMBER"; 15 | export const STRING = "STRING"; 16 | export const TRUE = "TRUE"; 17 | export const FALSE = "FALSE"; 18 | export const NULL = "NULL"; 19 | export const BIT_NOT = "BIT_NOT"; 20 | export const NOT = "NOT"; 21 | export const MOD = "MOD"; 22 | export const DIV = "DIV"; 23 | export const MUL = "MUL"; 24 | export const ADD = "ADD"; 25 | export const SUB = "SUB"; 26 | export const LESS = "LESS"; 27 | export const LESS_EQUAL = "LESS_EQUAL"; 28 | export const EQUAL = "EQUAL"; 29 | export const NOT_EQUAL = "NOT_EQUAL"; 30 | export const GREATER = "GREATER"; 31 | export const GREATER_EQUAL = "GREATER_EQUAL"; 32 | export const BIT_AND = "BIT_AND"; 33 | export const LOGIC_OR = "LOGIC_OR"; 34 | export const BIT_OR = "BIT_OR"; 35 | export const LOGIN_AND = "LOGIN_AND"; 36 | export const ADD_ONE = "ADD_ONE"; 37 | export const SUB_ONE = "SUB_ONE"; 38 | export const MAIN = "main"; 39 | //运算符常量列表 40 | export const OPERATOR_LIST = [ADD_ONE, SUB_ONE, BIT_NOT, NOT, DIV, MOD, MUL, ADD, SUB, LESS, LESS_EQUAL, EQUAL, NOT_EQUAL, GREATER, GREATER_EQUAL, BIT_AND, LOGIC_OR, BIT_OR, LOGIN_AND]; 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/Lexer/DataStruct/Token.ts: -------------------------------------------------------------------------------- 1 | import {T} from "./V_T"; 2 | 3 | export const EOF = '\0';//文件结束标记,供词法分析器使用 4 | 5 | export const keywordTable = {//关键字表 6 | let: T.LET, 7 | fun: T.FUN, 8 | import: T.IMPORT, 9 | export: T.EXPORT, 10 | module: T.MODULE, 11 | if: T.IF, 12 | else: T.ELSE, 13 | while: T.WHILE, 14 | return: T.RETURN, 15 | true: T.TRUE, 16 | false: T.FALSE, 17 | null: T.NULL, 18 | static:T.STATIC 19 | }; 20 | 21 | export class LexerToken { 22 | //用于词法分析处理过程中辅助用的Token 23 | length: number;//token长度 24 | value: any;//token值 25 | tokenType: T;//token类型 26 | //报错信息 27 | errorMsg?: string; 28 | start?: number; 29 | lineNo?: number; 30 | 31 | constructor(length: number, value: any, tokenType: T, errorMsg?: string) { 32 | this.length = length; 33 | this.value = value; 34 | this.tokenType = tokenType; 35 | this.errorMsg = errorMsg; 36 | } 37 | } 38 | 39 | export class Token { 40 | tokenType: T;//token的类型 41 | value: string;//token的值 42 | start: number;//token在第N行的起始位置 43 | length: number;//token的长度 44 | lineNo: number;//token在第几行 45 | constructor() { 46 | //初始化token 47 | this.tokenType = T.NULL; 48 | this.value = ""; 49 | this.start = 0; 50 | this.length = 0; 51 | this.lineNo = 0; 52 | } 53 | getTokenTypeValue(){ 54 | //获取type的字符串形式 55 | return T[this.tokenType]; 56 | } 57 | } 58 | 59 | export function createSampleToken(tokenType: T, value: string) { 60 | let token = new Token(); 61 | token.tokenType = tokenType; 62 | token.value = value; 63 | return token; 64 | } 65 | -------------------------------------------------------------------------------- /src/Lexer/DataStruct/V_T.ts: -------------------------------------------------------------------------------- 1 | //非终结符 2 | export enum V { 3 | Module, 4 | ModuleDefine, 5 | ModuleStmts, 6 | ModuleSelfDefine, 7 | ModuleImportDefineList, 8 | ModuleExportList, 9 | ModuleImportDefine, 10 | ModuleExport, 11 | VarDefStmt, 12 | FunDefStmt, 13 | FunDef, 14 | ParamList, 15 | BlockStmt, 16 | Stmts, 17 | Stmt, 18 | VariableDef, 19 | VariableExp, 20 | InnerFunDefStmt, 21 | IfStmt, 22 | WhileStmt, 23 | ReturnStmt, 24 | AssignStmt, 25 | Exp, 26 | ArrayExp, 27 | IDExp, 28 | CalExp, 29 | ArrayItems, 30 | Literal, 31 | CallExp, 32 | ArraySub, 33 | ArgumentList, 34 | LogicOperator, 35 | LogicExp, 36 | BitOperator, 37 | BitExp, 38 | RelationalOperator, 39 | RelationExp, 40 | AdditiveOperator, 41 | AdditiveExp, 42 | FactorOperator, 43 | FactorExp, 44 | UnaryBeforeOperator, 45 | UnaryExp, 46 | UnaryAfterOperator, 47 | } 48 | 49 | //终结符 50 | export enum T { 51 | AT, 52 | MODULE, 53 | COLON, 54 | ID, 55 | SEMI, 56 | IMPORT, 57 | EXPORT, 58 | STATIC, 59 | FUN, 60 | LEFT_PAREN, 61 | RIGHT_PAREN, 62 | COMMA, 63 | LEFT_BRACE, 64 | RIGHT_BRACE, 65 | LET, 66 | ASSIGN, 67 | IF, 68 | ELSE, 69 | WHILE, 70 | RETURN, 71 | LEFT_BRACKET, 72 | RIGHT_BRACKET, 73 | MODULE_SCOPE, 74 | DOT, 75 | LOGIC_OR, 76 | LOGIC_AND, 77 | BIT_AND, 78 | BIT_OR, 79 | LESS, 80 | LESS_EQUAL, 81 | EQUAL, 82 | NOT_EQUAL, 83 | GREATER, 84 | GREATER_EQUAL, 85 | ADD, 86 | SUB, 87 | MOD, 88 | DIV, 89 | MUL, 90 | BIT_NOT, 91 | NOT, 92 | ADD_ONE, 93 | SUB_ONE, 94 | NUMBER, 95 | STRING, 96 | TRUE, 97 | FALSE, 98 | NULL, 99 | 100 | ERROR,//错误token 101 | EOF//终结状态 102 | } 103 | 104 | export type V_T = T | V; -------------------------------------------------------------------------------- /src/Interpreter/DataStruct/Module.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020. yaser. All rights reserved 3 | * Description: 程序中每一个模块的信息 4 | */ 5 | 6 | import {ModuleFunDefStmt} from "../../Parser/DataStruct/ASTNode"; 7 | import {createFunByFunDefStmt, GeneralFun, StaticFun} from "./Fun"; 8 | 9 | export class QSModule { 10 | private _moduleName: string = "";//当前模块名字 11 | private _importModules: Set = new Set();//导入的模块名字 12 | private _exportSet: Set = new Set();//需要导出的函数名以及变量名 13 | private _moduleVar: Array = [];//该模块的模块变量名列表,主要用于模块加载的时候遍历并初始化 14 | private _moduleFun: object = {};//该模块函数的语法树 15 | private _hasLoad: boolean = false;//默认是不对模块进行初始化操作 16 | 17 | get hasLoad(): boolean { 18 | return this._hasLoad; 19 | } 20 | 21 | set hasLoad(value: boolean) { 22 | this._hasLoad = value; 23 | } 24 | 25 | pushModuleVar(varName: string) { 26 | this._moduleVar.push(varName); 27 | } 28 | 29 | pushModuleFunDef(funDefStmt: ModuleFunDefStmt) { 30 | this._moduleFun[funDefStmt.getFunName()] = funDefStmt; 31 | } 32 | 33 | get moduleVar(): Array { 34 | return this._moduleVar; 35 | } 36 | 37 | createModuleFunByFunName(funName): StaticFun | GeneralFun | null { 38 | let moduleFunDefStmt: ModuleFunDefStmt = this._moduleFun[funName]; 39 | if (moduleFunDefStmt) { 40 | return createFunByFunDefStmt(moduleFunDefStmt); 41 | } else { 42 | return null; 43 | } 44 | } 45 | 46 | get moduleName(): string { 47 | return this._moduleName; 48 | } 49 | 50 | set moduleName(value: string) { 51 | this._moduleName = value; 52 | } 53 | 54 | pushImportModule(importModule: string) { 55 | this._importModules.add(importModule); 56 | } 57 | 58 | pushExport(exportName: string) { 59 | this._exportSet.add(exportName); 60 | } 61 | 62 | moduleHasImport(moduleName: string): boolean { 63 | return this._importModules.has(moduleName); 64 | } 65 | 66 | hasExport(idName: string): boolean { 67 | return this._exportSet.has(idName); 68 | } 69 | } -------------------------------------------------------------------------------- /src/Utils/utils.ts: -------------------------------------------------------------------------------- 1 | //工具包 2 | import * as fs from "fs"; 3 | import {printFatalError} from "../Log"; 4 | 5 | export async function readFromFile(path: string): Promise { 6 | //读取文件流 7 | let codeSource; 8 | try { 9 | if (await fs.existsSync(path)) { 10 | codeSource = await fs.readFileSync(path, "utf8") 11 | } else { 12 | printFatalError(`文件:${path}不存在!`); 13 | } 14 | } catch (e) { 15 | printFatalError(e); 16 | } 17 | return codeSource; 18 | } 19 | 20 | export async function writeToFile(data: any, path: string, needDate: boolean = true) { 21 | if (needDate) { 22 | data = "打印时间:" + new Date() + "\n" + data; 23 | } 24 | fs.writeFileSync(path, data, 'utf8') 25 | } 26 | 27 | export function kill() { 28 | //直接杀死进程 29 | process.exit(); 30 | } 31 | 32 | export function hashCode(str: string): number { 33 | let h = 0, off = 0; 34 | let len = str.length; 35 | for (let i = 0; i < len; i++) { 36 | h = (31 * h + str.charCodeAt(off++)) % 4294967296; 37 | } 38 | return h % 4294967296; 39 | } 40 | 41 | let chars = { 42 | space: ' ', 43 | pre: '│ ', 44 | first: '├── ', 45 | last: '└── ' 46 | }; 47 | 48 | export function createUniqueId(): string { 49 | return Number(Math.random().toString().substr(2)).toString(36); 50 | } 51 | 52 | let toString = function (tree, pre) { 53 | let string = [], childrenPre = []; 54 | tree.forEach(function (node, index) { 55 | let last = index === tree.length - 1; 56 | //@ts-ignore 57 | string.push([].concat(pre, last ? chars.last : chars.first, node.name).join('')); 58 | if (node.children && node.children.length) { 59 | if (pre.length) { 60 | childrenPre = pre.concat(last ? chars.space : chars.pre); 61 | } else { 62 | //@ts-ignore 63 | childrenPre = [last ? chars.space : chars.pre]; 64 | } 65 | string = string.concat(toString(node.children, childrenPre)); 66 | } 67 | }); 68 | return string; 69 | }; 70 | 71 | export function tree(tree) { 72 | let string = [tree.name]; 73 | if (tree.children && tree.children.length) { 74 | string = string.concat(toString(tree.children, [])); 75 | } 76 | return string.join('\n'); 77 | } 78 | -------------------------------------------------------------------------------- /src/Interpreter/DataStruct/Interpreter.ts: -------------------------------------------------------------------------------- 1 | import {QSModule} from "./Module"; 2 | import {FUN_CLASSES, GeneralFun, InnerFun, StaticFun} from "./Fun"; 3 | import {MAIN} from "../../Parser/DataStruct/TConstant"; 4 | import {printInterpreterError} from "../../Log"; 5 | import {BlockStmt, ModuleFunDefStmt} from "../../Parser/DataStruct/ASTNode"; 6 | 7 | let interpreter: Interpreter|null; 8 | 9 | export class Interpreter { 10 | private _moduleMap: Map = new Map();//模块映射表 11 | protected _curModule: QSModule | null = null;//当前模块 12 | protected _enter: ModuleFunDefStmt | null = null;//入口方法 13 | private _curFun: FUN_CLASSES | null = null;//当前所处函数 14 | private _curBlock: BlockStmt | null = null;//当前所处scope的深度 15 | 16 | //添加模块 17 | putModule(qsModule: QSModule) { 18 | this._moduleMap.set(qsModule.moduleName, qsModule); 19 | } 20 | 21 | getModuleByName(moduleName: string): QSModule | null { 22 | let qsModule = this._moduleMap.get(moduleName); 23 | if (qsModule) { 24 | return qsModule 25 | } 26 | return null; 27 | } 28 | 29 | setEnter(enter: ModuleFunDefStmt) { 30 | if (this._enter && this._enter.getFunName() === MAIN) { 31 | printInterpreterError("main函数只能有一个!"); 32 | } 33 | this._enter = enter 34 | } 35 | 36 | get enter(): ModuleFunDefStmt | null { 37 | return this._enter; 38 | } 39 | 40 | setCurModule(moduleName: QSModule) { 41 | this._curModule = moduleName; 42 | } 43 | 44 | get curModule(): QSModule | null { 45 | return this._curModule; 46 | } 47 | 48 | get moduleMap(): Map { 49 | return this._moduleMap; 50 | } 51 | 52 | set moduleMap(value: Map) { 53 | this._moduleMap = value; 54 | } 55 | 56 | get curFun(): FUN_CLASSES | null { 57 | return this._curFun; 58 | } 59 | 60 | set curFun(value: FUN_CLASSES | null) { 61 | this._curFun = value; 62 | } 63 | 64 | get curBlock(): BlockStmt | null { 65 | return this._curBlock; 66 | } 67 | 68 | set curBlock(value: BlockStmt | null) { 69 | this._curBlock = value; 70 | } 71 | 72 | } 73 | 74 | 75 | export function getInterpreter(): Interpreter { 76 | if (!interpreter) { 77 | interpreter = new Interpreter(); 78 | } 79 | 80 | return interpreter; 81 | } 82 | 83 | export function cleanInterpreter() { 84 | interpreter = null; 85 | } -------------------------------------------------------------------------------- /QS/src/grammar/grammar.txt: -------------------------------------------------------------------------------- 1 | #语法文件,请勿删除!!! 2 | Start -> Module 3 | Module -> ModuleDefine ModuleStmts 4 | ModuleDefine -> ModuleSelfDefine | ModuleSelfDefine ModuleImportDefineList | ModuleSelfDefine ModuleExportList | ModuleSelfDefine ModuleImportDefineList ModuleExportList 5 | ModuleSelfDefine -> AT MODULE COLON ID SEMI 6 | ModuleImportDefineList -> ModuleImportDefineList ModuleImportDefine | ModuleImportDefine 7 | ModuleImportDefine -> IMPORT COLON ID SEMI 8 | ModuleExportList -> ModuleExportList ModuleExport | ModuleExport 9 | ModuleExport -> EXPORT COLON ID SEMI 10 | ModuleStmts -> ModuleStmts VariableDef | ModuleStmts FunDefStmt | FunDefStmt | VariableDef | E 11 | # 函数定义语句,包含静态函数与普通函数 12 | FunDefStmt -> FunDef | STATIC FunDef 13 | # 所有函数定义,不区分静态或普通 14 | FunDef -> FUN ID LEFT_PAREN ParamList RIGHT_PAREN BlockStmt 15 | ParamList -> ID | ParamList COMMA ID | E 16 | 17 | Stmts -> Stmts Stmt | E 18 | Stmt -> InnerFunDefStmt | IfStmt | BlockStmt | VariableDef | WhileStmt | ReturnStmt | AssignStmt | Exp SEMI 19 | BlockStmt -> LEFT_BRACE Stmts RIGHT_BRACE 20 | 21 | # 变量定义包括普通变量与静态变量定义 22 | VariableDef -> STATIC VarDefStmt | VarDefStmt 23 | # 所有变量的定义语句,对变量类型不加区分 24 | VarDefStmt -> LET ID ASSIGN Exp SEMI | LET ID SEMI 25 | 26 | # 用于处理所有的变量表达式 27 | VariableExp -> IDExp ArraySub | IDExp 28 | IDExp -> ID | ID DOT IDExp | AT IDExp | ID MODULE_SCOPE IDExp 29 | 30 | # 内部函数 31 | InnerFunDefStmt -> AT FunDef 32 | 33 | IfStmt -> IF LEFT_PAREN Exp RIGHT_PAREN Stmt | IfStmt ELSE Stmt 34 | WhileStmt -> WHILE LEFT_PAREN Exp RIGHT_PAREN Stmt 35 | ReturnStmt -> RETURN Exp SEMI | RETURN SEMI 36 | AssignStmt -> VariableExp ASSIGN Exp SEMI 37 | 38 | 39 | Exp -> ArrayExp | CalExp 40 | 41 | ArrayExp -> LEFT_BRACKET ArrayItems RIGHT_BRACKET | LEFT_BRACKET RIGHT_BRACKET 42 | ArrayItems -> Exp | Exp COMMA ArrayItems 43 | ArraySub -> LEFT_BRACKET Exp RIGHT_BRACKET | ArraySub LEFT_BRACKET Exp RIGHT_BRACKET 44 | 45 | CallExp -> IDExp LEFT_PAREN ArgumentList RIGHT_PAREN 46 | ArgumentList -> Exp | ArgumentList COMMA Exp | E 47 | 48 | # 可计算表达式,包括数值计算,布尔计算以及位运算 49 | CalExp -> CalExp LogicOperator LogicExp | LogicExp 50 | LogicOperator -> LOGIC_OR | LOGIC_AND 51 | 52 | LogicExp -> LogicExp BitOperator BitExp | BitExp 53 | BitOperator -> BIT_AND | BIT_OR 54 | 55 | BitExp -> BitExp RelationalOperator RelationExp | RelationExp 56 | RelationalOperator -> LESS | LESS_EQUAL | EQUAL | NOT_EQUAL | GREATER | GREATER_EQUAL 57 | 58 | RelationExp -> RelationExp AdditiveOperator AdditiveExp | AdditiveExp 59 | AdditiveOperator -> ADD | SUB 60 | 61 | AdditiveExp -> AdditiveExp FactorOperator FactorExp | FactorExp 62 | FactorOperator -> MOD | DIV | MUL 63 | 64 | FactorExp -> UnaryBeforeOperator UnaryExp | UnaryExp UnaryAfterOperator | UnaryExp 65 | UnaryBeforeOperator -> BIT_NOT | NOT | ADD_ONE | SUB_ONE 66 | UnaryAfterOperator -> ADD_ONE | SUB_ONE 67 | 68 | UnaryExp -> Literal | VariableExp | LEFT_PAREN Exp RIGHT_PAREN | CallExp 69 | Literal -> NUMBER | STRING | TRUE | FALSE | NULL -------------------------------------------------------------------------------- /src/Interpreter/DataStruct/Reference.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020. yaser. All rights reserved 3 | * Description: 变量引用 4 | */ 5 | 6 | import {printInterpreterError} from "../../Log"; 7 | import {Variable, VARIABLE_TYPE, VariableMeta} from "./Variable"; 8 | 9 | export class Reference { 10 | referencedVar: Variable;//被引用的变量 11 | referenceList: Array = [];//只有在被引用变量是数组或复合体的时候,该项才有用,但不代表一定存在,反之如果存在,则一定是数组或复合体 12 | referencedType: VARIABLE_TYPE;//被引用对象的数据类型 13 | 14 | constructor(referencedVar: Variable, referencedType: VARIABLE_TYPE) { 15 | this.referencedVar = referencedVar; 16 | this.referencedType = referencedType; 17 | } 18 | 19 | setReferenceValue(varTypePair: VariableMeta) { 20 | //对所引用的变量值进行设置 21 | if (this.referenceList.length>0) { 22 | //如果存在index 23 | if (this.referencedType === VARIABLE_TYPE.ARRAY) { 24 | //如果是array,此时referenceIndex是一个数组形式 25 | let index = 0; 26 | let nowArray = this.referencedVar.getValue(); 27 | for (; index < this.referenceList.length - 1; index++) {//注意-1,此处操作用于将对多维数组的操作转化为对一维数组的操作 28 | nowArray = nowArray[this.referenceList[index]];//使用循环来读取多维数组中的数据,不断替换指向的数组,从最外层逐层向内读取 29 | if (!nowArray) { 30 | printInterpreterError("数组越界!"); 31 | } 32 | } 33 | nowArray[this.referenceList[index]] = varTypePair.value;//对一维数组设置值 34 | } else { 35 | //复合体变量 36 | this.referencedVar.getValue().setData(this.referenceList, varTypePair); 37 | } 38 | } else { 39 | //表示对当前变量重新赋值 40 | this.referencedVar.setValue(varTypePair); 41 | } 42 | } 43 | 44 | getReferenceValue(): any { 45 | //获取被引用的变量值 46 | let nowValue = this.referencedVar.getValue(); 47 | if (this.referenceList.length > 0) { 48 | //如果存在index 49 | if (this.referencedType === VARIABLE_TYPE.ARRAY) { 50 | //如果是array,此时referenceIndex是一个数组形式 51 | for (let i = 0; i < this.referenceList.length; i++) { 52 | nowValue = nowValue[this.referenceList[i]];//使用循环来读取多维数组中的数据,不断替换指向的数组,从最外层逐层向内读取 53 | if (nowValue===undefined) { 54 | printInterpreterError("数组越界!"); 55 | } 56 | } 57 | } else if (this.referencedType === VARIABLE_TYPE.STRING && this.referenceList.length === 1) { 58 | //字符串允许有一个下标 59 | nowValue = nowValue[this.referenceList[0]] 60 | } else if (this.referencedType === VARIABLE_TYPE.COMPLEXUS) { 61 | nowValue = nowValue.getRawData(this.referenceList); 62 | } else { 63 | //不能有数组下标 64 | return null; 65 | } 66 | } 67 | return nowValue; 68 | } 69 | } -------------------------------------------------------------------------------- /编译器和解释器各有什么特点与区别.md: -------------------------------------------------------------------------------- 1 | ### 编译器和解释器各有什么特点与区别 2 | 3 | 这是我们编译原理老师前几天发在在线学习平台上(没办法,因为肺炎,都只能搞个在线学习了)的一个课前讨论问题,写着写着就发现好像写的有点多了,不好发布在平台上了,于是就干脆写成了文章的形式,发布在了知乎上面,也算是自己的之前学习编译原理后的复习与总结,如有遗漏或错误,欢迎大家进行指正。 4 | 5 | --- 6 | 7 | 如果直接说解释器与编译器的特点与区别,会比较抽象,不好理解,最好拿一些特定的编程语言来举例子。 8 | 9 | 首先我们来列举一下常见的编程语言:Java、C、C++、Python、JavaScript、PHP..... 10 | 11 | 然后我们把这些语言分个类, 12 | 13 | - 类型1:C、C++ 14 | 15 | - 类型2:JavaScript、Python、PHP 16 | 17 | - 类型3:Java 18 | 19 | 这个分类是按照使用编译器还是解释器来进行分的,或许你会比较疑惑的是,为啥会有三个类别呢,不应该是两个吗? 20 | 21 | 其实确实应该是两个,但问题是,Java既用了解释器也用编译器,所以只能单独立出来了。 22 | 23 | 对于类型1,我们一般称为编译型语言,也就是需要用到编译器进行编译。 24 | 25 | 对于类型2,我们一般称为解释型语言,或是脚本语言,也就是要用解释器进行解释。 26 | 27 | 在说具体的解释型语言与编译型语言之前,我想提一下,或许有的人会有这样的一种认知,能直接运行的就是编译型语言,不能直接运行的就是解释性语言,这种理解其实是有偏差的,**不管是编译型还是解释型语言,它们都是无法直接运行的**,在windows下可以直接运行的一般情况下只有以.exe结尾的可执行文件,而.exe文件里都是二进制数据,之所以是二进制数据的原因是,**最终执行程序的不是系统,而是CPU,而CPU它只认识二进制数**。 28 | 29 | 既然操作系统或者CPU都无法直接执行这些语言,那怎么办呢,这时就需要编译器或解释器了,它们起到了一个*翻译官*的作用,它们将自己认识的语言翻译成操作系统或者CPU可以执行的二进制数据,同时这二者的区别就体现在了这个翻译的过程里。 30 | 31 | 在我们的日常生活中也有许多做翻译工作的人,大多数可以分为两类,一类是笔译,一类是口译,笔译就是用文字将一份文档翻译成另一种语言编写的文档,口译就是以口语的方式,将译入语转换为译出语的方式。 32 | 33 | 而编译器与解释器就类似于笔译工作者与口译工作者的区别,**编译器就是笔译工作者,而解释器就是口译工作者。** 34 | 35 | - 编译器在编译的过程中,读入源程序文件,输出一份等价的二进制可执行文件,就和笔译工作者一样,他们都会输出一份翻译后的文件。 36 | 37 | - 解释器在解释的过程中,读入源程序文件,输出的是执行的结果,就和口译工作者一样,他们输出的是已经完成翻译的结果。 38 | 39 | **输出的不同是这两者最大的区别,一个会输出用于执行的文件,另一个只会输出运行的结果;** 40 | 41 | 同时,我们都知道,一般情况下,编译器输出的执行文件在执行的过程中,不管是运行速度还是效率都能甩解释器几条大街,那是不是就是说,编译型语言就比解释型语言要好呢?或者说我们有编译器就够了,还要啥解释器呀,速度又慢,效率又低,运行还要装个解释器,麻烦的要死。 42 | 43 | 其实并不是这样的,任何事物的存在性必有其合理性,事实上解释器也有许多编译器没有的优点。 44 | 45 | 首先,最广为人知的一点是,**解释型语言可以跨平台执行**,只要这个平台有对应的解释器就行,毕竟真正执行程序的是解释器而不是平台系统。 46 | 47 | 另外,**解释型语言在开发效率上比编译型语言强大许多**,同样的功能,用解释型语言写的代码要远远少于编译型语言的代码量。 48 | 49 | 还有一点就是,**其实解释型语言并不慢**,甚至某种程度上比编译型语言还要快上好几分,我估计不少人要犯嘀咕了,前面不是说编译型更快吗,怎么这里又说解释型更快了呢? 50 | 51 | 其实是这样的,我们在执行编译型语言的时候,大都**忽略了编译器在编译的时候所花的时间**,但其实这个时间应该是要算上的,如果不算上的话,对解释器就太不公平了,就和两个人比赛百米赛跑,但其中一个人在起跑的时候已经站在50米的位置了,这明显就是欺负人。 52 | 53 | 事实上编译器在编译的过程中所花的时间是极高的,甚至可以这么说,分别用解释型语言和编译型语言写同一个程序,然后同时开始运行(注:此处运行的条件是二者都是源代码的情况下,也就是说编译型语言还需要编译),解释器都运行结束,结果都出来了,而编译器还在编译呢,别说结果了,还没正式开始运行呢。 54 | 55 | 曾经在网上看到过有人吐槽C++编译太慢的问题,说早上来到公司,看到有一个Bug被上报了,然后开始愉快的Debug,改了十分钟就改好了,然后按下了编译键,接着开始等它编译完成,一直等到下午快下班的时候才显示编译完成,于是一天就改了一个bug。 56 | 57 | 或许有人不服,说自己c++编译很快的,几秒就完成了,那是因为你C++文件太少了,一两个确实快呀,可问题是你见过哪个公司项目中只有一两个C++文件的,大都是几百甚至上千个文件,所以这个时候,用c++进行调试工作是一件及其耗时的事情,而解释型语言就不会有这个问题,**换句话说解释型语言启动速度快,但启动后的运行效率不高,而编译型语言启动速度慢,但启动后运行效率高,这也是两者一个极大的区别。** 58 | 59 | 这里简单提一下上面的类型3,也就是Java这个语言,**它既可以说是编译型语言也可以说是解释型语言,因为它内部既有解释器也有编译器(还不止一个)的存在**。 60 | 61 | Java中编译器比较多,它包含*一个前端编译器,一个后端编译器(JIT)以及一个静态预编译器(AOT)*。 62 | 63 | - 前端编译器的功能是从源代码生成Java字节码,也就是中间代码; 64 | 65 | - 后端编译器,也叫作即时编译器(JIT)它是包含在了JVM中,用于在执行的过程中,将热点代码(也就是执行次数比较多的代码)转化为本地机器码,并做一些优化,以加速执行效率。 66 | - 静态预编译器(AOT)它是直接将java源代码编译成本地机器码,也就是传统意义上的编译器,但用的不多,因为这样会使java的一些特性丢失。 67 | 68 | Java中的解释器与JIT一起打包,作为JVM中的*执行引擎*,解释器主要将字节码进行解释执行,同时配合JIT进行代码的优化操作。 69 | 70 | 最后,这里总结一下编译器与解释器的特点和区别 71 | 72 | ### 特点: 73 | 74 | - 解释器: 75 | 76 | - 优点:跨平台、启动速度快、开发效率高 77 | - 缺点:执行速度慢,执行效率低 78 | 79 | - 编译器: 80 | 81 | - 优点:执行速度快、执行效率高 82 | - 缺点:平台相关性高,编译速度(启动速度)慢,开发效率低 83 | 84 | 可以看出,二者的特点起到了一个很好的互补关系,所以没有谁好谁坏的说法,同时Java很好的融合了这两者的优点。 85 | 86 | ### 区别: 87 | 88 | - 编译器输出一个翻译完成后的可执行文件,是一个二进制数据流;解释器输出解释后运行的结果; 89 | 90 | -------------------------------------------------------------------------------- /src/Parser/AnalyzeGrammar/Index.ts: -------------------------------------------------------------------------------- 1 | import {hashCode, readFromFile, writeToFile} from "../../Utils/utils"; 2 | import {CACHE_FILE, HASH_FILE} from "../../Cli/config"; 3 | import {ActionForm, GotoForm} from "../DataStruct/Form"; 4 | import {analyzeGrammar} from "./BuildActionAndGoTo"; 5 | import * as fs from "fs"; 6 | import {HashFile} from "../DataStruct/HashFile"; 7 | import {printBuildFormError, printInfo, printWarn} from "../../Log"; 8 | 9 | export async function buildLRAnalyzeForm(grammarFile: string): Promise<{ actionForm, gotoForm } | null> { 10 | printInfo("读取语法文件..."); 11 | let grammar = await readFromFile(grammarFile);//读取需要分析的文法 12 | printInfo("语法文件读取成功!"); 13 | //判断是否存在缓存 14 | let hashValue = hashCode(grammar);//获取当前语法文件的hash值 15 | if (await hasCache(hashValue)) { 16 | printInfo("语法缓存文件读取成功,开始从缓存中重构分析表数据..."); 17 | //如果存在缓存,则读取 18 | let cache = await readFromFile(CACHE_FILE); 19 | let cacheData = JSON.parse(cache); 20 | //从缓存中重建实例对象 21 | let actionForm = ActionForm.buildActionFromCache(cacheData.actionForm); 22 | let gotoForm = GotoForm.buildGotoFromCache(cacheData.gotoForm); 23 | if (actionForm && gotoForm) { 24 | printInfo("重构分析表数据成功!"); 25 | return { 26 | actionForm: actionForm, 27 | gotoForm: gotoForm 28 | } 29 | } else { 30 | printWarn("从缓存中重构分析表数据失败,开始分析语法文件重构分析表!"); 31 | } 32 | } else { 33 | printWarn("语法缓存文件已过期或查找失败!"); 34 | } 35 | await cleanCache();//缓存已失效,清除缓存文件 36 | //如果不存在缓存,或缓存过期,则重新构建分析表 37 | let form = analyzeGrammar(grammar); 38 | printBuildFormError();//打印解析表冲突信息 39 | if (form) { 40 | printInfo("语法解析成功!"); 41 | await writeCache(hashValue, form);//写入缓存 42 | } 43 | return form; 44 | } 45 | 46 | 47 | async function writeCache(hashValue: number, cache: any) { 48 | printInfo("写入语法缓存文件..."); 49 | //写入cache文件,写入grammar的hash值以及cache文件的修改日期hash值 50 | let cacheData = JSON.stringify(cache); 51 | //写入缓存 52 | await writeToFile(cacheData, CACHE_FILE, false); 53 | let state = await fs.statSync(CACHE_FILE); 54 | let hashDate = hashCode(state.mtime.toLocaleString()); 55 | let data = new HashFile(hashValue, hashDate); 56 | await writeToFile(JSON.stringify(data), HASH_FILE, false); 57 | } 58 | 59 | async function cleanCache() { 60 | printInfo("清除语法缓存文件.."); 61 | //清空cache文件 62 | if (await fs.existsSync(HASH_FILE)) { 63 | fs.unlinkSync(HASH_FILE); 64 | } 65 | if (await fs.existsSync(CACHE_FILE)) { 66 | fs.unlinkSync(CACHE_FILE); 67 | } 68 | } 69 | 70 | async function hasCache(nowHashValue: number): Promise { 71 | printInfo("检查语法文件的缓存数据..."); 72 | if (await fs.existsSync(HASH_FILE)) { 73 | //如果存在hash文件,则表示可能存在缓存,接着读取hash文件,查看数值是否正确 74 | let str = await readFromFile(HASH_FILE);//读取hash文件数据 75 | let hashFile: HashFile = JSON.parse(str);// 76 | if (hashFile.hashValue === nowHashValue) { 77 | //如果hash值正确 78 | if (await fs.existsSync(CACHE_FILE)) { 79 | printInfo("语法缓存文件存在,开始读取数据..."); 80 | //如果缓存文件存在 81 | let state = await fs.statSync(CACHE_FILE);//读取文件状态信息 82 | let hashDate = hashCode(state.mtime.toLocaleString()); 83 | return hashDate === hashFile.hashDate;//最后查看是否更改了,因为光hash正确也可能是因为产生了碰撞 84 | } 85 | } 86 | } 87 | return false; 88 | } 89 | -------------------------------------------------------------------------------- /src/Parser/DataStruct/FormItem.ts: -------------------------------------------------------------------------------- 1 | import {Production} from "./Production"; 2 | import {hashCode} from "../../Utils/utils"; 3 | 4 | export class GotoFormItem { 5 | //LR分析表中Goto子表的项目 6 | expected: string; 7 | stateIndex: number = 0;//状态索引 8 | shiftTo: number; 9 | errMsg: string = ""; 10 | private hashCode: number = 0; 11 | 12 | constructor(expected: string, shiftTo: number, stateIndex: number) { 13 | this.expected = expected; 14 | this.stateIndex = stateIndex; 15 | this.shiftTo = shiftTo; 16 | this.hashCode = hashCode(this.getInfo()); 17 | } 18 | 19 | getHash() { 20 | return this.hashCode; 21 | } 22 | 23 | isSame(item: GotoFormItem) { 24 | return item.getHash() === this.hashCode; 25 | } 26 | 27 | getInfo() { 28 | return " expected: " + this.expected + " value: " + this.shiftTo + "\n"; 29 | } 30 | } 31 | 32 | export enum ActionStatus { 33 | //操作 34 | ACC, 35 | SHIFT, 36 | REDUCE, 37 | ERROR, 38 | SHIFT_BY_E,//使用空字符转移 39 | } 40 | 41 | export class ActionFormItem { 42 | //LR分析表中Action子表的项目 43 | shiftTo?: number;//要转移到的状态 44 | private _action: ActionStatus = ActionStatus.ERROR; 45 | expected: string;//期望的字符 46 | reduceBy?: Production;//使用哪个产生式进行reduce 47 | errMsg: string = ""; 48 | stateIndex?: number = 0; 49 | hasConflict: boolean = false; 50 | conflictArray: Array = new Array(); 51 | private hashCode: number = 0; 52 | 53 | get action(): ActionStatus { 54 | return this._action; 55 | } 56 | 57 | isSame(item: ActionFormItem) { 58 | if (this.hasConflict) { 59 | for (let conflictItem of this.conflictArray) { 60 | if (conflictItem.getHash() === item.getHash()) { 61 | return true; 62 | } 63 | } 64 | } 65 | return item.getHash() === this.getHash(); 66 | } 67 | 68 | constructor(expected: string, action: ActionStatus, stateIndex?: number, shiftToOrReduceBy?: number | Production) { 69 | this.expected = expected; 70 | this.stateIndex = stateIndex; 71 | this.setOperationByAction(action, shiftToOrReduceBy); 72 | } 73 | 74 | 75 | setOperationByAction(action: ActionStatus, shiftToOrReduceBy?: number | Production) { 76 | this._action = action; 77 | if (shiftToOrReduceBy) { 78 | switch (action) { 79 | case ActionStatus.REDUCE: 80 | this.reduceBy = shiftToOrReduceBy; 81 | break; 82 | case ActionStatus.SHIFT : 83 | this.shiftTo = shiftToOrReduceBy; 84 | break; 85 | case ActionStatus.SHIFT_BY_E: 86 | this.shiftTo = shiftToOrReduceBy; 87 | break; 88 | case ActionStatus.ACC: 89 | this.reduceBy = shiftToOrReduceBy; 90 | break; 91 | } 92 | } 93 | } 94 | 95 | getHash() { 96 | return hashCode(this.getInfo()); 97 | } 98 | 99 | getInfo() { 100 | let info = ""; 101 | info += " expected: " + this.expected; 102 | if (this.action === ActionStatus.REDUCE) { 103 | info += " reduceBy: " + (this.reduceBy).getValue(false) + "\n" 104 | } else if (this.action === ActionStatus.ACC) { 105 | info += " ACC" 106 | } else { 107 | info += " shiftTo: " + this.shiftTo + "\n"; 108 | } 109 | return info; 110 | } 111 | } 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /src/Cli/QScli.ts: -------------------------------------------------------------------------------- 1 | import * as readline from "readline" 2 | import * as fs from "fs"; 3 | import {printErr, printInfo, printWarn} from "../Log"; 4 | import {parseSingleModule} from "../Parser/ParseModule"; 5 | import {PROJECT_DIR} from "./config"; 6 | import {readProject} from "../Project"; 7 | import {getInterpreter} from "../Interpreter/DataStruct/Interpreter"; 8 | import {getParsedModule} from "../Parser/BuildAST"; 9 | import {runInterpreter} from "../Interpreter"; 10 | import {grammarForms} from "../main"; 11 | 12 | export function cli() { 13 | let version = "QinScript Version 1.0" 14 | console.log(version); 15 | console.log("该项目仅供学习使用,请勿用于任何实际项目中,否则后果自负!"); 16 | console.log("-------------------------------------------------"); 17 | const rl = readline.createInterface({ 18 | input: process.stdin, 19 | output: process.stdout, 20 | prompt: 'QS Cli(可输入-help提示)>: ' 21 | }); 22 | rl.prompt(); 23 | rl.on('line', (commands) => { 24 | let command = commands.split(" "); 25 | switch (command[0]) { 26 | case "-help": 27 | printInfo("-version\t版本号\nrun (projectPath)\t执行指定路径的项目,路径可选,没有则自动执行默认参数\n-quit\t退出\n-help\t查看命令", false); 28 | rl.prompt(); 29 | break; 30 | case "-version": 31 | printInfo(version, false); 32 | rl.prompt(); 33 | break; 34 | case "run": 35 | if (command.length === 1) { 36 | readProject(PROJECT_DIR).then(async fileList => { 37 | await runProject(fileList); 38 | rl.prompt(); 39 | }) 40 | } else if (command.length === 2) { 41 | fs.stat(command[1], async (err, stat) => { 42 | if (err) { 43 | printErr("非法的文件路径!", false); 44 | rl.prompt(); 45 | } else { 46 | if (stat.isDirectory()) { 47 | readProject(command[1]).then(async fileList => { 48 | await runProject(fileList); 49 | rl.prompt(); 50 | }) 51 | } else { 52 | printWarn("非法的项目根目录路径!", false); 53 | rl.prompt(); 54 | } 55 | } 56 | }) 57 | } else { 58 | printErr(commands + " 非法的命令!", false); 59 | rl.prompt(); 60 | } 61 | break; 62 | case "-quit": 63 | rl.close(); 64 | break; 65 | default: 66 | printErr(commands + " 非法的命令!", false); 67 | rl.prompt(); 68 | } 69 | }).on('close', () => { 70 | printInfo('再见!'); 71 | process.exit(0); 72 | }); 73 | } 74 | 75 | 76 | async function runProject(filePathList: Array) { 77 | //读取语法文件,并解析出分析表 78 | if (grammarForms) { 79 | //如果读取列表成功 80 | //对每一个文件,也就是模块进行解析操作 81 | printInfo(`当前项目路径下,共识别出${filePathList.length}个模块文件,开始逐个解析。。。`); 82 | let interpreterInfo = getInterpreter();//获取解释器信息表 83 | let flag = true; 84 | for (let i = 0; i < filePathList.length; i++) { 85 | printInfo(`--------开始解析第${i + 1}个模块文件--------`); 86 | const filePath = filePathList[i]; 87 | printInfo(`模块路径:${filePath}`); 88 | if (await parseSingleModule(filePath, grammarForms)) {//解析模块 89 | printInfo(`--------第${i + 1}个模块文件语法分析成功!--------`); 90 | let qsModule = getParsedModule();//获取模块 91 | interpreterInfo.putModule(qsModule);//将解析后的模块加入到解释器信息表中 92 | } else { 93 | flag = false; 94 | printErr(`--------第${i + 1}个模块文件语法树构建失败--------`); 95 | break; 96 | } 97 | } 98 | if (flag) { 99 | printInfo("所有模块解析完毕!"); 100 | runInterpreter();//执行解释器 101 | } else { 102 | printErr("项目解析失败!"); 103 | } 104 | } else { 105 | printErr("语法文件解析失败!"); 106 | } 107 | printInfo("项目运行结束!") 108 | } 109 | 110 | -------------------------------------------------------------------------------- /src/Parser/DataStruct/Production.ts: -------------------------------------------------------------------------------- 1 | //用于构建分析表的数据结构 2 | import {hashCode} from "../../Utils/utils"; 3 | 4 | export const EOF = "EOF"; 5 | export const E = "E";//表示空字符 6 | 7 | export class Production { 8 | key: string;//对应产生式的左边 9 | private nowDotAfter: number = 0;//当前原点后面的第一个终结符或非终结符索引 10 | private valueWithDot: string = "";//产生式右部含有点的值 11 | private valueWithOutDot: string = "";//产生式右部不含有点与展望符的值 12 | 13 | private _search: string = EOF;//展望信息,默认为EOF 14 | private _nodeList: Array = new Array();//该产生式的node数组 15 | private hashWithDot: string = "";//有点的hash值 16 | private hashWithoutDot: string = "";//没有点的hash值 17 | flag: boolean = false;//产生式标志位,如果为true,表示已经处理过了 18 | 19 | get search(): string { 20 | return this._search; 21 | } 22 | copy(production:Production){ 23 | this.nowDotAfter = production.nowDotAfter; 24 | this.valueWithOutDot = production.valueWithOutDot; 25 | this._search = production._search; 26 | this._nodeList = production._nodeList; 27 | this.hashWithDot = production.hashWithDot; 28 | this.hashWithoutDot = production.hashWithoutDot; 29 | } 30 | getHashCode(needDot: boolean = true): string { 31 | if (needDot) { 32 | if (this.hashWithDot.length === 0) { 33 | this.hashWithDot = hashCode(this.getValue(true)).toString(); 34 | } 35 | return this.hashWithDot 36 | } else { 37 | if (this.hashWithoutDot.length === 0) { 38 | this.hashWithoutDot = hashCode(this.getValue(false)).toString(); 39 | } 40 | return this.hashWithoutDot 41 | } 42 | } 43 | 44 | setSearch(search: string) { 45 | this._search = search; 46 | this.valueWithDot = ""; 47 | this.getValue(); 48 | } 49 | 50 | getProductionLength(): number { 51 | return this._nodeList.length; 52 | } 53 | 54 | pushItem(item: string) { 55 | this._nodeList.push(item); 56 | } 57 | 58 | get nodeList(): Array { 59 | return this._nodeList; 60 | } 61 | 62 | advance(): boolean | string { 63 | if (this.nowDotAfter < this._nodeList.length) { 64 | let res = this._nodeList[this.nowDotAfter++]; 65 | this.valueWithDot = ""; 66 | this.getValue(); 67 | return res; 68 | } else { 69 | return false; 70 | } 71 | } 72 | 73 | getNowDotAfter(): string { 74 | if (this.nowDotAfter < this._nodeList.length) { 75 | return this._nodeList[this.nowDotAfter]; 76 | } else { 77 | return EOF; 78 | } 79 | } 80 | 81 | getNodeToCalFirst(): Array { 82 | //获取需要进行计算first集合的节点 83 | let nodes = new Array(); 84 | for (let index = this.nowDotAfter + 1; index < this.nodeList.length; index++) { 85 | nodes.push(this.nodeList[index]); 86 | } 87 | nodes.push(this._search); 88 | return nodes; 89 | } 90 | 91 | getValue(needDot: boolean = true): string { 92 | if (needDot) { 93 | if (this.valueWithDot.length == 0) { 94 | let value = "[" + this.key + "->"; 95 | //如果值不存在,则遍历链表,获取值 96 | this._nodeList.forEach((node, index) => { 97 | if (index === this.nowDotAfter) { 98 | value = value + "." + node; 99 | } else { 100 | value += " "+node; 101 | } 102 | }); 103 | if (this.nowDotAfter === this._nodeList.length) { 104 | value += "."; 105 | } 106 | value += ", " + this._search + "]"; 107 | this.valueWithDot = value; 108 | } 109 | return this.valueWithDot 110 | } else { 111 | if (this.valueWithOutDot.length == 0) { 112 | let value = this.key + "->"; 113 | //如果值不存在,则遍历链表,获取值 114 | this._nodeList.forEach((node, index) => { 115 | value += " "+node; 116 | }); 117 | this.valueWithOutDot = value; 118 | } 119 | return this.valueWithOutDot 120 | } 121 | } 122 | 123 | constructor(key: string) { 124 | this.key = key; 125 | } 126 | } -------------------------------------------------------------------------------- /src/Parser/DataStruct/V_T_Wrap.ts: -------------------------------------------------------------------------------- 1 | //是一个终结符与非终结符的包装类,用于原始Token的规约,以及转化为AST时使用 2 | import {V, V_T} from "../../Lexer/DataStruct/V_T"; 3 | import {Token} from "../../Lexer/DataStruct/Token"; 4 | import {Production} from "./Production"; 5 | import {isArray} from "util"; 6 | 7 | export class V_T_Wrap { 8 | private _isT: boolean = false;//是否是终结符,默认是非终结符 9 | private symbolType: V_T; 10 | lineNo: number=0;//行号 11 | //如果是终结符则有Token,否则没有Token 12 | token?: Token; 13 | children: object = {}; 14 | private _isNull: boolean = false; 15 | private _childNums: number = 0; 16 | private symbolTypeValue: string;//用于调试 17 | 18 | 19 | get isT(): boolean { 20 | return this._isT; 21 | } 22 | 23 | get isNull(): boolean { 24 | return this._isNull; 25 | } 26 | 27 | testChild(childName: string): boolean { 28 | //测试孩子是否存在 29 | return !!this.children[childName]; 30 | } 31 | 32 | getChildToken(childName: string): Token | Array | null { 33 | //返回匹配成功的Token或Token列表 34 | if (this.children[childName]) { 35 | //存在 36 | if (Array.isArray(this.children[childName])) { 37 | //如果是数组形式 38 | let tokenArray: Array = []; 39 | let childArray = this.children[childName]; 40 | for (let i = 0; i < childArray.length; i++) { 41 | if (childArray[i].token) { 42 | tokenArray.push(childArray[i].token) 43 | } 44 | } 45 | return tokenArray 46 | } else { 47 | //普通模式 48 | if (this.children[childName].token) { 49 | return this.children[childName].token 50 | } 51 | } 52 | } 53 | return null; 54 | } 55 | 56 | getChildTokenByList(childNameList: Array): Token | Array | null { 57 | //list中都是待识别的tokenName 58 | //返回匹配成功的Token或Token列表 59 | for (let i = 0; i < childNameList.length; i++) { 60 | let value = this.getChildToken(childNameList[i]); 61 | if (value) { 62 | return value; 63 | } 64 | } 65 | return null; 66 | } 67 | 68 | getSymbolValue(isString: boolean = true): string | number { 69 | if (isString) { 70 | //需要string类型的值 71 | if (this._isT && this.token) { 72 | //如果是终结符 73 | return this.token.getTokenTypeValue(); 74 | } else { 75 | //如果是非终结符 76 | return V[this.symbolType]; 77 | } 78 | } else { 79 | //需要number类型的值 80 | if (this._isT && this.token) { 81 | //如果是终结符 82 | return this.token.tokenType; 83 | } else { 84 | //如果是非终结符 85 | return this.symbolType; 86 | } 87 | } 88 | } 89 | 90 | constructor(symbolType: V_T, lineNo?:number,token?: Token) { 91 | this.symbolType = symbolType; 92 | if (lineNo != null) { 93 | this.lineNo = lineNo; 94 | } 95 | if (token) { 96 | //如果是终结符,还需要设置Token 97 | this.token = token; 98 | this._isT = true; 99 | } 100 | this.symbolTypeValue = this.getSymbolValue(); 101 | } 102 | 103 | pushChild(child: V_T_Wrap) { 104 | if (child.getSymbolValue() === "NULL") { 105 | this._isNull = true; 106 | } else { 107 | let childName = child.getSymbolValue(); 108 | if (this.children[childName]) { 109 | //如果已经存在同名的child了,则将该值扩展为数组类型 110 | if (Array.isArray(this.children[childName])) { 111 | //如果该节点已经是数组,则直接加入新的值 112 | this.children[childName].push(child); 113 | } else { 114 | //还不是数组对象,将之扩展为数组 115 | let childArray: Array = []; 116 | childArray.push(this.children[childName]); 117 | childArray.push(child); 118 | this.children[childName] = childArray; 119 | } 120 | } else { 121 | //没有同名对象,则使用普通形式 122 | this.children[childName] = child; 123 | this._childNums++; 124 | } 125 | } 126 | } 127 | 128 | get childNums(): number { 129 | return this._childNums; 130 | } 131 | } 132 | 133 | export function createVTByProduction(production: Production, vtList: Array) { 134 | //使用产生式来 创建VTWrap 135 | let vtWrap = new V_T_Wrap(V[production.key]); 136 | vtList.forEach(item => { 137 | vtWrap.pushChild(item); 138 | if (!vtWrap.lineNo&&item.lineNo>0){ 139 | vtWrap.lineNo = item.lineNo 140 | } 141 | }); 142 | return vtWrap; 143 | } 144 | -------------------------------------------------------------------------------- /src/Log/Index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020. yaser. All rights reserved 3 | * Description: 日志处理 4 | */ 5 | 6 | import {kill, writeToFile} from "../Utils/utils"; 7 | import {LexerToken, Token} from "../Lexer/DataStruct/Token"; 8 | import {FORM_ERROR_FILE} from "../Cli/config"; 9 | import {getCurParsingModuleInfo} from "../Parser/ParseModule"; 10 | import {getCurRunningModule} from "../Interpreter"; 11 | 12 | let colors = require('colors'); 13 | 14 | let errorNum = 0; 15 | 16 | export function hasError(): boolean { 17 | return errorNum > 0; 18 | } 19 | 20 | function getTime(): string { 21 | return new Date().toLocaleString() + " "; 22 | } 23 | 24 | export function Log(...text) { 25 | for (let i = 0; i < text.length; i++) { 26 | console.log(text[i]) 27 | } 28 | } 29 | 30 | export function printErr(errMsg,needTime=true) { 31 | //通用报错打印 32 | if (needTime){ 33 | errMsg = getTime() + errMsg; 34 | } 35 | console.log(errMsg.red) 36 | } 37 | 38 | export function printWarn(warnMsg,needTime=true) { 39 | //通用警告打印 40 | if (needTime){ 41 | warnMsg = getTime() + warnMsg; 42 | } 43 | console.log(warnMsg.yellow); 44 | } 45 | 46 | export function printInfo(info, needTime = true) { 47 | //通用日志信息打印 48 | if (needTime) 49 | info = getTime() + info; 50 | console.log(info.green); 51 | } 52 | 53 | export function printFatalError(errMsg) { 54 | printErr("\n====================发生致命错误====================\n" + errMsg); 55 | kill(); 56 | } 57 | 58 | export function printLexerError(lexerTokens: LexerToken[], file) { 59 | //词法分析错误 60 | let errorMsg = "\n====================发生词法分析错误====================\n"; 61 | const parsingModule = getCurParsingModuleInfo(); 62 | errorMsg += `错误模块:${parsingModule.moduleName}\n`; 63 | errorMsg += `错误模块路径:${parsingModule.path}\n`; 64 | for (let index = 0; index < lexerTokens.length; index++) { 65 | errorMsg += `第${index + 1}个错误:\n`; 66 | errorMsg += " 错误内容:" + lexerTokens[index].errorMsg + '\n'; 67 | errorMsg += " 错误发生的文件:" + file + '\n'; 68 | errorMsg += " 错误发生的行号:" + lexerTokens[index].lineNo + '\n'; 69 | errorMsg += " 错误发生的位置:" + lexerTokens[index].start + '\n'; 70 | errorMsg += " 错误的Token值:\"" + lexerTokens[index].value + '\"\n'; 71 | errorMsg += " 错误的Token长度:" + lexerTokens[index].length + '\n'; 72 | errorMsg += "====================================================\n"; 73 | } 74 | printErr(errorMsg); 75 | errorNum += lexerTokens.length; 76 | } 77 | 78 | let formError = ""; 79 | let formErrorNum = 0; 80 | 81 | export function addBuildFormError(error) { 82 | formError += error; 83 | formErrorNum++; 84 | } 85 | 86 | export function printBuildFormError() { 87 | if (formErrorNum > 0) { 88 | printWarn("分析表有" + formErrorNum + "个冲突,请查看日志!"); 89 | let errorMsg = "\n====================LR(1)分析表构造错误====================\n"; 90 | errorMsg += formError; 91 | errorMsg += "====================================================\n"; 92 | writeToFile(errorMsg, FORM_ERROR_FILE) 93 | } else { 94 | printInfo("分析表无冲突!"); 95 | writeToFile("无异常!", FORM_ERROR_FILE) 96 | } 97 | formErrorNum = 0; 98 | formError = ""; 99 | } 100 | 101 | export function printParseModuleError(Token: Token, formItemErrorMsg: string) { 102 | let errorMsg = "\n====================发生语法分析错误====================\n"; 103 | const parsingModule = getCurParsingModuleInfo(); 104 | errorMsg += `错误模块:${parsingModule.moduleName}\n`; 105 | errorMsg += `错误模块路径:${parsingModule.path}\n`; 106 | errorMsg += "分析表错误信息:\n"; 107 | errorMsg += " " + formItemErrorMsg + "\n"; 108 | errorMsg += "错误的Token信息:\n"; 109 | errorMsg += " 错误发生的行号:" + Token.lineNo + '\n'; 110 | errorMsg += " 错误发生的位置:" + Token.start + '\n'; 111 | errorMsg += " 错误的Token值:\"" + Token.value + '\"\n'; 112 | errorMsg += " 错误的Token长度:" + Token.length + '\n'; 113 | errorMsg += "====================================================\n"; 114 | printErr(errorMsg); 115 | } 116 | 117 | export function printBuildASTError(ASTError: string, lineNo?: number) { 118 | let errorMsg = "====================语法树构建错误====================\n"; 119 | const parsingModule = getCurParsingModuleInfo(); 120 | errorMsg += `出错模块:${parsingModule.moduleName}\n`; 121 | errorMsg += `错误模块路径:${parsingModule.path}\n`; 122 | if (lineNo) { 123 | errorMsg += `错误行号:${lineNo}\n` 124 | } 125 | errorMsg += "语法树构建错误信息:\n"; 126 | errorMsg += " " + ASTError + "\n"; 127 | errorMsg += "====================================================\n"; 128 | printFatalError(errorMsg); 129 | } 130 | 131 | export function printInterpreterError(interpreterError: string, lineNo?: number) { 132 | let errorMsg = "====================解释器运行期错误====================\n"; 133 | const runningModule = getCurRunningModule(); 134 | if (runningModule) { 135 | errorMsg += `出错模块:${runningModule}\n`; 136 | } 137 | if (lineNo) { 138 | errorMsg += `错误行号:${lineNo}\n` 139 | } 140 | errorMsg += "错误信息:\n"; 141 | errorMsg += " " + interpreterError + "\n"; 142 | errorMsg += "====================================================\n"; 143 | printFatalError(errorMsg); 144 | } -------------------------------------------------------------------------------- /src/Parser/ParseModule.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020. yaser. All rights reserved 3 | * Description: 模块解析 4 | */ 5 | 6 | import {getNextToken, getPreToken, initLexer, lookAheadToken} from "../Lexer/Lexer"; 7 | import {printErr, printFatalError, printInfo, printParseModuleError, printWarn} from "../Log"; 8 | import {ActionForm, GotoForm} from "./DataStruct/Form"; 9 | import {Stack} from "./DataStruct/Stack"; 10 | import {createVTByProduction, V_T_Wrap} from "./DataStruct/V_T_Wrap"; 11 | import {createSampleToken, Token} from "../Lexer/DataStruct/Token"; 12 | import {T} from "../Lexer/DataStruct/V_T"; 13 | import {EOF} from "./DataStruct/Production"; 14 | import {ActionFormItem, ActionStatus} from "./DataStruct/FormItem"; 15 | import {initBuildAST, pushBlock, pushFun, SCOPE_TYPE, transferVTToASTNode} from "./BuildAST"; 16 | 17 | let actionForm: ActionForm, gotoForm: GotoForm; 18 | let symbolStack: Stack = new Stack();//符号栈 19 | let statusStack: Stack = new Stack();//状态栈 20 | let curModulePath: string = "";//当前解析的模块 21 | 22 | export function getCurParsingModuleInfo(): { moduleName, path } { 23 | const moduleName = curModulePath.substr(curModulePath.lastIndexOf("\\") + 1); 24 | return {moduleName: moduleName, path: curModulePath}; 25 | } 26 | 27 | //解析单一模块 28 | //使用LR分析器,根据已经生成的LR分析表,构建抽象语法树 29 | export async function parseSingleModule(filePath: string, forms: object): Promise { 30 | printInfo("解析模块..."); 31 | curModulePath = filePath; 32 | let initSuccess = await initLexer(filePath);//初始化词法分析器 33 | if (initSuccess) {//是否初始化成功 34 | printInfo("词法分析成功,开始执行语法分析..."); 35 | if (forms) { 36 | // @ts-ignore 37 | return BuildAST(forms.actionForm, forms.gotoForm); 38 | } 39 | } 40 | printErr("词法分析失败!"); 41 | return false; 42 | } 43 | 44 | 45 | //LR1 语法分析控制器,用于控制语法树的生成,一个模块即为一棵语法树,返回是否构建成功 46 | export function BuildAST(action: ActionForm, goto: GotoForm): boolean { 47 | let wrapToken = (token: Token) => { 48 | //将Token包装为V_T_Wrap 49 | return new V_T_Wrap(token.tokenType, token.lineNo, token); 50 | }; 51 | printInfo("构建语法树..."); 52 | //开始分析,控制器入口 53 | initBuildAST();//初始化语法树构造器 54 | actionForm = action; 55 | gotoForm = goto; 56 | let EOFToken = createSampleToken(T.EOF, EOF);//构造EOF 57 | symbolStack.push(wrapToken(EOFToken)); 58 | statusStack.push(0); 59 | let flag = true;//AST是否构造完毕,用于控制循环 60 | let success = true;//AST是否生成成功。 61 | printInfo("开始构造语法树!"); 62 | while (flag && success) { 63 | let nextToken = lookAheadToken();//向前读取一个token 64 | // @ts-ignore 65 | //根据栈顶状态,以及预读取的token,来获取下一个转移的状态 66 | let actionItem: ActionFormItem = actionForm.getActionItem(statusStack.peek(), nextToken.getTokenTypeValue()); 67 | if (actionItem.hasConflict) { 68 | printWarn("发生冲突!" + actionItem); 69 | } 70 | switch (actionItem.action) { 71 | case ActionStatus.ACC: 72 | printInfo("语法树生成完毕!"); 73 | flag = false; 74 | break; 75 | case ActionStatus.ERROR: 76 | //生成失败 77 | success = false; 78 | printParseModuleError(nextToken, actionItem.errMsg); 79 | break; 80 | case ActionStatus.REDUCE: 81 | //规约:根据产生式的长度,将指定长度的符号个数与状态个数弹出栈 82 | let production = actionItem.reduceBy; 83 | if (production) { 84 | //防止为空 85 | let popLength = production.getProductionLength();//获取产生式长度 86 | statusStack.popX(popLength);//将状态弹出 87 | let V_TList: Array = symbolStack.popX(popLength); 88 | let vtWrap = createVTByProduction(production, V_TList); 89 | symbolStack.push(vtWrap); 90 | // @ts-ignore 91 | let gotoItem = gotoForm.getGotoItem(statusStack.peek(), vtWrap.getSymbolValue()); 92 | if (gotoItem.shiftTo !== -1) { 93 | statusStack.push(gotoItem.shiftTo); 94 | transferVTToASTNode(vtWrap);//构建状态树 95 | } else { 96 | success = false; 97 | printParseModuleError(nextToken, gotoItem.errMsg); 98 | } 99 | } else { 100 | success = false; 101 | printParseModuleError(nextToken, "运行时错误,规约失败,产生式缺失!"); 102 | } 103 | break; 104 | case ActionStatus.SHIFT: 105 | //移进处理 106 | symbolStack.push(wrapToken(getNextToken())); 107 | let nowToken = nextToken;//移进处理后,此时的nextToken指代的是当前已经移进的Token 108 | // @ts-ignore 109 | statusStack.push(actionItem.shiftTo); 110 | if (nowToken.tokenType === T.LEFT_BRACE) { 111 | //如果移进的是左大括号 112 | //则表示需要一个block 113 | pushBlock(); 114 | } else if (nowToken.tokenType === T.FUN) { 115 | //如果当前就是fun,那么下一个就是函数名 116 | const funNameToken = lookAheadToken();//向后读取一个token 117 | //根据前一个token的值来判断函数类型 118 | const preToken = getPreToken(); 119 | if (preToken) { 120 | let scopeType; 121 | switch (preToken.tokenType) { 122 | case T.STATIC: { 123 | scopeType = SCOPE_TYPE.STATIC_FUN; 124 | break; 125 | } 126 | case T.AT: { 127 | scopeType = SCOPE_TYPE.INNER_FUN; 128 | break; 129 | } 130 | default: { 131 | scopeType = SCOPE_TYPE.GENERATE_FUN; 132 | break; 133 | } 134 | } 135 | pushFun(funNameToken.value, scopeType); 136 | } 137 | } 138 | break; 139 | case ActionStatus.SHIFT_BY_E: 140 | symbolStack.push(wrapToken(createSampleToken(T.NULL, ""))); 141 | // @ts-ignore 142 | statusStack.push(actionItem.shiftTo); 143 | break; 144 | default: 145 | printFatalError("构建语法树时,发生未知错误!"); 146 | break; 147 | } 148 | } 149 | return success; 150 | } 151 | -------------------------------------------------------------------------------- /src/Interpreter/DataStruct/Fun.ts: -------------------------------------------------------------------------------- 1 | import {BlockStmt, FunDeclaration, InnerFunDefStmt, ModuleFunDefStmt} from "../../Parser/DataStruct/ASTNode"; 2 | import {IDWrap, Variable, VARIABLE_TYPE, VariableMeta} from "./Variable"; 3 | import {FunSymbolTable} from "./SymbolTable"; 4 | import {printInterpreterError, printWarn} from "../../Log"; 5 | import {Complexus} from "./Complexus"; 6 | 7 | export enum FUN_TYPE {//函数类型 8 | GENERAL,//普通函数 9 | STATIC,//静态函数 10 | INNER//内部函数 11 | } 12 | 13 | export type FUN_CLASSES = InnerFun | StaticFun | GeneralFun; 14 | 15 | abstract class Fun { 16 | protected readonly _funBlock?: BlockStmt;//悬挂的函数内部节点 17 | protected readonly _funName: string;//当前函数名 18 | protected readonly _moduleName: string;//所处模块名 19 | protected _paramList: Array = [];//形参名列表 20 | protected abstract readonly _funType: FUN_TYPE; 21 | protected _funSymbolTable: FunSymbolTable;//函数符号表,用于存放函数的局部变量,静态变量以及内部函数 22 | protected _returnValue: any = null; 23 | protected _rearOperatorList: Array = [];//后置运算数量 24 | 25 | constructor(moduleName: string, funName: string, funDefNode: FunDeclaration) { 26 | this._funName = funName; 27 | this._moduleName = moduleName; 28 | this._funSymbolTable = new FunSymbolTable(funName); 29 | if (funDefNode.body && funDefNode.params) { 30 | this._funBlock = funDefNode.body; 31 | funDefNode.params.forEach((name: string) => { 32 | this._paramList.push(name); 33 | }) 34 | } else { 35 | printInterpreterError("函数节点缺失,函数构建失败!"); 36 | } 37 | } 38 | 39 | addRearOperator(rearOperator: VariableMeta) { 40 | this._rearOperatorList.push(rearOperator); 41 | } 42 | 43 | subRearOperator(): VariableMeta { 44 | return this._rearOperatorList.pop(); 45 | } 46 | 47 | hasRearOperator() { 48 | return this._rearOperatorList.length > 0; 49 | } 50 | 51 | getLocalVariable(varName: string, blockStatement: BlockStmt): Variable | null { 52 | //获取局部变量 53 | return this._funSymbolTable.getVariableSymbol(varName, blockStatement); 54 | } 55 | 56 | pushVariable(blockStatement: BlockStmt, varTypePair: VariableMeta) { 57 | //添加变量到函数符号表中,函数符号表中的变量均为局部变量 58 | let variable: Variable = new Variable(this._moduleName); 59 | variable.initLocalVar(varTypePair, blockStatement);//使用varTypePair来对当前变量进行赋值,varTypePair可能是对变量的一个引用 60 | this._funSymbolTable.pushSymbol(variable); 61 | } 62 | 63 | cleanBlockVariable(blockStatement: BlockStmt){ 64 | //清除指定block下的variable 65 | this._funSymbolTable.clearBlockVariable(blockStatement); 66 | } 67 | 68 | get returnValue(): any { 69 | return this._returnValue; 70 | } 71 | 72 | set returnValue(value: any) { 73 | this._returnValue = value; 74 | } 75 | 76 | get moduleName(): string { 77 | return this._moduleName; 78 | } 79 | 80 | 81 | get funBlock(): BlockStmt | null { 82 | if (this._funBlock) 83 | return this._funBlock; 84 | return null; 85 | } 86 | 87 | get funName(): string { 88 | return this._funName; 89 | } 90 | 91 | get paramList(): Array { 92 | return this._paramList; 93 | } 94 | } 95 | 96 | //AST中FunDeclaration的包装类 97 | export class GeneralFun extends Fun {//函数类 98 | protected readonly _funType: FUN_TYPE = FUN_TYPE.GENERAL; 99 | get funType(): FUN_TYPE { 100 | return this._funType; 101 | } 102 | } 103 | 104 | export class InnerFun extends Fun { 105 | readonly _staticFunName: string = "";//如果是内部函数,则还需要其所属的静态函数名 106 | protected readonly _funType: FUN_TYPE = FUN_TYPE.INNER; 107 | protected brotherData: Variable;//在复合体数据中,与该内部函数同级的数据 108 | /*例如复合体x的数据为: 109 | { 110 | a: 123, 111 | b: "xyz", 112 | c: { 113 | d: "qwe", 114 | e: InnerFun, 115 | z:{ 116 | q:"123" 117 | } 118 | } 119 | } 120 | 如果调用x.c.e(),那么InnerFun里面的brotherData值为 121 | { 122 | d:"qwe", 123 | e:InnerFun, 124 | z:{ 125 | q:"123" 126 | } 127 | } 128 | 也就是同级属性() 129 | */ 130 | constructor(moduleName: string, funName: string, funDefNode: FunDeclaration, staticFunName: string, brotherData: Complexus) { 131 | super(moduleName, funName, funDefNode); 132 | this._staticFunName = staticFunName; 133 | //将复合体数据包装为变量 134 | let value = brotherData; 135 | let variable = new Variable(moduleName); 136 | let variableMeta = new VariableMeta(VARIABLE_TYPE.COMPLEXUS, value); 137 | variable.setValue(variableMeta); 138 | this.brotherData = variable; 139 | } 140 | 141 | get staticFunName(): string { 142 | return this._staticFunName; 143 | } 144 | 145 | getStaticVariable(): Variable { 146 | return this.brotherData; 147 | } 148 | 149 | get funType(): FUN_TYPE { 150 | return this._funType; 151 | } 152 | } 153 | 154 | export class StaticFun extends Fun { 155 | protected readonly _funType: FUN_TYPE = FUN_TYPE.STATIC; 156 | protected _returnValue: VariableMeta; 157 | 158 | get funType(): FUN_TYPE { 159 | return this._funType; 160 | } 161 | 162 | constructor(moduleName: string, staticFunName: string, funDefNode: FunDeclaration) { 163 | super(moduleName, staticFunName, funDefNode); 164 | this._returnValue = new VariableMeta(VARIABLE_TYPE.COMPLEXUS, new Complexus(moduleName, staticFunName)); 165 | } 166 | 167 | set returnValue(value: VariableMeta) { 168 | printWarn("静态函数不可以自定义返回值!"); 169 | } 170 | 171 | get returnValue(): VariableMeta { 172 | return this._returnValue; 173 | } 174 | 175 | getComplexus() { 176 | return this._returnValue.value; 177 | } 178 | } 179 | 180 | /** 181 | * 根据函数的语法树构建fun对象 182 | * @param FunDefStmt 指定的模块函数语法树 183 | * @param brotherData 只用在创建内部函数的时候才会传递 184 | */ 185 | //@ts-ignore 186 | export function createFunByFunDefStmt(FunDefStmt: ModuleFunDefStmt | InnerFunDefStmt, brotherData?: Complexus): GeneralFun | StaticFun | InnerFun { 187 | if (FunDefStmt instanceof ModuleFunDefStmt) { 188 | if (FunDefStmt.isStatic) { 189 | return new StaticFun(FunDefStmt.moduleName, FunDefStmt.getFunName(), FunDefStmt.funDeclaration); 190 | } else { 191 | return new GeneralFun(FunDefStmt.moduleName, FunDefStmt.getFunName(), FunDefStmt.funDeclaration); 192 | } 193 | } else if (brotherData) { 194 | return new InnerFun(FunDefStmt.moduleName, FunDefStmt.getFunName(), FunDefStmt.funDeclaration, FunDefStmt.staticFunName, brotherData); 195 | } 196 | printInterpreterError(FunDefStmt.getFunName() + "函数创建失败!"); 197 | } 198 | -------------------------------------------------------------------------------- /src/Interpreter/DataStruct/Complexus.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020. yaser. All rights reserved 3 | * Description: 复合体数据结构 4 | */ 5 | 6 | 7 | import {printInterpreterError, printWarn} from "../../Log"; 8 | import {Variable, VARIABLE_TYPE, VariableMeta} from "./Variable"; 9 | import {InnerFunDefStmt} from "../../Parser/DataStruct/ASTNode"; 10 | import _ = require("lodash"); 11 | 12 | export class Complexus { 13 | 14 | private readonly _moduleName: string; 15 | private readonly _staticFunName: string; 16 | private _data: object = {};//先使用JS原生的Object来代替 17 | constructor(moduleName: string, staticFunName: string) { 18 | this._moduleName = moduleName; 19 | this._staticFunName = staticFunName; 20 | } 21 | 22 | get data(): object { 23 | return this._data; 24 | } 25 | 26 | getInnerFunAndBotherData(funReferenceList: Array): { brotherComplexus, innerFun } { 27 | //用于获取指定的内部函数,以及与该内部函数同级的所有静态变量与内部函数 28 | let dataReferenceList = _.clone(funReferenceList); 29 | dataReferenceList.pop(); 30 | let innerFun = this.getRawData(funReferenceList); 31 | let newComplexus; 32 | if (innerFun instanceof InnerFunDefStmt) { 33 | newComplexus = new Complexus(this._moduleName, innerFun.staticFunName);//包装一个新的复合体给内部函数 34 | newComplexus._data = this.getRawData(dataReferenceList)//获取值,此处传递的是引用 35 | } else { 36 | printInterpreterError("无法找到指定内部函数" + funReferenceList.pop()); 37 | } 38 | return { 39 | brotherComplexus: newComplexus, 40 | innerFun: innerFun 41 | } 42 | } 43 | 44 | getComplexusData(referenceList: Array): Complexus { 45 | let newComplexus = new Complexus(this._moduleName, this._staticFunName); 46 | newComplexus._data = this.getRawData(referenceList); 47 | return newComplexus; 48 | } 49 | 50 | getRawData(referenceList: Array) { 51 | let index = 0; 52 | let nowValue = this._data; 53 | for (; index < referenceList.length; index++) { 54 | nowValue = nowValue[referenceList[index]]; 55 | if (nowValue === undefined) { 56 | //当前值不存在 57 | printInterpreterError("指定属性" + referenceList[index] + "不存在!"); 58 | } 59 | } 60 | return nowValue; 61 | } 62 | 63 | setData(referenceList: Array, varTypePair: VariableMeta) { 64 | let index = 0; 65 | let nowValue = this._data; 66 | for (; index < referenceList.length - 1; index++) { 67 | nowValue = nowValue[referenceList[index]]; 68 | if (!nowValue) { 69 | printInterpreterError("要设置的属性名不存在!"); 70 | } 71 | } 72 | nowValue[referenceList[index]] = varTypePair.value;//对一维数组设置值 73 | } 74 | 75 | setStaticVar(variable: Variable) { 76 | if (variable.variableType === VARIABLE_TYPE.COMPLEXUS) { 77 | this._data[variable.variableName] = variable.getValue().data; 78 | } else { 79 | this._data[variable.variableName] = variable.getValue(); 80 | } 81 | } 82 | 83 | setInnerFun(innerFunDefStmt: InnerFunDefStmt) { 84 | this._data[innerFunDefStmt.getFunName()] = innerFunDefStmt; 85 | } 86 | } 87 | 88 | /* 89 | //复合体缓存表 90 | export class ComplexusCacheTable { 91 | //使用二级缓存 92 | private complexusNodeCacheTable: object = {};//第一级缓存用于检索节点 93 | private valueCacheTables: Array = new Array();//第二级缓存用于检索节点下的值 94 | 95 | addNewComplexusNode(idNameList: string) { 96 | const hashKey = hashCode(idNameList).toString(); 97 | if (!this.complexusNodeCacheTable[hashKey]) { 98 | this.complexusNodeCacheTable[hashKey] = this.valueCacheTables.push({}) - 1;//value存放二级索引的index 99 | } 100 | } 101 | 102 | addNewValue(idNameList: string, valueIdName: string, valueNode: ComplexusValueNode) { 103 | const hashKey = hashCode(idNameList).toString(); 104 | const index = this.complexusNodeCacheTable[hashKey]; 105 | this.valueCacheTables[index][valueIdName] = valueNode;//此处存的是一个引用,而不是具体的值(吐槽:没有指针,真难用) 106 | } 107 | 108 | getValue(idNameList: string, valueIdName: string) { 109 | const hashKey = hashCode(idNameList).toString(); 110 | const index = this.complexusNodeCacheTable[hashKey]; 111 | return this.valueCacheTables[index][valueIdName].value; 112 | } 113 | 114 | } 115 | 116 | export class ComplexusValueTree { 117 | private root: ComplexusNode;//根节点 118 | private nodeStack: Stack = new Stack();//保存node的路径,且栈顶永远保存当前节点的父节点 119 | private curNode: ComplexusNode;//指向当前节点 120 | 121 | constructor(staticFunName: string) { 122 | this.root = new ComplexusNode(staticFunName, "", "root"); 123 | this.curNode = this.root; 124 | } 125 | 126 | //给当前节点添加值节点,该值就是基础数据类型的值,可以是字符串,数字,布尔或数组等形式 127 | addValueNode(idName: string, value: any) { 128 | this.curNode.valueArray.push(new ComplexusValueNode(idName, value)); 129 | } 130 | 131 | //给当前节点扩展一层新的Complexus节点,也就是扩展树的高度,并进入到该节点中 132 | extendComplexus(idName: string, staticFunName: string) { 133 | let newNode = new ComplexusNode(staticFunName, this.curNode.getIdNameList(), idName);//扩展一层新的节点 134 | this.curNode.valueArray.push(newNode);//将新生成的节点加入到当前节点的值列表中 135 | this.nodeStack.push(this.curNode);//保存当前节点 136 | this.curNode = newNode;//修改当前节点为新生成的节点 137 | } 138 | 139 | //返回到上一层的Complexus节点 140 | backPreNode() { 141 | if (!this.nodeStack.isEmpty()) { 142 | this.curNode = this.nodeStack.pop(); 143 | } 144 | } 145 | } 146 | 147 | type node = ComplexusNode | ComplexusValueNode; 148 | 149 | class ComplexusNode { 150 | private _preIdNames: string; 151 | private _idName: string;//id名 152 | private _valueArray: Array; 153 | private _staticFunName: string;//所处的静态函数名 154 | 155 | constructor(staticFunName: string, preIdNames: string, idName: string,) { 156 | this._idName = idName; 157 | this._preIdNames = preIdNames; 158 | this._valueArray = new Array(); 159 | this._staticFunName = staticFunName; 160 | } 161 | 162 | addValueNode(idName: string, value?: any) { 163 | this._valueArray.push(new ComplexusValueNode(idName, value)); 164 | } 165 | 166 | get valueArray(): Array { 167 | return this._valueArray; 168 | } 169 | 170 | get idName(): string { 171 | return this._idName; 172 | } 173 | 174 | get staticFunName(): string { 175 | return this._staticFunName; 176 | } 177 | 178 | getIdNameList(): string { 179 | return this._preIdNames + ";" + this._idName; 180 | } 181 | } 182 | 183 | class ComplexusValueNode { 184 | private _idName: string; 185 | private _value: any = null; 186 | 187 | constructor(idName: string, value?: any) { 188 | this._idName = idName; 189 | this._value = value; 190 | } 191 | 192 | get value(): any { 193 | return this._value; 194 | } 195 | 196 | set value(value: any) { 197 | this._value = value; 198 | } 199 | 200 | get idName(): string { 201 | return this._idName; 202 | } 203 | }*/ 204 | -------------------------------------------------------------------------------- /src/Interpreter/DataStruct/SymbolTable.ts: -------------------------------------------------------------------------------- 1 | import {Variable} from "./Variable"; 2 | import {hashCode} from "../../Utils/utils"; 3 | import {BlockStmt} from "../../Parser/DataStruct/ASTNode"; 4 | import {Log, printFatalError, printInterpreterError} from "../../Log"; 5 | 6 | //符号表抽象类 7 | abstract class SymbolTable { 8 | protected variablesValue: object = {}; 9 | 10 | protected symbolsSet: Set = new Set();//存symbol的hash值 11 | // 如果是变量,那么value就是该变量在variablesValue里面的索引 12 | // 如果是函数,那么value不存值,直接为统一值-1,只用来表示是否存在 13 | 14 | /** 15 | * 16 | * @param varOrModuleName 可能是变量,也可能是模块名 17 | * @param funName 如果存在,就是函数名 18 | */ 19 | abstract pushSymbol(varOrModuleName: Variable | string, funName?: string); 20 | 21 | 22 | abstract getVariableSymbol(varOrModuleName: string, blockOrVarName?: BlockStmt | string): Variable | null ; 23 | } 24 | 25 | 26 | //函数符号表,用于存局部变量、函数参数变量。 27 | export class FunSymbolTable extends SymbolTable { 28 | private readonly funName: string;//符号表所属的函数名 29 | 30 | constructor(funName: string) { 31 | super(); 32 | this.funName = funName; 33 | } 34 | 35 | pushSymbol(variableOrStaticFun: Variable | string, innerFun?: string) { 36 | if (variableOrStaticFun instanceof Variable) { 37 | let varName = variableOrStaticFun.variableName; 38 | //使用blockID与blockDepth来表示 39 | //@ts-ignore 40 | let blockDepth: number = variableOrStaticFun.blockDepth;//获取深度 41 | //@ts-ignore 42 | let blockID: string = variableOrStaticFun.blockID;//获取blockID 43 | let variableHash = wrapFunVariableToSymbolKey(blockDepth, blockID, varName); 44 | if (this.symbolsSet.has(variableHash)) { 45 | //有相同的变量已经定义了 46 | printInterpreterError(`${varName}变量在函数${this.funName}下重复定义!`); 47 | } else { 48 | //没有相同的变量 49 | if (!this.variablesValue[blockDepth]) { 50 | //如果该深度的block不存在,则创建 51 | this.variablesValue[blockDepth] = {}; 52 | } 53 | if (!this.variablesValue[blockDepth][blockID]) { 54 | //如果该指定id的block不存在,则创建 55 | this.variablesValue[blockDepth][blockID] = {}; 56 | } 57 | //添加变量 58 | this.variablesValue[blockDepth][blockID][varName] = variableOrStaticFun; 59 | this.symbolsSet.add(variableHash); 60 | } 61 | } else if (innerFun) { 62 | //加入内部函数 63 | let funHash = wrapModuleSymbolToSymbolKey(variableOrStaticFun, innerFun); 64 | if (this.symbolsSet.has(funHash)) { 65 | printFatalError(innerFun + "在静态函数:" + variableOrStaticFun + "中重复定义!"); 66 | } else { 67 | this.symbolsSet.add(funHash); 68 | } 69 | } 70 | } 71 | 72 | getVariableSymbol(varName: string, block: BlockStmt): Variable | null { 73 | //函数下的符号表用于查找局部变量 74 | let curBlock: BlockStmt | null = block; 75 | while (curBlock) { 76 | //如果当前block存在 77 | let variableHash = wrapFunVariableToSymbolKey(curBlock.blockDepth, curBlock.blockID, varName); 78 | if (this.symbolsSet.has(variableHash)) { 79 | //可以直接获取,返回获取的结果数据 80 | return this.variablesValue[curBlock.blockDepth][curBlock.blockID][varName]; 81 | } 82 | curBlock = curBlock.fatherBlock;//查看父block 83 | } 84 | return null; 85 | } 86 | 87 | clearBlockVariable(block: BlockStmt) { 88 | let blockDepth: number = block.blockDepth;//获取深度 89 | let blockID: string = block.blockID;//获取blockID 90 | if (this.variablesValue[blockDepth]) { 91 | //如果该层block存在变量,那么进行清除操作 92 | const varNames = Object.keys(this.variablesValue[blockDepth][blockID]);//获取所有要清除的变量名 93 | for (let i = 0; i < varNames.length; i++) { 94 | const varName = varNames[i]; 95 | let variableHash = wrapFunVariableToSymbolKey(blockDepth, blockID, varName); 96 | this.symbolsSet.delete(variableHash);//从set中删除 97 | } 98 | 99 | delete this.variablesValue[blockDepth][blockID]; 100 | 101 | } 102 | } 103 | } 104 | 105 | //全局符号表,用于存放模块函数与模块变量 106 | export class GlobalSymbolTable extends SymbolTable { 107 | 108 | pushSymbol(varOrModuleName: Variable | string, funName?: string) { 109 | if (varOrModuleName instanceof Variable) { 110 | let moduleName = varOrModuleName.moduleName; 111 | let varName = varOrModuleName.variableName; 112 | let variableHash = wrapModuleSymbolToSymbolKey(moduleName, varName);//获取hash值 113 | if (this.symbolsSet.has(variableHash)) { 114 | //有相同的变量已经定义了 115 | printFatalError(varName + "在模块:" + moduleName + "中重复定义!"); 116 | } else { 117 | //没有相同的变量存在 118 | if (!this.variablesValue[moduleName]) { 119 | //如果该模块不存在,则创建 120 | this.variablesValue[moduleName] = {};//模块变量 121 | } 122 | this.variablesValue[moduleName][varName] = varOrModuleName; 123 | this.symbolsSet.add(variableHash); 124 | } 125 | } else if (funName) { 126 | //将函数定义标识符加入到符号表中 127 | let funHash = wrapModuleSymbolToSymbolKey(varOrModuleName, funName); 128 | if (this.symbolsSet.has(funHash)) { 129 | printFatalError(funName + "在模块:" + varOrModuleName + "中重复定义!"); 130 | } else { 131 | this.symbolsSet.add(funHash); 132 | } 133 | } else { 134 | printFatalError("pushSymbol的参数匹配不正确!"); 135 | } 136 | } 137 | 138 | getVariableSymbol(moduleName: string, varName: string): Variable | null { 139 | //获取模块变量 140 | let variableHash = wrapModuleSymbolToSymbolKey(moduleName, varName);//获取hash值 141 | if (this.symbolsSet.has(variableHash)) { 142 | return this.variablesValue[moduleName][varName]; 143 | } else { 144 | return null; 145 | } 146 | } 147 | } 148 | 149 | let globalSymbolTable: GlobalSymbolTable | null;//全局符号表 150 | 151 | const SPLIT = ";"; 152 | 153 | /** 154 | * 将标识符信息转化为符号表的key 155 | * @param symbolsInfo 用于标识该标识符所需要的的所有信息 156 | */ 157 | function wrapToSymbolKey(...symbolsInfo: (number | string)[]): string { 158 | let symbolsKey = ""; 159 | for (let i = 0; i < symbolsInfo.length; i++) { 160 | const symbolInfo: number | string = symbolsInfo[i]; 161 | symbolsKey += symbolInfo + SPLIT;//必须要一个间隔符,否则可能会出现不同标识符的标识信息一样 162 | // 例如1.2.3如果没有分隔符,那么与1.23是一样的。 163 | } 164 | return hashCode(symbolsKey).toString(); 165 | } 166 | 167 | export function wrapFunVariableToSymbolKey(blockDepth, blockID, varName): string { 168 | return wrapToSymbolKey(blockDepth, blockID, varName); 169 | } 170 | 171 | export function wrapModuleSymbolToSymbolKey(moduleName, varOrFunName): string { 172 | return wrapToSymbolKey(moduleName, varOrFunName); 173 | } 174 | 175 | export function getGlobalSymbolTable(): GlobalSymbolTable { 176 | if (!globalSymbolTable) { 177 | globalSymbolTable = new GlobalSymbolTable(); 178 | } 179 | return globalSymbolTable; 180 | } 181 | 182 | export function cleanGlobalSymbolTable() { 183 | globalSymbolTable = null; 184 | } -------------------------------------------------------------------------------- /src/Interpreter/DataStruct/Variable.ts: -------------------------------------------------------------------------------- 1 | //变量包装类 2 | import {BlockStmt, Exp, VariableDef} from "../../Parser/DataStruct/ASTNode"; 3 | import {printInterpreterError} from "../../Log"; 4 | import {Reference} from "./Reference"; 5 | import {Complexus} from "./Complexus"; 6 | 7 | export enum VARIABLE_TYPE { 8 | STRING, 9 | NUMBER, 10 | ARRAY, 11 | NULL, 12 | BOOLEAN, 13 | COMPLEXUS,//复合体变量,因为QS是面向过程的语言,不能有对象,所以此处的复合体类似于结构体,具体实现的话还是用js中的对象来实现 14 | REFERENCE//引用变量,注:不属于可以直接使用的变量类型 15 | } 16 | 17 | //ID可能是单独的一个标识符,也可能是其它模块的标识符,也可能是复合体 18 | export class IDWrap { 19 | private readonly _idName: string;//ID名 20 | private readonly _moduleName: string;//ID所处模块名 21 | private readonly _hasAt: boolean;//是否有AT前缀,如果有则表示可能访问当前静态函数的静态变量,或调用当前静态函数的其它内部函数 22 | private _referenceList: Array = [];//id引用链 23 | 24 | constructor(idName: string, moduleName: string, hasAt: boolean=false) { 25 | this._idName = idName; 26 | this._moduleName = moduleName; 27 | this._hasAt = hasAt; 28 | } 29 | 30 | get idName(): string { 31 | return this._idName; 32 | } 33 | 34 | 35 | get moduleName(): string { 36 | return this._moduleName; 37 | } 38 | 39 | get hasAt(): boolean { 40 | return this._hasAt; 41 | } 42 | 43 | get referenceList(): Array { 44 | return this._referenceList; 45 | } 46 | 47 | set referenceList(value: Array) { 48 | this._referenceList = value; 49 | } 50 | } 51 | 52 | /*type referenceType = 53 | VARIABLE_TYPE.STRING 54 | | VARIABLE_TYPE.NUMBER 55 | | VARIABLE_TYPE.BOOLEAN 56 | | VARIABLE_TYPE.COMPLEXUS 57 | | VARIABLE_TYPE.NULL 58 | | VARIABLE_TYPE.ARRAY;*/ 59 | export function getValueType(value): VARIABLE_TYPE { 60 | //设置运算结果的数据类型,只处理非引用型数据类型 61 | let valueType; 62 | switch (typeof value) { 63 | case "boolean": 64 | valueType = VARIABLE_TYPE.BOOLEAN; 65 | break; 66 | case "number": 67 | valueType = VARIABLE_TYPE.NUMBER; 68 | break; 69 | case "string": 70 | valueType = VARIABLE_TYPE.STRING; 71 | break; 72 | case "object": 73 | if (Array.isArray(value)) { 74 | valueType = VARIABLE_TYPE.ARRAY; 75 | } else { 76 | valueType = VARIABLE_TYPE.COMPLEXUS; 77 | } 78 | break; 79 | default: 80 | valueType = VARIABLE_TYPE.NULL; 81 | break; 82 | } 83 | return valueType; 84 | } 85 | 86 | 87 | 88 | export class VariableMeta { 89 | //用于描述变量的数据 90 | private _value: any; 91 | type: VARIABLE_TYPE; 92 | varName?: string; 93 | reference: Reference | null = null; 94 | 95 | constructor(type: VARIABLE_TYPE, valueOrReference: any, varName?: string) { 96 | this.type = type; 97 | this.varName = varName; 98 | if (type === VARIABLE_TYPE.REFERENCE) { 99 | this.reference = valueOrReference; 100 | this._value = (valueOrReference).getReferenceValue(); 101 | } else { 102 | this._value = valueOrReference; 103 | } 104 | } 105 | 106 | get value(): any { 107 | return this._value; 108 | } 109 | 110 | set value(value: any) { 111 | this._value = value; 112 | } 113 | 114 | resetValue() { 115 | //重置值,因为在加入了对引用变量的索引后,当前的值已经过期了,需要重新检索值 116 | if (this.reference) { 117 | this._value = this.reference.getReferenceValue(); 118 | } 119 | } 120 | 121 | setValueToReference() { 122 | //将当前的value值赋值给自己所引用的变量 123 | if (this.reference) { 124 | this.reference.referencedVar.setValue(this, true) 125 | } else { 126 | printInterpreterError("引用的变量不存在!"); 127 | } 128 | } 129 | } 130 | 131 | export class Variable { 132 | private _variableName: string = "";//变量名 133 | private _variableValue: any = null;//变量值在执行的时候赋值 134 | private _variableType: VARIABLE_TYPE = VARIABLE_TYPE.NULL;//变量类型,默认为null 135 | private readonly _varInitExp: Exp | null = null;//变量初始化表达式 136 | private _hasDeclared: boolean = false;//是否定义了,对于模块变量,可能出现定义了,但没有初始化的情况 137 | private isStatic: boolean = false;//是否为静态变量 138 | private isModuleVar: boolean = false;//是否是模块变量,只有模块变量是可以导出的 139 | private readonly _moduleName: string;//所处模块名 140 | private _blockDepth?: number;//在方法体中所处的深度,如果是模块变量,则该属性为空 141 | private _blockID?: string;//因为相同深度的scope也会有多个,所以使用id来进行区分 142 | 143 | constructor(moduleName: string, variableDef?: VariableDef) { 144 | this._moduleName = moduleName; 145 | if (variableDef) { 146 | //只有构造模块变量时才使用该方式 147 | let varDefStmt = variableDef.VarDefStmt; 148 | this._variableName = varDefStmt.id; 149 | this.isModuleVar = true; 150 | if (varDefStmt.init) { 151 | //设置初始值 152 | this._varInitExp = varDefStmt.init; 153 | } 154 | } 155 | } 156 | 157 | initLocalVar(varTypePair: VariableMeta, block: BlockStmt, isStatic: boolean = false) { 158 | this.setValue(varTypePair); 159 | this._blockDepth = block.blockDepth; 160 | this._blockID = block.blockID; 161 | this.isStatic = isStatic; 162 | if (varTypePair.varName) { 163 | this._variableName = varTypePair.varName; 164 | } 165 | } 166 | 167 | initModuleVar() { 168 | this._hasDeclared = true;//已定义 169 | return this._varInitExp;//返回用于构建模块变量值的表达式 170 | } 171 | 172 | get hasDeclared(): boolean { 173 | return this._hasDeclared; 174 | } 175 | 176 | getValue(): any { 177 | return this._variableValue 178 | } 179 | 180 | get variableType(): VARIABLE_TYPE { 181 | return this._variableType; 182 | } 183 | 184 | setValue(varTypePair: VariableMeta, forceSet: boolean = false) { 185 | //forceSet表示是否将varTypePair中的值强制赋值给当前variable 186 | this._variableType = varTypePair.type; 187 | this._hasDeclared = true;//已定义 188 | if (varTypePair.varName){ 189 | this._variableName = varTypePair.varName; 190 | } 191 | if (varTypePair.type === VARIABLE_TYPE.REFERENCE && !forceSet) { 192 | //如果是引用型数据,判断被引用的数据是不是基本型的,如果是基本型的就不进行引用 193 | if (varTypePair.reference) { 194 | let reference = varTypePair.reference;//获取引用 195 | /** 注:此处借用了部分JS的引用机制 196 | * 因为如果value的类型不是基本数据类型的话,也就是对象的话,其实此处保存的是地址 197 | * 但地址TS无法读取,也就无法实现,所以借用了JS对于对象的引用机制 198 | */ 199 | let value = reference.getReferenceValue();//获取引用的变量值 200 | this._variableType = getValueType(value);//获取引用的变量类型 201 | this._variableValue = value; 202 | } 203 | } else { 204 | if (this._variableValue instanceof Complexus){ 205 | //@ts-ignore 206 | this._variableValue.setData(varTypePair.reference.referenceList,varTypePair) 207 | }else{ 208 | this._variableValue = varTypePair.value; 209 | } 210 | } 211 | } 212 | 213 | 214 | get variableName(): string { 215 | return this._variableName; 216 | } 217 | 218 | get moduleName(): string { 219 | return this._moduleName; 220 | } 221 | 222 | get blockDepth(): number | null { 223 | if (this._blockDepth) 224 | return this._blockDepth; 225 | return null; 226 | } 227 | 228 | get blockID(): string | null { 229 | if (this._blockID) 230 | return this._blockID; 231 | return null 232 | } 233 | } -------------------------------------------------------------------------------- /src/Parser/DataStruct/Form.ts: -------------------------------------------------------------------------------- 1 | import {writeToFile} from "../../Utils/utils"; 2 | import {addBuildFormError, printBuildFormError, printFatalError, printWarn} from "../../Log"; 3 | import {E, Production} from "./Production"; 4 | import {ActionFormItem, ActionStatus, GotoFormItem} from "./FormItem"; 5 | import {ACTION_TABLE_FILE, GOTO_TABLE_FILE} from "../../Cli/config"; 6 | 7 | export class GotoForm { 8 | private items: Array;//数组下标表示状态码 9 | private errorItem: GotoFormItem; 10 | 11 | constructor(statusNum: number) { 12 | this.items = new Array(statusNum); 13 | this.errorItem = new GotoFormItem("", -1, -1); 14 | } 15 | 16 | setGotoItem(stateIndex: number, expected: string, shiftTo: number) { 17 | if (!this.items[stateIndex]) { 18 | this.items[stateIndex] = {}; 19 | } 20 | if (!this.items[stateIndex][expected]) { 21 | this.items[stateIndex][expected] = new GotoFormItem(expected, shiftTo, stateIndex) 22 | } else { 23 | //发生冲突 24 | let newItem = new GotoFormItem(expected, shiftTo, stateIndex); 25 | if (!newItem.isSame(this.items[stateIndex][expected])) { 26 | sendFormWarnMsg(this.items[stateIndex][expected], newItem); 27 | } 28 | } 29 | 30 | } 31 | 32 | static buildGotoFromCache(cache: GotoForm) { 33 | let newGoto: GotoForm = new GotoForm(cache.items.length); 34 | try { 35 | cache.items.forEach((item: object) => { 36 | for (let itemKey in item) { 37 | let gotoItem: GotoFormItem = item[itemKey]; 38 | newGoto.setGotoItem(gotoItem.stateIndex, gotoItem.expected, gotoItem.shiftTo); 39 | } 40 | }); 41 | return newGoto; 42 | } catch (e) { 43 | printWarn("Goto表缓存文件转换出现失败!"); 44 | return false; 45 | } 46 | 47 | 48 | } 49 | 50 | getGotoItem(stateIndex: number, expected: string): GotoFormItem { 51 | let item = this.items[stateIndex][expected]; 52 | if (item) { 53 | //如果存在 54 | return item; 55 | } else { 56 | this.errorItem.errMsg = "Goto表读取错误,当前状态:" + stateIndex + " 无法匹配" + expected + ";"; 57 | return this.errorItem; 58 | } 59 | } 60 | 61 | print() { 62 | //打印Goto表 63 | let str = "--------------------GotoForm--------------------\n"; 64 | this.items.forEach((item, index) => { 65 | str += "------------------------------------------------\n"; 66 | 67 | str += "状态:" + index + "\n"; 68 | for (let itemKey in item) { 69 | str += item[itemKey].getInfo() + "\n"; 70 | } 71 | str += "------------------------------------------------\n"; 72 | 73 | }); 74 | writeToFile(str, GOTO_TABLE_FILE); 75 | } 76 | } 77 | 78 | type formItem = ActionFormItem | GotoFormItem; 79 | 80 | function sendFormWarnMsg(oldItem: formItem, newItem: formItem) { 81 | let errorMsg = ""; 82 | if (oldItem instanceof ActionFormItem) { 83 | errorMsg = " Action表发生移进规约冲突;\n"; 84 | } else { 85 | errorMsg = " Goto表发生移进规约冲突;\n"; 86 | } 87 | errorMsg += " 在状态:" + oldItem.stateIndex + " 展望字符:" + oldItem.expected + " 上已有项目\n"; 88 | errorMsg += " 旧项目内容:\n"; 89 | errorMsg += oldItem.getInfo(); 90 | errorMsg += " 新项目内容:\n"; 91 | errorMsg += newItem.getInfo(); 92 | addBuildFormError(errorMsg) 93 | } 94 | 95 | export class ActionForm { 96 | private items: Array;//数组下标表示状态码 97 | private errorItem: ActionFormItem; 98 | 99 | constructor(statusNum: number) { 100 | this.items = new Array(statusNum); 101 | this.errorItem = new ActionFormItem("", ActionStatus.ERROR); 102 | } 103 | 104 | static buildActionFromCache(cache: ActionForm) { 105 | try { 106 | let newAction: ActionForm | boolean = new ActionForm(cache.items.length); 107 | let getProduction = (actionItem) => { 108 | let production = new Production(actionItem.reduceBy.key); 109 | production.copy(actionItem.reduceBy); 110 | return production; 111 | }; 112 | cache.items.forEach((item: object) => { 113 | for (let itemKey in item) { 114 | let actionItem = item[itemKey]; 115 | switch (actionItem._action) { 116 | case ActionStatus.SHIFT_BY_E: 117 | //@ts-ignore 118 | newAction.setActionItem(actionItem.stateIndex, ActionStatus.SHIFT_BY_E, actionItem.expected, actionItem.shiftTo); 119 | break; 120 | case ActionStatus.SHIFT: 121 | //@ts-ignore 122 | newAction.setActionItem(actionItem.stateIndex, ActionStatus.SHIFT, actionItem.expected, actionItem.shiftTo); 123 | break; 124 | case ActionStatus.REDUCE: 125 | //@ts-ignore 126 | newAction.setActionItem(actionItem.stateIndex, ActionStatus.REDUCE, actionItem.expected, getProduction(actionItem)); 127 | break; 128 | case ActionStatus.ACC: 129 | //@ts-ignore 130 | newAction.setActionItem(actionItem.stateIndex, ActionStatus.ACC, actionItem.expected, getProduction(actionItem)); 131 | break; 132 | } 133 | } 134 | }); 135 | return newAction; 136 | } catch (e) { 137 | printWarn("Action缓存文件转换出现失败!"); 138 | return false; 139 | } 140 | 141 | } 142 | 143 | setActionItem(stateIndex: number, action: ActionStatus, expected: string, shiftToOrReduceBy?: number | Production) { 144 | if (!this.items[stateIndex]) { 145 | this.items[stateIndex] = {}; 146 | } 147 | if (!this.items[stateIndex][expected]) { 148 | this.items[stateIndex][expected] = new ActionFormItem(expected, action, stateIndex, shiftToOrReduceBy) 149 | } else { 150 | //发生冲突 151 | let conflictItem = new ActionFormItem(expected, action, stateIndex, shiftToOrReduceBy); 152 | let item = this.items[stateIndex][expected]; 153 | if (!item.isSame(conflictItem)) { 154 | //如果发生了冲突,且与之前的不是同一个,则将新的冲突项加入 155 | item.hasConflict = true; 156 | item.conflictArray.push(conflictItem); 157 | sendFormWarnMsg(item, conflictItem);//发出冲突项提示 158 | } 159 | } 160 | } 161 | 162 | getActionItem(stateIndex: number, expected: string) { 163 | let item = this.items[stateIndex][expected]; 164 | if (item) { 165 | //如果存在 166 | return item; 167 | } else { 168 | //如果不存在可以识别的状态,则查看该状态是否有空字符,如果有,则返回该空字符的转移操作 169 | item = this.items[stateIndex][E]; 170 | if (item) { 171 | return item; 172 | } 173 | //失败信息 174 | this.errorItem.errMsg = "Action表读取失败,当前状态:" + stateIndex + " 无法匹配:" + expected; 175 | return this.errorItem; 176 | } 177 | } 178 | 179 | print() { 180 | //打印Action表 181 | let str = "--------------------ActionForm--------------------\n"; 182 | this.items.forEach((item, index) => { 183 | str += "------------------------------------------------\n"; 184 | str += "状态:" + index + "\n"; 185 | for (let itemKey in item) { 186 | str += item[itemKey].getInfo() + "\n"; 187 | if (item[itemKey].hasConflict) { 188 | str += "------------------------------冲突项-------------------\n"; 189 | item[itemKey].conflictArray.forEach((conflictItem: ActionFormItem) => { 190 | str += conflictItem.getInfo() + "\n"; 191 | }); 192 | str += "-------------------------------------------------------\n" 193 | } 194 | } 195 | str += "------------------------------------------------\n"; 196 | }); 197 | writeToFile(str, ACTION_TABLE_FILE); 198 | } 199 | } -------------------------------------------------------------------------------- /src/Lexer/Lexer.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020. yaser. All rights reserved 3 | * Description:词法分析器 4 | */ 5 | 6 | import {EOF, keywordTable, LexerToken, Token} from "./DataStruct/Token"; 7 | import {isID, isIDStart, isKeyword, isNumber, isNumberStart, isSpace, isSymbol} from "./ScannerUtils"; 8 | import {printErr, printInfo, printLexerError} from "../Log"; 9 | import {readFromFile} from "../Utils/utils"; 10 | import {T} from "./DataStruct/V_T"; 11 | import {printTokens} from "./PrintToken"; 12 | 13 | let code: string;//源码 14 | let curCodeIndex: number;//源码指针,指向下一个要读取的字符 15 | let tokens: Array;//所有token列表 16 | let usedToken: Array;//用于保存已使用过的Token,但至多只保存两个,一个是前一个token,另一个是当前的token 17 | let errorTokens: Array;//所有出错的token 18 | let lineNo: number;//当前行号 19 | let lineIndex: number;//行中的位置 20 | 21 | let createErrorLexerPair = (errMsg, errorString) => { 22 | return new LexerToken(errorString.length, errorString, T.ERROR, errMsg); 23 | }; 24 | 25 | function pushToken(lexerToken: LexerToken, token: Token) { 26 | //将二者合并,push进指定的token列表 27 | if (lexerToken.tokenType === T.ERROR) { 28 | //错误的token 29 | lexerToken.lineNo = token.lineNo; 30 | lexerToken.start = token.start; 31 | errorTokens.push(lexerToken); 32 | } else { 33 | token.length = lexerToken.length; 34 | token.value = lexerToken.value; 35 | token.tokenType = lexerToken.tokenType; 36 | tokens.push(token); 37 | } 38 | } 39 | 40 | function lookAheadChar(): string { 41 | //向前看一个单词 42 | return code[curCodeIndex]; 43 | } 44 | 45 | function lookAheadXChar(x: number): string { 46 | //返回向前看的x个字符 47 | return code.substr(curCodeIndex, x); 48 | } 49 | 50 | 51 | function getNextChar(): string { 52 | //获取一个单词 53 | lineIndex++; 54 | return code[curCodeIndex++]; 55 | } 56 | 57 | function handleNumber(start: string): LexerToken { 58 | //处理数字 59 | let digital = start; 60 | let dotCnt = 0; 61 | while (isNumber(lookAheadChar())) { 62 | let char = getNextChar(); 63 | if (char === '.') dotCnt++; 64 | digital += char; 65 | } 66 | if (dotCnt === 0) { 67 | //解析整数 68 | return new LexerToken(digital.length, Number.parseInt(digital), T.NUMBER); 69 | } else if (dotCnt === 1) { 70 | //解析浮点数 71 | return new LexerToken(digital.length, Number.parseFloat(digital), T.NUMBER); 72 | } else { 73 | //错误的数字 74 | return createErrorLexerPair("数字解析出错,数字中不能有两个及以上的小数点", digital); 75 | } 76 | } 77 | 78 | function handleID(start: string): LexerToken { 79 | //处理标识符 80 | let id = start; 81 | let tokenType = T.ID;//默认是用户自定义标识符 82 | while (isID(lookAheadChar())) { 83 | id += getNextChar(); 84 | } 85 | if (isKeyword(id)) { 86 | tokenType = keywordTable[id]; 87 | } 88 | return new LexerToken(id.length, id, tokenType); 89 | } 90 | 91 | function handleSymbol(start: string): LexerToken { 92 | let symbol = start; 93 | let symbolResult: LexerToken; 94 | symbolResult = new LexerToken(1, symbol, T.ASSIGN);//默认是等号 95 | let testNext = (targetSymbolList: string, type: T[]) => { 96 | //从targetSymbolList中测试下一个符号是否为其中的符号,如果是的话,则读入,并重置结果,否则不做操作 97 | let nextChar = lookAheadChar(); 98 | let index = targetSymbolList.indexOf(nextChar); 99 | if (index !== -1) { 100 | //如果存在 101 | symbol += getNextChar(); 102 | symbolResult.tokenType = type[index]; 103 | symbolResult.length = symbol.length; 104 | symbolResult.value = symbol; 105 | } 106 | }; 107 | switch (symbol) { 108 | //单独修改token类型 109 | case '=': 110 | testNext("=", [T.EQUAL]); 111 | break; 112 | case ',': 113 | symbolResult.tokenType = T.COMMA; 114 | break; 115 | case '[': 116 | symbolResult.tokenType = T.LEFT_BRACKET; 117 | break; 118 | case ']': 119 | symbolResult.tokenType = T.RIGHT_BRACKET; 120 | break; 121 | case '{': 122 | symbolResult.tokenType = T.LEFT_BRACE; 123 | break; 124 | case '}': 125 | symbolResult.tokenType = T.RIGHT_BRACE; 126 | break; 127 | case '(': 128 | symbolResult.tokenType = T.LEFT_PAREN; 129 | break; 130 | case ')': 131 | symbolResult.tokenType = T.RIGHT_PAREN; 132 | break; 133 | case ';': 134 | symbolResult.tokenType = T.SEMI; 135 | break; 136 | case '.': 137 | symbolResult.tokenType = T.DOT; 138 | break; 139 | case '@': 140 | symbolResult.tokenType = T.AT; 141 | break; 142 | case '+': 143 | symbolResult.tokenType = T.ADD; 144 | testNext("+", [T.ADD_ONE]); 145 | break; 146 | case '-': 147 | symbolResult.tokenType = T.SUB; 148 | testNext("-", [T.SUB_ONE]); 149 | break; 150 | case '*': 151 | symbolResult.tokenType = T.MUL; 152 | break; 153 | case '/': 154 | symbolResult.tokenType = T.DIV; 155 | break; 156 | case '%': 157 | symbolResult.tokenType = T.MOD; 158 | break; 159 | case '!': 160 | symbolResult.tokenType = T.NOT; 161 | testNext("=", [T.NOT_EQUAL]); 162 | break; 163 | case '&': 164 | symbolResult.tokenType = T.BIT_AND; 165 | testNext("&", [T.LOGIC_AND]); 166 | break; 167 | case '|': 168 | symbolResult.tokenType = T.BIT_OR; 169 | testNext("|", [T.LOGIC_OR]); 170 | break; 171 | case '~': 172 | symbolResult.tokenType = T.BIT_NOT; 173 | break; 174 | case '>': 175 | symbolResult.tokenType = T.GREATER; 176 | testNext("=", [T.GREATER_EQUAL]); 177 | break; 178 | case '<': 179 | symbolResult.tokenType = T.LESS; 180 | testNext("=", [T.LESS_EQUAL]); 181 | break; 182 | case ':': 183 | symbolResult.tokenType = T.COLON; 184 | testNext(":", [T.MODULE_SCOPE]); 185 | break; 186 | default: 187 | //正常来说该分支是不会到达的 188 | symbolResult.tokenType = T.ERROR; 189 | symbolResult.errorMsg = "非法的运算法"; 190 | } 191 | return symbolResult; 192 | } 193 | 194 | function skipSpace() { 195 | while (isSpace(lookAheadChar())) { 196 | getNextChar(); 197 | } 198 | } 199 | 200 | function handleString(): LexerToken { 201 | //处理字符串 202 | let string = ""; 203 | while (true) { 204 | let nextChar = lookAheadChar(); 205 | if (nextChar === '\"') { 206 | //结束字符串解析 207 | getNextChar();//读取掉右" 208 | return new LexerToken(string.length, string, T.STRING); 209 | } 210 | if (nextChar === EOF) { 211 | //报错 212 | return createErrorLexerPair("字符串缺少右引号", string); 213 | } 214 | string += getNextChar(); 215 | } 216 | } 217 | 218 | function skipAnnotation(start: string): boolean | LexerToken { 219 | 220 | let nextChar = getNextChar(); 221 | if (nextChar === '*') { 222 | let annotation = start + nextChar; 223 | //处理多行注释 224 | while (lookAheadXChar(2) !== '*/' && lookAheadChar() !== EOF) { 225 | //读取注释内容 226 | annotation += getNextChar(); 227 | } 228 | if (lookAheadXChar(2) === '*/') { 229 | //将收尾读取 230 | getNextChar(); 231 | getNextChar(); 232 | } else { 233 | //没有结尾的*/需要报错 234 | return createErrorLexerPair("多行注释需要使用 '*/' 结尾!", annotation); 235 | } 236 | } else { 237 | //处理单行注释 238 | while (lookAheadChar() !== '\n' && lookAheadChar() !== EOF) { 239 | //读取注释内容 240 | getNextChar(); 241 | } 242 | } 243 | return true; 244 | } 245 | 246 | 247 | function convertCodeToToken() { 248 | //读取源代码文件,并识别全部的token,保存到tokens数组中 249 | let nowChar: string; 250 | let token: Token; 251 | skipSpace();//跳过所有空格 252 | while (lookAheadChar() !== EOF) { 253 | token = new Token(); 254 | token.lineNo = lineNo; 255 | token.start = lineIndex; 256 | nowChar = getNextChar();//读取一个字符 257 | let next = lookAheadChar(); 258 | if (nowChar === '/' && (next === '/' || next === '*')) { 259 | //跳过注释 260 | let result = skipAnnotation(nowChar); 261 | if (typeof result !== "boolean") { 262 | pushToken(result, token) 263 | } 264 | } else if (isNumberStart(nowChar)) { 265 | //处理数字(包括正整数与浮点数) 266 | pushToken(handleNumber(nowChar), token); 267 | } else if (isIDStart(nowChar)) { 268 | //处理标识符,标识符是字母或下划线开头 269 | pushToken(handleID(nowChar), token); 270 | } else if (isSymbol(nowChar)) { 271 | //处理各种符号 272 | pushToken(handleSymbol(nowChar), token); 273 | } else if (nowChar === "\"") { 274 | //处理字符串 275 | pushToken(handleString(), token); 276 | } else if (nowChar === '\n') { 277 | //换行符 278 | lineNo++; 279 | lineIndex = 1; 280 | } else { 281 | pushToken(createErrorLexerPair("无法识别的Token", nowChar), token); 282 | } 283 | skipSpace();//跳过所有空格 284 | } 285 | } 286 | 287 | export async function initLexer(filePath: string): Promise { 288 | //初始化词法分析器 289 | //读取源码文件 290 | printInfo("初始化词法分析器..."); 291 | printInfo("读取源码文件..."); 292 | usedToken = []; 293 | code = await readFromFile(filePath); 294 | code += EOF;//在文件末尾添加标记,表示结束 295 | curCodeIndex = 0; 296 | tokens = []; 297 | lineNo = 1; 298 | lineIndex = 1; 299 | errorTokens = []; 300 | printInfo("解析Token..."); 301 | convertCodeToToken(); 302 | printInfo("Token解析完成!"); 303 | let EOFToken = new Token(); 304 | EOFToken.tokenType = T.EOF; 305 | EOFToken.value = "#"; 306 | tokens.push(EOFToken); 307 | printTokens(tokens, filePath); 308 | if (errorTokens.length > 0) { 309 | printLexerError(errorTokens, filePath);//打印错误信息 310 | return false; 311 | } 312 | return true;//返回词法解析是否成功 313 | } 314 | 315 | 316 | export function lookAheadToken(): Token { 317 | return tokens[0]; 318 | } 319 | 320 | export function getPreToken(): Token | null { 321 | if (usedToken.length < 2) {//如果长度小于2,则表示没有前一个token,只有当前的token 322 | return null; 323 | } 324 | return usedToken[0]; 325 | } 326 | 327 | export function getNextToken(): Token { 328 | // @ts-ignore 329 | const nowToken = tokens.shift() 330 | // @ts-ignore 331 | usedToken.push(nowToken); 332 | if (usedToken.length > 2) {//usedToken的长度永远小于等于2,当长度为2时,第1个为前一个token,第2个为当前token 333 | usedToken.shift(); 334 | } 335 | // @ts-ignore 336 | return nowToken; 337 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QS 2 | 3 | ## 简介 4 | 5 | **因目前正在读研,所做的研究方向(Domain Generalization in cv)与之不一致,目前已没有时间继续实现该语言的后续阶段,未来会进一步实现(可能会比较久)** 6 | 7 | QS全名QinScript,是一门面向过程的脚本语言,语法参考了JS与C,属于个人实验性质项目。 8 | 9 | *关于名字由来:e59ba0e4b8bae8bf99e698afe68891e8aebee8aea1e79a84e7acace4b880e4b8aae7bc96e7a88be8afade8a880efbc8ce8808ce68891e78eb0e59ca8e79a84e5a5b3e69c8be58f8be4b99fe698afe68891e79a84e5889de6818befbc8ce68980e4bba5e5b0b1e794a8e4ba86e68891e5a5b3e58f8be79a84e5a793efbc8ce4b99fe5b0b1e698af51696eefbc88e7a7a6efbc89e4bd9ce4b8bae5bc80e5a4b4efbc8ce5908ce697b6e59ba0e4b8bae698afe8849ae69cace8afade8a880efbc8ce68980e4bba5e58f88e59ca8e5908ee99da2e58aa0e4ba86e4b8aa536372697074efbc8ce8bf99e5b0b1e69e84e68890e4ba8651696e5363726970740a* 10 | 11 | ## 语言元素 12 | 13 | ### 模块 14 | 15 | QS中一个文件就是一个模块。 16 | 17 | - 模块定义使用`@module: 模块名`来定义,模块定义必须在第一行。 18 | 19 | - 模块导入使用`import: 模块名`来导入。 20 | 21 | - 模块中对于要导出的函数量使用`export: 导出对象`来定义。 22 | 23 | - 模块中要是用其它模块中导出的元素,需要使用模块名前缀:`模块名::导出元素` 24 | 25 | - 一个QS项目中必须要有一个main函数(有且只有一个),该函数作为程序入口。 26 | 样例: 27 | 28 | ``` 29 | @module: Main;//Main模块 30 | import: Math;//导入Math模块 31 | export: temp;//导出temp变量 32 | 33 | let temp;//模块变量 34 | fun main(){//入口函数 35 | let a = 12; 36 | let b = 33; 37 | let c = Math::min(a,b);//调用其它模块函数 38 | } 39 | ``` 40 | 41 | ### 变量 42 | 43 | QS中的变量定义使用let关键字,变量分为三种:模块变量、局部变量与静态变量。 44 | 45 | 变量类型有: 46 | 47 | - string 48 | 49 | - number 50 | 51 | - boolean 52 | 53 | - null 54 | 55 | - array 56 | 57 | - complexus(复合体,静态函数的返回值,详情见静态函数) 58 | 59 | #### 模块变量 60 | 61 | 在QS的变量中,只有模块变量是可以导出的,在全局可以访问。 62 | 63 | #### 局部变量 64 | 65 | 局部变量在函数内定义,根据局部变量定义时所处的作用域,只可以在该作用域或子作用域中访问,且可以被子作用域中同名局部变量覆盖。 66 | 67 | #### 静态变量 68 | 69 | 静态变量只能在静态函数中定义,使用`static`关键字定义,可以与局部变量同名,在静态函数或内部函数中访问时需要加`@`前缀,在静态函数外部访问需要使用**复合体**类型的变量来间接访问。 70 | 71 | 样例: 72 | 73 | ``` 74 | static fun test(){//静态函数定义 75 | static let staticVariable = 0;//静态变量 76 | @staticVariable = 12;//静态变量访问 77 | } 78 | fun main(){ 79 | let temp = test();//静态函数调用 80 | temp.staticVariable = 99;//静态变量访问 81 | } 82 | ``` 83 | 84 | ### 函数 85 | 86 | QS语言中函数是第一成员,函数有三种,一种是普通函数,一种是静态函数,还有一种是内部函数,在QS中除内部函数外都可以导出。 87 | 88 | #### 普通函数 89 | 90 | 普通函数拥有的功能与其他语言中的函数完全一致,因此不进行详细说明了,看样例即可。 91 | 92 | 样例: 93 | 94 | ``` 95 | fun test(arg1,arg2){//普通函数定义 96 | //语句 97 | } 98 | ``` 99 | 100 | #### 静态函数、内部函数 101 | 102 | 静态函数属于模块内部,使用`static`关键自定义,内部函数属于静态函数内部,定义与普通函数一致,但需要加前缀`@`。 103 | 104 | ##### 详细说明 105 | 106 | - 静态函数可以视为劣化版的类或是进阶版结构体,它介于二者之间,执行后会将内部的静态变量与内部函数一个整体返回,在这里称这个返回值为**复合体**。 107 | - 静态函数有**静态变量**,可视为成员变量,且**只有静态函数才有静态变量**。 108 | - 静态函数有**内部函数**,内部函数与普通函数完全一样,除了**不可以直接调用**,可以将它视为成员方法,且**只有静态函数有内部函数**。 109 | - 静态函数与普通函数使用**完全一致**,除了**没有return语句**,可以单独调用,也可以赋值给一个变量。 110 | - 静态函数单独调用与普通函数的单独调用,在**功能上完全一样**。 111 | - 静态函数如果赋值给变量,则该变量称为**复合体变量**。 112 | - 静态函数在调用之后,会执行除内部函数的其它语句,**可认为这是对静态函数的内部函数以及静态变量的初始化过程**。 113 | - 静态变量与内部函数也**属于语句**,**可以包裹在控制语句中**,但**不可以使用循环语句包裹**,换句话说,**静态变量与内部函数可以在调用静态函数的时候动态生成**。 114 | - 静态变量与内部函数在静态函数内**只可定义一次,多次定义会出错**。 115 | - 在**静态函数外部访问静态变量与内部函数**时,**必须通过复合体变量来间接访问**,不可以直接访问,访问方式是`复合体变量.静态变量或内部函数`。 116 | - 在静态函数中,静态变量与内部函数**只可以在内部函数中或是通过复合体变量调用**,**不可以在执行静态函数时使用。** 117 | - 静态变量与函数的局部变量不冲突,内部函数与普通函数不冲突,**但静态变量与内部函数是冲突的,在**静态函数内**使用静态变量需要**使用`@`做前缀**,在内部函数中调用本静态函数的其它内部函数**也需要使用`@`做前缀。** 118 | - 内部函数**只可访问静态函数的静态变量或模块变量**,**不可以访问静态函数的局部变量**。 119 | 120 | 样例: 121 | 122 | ```js 123 | static fun staticFun( val ){//静态函数定义 124 | static let staticVariable = 0;//静态变量定义与初始化 125 | //@staticVariable = 12;错误示例,静态变量不可在执行静态函数时使用 126 | @fun innerFun0(){//内部函数 127 | return 0; 128 | } 129 | //@innerFun0();错误示例,内部函数不可在执行静态函数时使用 130 | if(val == 0){//动态定义同一个内部函数的不同版本 131 | @fun innerFun(){//内部函数 132 | @staticVariable = @innerFun0();//调用其它内部函数 133 | } 134 | }else{ 135 | @fun innerFun(){//内部函数 136 | @staticVariable = 88;//(排版有毒,怎么都对不齐。。。) 137 | } 138 | } 139 | } 140 | fun main(){ 141 | let temp = staticFun(1);//静态函数调用 142 | temp.staticVariable = 99;//静态变量访问与赋值 143 | //因为动态创建的时候val的值为1,所以是else中的innerFun被执行了。 144 | temp.innerFun(); 145 | //print为原生函数,用于打印数据 146 | print(temp.staticVariable);//打印结果为88 147 | } 148 | ``` 149 | 150 | ### 作用域 151 | 152 | **同一作用域下的变量名与函数名不可重名** 153 | 154 | 1. 模块作用域下,**模块变量与模块下的函数冲突**,即不可与普通函数或静态函数重名。 155 | 2. 静态函数作用域下,**静态变量与内部函数冲突**。 156 | 3. 局部作用域下,**局部变量与所有函数均不冲突**。 157 | 158 | ### 语句 159 | 160 | 以下语句样例均不包含静态函数相关语句,静态函数的语句可以参考上文中的样例。 161 | 162 | #### 定义语句 163 | 164 | ```js 165 | let a;//模块变量定义 166 | 167 | fun fun2(){//普通函数定义 168 | let b = 99;//局部变量定义 169 | } 170 | 171 | ``` 172 | 173 | #### if语句 174 | 175 | ```js 176 | if(表达式){ 177 | 语句; 178 | }else{ 179 | 语句; 180 | } 181 | ``` 182 | 183 | #### while语句 184 | 185 | ```js 186 | while(表达式){ 187 | 语句; 188 | } 189 | ``` 190 | 191 | #### 函数调用语句 192 | 193 | ```js 194 | fun0(表达式列表); 195 | ``` 196 | 197 | #### return语句 198 | 199 | ```js 200 | return 表达式; 201 | return; 202 | ``` 203 | 204 | #### 赋值语句 205 | 206 | ```js 207 | ID = 表达式; 208 | ID[表达式] = 表达式 209 | ``` 210 | 211 | #### 表达式 212 | 213 | ```js 214 | ID; 215 | 1 * 12 + 43 - 4; 216 | "11231254231"; 217 | [1, 2, 3]; 218 | ``` 219 | 220 | ### 注释 221 | 222 | QS中支持单行注释与多行注释,具体的注释方式与C或JS完全一致。 223 | 224 | #### 单行注释 225 | 226 | ```c 227 | //这是单行注释 228 | ``` 229 | 230 | #### 多行注释 231 | 232 | ```c 233 | /*这是多行注释 234 | * 这是多行注释 235 | * 这是多行注释 236 | */ 237 | ``` 238 | 239 | ## QS实现概述 240 | 241 | QS使用模块化设计,一共有四个模块,词法分析器、语法分析器、解释器以及虚拟机。 242 | 243 | **注:此处只是简单介绍一下,正在准备相关[系列文章](https://zhuanlan.zhihu.com/p/126741399)对源码进行解读。** 244 | 245 | ### 开发环境介绍 246 | 247 | QS的实现准备分为两部分进行,第一部分包含:词法分析器、语法分析器以及解释器,第二部分为虚拟机,虚拟机包含:字节码执行器、JIT以及GC部分。 248 | 249 | 对于开发语言的选择方面,我综合考虑了许多语言,包括:C、Java、Python、JavaScript、TypeScript以及C++。 250 | 251 | C由于太过基础,实现起来需要写的代码就比较多;Java语法糖实在太繁琐了,写起来束手束脚的;JS与PY虽然写起来比较方便,但没有类型,估计BUG会很难发现,最后敲定用C++和TS。 252 | 253 | 大致上准备第一部分先用TS写第一版,因为开发效率高,用于验证思路的正确性,然后使用C++重构一遍,并进行一些优化处理;对于第二部分,也就是虚拟机部分,直接用C++写,因为TS没法做底层开发(虽然有扩展库,但兼容性是个问题)。 254 | 255 | 由于现在写的是第一部分,所以只需要搭建好TS部分的环境即可,在开发中,我没有使用任何辅助性框架,也就是说全部都是自己手写的。 256 | 257 | 开发工具:WebStrom、Node.js、yarn、Clion、Visual Studio。 258 | 259 | 前三个用于开发第一部分,后两个用于开发第二部分(暂时用不到) 260 | 261 | ### 项目核心目录结构介绍 262 | 263 | ![image-20200408102859776](picture/image-20200408102859776.png) 264 | 265 | 此处简单介绍一下项目整体的目录结构。 266 | 267 | 1. 根目录下的QS文件夹里面是一个QS项目。 268 | 269 | - out文件夹里面是该QS项目的一些输出文件,包括构建的LR(1)分析表缓存数据,项目日志数据,语言终结符与非终结符和词法分析的Token等。 270 | 271 | - src里面包含当前版本以及后续版本的语法文件和被测试的QS项目文件。 272 | 273 | 2. 根目录下的Src文件夹里面是对QS实现的具体代码文件。 274 | 275 | - cli是命令行工具。 276 | - Interpreter是QS解释器。 277 | - Lexer是词法分析器。 278 | - Log为日志输出,包含对错误以及警告等信息的日志输出。 279 | - Parser是语法分析程序,包含对语法文件的解析,语法树的生成等。 280 | - Project主要是对QS项目路径的解析读取。 281 | - QSLib是QS的原生库函数(TS版比较简单,不准备再添加了,后期准备C++版)。 282 | - Test是对一些模块进行单独的测试。 283 | - Utils是一些工具类 284 | - main是整体项目的入口。 285 | 286 | *PS:有一些项目目录下面比较混乱,一直没高兴去整理,还请见谅。* 287 | 288 | ### 词法分析器 289 | 290 | 词法分析器的源码均在[lexer文件夹](src/Lexer)下,主程序是[Lexer.ts](src/Lexer/Lexer.ts),词法分析器是手工编码的方式进行实现的。 291 | 292 | ### 语法分析器 293 | 294 | 语法分析源码在[parser文件夹下](src/Parser),主程序是[ParseModule.ts](src/Parser/ParseModule.ts),使用LR1语法分析方法,主要分为两个部分,一个部分是[解析器](src/Parser/AnalyzeGrammar/Index.ts),用于解析[语法文件](QS/src/grammar/grammar.txt),并生成对应的LR1分析表,另一部分是[语法树生成器](src/Parser/BuildAST/Index.ts),用于构建语法树,供解释器执行时使用。 295 | 296 | ### 解释器 297 | 298 | 解释器源码在[Interpreter文件夹](src/Interpreter)下,主程序是[Index.ts](src/Interpreter/Index.ts)。 299 | 300 | ### 虚拟机 301 | 302 | #### TODO 303 | 304 | ## 运行方式 305 | 306 | >1. 安装[node.js](https://nodejs.org/en/)。 307 | >2. 安装[Yarn](https://classic.yarnpkg.com/en/)。 308 | >3. 使用命令行到项目根目录下。 309 | >4. 执行`yarn install`进行依赖安装。 310 | >5. 执行`yarn run dev`运行。 311 | 312 | --- 313 | 314 | 315 | ## 开发计划 316 | 整体开发准备分为五个阶段。 317 | 318 | ### 当前开发状态: 319 | >前两阶段开发完成,由于精力有限,可能会有一些未知的bug,还请在issues中提出。 320 | 321 | 322 | - 当前阶段运行样例 323 | ```js 324 | @module:Main; 325 | import:Test; 326 | static fun Stack(len) { 327 | static let x = array(len,0); 328 | static let index = 0; 329 | @fun push(el){ 330 | @x[@index++] = el; 331 | } 332 | @fun pop(){ 333 | return @x[@index--]; 334 | } 335 | @fun getX(){ 336 | //只返回有值的部分 337 | let res = array(@index); 338 | let index = 0; 339 | while(index < @index){ 340 | res[index] = @x[index++]; 341 | } 342 | return res; 343 | } 344 | @fun getSize(){ 345 | return @index; 346 | } 347 | } 348 | 349 | fun main(){ 350 | //测试静态函数、多维数组 351 | let stack = Stack(100); 352 | let x= array(100,0); 353 | x[0]=[1,2,3]; 354 | x[1]=11; 355 | print(x[0][2],x[1]); 356 | stack.push("WYX"); 357 | stack.push("LOVE"); 358 | stack.push("QSN"); 359 | let len = 10; 360 | let index = 0; 361 | while(index++=0){ 391 | temp = temp + str[index--]; 392 | } 393 | return temp; 394 | } 395 | ``` 396 | - 输出结果: 397 | 398 | ![image-20200412215415982](picture/image-20200412215415982.png) 399 | 400 | ### 第一阶段 401 | 402 | #### 任务 403 | 404 | 此阶段的任务主要是:文法设计、词法分析、LR1分析表构建、语法树部分构建、解释器部分构建,部分语言功能的实现。 405 | 406 | 该阶段主要保证项目的整体可运行性,构建基础设施,带有测试目的。 407 | 408 | #### 需要完成的功能 409 | 410 | - 整体结构上,仅支持单模块,不支持多模块导入等功能。 411 | - 数据类型上暂时支持:string、number、boolean与null 412 | - 语句方面,暂时支持:普通函数定义、模块变量与局部变量定义、call语句、block语句、assign语句、while语句、return语句、可计算表达式(calExp)。 413 | - 标准库方面,实现原生函数print() 414 | 415 | #### 进度 416 | 417 | - [x] [文法设计](QS/src/grammar/grammar.txt) 418 | - [x] 词法分析 419 | - [x] LR1分析表构建 420 | - [x] AST部分构建 421 | - [x] 解释器部分构建 422 | - [x] 语言功能的部分实现 423 | 424 | ### 第二阶段 425 | 426 | - 计划实现AST的全部构建,解释器的全部构建,实现TS版的全部语言功能,发布V1.0.0 427 | 428 | #### 功能进度 429 | 430 | - [x] IF语句 431 | - [x] 多维数组 432 | - [x] 多模块加载 433 | - [x] 静态函数 434 | - [x] 命令行工具 435 | 436 | **PS:对于数组与静态函数的实现上,由于没法用指针,用了些取巧的办法,所以并不稳定,二者一起用的时候极有可能出现bug。** 437 | 438 | ### 第三阶段(TODO) 439 | 440 | - 计划实现C++版,但不实现解释器,解释部分由虚拟机来承担,添加字节码生成器。 441 | 442 | PS:之前是没有这个阶段的,但后来发现TS虽然效率不错,但性能着实捉急,然后在写复合体这个功能的时候加剧了我这一想法,本来准备参考V8对object的实现的,然而发现,V8里面object的实现各种指针,完全没法参考,现在的实现相当于给js原生的object套了几层壳。。准备等前两阶段完成后,再用C++全部重构一遍,并做优化处理。 443 | 444 | ### 第四阶段(TODO) 445 | 446 | - 设计并实现一部分虚拟机(先支持一些简单的语言元素,保证可以运行起来),包括设计一套字节码,编写字节码执行器、GC、以及JIT。 447 | 448 | ### 第五阶段(TODO) 449 | 450 | - 实现完整的虚拟机 451 | 452 | ### PS 453 | 454 | 上述的第二阶段之后的今年应该没有时间做,因为4月开始要准备考研事宜,所以只准备完成前两个阶段,后面的等考研结束再实现。 455 | 456 | 457 | ## 参考资料 458 | 459 | ### 书籍: 460 | 461 | - [编译器设计](https://book.douban.com/subject/20436488/) 462 | - [自制编程语言 基于C语言](https://book.douban.com/subject/30311070/) 463 | 464 | ### 视频: 465 | 466 | - [编译原理](https://www.icourse163.org/course/NUDT-1003101005) 467 | 468 | ### Git项目: 469 | 470 | - https://github.com/Xiang1993/jack-compiler 471 | - https://github.com/dejavudwh/C2j-Compiler 472 | - https://github.com/Yaser-wyx/the-super-tiny-compiler-modified 473 | 474 | ### 博客: 475 | 476 | - https://www.cnblogs.com/secoding/p/11393720.html 477 | -------------------------------------------------------------------------------- /src/Parser/AnalyzeGrammar/BuildActionAndGoTo.ts: -------------------------------------------------------------------------------- 1 | //用于构建LR分析的Action与Goto子表 2 | import {ActionStatus} from "../DataStruct/FormItem"; 3 | import {E, EOF, Production} from "../DataStruct/Production"; 4 | import {Closure} from "../DataStruct/Closure"; 5 | import {printBuildFormError, printInfo} from "../../Log"; 6 | import {ActionForm, GotoForm} from "../DataStruct/Form"; 7 | 8 | let _ = require("lodash"); 9 | 10 | let startProduction: Production; 11 | let productions = {};//key为产生式左部符号,value为一个数组,表示产生式右部符号(因为可能有多个右部产生式) 12 | let firstSet = {};//key为非终结符,value为该非终结符的first集合,是set数据结构 13 | let vSet = new Set();//非终结符 14 | let tSet = new Set();//终结符 15 | let symbols = new Set([EOF]);//所有符号 16 | let LR1: object; 17 | let LRIndex = 0;//规范族下一个索引,也可以作为个数使用 18 | let productionMap = {};//key为产生式值的hashcode,value为一个解析后的产生式,用于填表中确定规约的产生式 19 | const productionSplit = "\n"; 20 | const arrowSymbol = '->'; 21 | 22 | function generateProduction(grammar: string) { 23 | //从指定文法中获取产生式,并将其结构化 24 | let items = grammar.split(productionSplit); 25 | items.forEach(item => { 26 | if (item.startsWith("#")) { 27 | return; 28 | } 29 | item = item.replace(/\r\n/g, ""); 30 | if (item.length === 0) return; 31 | //遍历items 32 | let arrowIndex = item.indexOf(arrowSymbol); 33 | let key = item.substr(0, arrowIndex).trim(); 34 | symbols.add(key); 35 | let productionRightList = item.substr(arrowIndex + arrowSymbol.length).split("|");//获取该产生式的所有子产生式 36 | 37 | productions[key] = new Array();//构建一个子产生式列表 38 | productionRightList.forEach(productionRight => { 39 | //遍历子产生式 40 | let production = new Production(key);//新建一个子产生式 41 | productionRight = productionRight.trim(); 42 | let productionRightItems = productionRight.split(" ");//使用空格分隔 43 | productionRightItems.forEach(productionRightItem => { 44 | //添加该产生式的一个节点 45 | if (productionRightItem) { 46 | symbols.add(productionRightItem); 47 | production.pushItem(productionRightItem); 48 | } 49 | }); 50 | let productionHash = production.getHashCode(false);//获取产生式的hash值 51 | productionMap[productionHash] = _.cloneDeep(production);//防止数据被污染,clone一份 52 | if (!startProduction) { 53 | startProduction = production;//初始产生式保证了只有一个 54 | } 55 | productions[key].push(production); 56 | }); 57 | 58 | }); 59 | } 60 | 61 | function getVAndT() { 62 | //获取终结符与非终结符 63 | symbols.forEach(symbol => { 64 | if (productions[symbol]) { 65 | vSet.add(symbol); 66 | } else { 67 | tSet.add(symbol); 68 | } 69 | }); 70 | return; 71 | } 72 | 73 | function getLR1() { 74 | //获取LR1规范族 75 | if (startProduction) { 76 | let startClosure = new Closure([startProduction]);//计算起始节点闭包 77 | let closureSets = {}; 78 | let closureHashMap = {}; 79 | let flag = false; 80 | let pushClosure = (newClosure: Closure) => { 81 | let name = 'I' + LRIndex; 82 | newClosure.name = name; 83 | newClosure.stateNum = LRIndex++; 84 | closureSets[name] = newClosure; 85 | flag = true; 86 | closureHashMap[newClosure.getHashCode()] = closureSets[name]; 87 | }; 88 | let initClosure = calculateClosure(startClosure);//计算初始节点闭包 89 | pushClosure(initClosure); 90 | while (flag) { 91 | flag = false; 92 | for (let closureSetsKey in closureSets) { 93 | let proceedClosure: Closure = closureSets[closureSetsKey];//获取一个闭包来进行计算 94 | if (!proceedClosure.flag) { 95 | //该闭包未处理 96 | let closureInnerSet: Array = proceedClosure.innerSet;//处理闭包的每一个产生式 97 | let nextRecognizeSet = new Set();//待识别符号集合 98 | for (let production of closureInnerSet) { 99 | let nextRecognize = production.getNowDotAfter();//获取该产生式当前占位符后第一个节点的值 100 | if (nextRecognize !== EOF) { 101 | nextRecognizeSet.add(nextRecognize); 102 | } 103 | } 104 | nextRecognizeSet.forEach(nextRecognize => { 105 | let newClosure = Goto(proceedClosure, nextRecognize); 106 | if (closureHashMap[newClosure.getHashCode()]) { 107 | //如果当前闭包在接受一个符号计算后的新闭包是已经存在的,则直接建立连接,不再将该闭包加入 108 | proceedClosure.addClosureAfterRecognizeX(nextRecognize, closureHashMap[newClosure.getHashCode()]); 109 | } else { 110 | proceedClosure.addClosureAfterRecognizeX(nextRecognize, newClosure); 111 | pushClosure(newClosure);//计算当前闭包在识别了一个符号后,转移到的状态 112 | } 113 | }); 114 | proceedClosure.flag = true;//标记上,表示该闭包处理过了 115 | } 116 | } 117 | } 118 | LR1 = closureSets; 119 | } 120 | } 121 | 122 | function fillForm(): { actionForm, gotoForm } | null { 123 | //填Action与Goto表 124 | if (LR1) { 125 | let actionForm = new ActionForm(LRIndex);//创建action表 126 | let gotoForm = new GotoForm(LRIndex);//创建goto表 127 | let reduce = (stateNum: number, expected: string, production: Production) => { 128 | let productionHash = production.getHashCode(false); 129 | actionForm.setActionItem(stateNum, ActionStatus.REDUCE, expected, productionMap[productionHash]); 130 | }; 131 | let isAcc = (production: Production) => { 132 | return production.search === EOF && production.getHashCode(false) === startProduction.getHashCode(false); 133 | }; 134 | for (let lr1Key in LR1) { 135 | //遍历LR1规范族表 136 | let closure: Closure = LR1[lr1Key];//获取一个规范族 137 | closure.innerSet.forEach((production: Production) => { 138 | let needRecognize = production.getNowDotAfter(); 139 | let nextClosure = closure.getClosureAfterRecognizeX(needRecognize); 140 | if (nextClosure) { 141 | //如果存在移进项目 142 | if (tSet.has(needRecognize) && needRecognize !== EOF) { 143 | //如果是终结符 144 | if (needRecognize !== E) { 145 | actionForm.setActionItem(closure.stateNum, ActionStatus.SHIFT, needRecognize, nextClosure.stateNum); 146 | } else { 147 | actionForm.setActionItem(closure.stateNum, ActionStatus.SHIFT_BY_E, needRecognize, nextClosure.stateNum); 148 | } 149 | } else if (vSet.has(needRecognize)) { 150 | //如果是非终结符 151 | gotoForm.setGotoItem(closure.stateNum, needRecognize, nextClosure.stateNum); 152 | } 153 | } else if (needRecognize === EOF) { 154 | //如果是eof,则表示是一个规约项目 155 | if (isAcc(production)) { 156 | //如果是终态 157 | actionForm.setActionItem(closure.stateNum, ActionStatus.ACC, EOF, production); 158 | } else { 159 | reduce(closure.stateNum, production.search, production); 160 | } 161 | } 162 | }); 163 | } 164 | printInfo("分析表构建完成,开始输出分析表数据到文件。"); 165 | actionForm.print(); 166 | gotoForm.print(); 167 | return {actionForm: actionForm, gotoForm: gotoForm}; 168 | } 169 | return null 170 | } 171 | 172 | export function analyzeGrammar(grammar: string): { actionForm, gotoForm } | null { 173 | //开始解析语法 174 | printInfo("开始解析语法..."); 175 | printInfo("读取语法并结构化产生式..."); 176 | generateProduction(grammar);//读取产生式 177 | printInfo("获取终结符与非终结符..."); 178 | getVAndT();//获取终结符与非终结符 179 | printInfo("计算非终结符first集合..."); 180 | first();//计算非终结符的first集合 181 | printInfo("获取LR1规范族..."); 182 | getLR1();//获取LR1规范族 183 | printInfo("填写LR1分析表..."); 184 | return fillForm();//填写LR分析表 185 | } 186 | 187 | function printProductions(productions: object) { 188 | for (let key in productions) { 189 | let productionList: Array = productions[key]; 190 | productionList.forEach((production: Production) => { 191 | console.log(production.key, ":", production.getValue()); 192 | }) 193 | } 194 | } 195 | 196 | function calculateClosure(calClosure: Closure): Closure {//LR1 closure算法 197 | let newClosure: Closure = _.cloneDeep(calClosure);//复制一份闭包集合,不修改原有集合 198 | newClosure.resetProductionFlag();//重置闭包中所有产生式的标志位 199 | let newClosureSet = newClosure.innerSet; 200 | let hashSet = new Set();//用来记录所有已经在闭包中的产生式的hash值 201 | let flag: boolean = true;//flag表示闭包是否有更新 202 | let pushProduction = ((production: Production) => {//添加产生式到新建的闭包中 203 | newClosureSet.push(production); 204 | hashSet.add(production.getHashCode()); 205 | flag = true 206 | }); 207 | let isInClosure = ((production: Production) => {//是否在闭包中 208 | return hashSet.has(production.getHashCode()); 209 | }); 210 | while (flag) { 211 | flag = false;//立即重置 212 | newClosureSet.forEach(production => { 213 | //production为需要计算闭包的产生式 214 | //遍历闭包集合 215 | if (!production.flag) {//如果没有处理过 216 | production.flag = true;//标记为已处理 217 | let notT = production.getNowDotAfter();//获取占位符.后的第一个符号 218 | if (vSet.has(notT)) {//判断是否为非终结符 219 | //如果是非终结符 220 | let vProductions: Array = productions[notT];//获取该非终结符对应的产生式组 221 | if (vProductions) { 222 | for (let vProduction of vProductions) { 223 | //遍历该非终结符对应的产生式组 224 | let nodesToCalFirst = production.getNodeToCalFirst();//为了计算搜索符,先获取所有可能的符号 225 | let searchFirstSet = getSearchFirstSet(nodesToCalFirst);//计算搜索符 226 | searchFirstSet.forEach(search => {//遍历所有搜索符 227 | let newProduction = _.cloneDeep(vProduction); 228 | newProduction.setSearch(search); 229 | if (!isInClosure(newProduction)) { 230 | pushProduction(newProduction); 231 | } 232 | }); 233 | } 234 | } 235 | } 236 | } 237 | 238 | }) 239 | } 240 | return newClosure; 241 | } 242 | 243 | function getSearchFirstSet(nodes: Array): Set { 244 | let searchSet = new Set();//搜索符集合 245 | for (let node of nodes) { 246 | //遍历每一个节点 247 | if (vSet.has(node)) { 248 | //如果是非终结符 249 | let fSet: Set = firstSet[node];//获取该非终结符的first集合 250 | if (fSet) { 251 | fSet.forEach(value => { 252 | if (value != E) {//将所有非空字符加入 253 | searchSet.add(value); 254 | } 255 | }); 256 | if (!fSet.has(E)) { 257 | //如果没有E,则不需要再往下搜索 258 | break; 259 | } 260 | } 261 | } else { 262 | searchSet.add(node); 263 | break; 264 | } 265 | } 266 | return searchSet; 267 | } 268 | 269 | function Goto(closure: Closure, recognize: string): Closure {//LR1 Goto函数 270 | //从closureCollection识别一个符号后的新闭包 271 | let newClosure: Closure;//生成的新闭包 272 | let newProductionList = new Array();//需要计算闭包的产生式列表 273 | for (let production of closure.innerSet) { 274 | //遍历该闭包的产生式 275 | if (production.getNowDotAfter() === recognize) { 276 | //如果可以匹配 277 | let newProduction = _.cloneDeep(production);//新建一个产生式 278 | if (newProduction.advance()) {//将该产生式的.前进一位 279 | //如果可以前进 280 | newProductionList.push(newProduction);//将该产生式加入到要计算闭包的产生式列表中 281 | } 282 | } 283 | } 284 | newClosure = calculateClosure(new Closure(newProductionList));//获取由该闭包计算后的新闭包 285 | return newClosure; 286 | } 287 | 288 | //计算文法first集合 289 | function first() { 290 | let flag = true; 291 | let addFirstSet = (key: string, value: string) => { 292 | if (firstSet[key]) { 293 | if (!firstSet[key].has(value)) { 294 | flag = true; 295 | firstSet[key].add(value); 296 | } 297 | } else { 298 | firstSet[key] = new Set([value]); 299 | flag = true; 300 | } 301 | }; 302 | let isV = (value) => { 303 | return vSet.has(value); 304 | }; 305 | while (flag) { 306 | flag = false; 307 | vSet.forEach(key => { 308 | //遍历所有非终结符 309 | let productionList: Array = productions[key];//获取该非终结符所有的产生式 310 | productionList.forEach((production: Production) => { 311 | //遍历所有产生式 312 | let index = 0; 313 | for (let symbol of production.nodeList) { 314 | //遍历该产生式的所有节点 315 | if (isV(symbol)) { 316 | //如果是非终结符 317 | let valueFirstSet: Set = firstSet[symbol]; 318 | if (valueFirstSet) { 319 | //如果集合不为空 320 | if (valueFirstSet.has(E)) { 321 | //如果集合存在E,则需要继续遍历下一个,同时将当前的集合除E外全部加入 322 | valueFirstSet.forEach(value => { 323 | if (value !== E) { 324 | addFirstSet(key, value); 325 | } 326 | }); 327 | if (index === production.nodeList.length - 1) { 328 | //最后一个node了,但任然有E,则加入它 329 | addFirstSet(key, E); 330 | } 331 | } else { 332 | //如果不存在E,则表示不需要遍历下一个,同时将当前的集合除E外全部加入 333 | valueFirstSet.forEach(value => { 334 | addFirstSet(key, value); 335 | }); 336 | break; 337 | } 338 | } else { 339 | //集合为空则退出 340 | break; 341 | } 342 | } else { 343 | //如果是终结符 344 | addFirstSet(key, symbol); 345 | break; 346 | } 347 | index++; 348 | } 349 | }) 350 | }) 351 | } 352 | } 353 | -------------------------------------------------------------------------------- /src/Parser/DataStruct/ASTNode.ts: -------------------------------------------------------------------------------- 1 | //AST节点定义 2 | 3 | export enum NODE_TYPE { 4 | VARIABLE_EXP, 5 | PARAM_LIST,//函数参数列表 6 | VARIABLE_DEF,//模块变量,局部变量或静态变量定义语句 7 | VAR_DEF_STMT,//基础变量声明语句 8 | RETURN_STMT,//返回语句 9 | MODULE_FUN_DECLARATION,//模块函数定义 10 | INNER_FUN_DEF_STMT,//内部函数定义 11 | FUN_DECLARATION,//基础函数定义 12 | ID_EXP,//ID表达式 13 | EXPRESSION_STMT,//表达式语句 14 | IF_STMT,//if语句 15 | WHILE_STMT,//while语句 16 | CALL_EXPRESSION,//函数调用表达式 17 | ARGUMENT_LIST,//实参列表 18 | ARRAY_EXP,//数组表达式 19 | UNARY_OPERATOR, 20 | UNARY_EXP,//一元运算符 21 | BINARY_EXP,//二元运算符 22 | ASSIGN_STMT,//赋值表达式 23 | ARRAY_SUB,//数组下标 24 | LITERAL,//字面量 25 | BLOCK_STMT,//块语句 26 | } 27 | 28 | export enum OPERATOR { 29 | null, 30 | NOT, 31 | ADD, 32 | ADD_ONE, 33 | BIT_NOT, 34 | SUB_ONE, 35 | SUB, 36 | MOD, 37 | DIV, 38 | MUL, 39 | LESS, 40 | LESS_EQUAL, 41 | EQUAL, 42 | NOT_EQUAL, 43 | GREATER, 44 | GREATER_EQUAL, 45 | BIT_AND, 46 | BIT_OR, 47 | LOGIC_OR, 48 | LOGIC_AND 49 | } 50 | 51 | export enum OPERATOR_TYPE { 52 | UNARY_OPERATOR,//单元运算符 53 | ARITHMETIC_OPERATOR,//算数运算符 54 | LOGICAL_OPERATOR,//逻辑运算符 55 | } 56 | 57 | export type Node = 58 | | FunDeclaration 59 | | ArgumentList 60 | | ParamList 61 | | ArraySub 62 | | Operator 63 | | Statement; 64 | 65 | abstract class ASTNode { 66 | //抽象语法树节点接口 67 | abstract readonly nodeType: NODE_TYPE;//节点类型 68 | abstract lineNo: number;//行号 69 | } 70 | 71 | //内部函数的定义节点 72 | export class InnerFunDefStmt implements ASTNode { 73 | readonly nodeType: NODE_TYPE = NODE_TYPE.INNER_FUN_DEF_STMT; 74 | lineNo: number = 0;//行号 75 | private readonly _funDeclaration: FunDeclaration; 76 | private readonly _moduleName: string;//所属的模块名 77 | private readonly _staticFunName: string;//所属的静态函数名 78 | 79 | constructor(funDeclaration: FunDeclaration, moduleName: string, staticFunName: string) { 80 | if (funDeclaration.body){ 81 | funDeclaration.body.clearFather();//内部函数不需要外层 82 | } 83 | this._funDeclaration = funDeclaration; 84 | this._moduleName = moduleName; 85 | this._staticFunName = staticFunName; 86 | } 87 | 88 | getFunName() { 89 | return this._funDeclaration.id; 90 | } 91 | 92 | get funDeclaration(): FunDeclaration { 93 | return this._funDeclaration; 94 | } 95 | 96 | get moduleName(): string { 97 | return this._moduleName; 98 | } 99 | 100 | get staticFunName(): string { 101 | return this._staticFunName; 102 | } 103 | } 104 | 105 | //模块函数的定义节点,区分是静态函数,还是普通函数 106 | export class ModuleFunDefStmt implements ASTNode { 107 | readonly nodeType: NODE_TYPE = NODE_TYPE.MODULE_FUN_DECLARATION; 108 | private readonly _isStatic: boolean; 109 | private readonly _moduleName: string;//所属的模块名 110 | private readonly _funDeclaration: FunDeclaration; 111 | lineNo: number = 0;//行号 112 | 113 | constructor(funDeclaration: FunDeclaration, moduleName: string, isStatic: boolean = false) { 114 | this._moduleName = moduleName; 115 | this._isStatic = isStatic; 116 | this._funDeclaration = funDeclaration; 117 | } 118 | 119 | get moduleName(): string { 120 | return this._moduleName; 121 | } 122 | 123 | getFunName() { 124 | return this._funDeclaration.id; 125 | } 126 | 127 | get isStatic(): boolean { 128 | return this._isStatic; 129 | } 130 | 131 | get funDeclaration(): FunDeclaration { 132 | return this._funDeclaration; 133 | } 134 | } 135 | 136 | //函数定义节点,不区分是何种函数,可以是静态函数、普通函数或内部函数 137 | export class FunDeclaration implements ASTNode { 138 | 139 | readonly nodeType: NODE_TYPE = NODE_TYPE.FUN_DECLARATION; 140 | readonly id: string; 141 | private _params: Array | null = null;//形参列表 142 | private _body: BlockStmt | null = null; 143 | lineNo: number = 0;//行号 144 | 145 | constructor(id: string) { 146 | this.id = id; 147 | } 148 | 149 | get params(): Array | null { 150 | if (this._params) { 151 | return this._params; 152 | } else { 153 | return null 154 | } 155 | } 156 | 157 | set params(value: Array | null) { 158 | this._params = value; 159 | } 160 | 161 | get body(): BlockStmt | null { 162 | return this._body; 163 | } 164 | 165 | set body(value: BlockStmt | null) { 166 | this._body = value; 167 | } 168 | } 169 | 170 | export class ParamList implements ASTNode { 171 | readonly nodeType: NODE_TYPE = NODE_TYPE.PARAM_LIST; 172 | private _params: Array = []; 173 | lineNo: number = 0;//行号 174 | 175 | pushParam(id: string) { 176 | this._params.push(id); 177 | } 178 | 179 | get params(): Array { 180 | return this._params; 181 | } 182 | } 183 | 184 | export class VariableDef implements ASTNode { 185 | readonly nodeType: NODE_TYPE = NODE_TYPE.VARIABLE_DEF; 186 | //默认是局部变量 187 | private _isStatic: boolean;//是否是静态变量 188 | readonly isModuleVar: boolean;//是否是模块变量 189 | readonly VarDefStmt: VarDefStmt;//变量定义语句 190 | lineNo: number = 0;//行号 191 | 192 | 193 | constructor(VarDefStmt: VarDefStmt, isModuleVar: boolean = false, isStatic: boolean = false) { 194 | this._isStatic = isStatic; 195 | this.isModuleVar = isModuleVar; 196 | this.VarDefStmt = VarDefStmt; 197 | } 198 | 199 | get isStatic(): boolean { 200 | return this._isStatic; 201 | } 202 | 203 | set isStatic(value: boolean) { 204 | this._isStatic = value; 205 | } 206 | } 207 | 208 | export class VarDefStmt implements ASTNode { 209 | readonly nodeType: NODE_TYPE = NODE_TYPE.VAR_DEF_STMT; 210 | readonly id: string;//要被声明的变量 211 | readonly init?: Exp | null;//要被初始化的值,默认为null,可以初始化为字面量 212 | lineNo: number = 0;//行号 213 | 214 | constructor(id: string, init?: Exp) { 215 | this.id = id; 216 | this.init = init; 217 | } 218 | } 219 | 220 | export type Statement = 221 | AssignStmt 222 | | Expression 223 | | BlockStmt 224 | | InnerFunDefStmt 225 | | VarDefStmt 226 | | VariableDef 227 | | ReturnStmt 228 | | IfStmt 229 | | WhileStmt 230 | 231 | export class ReturnStmt implements ASTNode { 232 | readonly nodeType: NODE_TYPE = NODE_TYPE.RETURN_STMT; 233 | private readonly _argument: Expression | null = null;//返回值,默认为空 234 | lineNo: number = 0;//行号 235 | 236 | get argument(): Expression | null { 237 | return this._argument; 238 | } 239 | 240 | constructor(argument?: Expression) { 241 | if (argument) { 242 | this._argument = argument; 243 | } 244 | } 245 | } 246 | 247 | export class IfStmt implements ASTNode { 248 | readonly nodeType: NODE_TYPE = NODE_TYPE.IF_STMT; 249 | private readonly _test: Expression;//测试条件 250 | private readonly _consequent: Statement;//测试条件成立,则执行 251 | private _alternate: Statement | null = null;//测试条件不成立,则执行 252 | lineNo: number = 0;//行号 253 | 254 | constructor(test: Expression, consequent: Statement) { 255 | this._test = test; 256 | this._consequent = consequent; 257 | } 258 | 259 | 260 | get test(): Expression { 261 | return this._test; 262 | } 263 | 264 | get consequent(): Statement { 265 | return this._consequent; 266 | } 267 | 268 | get alternate(): Statement | null { 269 | return this._alternate; 270 | } 271 | 272 | set alternate(value: Statement | null) { 273 | this._alternate = value; 274 | } 275 | } 276 | 277 | export class WhileStmt implements ASTNode { 278 | readonly nodeType: NODE_TYPE = NODE_TYPE.WHILE_STMT; 279 | readonly test: Expression;//循环条件 280 | readonly body: Statement;//循环体语句,可以是单个语句,也可以是语句块 281 | lineNo: number = 0;//行号 282 | 283 | constructor(test: Expression, body: Statement) { 284 | this.test = test; 285 | this.body = body; 286 | } 287 | } 288 | 289 | export class BlockStmt implements ASTNode { 290 | readonly nodeType: NODE_TYPE = NODE_TYPE.BLOCK_STMT; 291 | private _body: Array = [];//block的内容 292 | private readonly _blockID: string;//当前block的id 293 | private readonly _blockDepth: number;//当前block的深度 294 | private _fatherBlock: BlockStmt | null;//父block 295 | lineNo: number = 0;//行号 296 | 297 | constructor(blockID: string, blockDepth: number, fatherBlock: BlockStmt | null) { 298 | this._blockID = blockID; 299 | this._blockDepth = blockDepth; 300 | this._fatherBlock = fatherBlock; 301 | } 302 | 303 | 304 | get fatherBlock(): BlockStmt | null { 305 | return this._fatherBlock; 306 | } 307 | 308 | pushStmt(statement: Statement) { 309 | this._body.push(statement); 310 | } 311 | 312 | get body(): Array { 313 | return this._body; 314 | } 315 | 316 | get blockID(): string { 317 | return this._blockID; 318 | } 319 | 320 | get blockDepth(): number { 321 | return this._blockDepth; 322 | } 323 | clearFather(){ 324 | this._fatherBlock = null; 325 | } 326 | } 327 | 328 | export type Expression = 329 | CallExp 330 | | ArrayExp 331 | | IDExp 332 | | BinaryExp 333 | | UnaryExp 334 | | Literal 335 | | VariableExp 336 | | Exp 337 | 338 | 339 | export class Exp implements ASTNode { 340 | readonly nodeType: NODE_TYPE = NODE_TYPE.EXPRESSION_STMT; 341 | readonly exp: Expression; 342 | lineNo: number = 0;//行号 343 | 344 | constructor(exp: Expression) { 345 | this.exp = exp; 346 | } 347 | } 348 | 349 | export class ArgumentList implements ASTNode { 350 | readonly nodeType: NODE_TYPE = NODE_TYPE.ARGUMENT_LIST; 351 | private _args: Array = []; 352 | lineNo: number = 0;//行号 353 | 354 | pushArgs(exp: Expression) { 355 | this._args.push(exp); 356 | } 357 | 358 | get args(): Array { 359 | return this._args; 360 | } 361 | } 362 | 363 | export class CallExp implements ASTNode { 364 | readonly nodeType: NODE_TYPE = NODE_TYPE.CALL_EXPRESSION; 365 | readonly callee: IDExp;//使用IDExp来代表ID链 366 | private _args: ArgumentList;//实参列表节点 367 | lineNo: number = 0;//行号 368 | 369 | constructor(callee: IDExp, argumentList: ArgumentList) { 370 | this.callee = callee; 371 | this._args = argumentList; 372 | } 373 | 374 | get argList(): Array { 375 | return this._args.args; 376 | } 377 | } 378 | 379 | 380 | 381 | export class ArraySub implements ASTNode { 382 | readonly nodeType: NODE_TYPE = NODE_TYPE.ARRAY_SUB; 383 | private _arraySub: Array = []; 384 | lineNo: number = 0;//行号 385 | 386 | pushSub(exp: Exp) { 387 | this._arraySub.push(exp) 388 | } 389 | 390 | get arraySub(): Array { 391 | return this._arraySub; 392 | } 393 | } 394 | 395 | 396 | export class ArrayExp implements ASTNode { 397 | readonly nodeType: NODE_TYPE = NODE_TYPE.ARRAY_EXP; 398 | private _elements: Array = [];//表示数组元素列表 399 | lineNo: number = 0;//行号 400 | 401 | pushElement(el: Expression) { 402 | this._elements.push(el); 403 | } 404 | 405 | get elements(): Array { 406 | return this._elements; 407 | } 408 | } 409 | 410 | export enum ID_TYPE { 411 | GENERAL_ID,//普通的id,单个的 412 | GENERAL_ID_LIST,//普通ID链表 413 | AT_ID,//如果有前缀AT,就代表是可能是对静态变量的访问,也可能是对内部函数的访问 414 | MODULE_ID//如果有中缀::,就代表是外部模块的变量或函数,那么ID链表中的第一个ID就是模块名,后面的就是相关的ID引用 415 | } 416 | 417 | export class IDExp implements ASTNode { 418 | readonly nodeType: NODE_TYPE = NODE_TYPE.ID_EXP; 419 | private _idList: Array = new Array();//ID链 420 | private _idType: ID_TYPE; 421 | lineNo: number = 0;//行号 422 | 423 | constructor(idName: string) { 424 | this._idList.push(idName); 425 | this._idType = ID_TYPE.GENERAL_ID 426 | } 427 | 428 | pushID(idName: string) { 429 | this._idList.unshift(idName);//注意:此处是逆序加入 430 | } 431 | 432 | 433 | get idList(): Array { 434 | return this._idList; 435 | } 436 | 437 | set idType(value: ID_TYPE) { 438 | //只可以对当前idType为general时才可以设置 439 | this._idType = value; 440 | } 441 | 442 | get idType(): ID_TYPE { 443 | return this._idType; 444 | } 445 | } 446 | 447 | export class VariableExp implements ASTNode { 448 | readonly nodeType: NODE_TYPE = NODE_TYPE.VARIABLE_EXP; 449 | private readonly _idExp: IDExp; 450 | private readonly _arraySub?: Array; 451 | lineNo: number = 0;//行号 452 | 453 | constructor(_varName: IDExp, arraySub?: ArraySub) { 454 | this._idExp = _varName; 455 | if (arraySub) { 456 | this._arraySub = arraySub.arraySub; 457 | } 458 | } 459 | 460 | get arraySub(): any { 461 | return this._arraySub; 462 | } 463 | 464 | get idExp(): IDExp { 465 | return this._idExp; 466 | } 467 | } 468 | 469 | export class AssignStmt implements ASTNode { 470 | readonly nodeType: NODE_TYPE = NODE_TYPE.ASSIGN_STMT; 471 | readonly left: VariableExp; 472 | readonly right: Expression; 473 | lineNo: number = 0;//行号 474 | 475 | constructor(left: VariableExp, right: Expression) { 476 | this.left = left; 477 | this.right = right; 478 | } 479 | } 480 | 481 | export type ArithmeticOperator = 482 | OPERATOR.ADD 483 | | OPERATOR.SUB 484 | | OPERATOR.MUL 485 | | OPERATOR.DIV 486 | | OPERATOR.MOD 487 | | OPERATOR.BIT_OR 488 | | OPERATOR.BIT_AND ; 489 | 490 | export type LogicalOperator = 491 | OPERATOR.EQUAL 492 | | OPERATOR.NOT_EQUAL 493 | | OPERATOR.LESS 494 | | OPERATOR.LESS_EQUAL 495 | | OPERATOR.GREATER 496 | | OPERATOR.GREATER_EQUAL 497 | | OPERATOR.LOGIC_OR 498 | | OPERATOR.LOGIC_AND; 499 | 500 | export type UnaryOperator = OPERATOR.NOT | OPERATOR.ADD_ONE | OPERATOR.SUB_ONE | OPERATOR.BIT_NOT ; 501 | 502 | export class Operator implements ASTNode { 503 | readonly nodeType: NODE_TYPE = NODE_TYPE.UNARY_OPERATOR; 504 | readonly operatorType: OPERATOR_TYPE; 505 | readonly unaryOperator?: UnaryOperator; 506 | readonly logicOperator?: LogicalOperator; 507 | readonly arithmeticOperator?: ArithmeticOperator; 508 | lineNo: number = 0;//行号 509 | 510 | constructor(operatorType: OPERATOR_TYPE, operator: OPERATOR) { 511 | this.operatorType = operatorType; 512 | switch (operatorType) { 513 | case OPERATOR_TYPE.ARITHMETIC_OPERATOR: 514 | this.arithmeticOperator = operator; 515 | break; 516 | case OPERATOR_TYPE.LOGICAL_OPERATOR: 517 | this.logicOperator = operator; 518 | break; 519 | case OPERATOR_TYPE.UNARY_OPERATOR: 520 | this.unaryOperator = operator; 521 | break; 522 | } 523 | } 524 | } 525 | 526 | export class UnaryExp implements ASTNode { 527 | //一元运算 528 | readonly nodeType: NODE_TYPE = NODE_TYPE.UNARY_EXP; 529 | private _operator?: Operator; 530 | private _isPreOperator: boolean = false; 531 | readonly argument: Expression; 532 | lineNo: number = 0;//行号 533 | 534 | constructor(argument: Expression, operator?: Operator) { 535 | this._operator = operator; 536 | this.argument = argument; 537 | } 538 | 539 | get isPreOperator(): boolean { 540 | return this._isPreOperator; 541 | } 542 | 543 | set isPreOperator(value: boolean) { 544 | this._isPreOperator = value; 545 | } 546 | 547 | setOperator(operator: Operator) { 548 | this._operator = operator 549 | } 550 | 551 | get operator(): Operator | null { 552 | if (this._operator) { 553 | return this._operator; 554 | } 555 | return null; 556 | } 557 | } 558 | 559 | 560 | export class BinaryExp implements ASTNode { 561 | //二元算数运算 562 | readonly nodeType: NODE_TYPE = NODE_TYPE.BINARY_EXP; 563 | readonly operator: Operator; 564 | readonly left: Expression; 565 | readonly right: Expression; 566 | lineNo: number = 0;//行号 567 | 568 | constructor(operator: Operator, left: Expression, right: Expression) { 569 | this.operator = operator; 570 | this.left = left; 571 | this.right = right; 572 | } 573 | } 574 | 575 | export class Literal implements ASTNode { 576 | //字面量 577 | readonly nodeType: NODE_TYPE = NODE_TYPE.LITERAL; 578 | readonly value: string | boolean | number | null;//字面量的值 579 | lineNo: number = 0;//行号 580 | 581 | constructor(value: string | boolean | number | null) { 582 | this.value = value; 583 | } 584 | } -------------------------------------------------------------------------------- /src/Interpreter/Index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020. yaser. All rights reserved 3 | * Description: 解释器 4 | */ 5 | import {cleanInterpreter, getInterpreter, Interpreter} from "./DataStruct/Interpreter"; 6 | import {createFunByFunDefStmt, FUN_CLASSES, FUN_TYPE, GeneralFun, InnerFun, StaticFun} from "./DataStruct/Fun"; 7 | import {Stack} from "../Parser/DataStruct/Stack"; 8 | import {cleanGlobalSymbolTable, getGlobalSymbolTable, GlobalSymbolTable} from "./DataStruct/SymbolTable"; 9 | import {printInfo, printInterpreterError} from "../Log"; 10 | import { 11 | ArithmeticOperator, 12 | ArrayExp, 13 | AssignStmt, 14 | BinaryExp, 15 | BlockStmt, 16 | CallExp, 17 | Exp, 18 | Expression, 19 | ID_TYPE, 20 | IDExp, 21 | IfStmt, 22 | InnerFunDefStmt, 23 | Literal, 24 | LogicalOperator, 25 | ModuleFunDefStmt, 26 | NODE_TYPE, 27 | OPERATOR, 28 | OPERATOR_TYPE, 29 | ReturnStmt, 30 | Statement, 31 | UnaryExp, 32 | VarDefStmt, 33 | VariableDef, 34 | VariableExp, 35 | WhileStmt 36 | } from "../Parser/DataStruct/ASTNode"; 37 | import {getValueType, IDWrap, Variable, VARIABLE_TYPE, VariableMeta} from "./DataStruct/Variable"; 38 | import {QSModule} from "./DataStruct/Module"; 39 | import {QSFunMap, runLib} from "../QSLib"; 40 | import {Reference} from "./DataStruct/Reference"; 41 | import {Complexus} from "./DataStruct/Complexus"; 42 | 43 | let _ = require("lodash"); 44 | let runTimeStack = new Stack();//运行时栈 45 | let funRunTimeStack = new Stack();//函数运行时栈 46 | let interpreter: Interpreter; 47 | let symbolTable: GlobalSymbolTable; 48 | 49 | export function getCurRunningModule() { 50 | if (interpreter.curModule) { 51 | return interpreter.curModule.moduleName; 52 | } 53 | } 54 | 55 | /** 56 | * 测试待获取的id是否可以使用,如果不可使用,则直接退出解释器 57 | * 可以使用需要满足三个条件 58 | * 1. 指定模块是否在当前模块中导入 59 | * 2. 这些变量或函数是否进行了导出 60 | * 3. 指定模块是否进行了加载 61 | * @param moduleName 62 | * @param idName 待获取的id 63 | */ 64 | 65 | function testIdIsAvailable(moduleName: string, idName: string) { 66 | const targetModule = getModuleByName(moduleName);//获取目标模块 67 | if (curModule().moduleHasImport(moduleName)) {//检查当前模块是否导入目标模块 68 | if (targetModule.hasExport(idName)) {//检查目标模块是否导出 69 | if (!targetModule.hasLoad) { 70 | //如果模块没有加载,则执行加载操作 71 | loadModule(moduleName); 72 | } 73 | } else { 74 | printInterpreterError(`模块${moduleName}没有导出成员${idName}!`); 75 | } 76 | } else { 77 | printInterpreterError(`模块${moduleName}没有导入!`); 78 | } 79 | } 80 | 81 | /** 82 | * 统一的变量获取函数 83 | * @param idWrap 待获取的变量信息 84 | */ 85 | function getVariable(idWrap: IDWrap): Variable | null { 86 | let variable: Variable | null = null; 87 | let varName: string = idWrap.idName;//获取变量名 88 | let moduleName = curModuleName(); 89 | const idModuleName = idWrap.moduleName; 90 | if (idModuleName === moduleName) {//如果模块名一致 91 | //从当前函数的符号表中获取 92 | let fun = curFun(); 93 | if (fun) { 94 | //如果处于函数内部,则先从函数内获取变量 95 | if (idWrap.hasAt) { 96 | //如果有@前缀,说明要获取的是一个静态变量 97 | if (fun instanceof InnerFun) { 98 | //是内部函数 99 | variable = fun.getStaticVariable(); 100 | } else { 101 | printInterpreterError(`当前函数${fun.funName}不是一个内部函数,只有在内部函数中才可以访问静态变量!`); 102 | } 103 | } else { 104 | //如果当前在函数内,则从函数符号表中获取变量 105 | variable = fun.getLocalVariable(varName, curBlock()); 106 | } 107 | } 108 | } else { 109 | //如果模块名不同,则需要测试指定模块是否已加载 110 | moduleName = idModuleName; 111 | testIdIsAvailable(idModuleName, varName); 112 | } 113 | if (!variable) { 114 | //从全局符号表中获取 115 | variable = symbolTable.getVariableSymbol(moduleName, varName); 116 | } 117 | return variable; 118 | } 119 | 120 | //获取普通函数、静态函数与内部函数 121 | function getFun(funIDWrap: IDWrap): FUN_CLASSES | null { 122 | if (funIDWrap.referenceList.length > 0) { 123 | //如果引用链的长度大于0,说明调用的是复合体的内部函数 124 | //先从符号表中获取复合体 125 | let variable = getVariable(funIDWrap); 126 | if (variable) { 127 | //变量存在 128 | let complexus = variable.getValue(); 129 | if (complexus instanceof Complexus) { 130 | //是一个复合体变量 131 | const {brotherComplexus, innerFun} = complexus.getInnerFunAndBotherData(funIDWrap.referenceList); 132 | if (innerFun instanceof InnerFunDefStmt) { 133 | return createFunByFunDefStmt(innerFun, brotherComplexus); 134 | } 135 | } 136 | } 137 | return null; 138 | } 139 | 140 | 141 | let moduleFun: StaticFun | GeneralFun | null; 142 | let funModuleName: string = funIDWrap.moduleName; 143 | const funName = funIDWrap.idName; 144 | if (funModuleName === curModuleName()) {//与当前模块名一致,也就是说是在当前模块中 145 | moduleFun = curModule().createModuleFunByFunName(funName);//获取函数AST 146 | } else { 147 | //与当前模块名不一致 148 | testIdIsAvailable(funModuleName, funName);//测试是否可用 149 | moduleFun = getModuleByName(funModuleName).createModuleFunByFunName(funName);//获取函数AST 150 | } 151 | 152 | return moduleFun; 153 | } 154 | 155 | function pushToStack(value) { 156 | runTimeStack.push(value); 157 | } 158 | 159 | function popFromStack() { 160 | return runTimeStack.pop(); 161 | } 162 | 163 | const curBlock = (): BlockStmt => { 164 | return interpreter.curBlock; 165 | }; 166 | const curModuleName = (): string => { 167 | //@ts-ignore 168 | return interpreter.curModule.moduleName; 169 | }; 170 | const curModule = (): QSModule => { 171 | //@ts-ignore 172 | return interpreter.curModule 173 | }; 174 | 175 | const curFun = (): FUN_CLASSES => { 176 | return interpreter.curFun; 177 | }; 178 | const curFunType = (): FUN_TYPE => { 179 | //@ts-ignore 180 | return interpreter.curFun.funType 181 | } 182 | 183 | const wrapToVariableMeta = (valueOrReference: any = null, type: VARIABLE_TYPE = VARIABLE_TYPE.NULL, varName?: string): VariableMeta => { 184 | return new VariableMeta(type, valueOrReference, varName); 185 | }; 186 | const nullValue: VariableMeta = wrapToVariableMeta(); 187 | 188 | //@ts-ignore 189 | let getModuleByName = (moduleName: string): QSModule => { 190 | let qsModule = interpreter.getModuleByName(moduleName); 191 | if (qsModule) { 192 | return qsModule; 193 | } else { 194 | printInterpreterError(moduleName + "模块缺失!"); 195 | } 196 | }; 197 | 198 | export function runInterpreter() { 199 | printInfo("开始执行!"); 200 | printInfo("====================代码执行区输出====================", false); 201 | console.log("\n"); 202 | interpreter = getInterpreter(); 203 | symbolTable = getGlobalSymbolTable(); 204 | if (interpreter.enter) { 205 | let mainFunDefStmt = interpreter.enter;//获取main节点 206 | const moduleName = mainFunDefStmt.moduleName; 207 | loadModule(moduleName);//加载指定模块 208 | switchToModule(moduleName);//切换到main函数所在的module 209 | createAndPushFun(mainFunDefStmt);//构建main函数 210 | runFun();//执行main函数 211 | popAndSetFun();//执行完成,弹出main函数 212 | } else { 213 | printInterpreterError("缺少main函数!"); 214 | } 215 | console.log("\n"); 216 | printInfo("====================代码执行区输出====================", false); 217 | cleanInterpreter(); 218 | cleanGlobalSymbolTable(); 219 | } 220 | 221 | //构建函数 222 | function createFun(funDefStmt: ModuleFunDefStmt) { 223 | return createFunByFunDefStmt(funDefStmt);//构建fun 224 | } 225 | 226 | function pushFun(fun: FUN_CLASSES) { 227 | funRunTimeStack.push(fun);//将fun压栈 228 | interpreter.curFun = fun;//设置当前fun 229 | } 230 | 231 | function createAndPushFun(funDefStmt: ModuleFunDefStmt) { 232 | pushFun(createFun(funDefStmt)); 233 | } 234 | 235 | /** 236 | * 弹出函数,并将下一个函数设置为当前函数(如果存在的话) 237 | */ 238 | function popAndSetFun() { 239 | //从运行时栈中拿出当前fun,并销毁 240 | if (!funRunTimeStack.isEmpty()) { 241 | funRunTimeStack.pop(); 242 | if (!funRunTimeStack.isEmpty()) { 243 | const fun = funRunTimeStack.peek(); 244 | if (fun && fun.moduleName === curModuleName()) {//如果函数存在,且是当前模块的函数 245 | interpreter.curFun = fun;//设置当前fun 246 | return; 247 | } 248 | } 249 | } 250 | interpreter.curFun = null;//设置为null 251 | } 252 | 253 | /** 254 | * 切换到目标模块,并保存当前上下文环境 255 | * @param moduleName 目标模块 256 | */ 257 | function switchToModule(moduleName: string) { 258 | if (curModule()) {//如果当前存在模块 259 | pushToStack(curModule());//将当前模块压栈 260 | } 261 | interpreter.curFun = null;//切换到新的模块后,当前函数应为null,因为函数都保存在函数栈中,所以不需要再次保存 262 | let nowModule = getModuleByName(moduleName);//获取要切换的module 263 | interpreter.setCurModule(nowModule);//设置当前module 264 | } 265 | 266 | /** 267 | * 恢复到之前的模块 268 | */ 269 | function recoverModule() { 270 | let preModule = popFromStack(); 271 | if (preModule instanceof QSModule) { 272 | interpreter.setCurModule(preModule);//恢复模块 273 | } else { 274 | printInterpreterError("运行时错误,模块恢复失败!"); 275 | } 276 | const fun = funRunTimeStack.peek(); 277 | if (fun && fun.moduleName === curModuleName()) { 278 | interpreter.curFun = fun;//恢复函数 279 | } 280 | } 281 | 282 | function loadModule(moduleName: string) { 283 | //加载指定模块,并将所有的模块变量做初始化操作 284 | const preModule = curModule(); 285 | switchToModule(moduleName);//切换到目标模块 286 | let nowModule = curModule(); 287 | if (!nowModule.hasLoad) { 288 | //如果没有加载 289 | nowModule.moduleVar.forEach(varName => {//对所有模块变量进行逐个初始化操作 290 | let idWrap = new IDWrap(varName, nowModule.moduleName); 291 | let variable = getVariable(idWrap);//获取要初始化的模块变量 292 | if (variable) { 293 | let initExp = variable.initModuleVar();//将该变量初始化为模块变量 294 | if (initExp) { 295 | variable.setValue(runExpression(initExp));//给模块变量赋值 296 | } 297 | } else { 298 | printInterpreterError(`模块${moduleName}没有${varName}模块变量!`); 299 | } 300 | }); 301 | nowModule.hasLoad = true;//将模块标记为加载完成。 302 | } 303 | if (preModule) { 304 | //如果之前的模块存在,则进行恢复,否则不处理 305 | recoverModule();//加载完成,切换为原来的模块 306 | } 307 | } 308 | 309 | function runFun(): VariableMeta { 310 | //执行函数,要执行的函数可能有三种,普通函数、静态函数和内部函数 311 | //读取当前函数的参数 312 | let nowFun: FUN_CLASSES = curFun(); 313 | 314 | let block = nowFun.funBlock; 315 | if (block) { 316 | for (let i = 0; i < nowFun.paramList.length; i++) {//读取函数的实参,并添加到函数的符号表下 317 | let variableMeta = popFromStack(); 318 | variableMeta.varName = nowFun.paramList[i]; 319 | //每读取一个实参,就将其保存到符号表中 320 | nowFun.pushVariable(block, variableMeta); 321 | } 322 | runBlockStmt(block);//执行block中的语句 323 | //读取返回值 324 | if (curFun().returnValue) { 325 | //如果有值,则直接返回 326 | return curFun().returnValue; 327 | } else { 328 | //如果没有值,则包装一个null值 329 | return nullValue; 330 | } 331 | } 332 | printInterpreterError(nowFun.funName + "函数体缺失!"); 333 | return nullValue; 334 | } 335 | 336 | let statementExecutorMap = { 337 | [NODE_TYPE.ASSIGN_STMT]: runAssignStmt, 338 | [NODE_TYPE.BLOCK_STMT]: runBlockStmt, 339 | [NODE_TYPE.INNER_FUN_DEF_STMT]: runInnerFunDefStmt, 340 | // [NODE_TYPE.VAR_DEF_STMT]: runVarDefStmt, 341 | [NODE_TYPE.VARIABLE_DEF]: runVariableDefStmt, 342 | [NODE_TYPE.RETURN_STMT]: runReturnStmt, 343 | [NODE_TYPE.IF_STMT]: runIfStmt, 344 | [NODE_TYPE.WHILE_STMT]: runWhileStmt, 345 | [NODE_TYPE.EXPRESSION_STMT]: runExpression 346 | }; 347 | 348 | function runStmt(statement: Statement): boolean { 349 | let runner = statementExecutorMap[statement.nodeType];//获取执行器 350 | runner(statement);//执行 351 | 352 | if (curFun().hasRearOperator()) { 353 | //如果有后置运算,则执行 354 | executeRearOperation() 355 | } 356 | if (curFunType() !== FUN_TYPE.STATIC) { 357 | //如果不是静态函数 358 | return curFun().returnValue;//返回是否存在返回值 359 | } 360 | //如果是静态函数,则永远不返回值 361 | return false; 362 | } 363 | 364 | function runBlockStmt(block: BlockStmt) { 365 | let body = block.body; 366 | pushToStack(interpreter.curBlock);//保存当前block 367 | interpreter.curBlock = block;//切换Block 368 | for (let index = 0; index < body.length; index++) { 369 | let statement: Statement = body[index];//获取block中的语句 370 | if (runStmt(statement)) { 371 | break; 372 | } 373 | } 374 | let fun = curFun(); 375 | if (fun){ 376 | //如果当前是在函数下,那么需要先将该block下的变量全部清除 377 | fun.cleanBlockVariable(block); 378 | } 379 | interpreter.curBlock = popFromStack();//恢复当前block 380 | } 381 | 382 | function runAssignStmt(assignStmt: AssignStmt) { 383 | let leftVariable: VariableMeta = runVariableExp(assignStmt.left);//获取左值 384 | let rightValue: VariableMeta = runExpression(assignStmt.right);//获取右值 385 | 386 | //判断左值variable是否为对一个变量的引用 387 | if (leftVariable.type === VARIABLE_TYPE.REFERENCE && leftVariable.reference) { 388 | //对引用的变量进行赋值 389 | leftVariable.reference.setReferenceValue(rightValue); 390 | } 391 | } 392 | 393 | function runInnerFunDefStmt(innerFunDefStmt: InnerFunDefStmt) { 394 | const fun = curFun(); 395 | 396 | if (fun instanceof StaticFun) { 397 | //当前处于静态函数内部 398 | fun.getComplexus().setInnerFun(innerFunDefStmt);//将静态变量的值添加到复合体上 399 | } else { 400 | printInterpreterError("内部函数只可在静态函数内定义!"); 401 | } 402 | } 403 | 404 | //定义变量 405 | function runVariableDefStmt(variableDef: VariableDef) { 406 | const variableMeta = runVarDefStmt(variableDef.VarDefStmt); 407 | const fun = curFun(); 408 | if (variableDef.isStatic) { 409 | //如果是静态变量 410 | if (fun instanceof StaticFun) { 411 | let variable = new Variable(curModuleName()); 412 | variable.setValue(variableMeta) 413 | fun.getComplexus().setStaticVar(variable);//将静态变量的值添加到复合体上 414 | } else { 415 | printInterpreterError("静态变量只可在静态函数内定义!"); 416 | } 417 | } else { 418 | fun.pushVariable(curBlock(), variableMeta); 419 | } 420 | } 421 | 422 | function runVarDefStmt(varDefStmt: VarDefStmt): VariableMeta { 423 | let varName = varDefStmt.id; 424 | let initExp = varDefStmt.init; 425 | let variableMeta: VariableMeta = wrapToVariableMeta(null, VARIABLE_TYPE.NULL, varName); 426 | if (initExp) { 427 | //存在初始值 428 | variableMeta = runExpression(initExp);//可能返回回来的是一个引用 429 | variableMeta.varName = varName; 430 | } 431 | return variableMeta; 432 | } 433 | 434 | function runReturnStmt(returnStmt: ReturnStmt) { 435 | if (returnStmt.argument) { 436 | curFun().returnValue = _.cloneDeep(runExpression(returnStmt.argument)); 437 | } else { 438 | curFun().returnValue = wrapToVariableMeta(); 439 | } 440 | } 441 | 442 | function runIfStmt(ifStmt: IfStmt) { 443 | //读取测试条件 444 | let testVal = runExpression(ifStmt.test);//获取结果值 445 | let statement;//要执行的语句 446 | if (testVal.value) { 447 | statement = ifStmt.consequent; 448 | } else { 449 | statement = ifStmt.alternate;//可能为null 450 | } 451 | if (statement) { 452 | runStmt(statement) 453 | } 454 | } 455 | 456 | 457 | function runWhileStmt(whileStmt: WhileStmt) { 458 | let getTestRes = () => { 459 | let testRes: VariableMeta = runExpression(whileStmt.test); 460 | return testRes.value 461 | }; 462 | while (getTestRes()) { 463 | runStmt(whileStmt.body); 464 | } 465 | } 466 | 467 | let expressionExecutorMap = { 468 | [NODE_TYPE.CALL_EXPRESSION]: runCallExp, 469 | [NODE_TYPE.ARRAY_EXP]: runArrayExp, 470 | [NODE_TYPE.BINARY_EXP]: runBinaryExp, 471 | [NODE_TYPE.UNARY_EXP]: runUnaryExp, 472 | [NODE_TYPE.LITERAL]: runLiteral, 473 | [NODE_TYPE.VARIABLE_EXP]: runVariableExp, 474 | [NODE_TYPE.EXPRESSION_STMT]: runExpression 475 | }; 476 | 477 | //对exp进行拆分 478 | function runExpression(exp: Expression): VariableMeta { 479 | //根据exp的类型执行不同的表达式 480 | if (exp instanceof Exp) { 481 | let expExecutor = expressionExecutorMap[exp.exp.nodeType]; 482 | return expExecutor(exp.exp); 483 | } else { 484 | let expExecutor = expressionExecutorMap[exp.nodeType]; 485 | return expExecutor(exp); 486 | } 487 | } 488 | 489 | function runCallExp(callExp: CallExp): VariableMeta { 490 | //构造要调用的函数,并保存该函数到栈中 491 | let funIDWrap: IDWrap = runIDExp(callExp.callee); 492 | if (funIDWrap.hasAt) { 493 | //存在有AT前缀,则是在静态函数里调用内部函数 494 | if (curFunType() !== FUN_TYPE.INNER) { 495 | //不在内部函数中 496 | printInterpreterError("只有在内部函数中,可以使用前缀@来对内部函数进行调用", callExp.lineNo) 497 | } 498 | } 499 | //调用的可能是普通函数,静态函数或内部函数 500 | let fun: GeneralFun | StaticFun | InnerFun | null = getFun(funIDWrap);//获取并构造fun 501 | //获取到了函数 502 | let args: Array = []; 503 | //计算所有实参的值,并转化为值类型的表示法 504 | callExp.argList.forEach(argExp => { 505 | args.push(runExpression(argExp)); 506 | }); 507 | if (fun) { 508 | //如果存在,也就是说不是原生函数 509 | if (fun.paramList.length === callExp.argList.length) { 510 | //函数存在,且参数匹配 511 | let hasSwitch: boolean = false; 512 | //判断要执行的函数是否在当前模块下,如果是则直接运行,不是则需要切换模块。 513 | if (fun.moduleName !== curModuleName()) { 514 | //模块名不同,说明不处于当前模块下,需要切换模块 515 | hasSwitch = true; 516 | switchToModule(fun.moduleName); 517 | } 518 | while (args.length > 0) { 519 | pushToStack(args.pop());//将实参从右至左压入栈中,栈顶为最左边的元素 520 | } 521 | pushFun(fun);//压入栈 522 | //调用函数执行,并获取返回结果 523 | let value = runFun(); 524 | //恢复上下文环境 525 | popAndSetFun(); 526 | if (hasSwitch) { 527 | //如果切换过模块,则进行恢复,否则不处理 528 | recoverModule();//加载完成,切换为原来的模块 529 | } 530 | return value;//返回执行结果 531 | } else { 532 | printInterpreterError(callExp.callee + "函数在调用时的实参与定义的形参个数不匹配!", callExp.lineNo); 533 | return nullValue; 534 | } 535 | } else { 536 | //处理原生函数 537 | let libCall = QSFunMap[funIDWrap.idName]; 538 | if (libCall) { 539 | //如果是原生函数 540 | let value = runLib(libCall, args); 541 | if (value !== undefined) { 542 | //如果有值 543 | return wrapToVariableMeta(value, getValueType(value)); 544 | } else { 545 | return nullValue; 546 | } 547 | } else { 548 | //既不是原生函数也不是自定义函数 549 | printInterpreterError(callExp.callee + "函数未定义 ", callExp.lineNo); 550 | return nullValue; 551 | } 552 | } 553 | } 554 | 555 | function runArrayExp(arrayExp: ArrayExp) { 556 | //计算array里的数值内容 557 | let array: Array = []; 558 | for (let i = arrayExp.elements.length - 1; i >= 0; i--) { 559 | array.push(runExpression(arrayExp.elements[i]).value) 560 | } 561 | return wrapToVariableMeta(array, VARIABLE_TYPE.ARRAY) 562 | } 563 | 564 | function handleArithmetic(left: VariableMeta, right: VariableMeta, operatorType: ArithmeticOperator): VariableMeta { 565 | let resValue: VariableMeta = wrapToVariableMeta();//默认为null 566 | switch (operatorType) { 567 | case OPERATOR.ADD: 568 | resValue.value = left.value + right.value; 569 | break; 570 | case OPERATOR.BIT_AND: 571 | resValue.value = left.value & right.value; 572 | break; 573 | case OPERATOR.BIT_OR: 574 | resValue.value = left.value | right.value; 575 | break; 576 | case OPERATOR.DIV: 577 | resValue.value = left.value / right.value; 578 | break; 579 | case OPERATOR.MOD: 580 | resValue.value = left.value % right.value; 581 | break; 582 | case OPERATOR.MUL: 583 | resValue.value = left.value * right.value; 584 | break; 585 | case OPERATOR.SUB: 586 | resValue.value = left.value - right.value; 587 | break; 588 | default: 589 | printInterpreterError(operatorType + "未定义的运算符!") 590 | } 591 | resValue.type = getValueType(resValue.value); 592 | return resValue; 593 | } 594 | 595 | function handleLogic(left: VariableMeta, right: VariableMeta, operatorType: LogicalOperator): VariableMeta { 596 | let resValue: VariableMeta = wrapToVariableMeta();//默认为null 597 | switch (operatorType) { 598 | case OPERATOR.EQUAL: 599 | resValue.value = left.value === right.value; 600 | break; 601 | case OPERATOR.GREATER: 602 | resValue.value = left.value > right.value; 603 | break; 604 | case OPERATOR.GREATER_EQUAL: 605 | resValue.value = left.value >= right.value; 606 | break; 607 | case OPERATOR.LESS: 608 | resValue.value = left.value < right.value; 609 | break; 610 | case OPERATOR.LESS_EQUAL: 611 | resValue.value = left.value <= right.value; 612 | break; 613 | case OPERATOR.LOGIC_AND: 614 | resValue.value = left.value && right.value; 615 | break; 616 | case OPERATOR.LOGIC_OR: 617 | resValue.value = left.value || right.value; 618 | break; 619 | case OPERATOR.NOT_EQUAL: 620 | resValue.value = left.value !== right.value; 621 | break; 622 | default: 623 | printInterpreterError(operatorType + "未定义的运算符!") 624 | } 625 | resValue.type = getValueType(resValue.value); 626 | return resValue; 627 | } 628 | 629 | function runBinaryExp(binaryExp: BinaryExp): VariableMeta { 630 | let left: VariableMeta = runExpression(binaryExp.left); 631 | let right: VariableMeta = runExpression(binaryExp.right); 632 | switch (binaryExp.operator.operatorType) { 633 | case OPERATOR_TYPE.LOGICAL_OPERATOR: 634 | return handleLogic(left, right, binaryExp.operator.logicOperator); 635 | case OPERATOR_TYPE.ARITHMETIC_OPERATOR: 636 | return handleArithmetic(left, right, binaryExp.operator.arithmeticOperator); 637 | default: 638 | printInterpreterError(binaryExp.operator + "未定义的运算符!", binaryExp.lineNo); 639 | return nullValue; 640 | } 641 | } 642 | 643 | function executeRearOperation() { 644 | //执行后置运算操作 645 | while (curFun().hasRearOperator()) { 646 | let variableMeta = curFun().subRearOperator(); 647 | variableMeta.setValueToReference(); 648 | } 649 | } 650 | 651 | function addRearOperation(variableMeta: VariableMeta) { 652 | //添加后置运算 653 | curFun().addRearOperator(variableMeta); 654 | } 655 | 656 | function runUnaryExp(unaryExp: UnaryExp): VariableMeta { 657 | let operand: VariableMeta = runExpression(unaryExp.argument);//获取操作数 658 | let referencedVar: Variable | null = null;//被引用的变量 659 | if (operand.reference) { 660 | referencedVar = operand.reference.referencedVar 661 | } 662 | if (unaryExp.operator) { 663 | //如果存在运算符 664 | let operator = unaryExp.operator.unaryOperator; 665 | let selfOperator = false;//是否是自运算 666 | //使用运算符进行运算操作 667 | if (operator) { 668 | switch (operator) { 669 | case OPERATOR.ADD_ONE: 670 | if (referencedVar) { 671 | //只有是对变量的引用才能进行自增操作 672 | selfOperator = true; 673 | operand.value++; 674 | } else { 675 | //报错 676 | printInterpreterError("只有变量才能进行自增操作", unaryExp.lineNo); 677 | } 678 | break; 679 | case OPERATOR.BIT_NOT: 680 | operand.value = ~operand.value; 681 | break; 682 | case OPERATOR.NOT: 683 | operand.value = !operand.value; 684 | break; 685 | case OPERATOR.SUB_ONE: 686 | if (operand.reference) { 687 | //只有变量才能进行自减操作 688 | selfOperator = true; 689 | operand.value--; 690 | } else { 691 | //报错 692 | printInterpreterError("只有变量才能进行自减操作", unaryExp.lineNo); 693 | } 694 | break; 695 | } 696 | if (operand.type !== VARIABLE_TYPE.REFERENCE) { 697 | operand.type = getValueType(operand.value); 698 | } 699 | if (selfOperator && referencedVar) { 700 | //如果是自运算操作,且运算对象是变量 701 | if (!unaryExp.isPreOperator) { 702 | //后置运算打标记,并将要进行的后置运算加入栈中 703 | addRearOperation(_.clone(operand)); 704 | //恢复值 705 | operand.value = referencedVar.getValue(); 706 | operand.type = referencedVar.variableType; 707 | } else { 708 | //前置运算,直接赋值 709 | operand.setValueToReference() 710 | } 711 | } 712 | } 713 | } 714 | return operand; 715 | } 716 | 717 | 718 | function runLiteral(literal: Literal): VariableMeta { 719 | let value = literal.value; 720 | return wrapToVariableMeta(value, getValueType(value)); 721 | } 722 | 723 | 724 | function runIDExp(idExp: IDExp): IDWrap { 725 | let referenceIndex = new Array();//引用链 726 | const hasAt = idExp.idType === ID_TYPE.AT_ID;//是否有AT, 727 | let index = 0; 728 | let moduleName: string = curModuleName();//变量所处模块名,默认为当前模块 729 | let varName: string = "";//变量名 730 | let idArray = idExp.idList; 731 | if (!hasAt) { 732 | //如果没有AT,说明不是在内部函数中,访问静态变量 733 | if (idExp.idType === ID_TYPE.MODULE_ID) {//是否为其它模块的 734 | //如果是其它模块的,则设置指定的模块名 735 | moduleName = idArray[index++];//如果为其它模块的,那么id链中第一个为模块名 736 | } 737 | varName = idArray[index++];//模块名下一个是变量名 738 | } 739 | //对IDExp的结果进行包装处理 740 | let idWrap: IDWrap = new IDWrap(varName, moduleName, hasAt); 741 | //从id链中读取剩余的id 742 | for (; index < idArray.length; index++) { 743 | referenceIndex.push(idArray[index]); 744 | } 745 | idWrap.referenceList = referenceIndex; 746 | return idWrap; 747 | } 748 | 749 | function runVariableExp(variableExp: VariableExp): VariableMeta { 750 | //解析idExp 751 | let idExp = variableExp.idExp; 752 | let varIDWrap: IDWrap = runIDExp(idExp); 753 | //从符号表中读取variable 754 | let variable: Variable = getVariable(varIDWrap); 755 | if (variable && variable.hasDeclared) { 756 | //变量存在,并定义了 757 | let reference: Reference = new Reference(variable, variable.variableType);//将变量包装为引用 758 | let idVar: VariableMeta = wrapToVariableMeta(reference, VARIABLE_TYPE.REFERENCE, variable.variableName);//将引用包装成统一的格式进行回传 759 | //设置引用链 760 | if (variableExp.arraySub) { 761 | //如果要获取的是数组变量 762 | //解析arraySub 763 | let arraySub: Array = []; 764 | for (let i = 0; i < variableExp.arraySub.length; i++) { 765 | let data = runExpression(variableExp.arraySub[i]) 766 | if (data.reference&&data.reference.referencedType===VARIABLE_TYPE.COMPLEXUS){ 767 | //如果是复合体,则还需要解析 768 | arraySub.push(data.reference.getReferenceValue()) 769 | }else{ 770 | arraySub.push(data.value) 771 | } 772 | } 773 | if (varIDWrap.hasAt) { 774 | //如果有@前缀,说明访问数组同时还是静态变量 775 | //@ts-ignore 776 | idVar.reference.referenceList = _.concat(varIDWrap.referenceList, arraySub); 777 | } else { 778 | //@ts-ignore 779 | idVar.reference.referenceList = arraySub; 780 | } 781 | } else { 782 | //@ts-ignore 783 | idVar.reference.referenceList = varIDWrap.referenceList 784 | } 785 | idVar.resetValue(); 786 | return idVar; 787 | } else { 788 | printInterpreterError(varIDWrap.idName + "变量未定义!", variableExp.lineNo); 789 | return nullValue; 790 | } 791 | } 792 | 793 | -------------------------------------------------------------------------------- /src/Parser/BuildAST/Index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020. yaser. All rights reserved 3 | * Description: 构建语法树 4 | */ 5 | import {Stack} from "../DataStruct/Stack"; 6 | import { 7 | ArgumentList, 8 | ArrayExp, 9 | ArraySub, 10 | AssignStmt, 11 | BinaryExp, 12 | BlockStmt, 13 | CallExp, 14 | Exp, 15 | Expression, 16 | FunDeclaration, 17 | ID_TYPE, 18 | IDExp, 19 | IfStmt, InnerFunDefStmt, 20 | Literal, 21 | ModuleFunDefStmt, 22 | Node, 23 | NODE_TYPE, 24 | OPERATOR, 25 | Operator, 26 | OPERATOR_TYPE, 27 | ParamList, 28 | ReturnStmt, 29 | Statement, 30 | UnaryExp, 31 | VarDefStmt, 32 | VariableDef, 33 | VariableExp, 34 | WhileStmt 35 | } from "../DataStruct/ASTNode"; 36 | import {V_T_Wrap} from "../DataStruct/V_T_Wrap"; 37 | import {T, V} from "../../Lexer/DataStruct/V_T"; 38 | import { 39 | ARRAY_SUB, AT, 40 | COMMA, 41 | DOT, 42 | ELSE, 43 | EXP, 44 | FALSE, 45 | ID, 46 | MAIN, MODULE_SCOPE, 47 | NULL, 48 | NUMBER, 49 | OPERATOR_LIST, 50 | STATIC, 51 | STRING, 52 | TRUE, 53 | UNARY_AFTER_OPERATOR, 54 | UNARY_BEFORE_OPERATOR, 55 | VARIABLE_EXP, 56 | } from "../DataStruct/TConstant"; 57 | import {QSModule} from "../../Interpreter/DataStruct/Module"; 58 | import {Token} from "../../Lexer/DataStruct/Token"; 59 | import {getGlobalSymbolTable, GlobalSymbolTable} from "../../Interpreter/DataStruct/SymbolTable"; 60 | import {Variable} from "../../Interpreter/DataStruct/Variable"; 61 | import {createUniqueId} from "../../Utils/utils"; 62 | import {getInterpreter, Interpreter} from "../../Interpreter/DataStruct/Interpreter"; 63 | import {printBuildASTError, printInfo} from "../../Log"; 64 | 65 | let ASTStack: Stack; 66 | let blockStack: Stack; 67 | let funStack: Stack; 68 | let hasImport = false; 69 | let qsModule: QSModule; 70 | let globalSymbolTable: GlobalSymbolTable; 71 | let scopeStateStack: Stack; 72 | let curBlockDepth: number = 0;//当前所处scope的深度 73 | let curBlockID: string = "";//当前所处scope的ID 74 | let interpreter: Interpreter; 75 | 76 | const curScope = () => { 77 | return scopeStateStack.peek(); 78 | } 79 | const preScope = () => { 80 | return scopeStateStack.peekX(2); 81 | } 82 | 83 | //构建AST时目前所处的作用域 84 | export enum SCOPE_TYPE { 85 | MODULE,//模块作用域 86 | GENERATE_FUN,//普通函数作用域 87 | STATIC_FUN,//静态函数作用域 88 | INNER_FUN//内部函数作用域 89 | } 90 | 91 | export function pushFun(funName: string, scopeType: SCOPE_TYPE) { 92 | let newFun: FunDeclaration = new FunDeclaration(funName); 93 | scopeStateStack.push(scopeType);//进入到函数作用域中 94 | funStack.push(newFun); 95 | } 96 | 97 | export function pushBlock() { 98 | curBlockDepth++;//block层次加深 99 | curBlockID = createUniqueId();//给新的block设置id 100 | let blockStatement: BlockStmt = new BlockStmt(curBlockID, curBlockDepth, blockStack.peek()); 101 | blockStack.push(blockStatement); 102 | } 103 | 104 | function popBlock(): BlockStmt | null { 105 | if (!blockStack.isEmpty()) { 106 | let block: BlockStmt = blockStack.pop(); 107 | if (!blockStack.isEmpty()) { 108 | let blockTemp = blockStack.peek(); 109 | curBlockDepth = (blockTemp).blockDepth; 110 | curBlockID = (blockTemp).blockID; 111 | } else { 112 | curBlockDepth = 0; 113 | curBlockID = ""; 114 | } 115 | return block; 116 | } 117 | return null; 118 | } 119 | 120 | function hasNull(list: Array): boolean { 121 | let flag = false; 122 | for (let i = 0; i < list.length; i++) { 123 | if (!list[i]) { 124 | flag = true; 125 | break; 126 | } 127 | } 128 | return flag; 129 | } 130 | 131 | export function initBuildAST() { 132 | printInfo("初始化语法树构造器..."); 133 | //初始化AST构建程序 134 | interpreter = getInterpreter(); 135 | ASTStack = new Stack(); 136 | blockStack = new Stack(); 137 | funStack = new Stack(); 138 | hasImport = false; 139 | qsModule = new QSModule(); 140 | globalSymbolTable = getGlobalSymbolTable(); 141 | curBlockDepth = 0; 142 | scopeStateStack = new Stack(SCOPE_TYPE.MODULE);//默认是处于模块作用域中 143 | curBlockID = ""; 144 | printInfo("语法树构造器初始化完成。"); 145 | } 146 | 147 | //状态树构建方法表 148 | let ASTBuildMap = { 149 | [V.ModuleSelfDefine]: buildModuleSelfDefine, 150 | [V.ModuleImportDefine]: buildModuleImportDefine, 151 | [V.ModuleExport]: buildModuleExport, 152 | [V.FunDefStmt]: buildModuleFunDefStmt, 153 | [V.FunDef]: buildFunDef, 154 | [V.ParamList]: buildParamList, 155 | [V.Stmts]: buildStmts, 156 | [V.BlockStmt]: buildBlockStmt, 157 | [V.VariableDef]: buildVariableDef, 158 | [V.VariableExp]: buildVariableExp, 159 | [V.VarDefStmt]: buildVarDefStmt, 160 | [V.InnerFunDefStmt]: buildInnerFunDefStmt, 161 | [V.IfStmt]: buildIfStmt, 162 | [V.WhileStmt]: buildWhileStmt, 163 | [V.ReturnStmt]: buildReturnStmt, 164 | [V.AssignStmt]: buildAssignStmt, 165 | [V.Exp]: buildExp, 166 | [V.ArrayExp]: buildArrayExp, 167 | [V.ArrayItems]: buildArrayItems, 168 | [V.IDExp]: buildIDExp, 169 | [V.ArraySub]: buildArraySub, 170 | [V.CallExp]: buildCallExp, 171 | [V.ArgumentList]: buildArgumentList, 172 | [V.CalExp]: buildBinaryExp, 173 | [V.LogicOperator]: buildOperator, 174 | [V.LogicExp]: buildBinaryExp, 175 | [V.BitOperator]: buildOperator, 176 | [V.BitExp]: buildBinaryExp, 177 | [V.RelationalOperator]: buildOperator, 178 | [V.RelationExp]: buildBinaryExp, 179 | [V.AdditiveOperator]: buildOperator, 180 | [V.AdditiveExp]: buildBinaryExp, 181 | [V.FactorOperator]: buildOperator, 182 | [V.FactorExp]: buildFactorExp, 183 | [V.UnaryBeforeOperator]: buildOperator, 184 | [V.UnaryAfterOperator]: buildOperator, 185 | [V.UnaryExp]: buildUnaryExp, 186 | [V.Literal]: buildLiteral, 187 | }; 188 | 189 | //该文件用于构建抽象语法树每一个子节点,同时在栈中保存已经生成的语法树节点 190 | export function getParsedModule(): QSModule { 191 | //获取解析后的模块 192 | return qsModule; 193 | 194 | } 195 | 196 | export function transferVTToASTNode(vtWrap: V_T_Wrap) { 197 | //将vtWrap转化为AST上的节点 198 | let call: Function = ASTBuildMap[vtWrap.getSymbolValue(false)];//从映射表获取对应的方法 199 | if (call) { 200 | let node: Node | undefined = call(vtWrap);//执行并获取节点数据 201 | if (node) { 202 | node.lineNo = vtWrap.lineNo; 203 | ASTStack.push(node); 204 | } 205 | } 206 | } 207 | 208 | //以下为各个非终结符节点的构建方式,同时添加程序的语义 209 | function buildModuleSelfDefine(vtWrap: V_T_Wrap) { 210 | let moduleName: Token = vtWrap.getChildToken(ID); 211 | if (moduleName) { 212 | qsModule.moduleName = moduleName.value; 213 | } else { 214 | printBuildASTError("当前模块名缺失!", vtWrap.lineNo); 215 | } 216 | } 217 | 218 | function buildModuleImportDefine(vtWrap: V_T_Wrap) { 219 | let importModule: Token = vtWrap.getChildToken(ID); 220 | if (importModule) { 221 | qsModule.pushImportModule(importModule.value); 222 | } else { 223 | printBuildASTError("要导入的模块名缺失!", vtWrap.lineNo) 224 | } 225 | } 226 | 227 | function buildModuleExport(vtWrap: V_T_Wrap) { 228 | let exportName: Token = vtWrap.getChildToken(ID); 229 | if (exportName) { 230 | qsModule.pushExport(exportName.value); 231 | } else { 232 | printBuildASTError("要导出的元素名缺失!", vtWrap.lineNo) 233 | } 234 | } 235 | 236 | function buildModuleFunDefStmt(vtWrap: V_T_Wrap) { 237 | //构建模块函数定义节点 238 | let funDeclaration: FunDeclaration = ASTStack.pop(); 239 | if (funDeclaration) { 240 | globalSymbolTable.pushSymbol(qsModule.moduleName,funDeclaration.id); 241 | let funDefStmt: ModuleFunDefStmt = new ModuleFunDefStmt(funDeclaration, qsModule.moduleName, vtWrap.testChild(STATIC)); 242 | qsModule.pushModuleFunDef(funDefStmt);//将函数加入到模块中 243 | if (funDefStmt.getFunName() === MAIN) { 244 | //main函数入口 245 | interpreter.setEnter(funDefStmt); 246 | } 247 | scopeStateStack.pop();//退出到模块作用域中 248 | } else { 249 | printBuildASTError("运行时错误,函数定义节点丢失!"); 250 | } 251 | } 252 | 253 | function buildFunDef(vtWrap: V_T_Wrap) { 254 | //构建基础的函数定义节点 255 | let idToken = vtWrap.getChildToken(ID); 256 | if (idToken) { 257 | //id存在 258 | let nodeList = ASTStack.popX(2); 259 | if (!hasNull(nodeList)) { 260 | //没有空值 261 | let funDeclaration = funStack.pop();//弹出一个函数 262 | if (funDeclaration) { 263 | funDeclaration.body = nodeList[1]; 264 | funDeclaration.params = (nodeList[0]).params; 265 | return funDeclaration; 266 | } else { 267 | printBuildASTError("函数定义丢失!", vtWrap.lineNo); 268 | } 269 | } 270 | printBuildASTError("运行时错误,函数参数列表与函数体节点丢失!"); 271 | } else { 272 | printBuildASTError("函数名缺失!", vtWrap.lineNo); 273 | } 274 | } 275 | 276 | function buildParamList(vtWrap: V_T_Wrap) { 277 | if (!vtWrap.isNull) { 278 | //没有使用空字符匹配 279 | let idToken: Token = vtWrap.getChildToken(ID); 280 | if (idToken) { 281 | if (vtWrap.testChild(COMMA)) { 282 | //该参数列表有多个参数 283 | let paramList: ParamList = ASTStack.pop(); 284 | if (paramList instanceof ParamList) { 285 | paramList.pushParam(idToken.value); 286 | return paramList; 287 | } 288 | } else { 289 | //只有一个参数 290 | let paramList: ParamList = new ParamList(); 291 | paramList.pushParam(idToken.value); 292 | return paramList; 293 | } 294 | } else { 295 | printBuildASTError("形参列表参数名缺失!", vtWrap.lineNo); 296 | } 297 | } else { 298 | return new ParamList();//返回一个空的paramList用于占位 299 | } 300 | } 301 | 302 | function buildStmts(vtWrap: V_T_Wrap) {//将所有的stmt添加到栈顶的block中 303 | if (!vtWrap.isNull) { 304 | //不是空字符 305 | let stmt: Statement = ASTStack.pop(); 306 | if (stmt) { 307 | let blockStatement: BlockStmt = blockStack.peek(); 308 | if (blockStatement) { 309 | blockStatement.pushStmt(stmt); 310 | } else { 311 | printBuildASTError("运行时错误,block节点丢失!"); 312 | } 313 | } else { 314 | printBuildASTError("运行时错误,语句节点丢失!"); 315 | } 316 | } 317 | } 318 | 319 | function buildBlockStmt() { 320 | //规约block 321 | let blockStatement: BlockStmt = popBlock(); 322 | if (blockStatement) { 323 | return blockStatement; 324 | } else { 325 | printBuildASTError("运行时错误,block节点丢失!"); 326 | } 327 | } 328 | 329 | function buildVariableDef(vtWrap: V_T_Wrap) { 330 | //模块、局部以及静态变量定义 331 | let varDefStmt: any = ASTStack.pop(); 332 | if (varDefStmt instanceof VarDefStmt) { 333 | if (vtWrap.testChild(STATIC)) { 334 | //是静态变量 335 | if (curScope() === SCOPE_TYPE.STATIC_FUN) { 336 | return new VariableDef(varDefStmt, false, true); 337 | } else { 338 | printBuildASTError("静态变量只可在静态函数中声明", vtWrap.lineNo); 339 | } 340 | } else { 341 | //是普通变量 342 | if (curScope() === SCOPE_TYPE.MODULE) { 343 | let variableDef: VariableDef = new VariableDef(varDefStmt, true); 344 | //处于模块作用域中,那么就是模块变量,加入到全局符号表中 345 | let variable: Variable = new Variable(qsModule.moduleName, variableDef); 346 | globalSymbolTable.pushSymbol(variable); 347 | qsModule.pushModuleVar(varDefStmt.id); 348 | } else { 349 | //否则就是局部变量,添加到AST中 350 | return new VariableDef(varDefStmt); 351 | } 352 | } 353 | } else { 354 | printBuildASTError("运行时错误,语法树节点无法匹配,当前需要VarDefStmt节点,获取到的是" + varDefStmt.constructor.name); 355 | } 356 | } 357 | 358 | function buildVariableExp(vtWrap: V_T_Wrap) { 359 | if (vtWrap.testChild(ARRAY_SUB)) { 360 | let arraySub: ArraySub = ASTStack.pop(); 361 | let idExp: IDExp = ASTStack.pop(); 362 | if (arraySub instanceof ArraySub && idExp instanceof IDExp) { 363 | return new VariableExp(idExp, arraySub); 364 | } else { 365 | printBuildASTError("类型不匹配,需要IDExp类型与ArraySub类型数据") 366 | } 367 | } else { 368 | let idExp: IDExp = ASTStack.pop(); 369 | if (idExp instanceof IDExp) { 370 | return new VariableExp(idExp); 371 | } else { 372 | printBuildASTError("类型不匹配,需要IDExp类型数据") 373 | } 374 | } 375 | } 376 | 377 | function buildIDExp(vtWrap: V_T_Wrap) { 378 | let testIDTypeBeforeSet = (idExp: IDExp) => { 379 | //对当前idType进行测试,只有为general时才可以设置 380 | if (idExp.idType !== ID_TYPE.GENERAL_ID && idExp.idType !== ID_TYPE.GENERAL_ID_LIST) { 381 | printBuildASTError("ID有语法错误!", vtWrap.lineNo) 382 | } 383 | }; 384 | switch (vtWrap.childNums) { 385 | case 1: { 386 | //只有一个表明是单一id 387 | let idToken: Token = vtWrap.getChildToken(ID); 388 | return new IDExp(idToken.value); 389 | } 390 | case 2: { 391 | if (vtWrap.testChild(AT)) { 392 | //存在AT 393 | let idExp: IDExp = ASTStack.peek(); 394 | if (idExp instanceof IDExp) { 395 | testIDTypeBeforeSet(idExp); 396 | idExp.idType = ID_TYPE.AT_ID; 397 | } else { 398 | printBuildASTError("运行时错误,需要IDExp类型的数据"); 399 | } 400 | } else { 401 | printBuildASTError("无法匹配IDExp!", vtWrap.lineNo); 402 | } 403 | break; 404 | } 405 | case 3: { 406 | if (vtWrap.testChild(DOT)) { 407 | //是id链 408 | let idExp: IDExp = ASTStack.peek(); 409 | if (idExp instanceof IDExp) { 410 | testIDTypeBeforeSet(idExp); 411 | let idToken: Token = vtWrap.getChildToken(ID); 412 | idExp.pushID(idToken.value); 413 | idExp.idType = ID_TYPE.GENERAL_ID_LIST; 414 | } else { 415 | printBuildASTError("运行时错误,需要IDExp类型的数据"); 416 | } 417 | } else if (vtWrap.testChild(MODULE_SCOPE)) { 418 | //只可能是其它模块的ID 419 | let idExp: IDExp = ASTStack.peek(); 420 | if (idExp instanceof IDExp) { 421 | testIDTypeBeforeSet(idExp); 422 | let idToken: Token = vtWrap.getChildToken(ID); 423 | idExp.pushID(idToken.value); 424 | idExp.idType = ID_TYPE.MODULE_ID; 425 | } else { 426 | printBuildASTError("运行时错误,需要IDExp类型的数据"); 427 | } 428 | } else { 429 | printBuildASTError("无法匹配IDExp!", vtWrap.lineNo); 430 | } 431 | break; 432 | } 433 | default: 434 | printBuildASTError("无法匹配IDExp!", vtWrap.lineNo); 435 | } 436 | } 437 | 438 | function buildVarDefStmt(vtWrap: V_T_Wrap) { 439 | //变量定义,无关类型 440 | let idToken: Token = vtWrap.getChildToken(ID); 441 | if (idToken) { 442 | if (vtWrap.testChild(EXP)) { 443 | //有初始化的值 444 | let expression: Exp = ASTStack.pop(); 445 | if (expression instanceof Exp) { 446 | return new VarDefStmt(idToken.value, expression); 447 | } 448 | } else { 449 | //没有初始化的值 450 | return new VarDefStmt(idToken.value) 451 | } 452 | } else { 453 | printBuildASTError("变量定义时,变量名缺失!", vtWrap.lineNo); 454 | } 455 | } 456 | 457 | function buildWhileStmt() { 458 | let whileStmtNodeList = ASTStack.popX(2); 459 | if (!hasNull(whileStmtNodeList)) { 460 | //没有空值 461 | return new WhileStmt(whileStmtNodeList[0], whileStmtNodeList[1]); 462 | } else { 463 | printBuildASTError("运行时错误,while节点的Exp与stmt节点丢失!"); 464 | } 465 | } 466 | 467 | function buildCallExp() { 468 | let argumentList: ArgumentList = ASTStack.pop(); 469 | let idExp: IDExp = ASTStack.pop(); 470 | if (argumentList instanceof ArgumentList && idExp instanceof IDExp) { 471 | return new CallExp(idExp, argumentList); 472 | } else { 473 | printBuildASTError("类型不匹配,需要IDExp类型与ArgumentList类型数据") 474 | } 475 | } 476 | 477 | function buildArgumentList(vtWrap: V_T_Wrap) { 478 | if (!vtWrap.isNull) { 479 | if (vtWrap.testChild(COMMA)) { 480 | //如果有多个实参 481 | let nodeList = ASTStack.popX(2); 482 | if (!hasNull(nodeList)) { 483 | let argumentList: ArgumentList = nodeList[0]; 484 | argumentList.pushArgs(nodeList[1]); 485 | return argumentList; 486 | } 487 | } else { 488 | //只有一个实参 489 | let exp: Exp = ASTStack.pop(); 490 | if (exp instanceof Exp) { 491 | let argumentList: ArgumentList = new ArgumentList(); 492 | argumentList.pushArgs(exp); 493 | return argumentList; 494 | } 495 | } 496 | } else { 497 | return new ArgumentList();//返回一个空的实参列表,用于占位 498 | } 499 | } 500 | 501 | function buildReturnStmt(vtWrap: V_T_Wrap) { 502 | if (vtWrap.childNums === 2) { 503 | //没有返回值 504 | return new ReturnStmt() 505 | } else if (vtWrap.testChild(EXP)) { 506 | //有返回值 507 | let exp: Exp = ASTStack.pop(); 508 | if (exp instanceof Exp) { 509 | return new ReturnStmt(exp) 510 | } 511 | } 512 | } 513 | 514 | function buildAssignStmt(vtWrap: V_T_Wrap) { 515 | if (vtWrap.testChild(VARIABLE_EXP)) { 516 | //对普通变量进行赋值 517 | let exp: Exp = ASTStack.pop(); 518 | let variableExp: VariableExp = ASTStack.pop(); 519 | if (exp instanceof Exp && variableExp instanceof VariableExp) { 520 | return new AssignStmt(variableExp, exp); 521 | } else { 522 | printBuildASTError("赋值语句构建失败!", vtWrap.lineNo); 523 | } 524 | } else { 525 | 526 | } 527 | } 528 | 529 | function buildExp() { 530 | let exp: Expression = ASTStack.pop(); 531 | if (exp) { 532 | //包装为表达式 533 | return new Exp(exp); 534 | } else { 535 | printBuildASTError("运行时错误,exp节点丢失!"); 536 | } 537 | } 538 | 539 | 540 | function buildOperator(vtWrap: V_T_Wrap) { 541 | //构建所有的运算符 542 | let operatorToken: Token = vtWrap.getChildTokenByList(OPERATOR_LIST); 543 | if (operatorToken) { 544 | let operator; 545 | switch (operatorToken.tokenType) { 546 | case T.BIT_NOT: 547 | operator = new Operator(OPERATOR_TYPE.UNARY_OPERATOR, OPERATOR.BIT_NOT); 548 | break; 549 | case T.NOT: 550 | operator = new Operator(OPERATOR_TYPE.UNARY_OPERATOR, OPERATOR.NOT); 551 | break; 552 | case T.ADD_ONE: 553 | operator = new Operator(OPERATOR_TYPE.UNARY_OPERATOR, OPERATOR.ADD_ONE); 554 | break; 555 | case T.SUB_ONE: 556 | operator = new Operator(OPERATOR_TYPE.UNARY_OPERATOR, OPERATOR.SUB_ONE); 557 | break; 558 | case T.MOD: 559 | operator = new Operator(OPERATOR_TYPE.ARITHMETIC_OPERATOR, OPERATOR.MOD); 560 | break; 561 | case T.DIV: 562 | operator = new Operator(OPERATOR_TYPE.ARITHMETIC_OPERATOR, OPERATOR.DIV); 563 | break; 564 | case T.MUL: 565 | operator = new Operator(OPERATOR_TYPE.ARITHMETIC_OPERATOR, OPERATOR.MUL); 566 | break; 567 | case T.ADD: 568 | operator = new Operator(OPERATOR_TYPE.ARITHMETIC_OPERATOR, OPERATOR.ADD); 569 | break; 570 | case T.SUB: 571 | operator = new Operator(OPERATOR_TYPE.ARITHMETIC_OPERATOR, OPERATOR.SUB); 572 | break; 573 | case T.BIT_AND: 574 | operator = new Operator(OPERATOR_TYPE.ARITHMETIC_OPERATOR, OPERATOR.BIT_AND); 575 | break; 576 | case T.BIT_OR: 577 | operator = new Operator(OPERATOR_TYPE.ARITHMETIC_OPERATOR, OPERATOR.BIT_OR); 578 | break; 579 | case T.LESS: 580 | operator = new Operator(OPERATOR_TYPE.LOGICAL_OPERATOR, OPERATOR.LESS); 581 | break; 582 | case T.LESS_EQUAL: 583 | operator = new Operator(OPERATOR_TYPE.LOGICAL_OPERATOR, OPERATOR.LESS_EQUAL); 584 | break; 585 | case T.EQUAL: 586 | operator = new Operator(OPERATOR_TYPE.LOGICAL_OPERATOR, OPERATOR.EQUAL); 587 | break; 588 | case T.NOT_EQUAL: 589 | operator = new Operator(OPERATOR_TYPE.LOGICAL_OPERATOR, OPERATOR.NOT_EQUAL); 590 | break; 591 | case T.GREATER: 592 | operator = new Operator(OPERATOR_TYPE.LOGICAL_OPERATOR, OPERATOR.GREATER); 593 | break; 594 | case T.GREATER_EQUAL: 595 | operator = new Operator(OPERATOR_TYPE.LOGICAL_OPERATOR, OPERATOR.GREATER_EQUAL); 596 | break; 597 | case T.LOGIC_OR: 598 | operator = new Operator(OPERATOR_TYPE.LOGICAL_OPERATOR, OPERATOR.LOGIC_OR); 599 | break; 600 | case T.LOGIC_AND: 601 | operator = new Operator(OPERATOR_TYPE.LOGICAL_OPERATOR, OPERATOR.LOGIC_AND); 602 | break; 603 | } 604 | if (operator) { 605 | return operator; 606 | } 607 | } else { 608 | printBuildASTError("运算符号缺失 !", vtWrap.lineNo); 609 | } 610 | } 611 | 612 | function buildBinaryExp(vtWrap: V_T_Wrap) { 613 | //构建二元运算,因为二元运算比较通用,所以直接统一构建,对于规约的时候只有单个节点的产生式直接忽视, 614 | // 因为对其做规约无意义,只会增加树的深度,不会增加语义 615 | if (vtWrap.childNums !== 1) { 616 | let binaryExpList: Array = ASTStack.popX(3); 617 | //二元运算的子节点都是三个 618 | //检查是否为空 619 | if (!hasNull(binaryExpList)) { 620 | return new BinaryExp(binaryExpList[1], binaryExpList[0], binaryExpList[2]); 621 | } 622 | } 623 | } 624 | 625 | function buildFactorExp(vtWrap: V_T_Wrap) { 626 | let unaryExp: UnaryExp | null = null; 627 | let operator: Operator | null = null; 628 | if (vtWrap.testChild(UNARY_BEFORE_OPERATOR)) { 629 | //前缀运算符 630 | unaryExp = ASTStack.pop(); 631 | operator = ASTStack.pop(); 632 | unaryExp.isPreOperator = true; 633 | } else if (vtWrap.testChild(UNARY_AFTER_OPERATOR)) { 634 | //后缀运算符 635 | operator = ASTStack.pop(); 636 | unaryExp = ASTStack.pop(); 637 | } 638 | if (unaryExp && operator) { 639 | unaryExp.setOperator(operator); 640 | return unaryExp; 641 | } 642 | } 643 | 644 | function buildUnaryExp() { 645 | let value: Expression = ASTStack.pop(); 646 | if (value instanceof Literal || value instanceof VariableExp || value instanceof Exp || value instanceof CallExp) { 647 | return new UnaryExp(value); 648 | } 649 | } 650 | 651 | function buildLiteral(vtWrap: V_T_Wrap) { 652 | //构建字面量 653 | let valueToken: Token = vtWrap.getChildTokenByList([NUMBER, STRING, FALSE, TRUE, NULL]); 654 | if (valueToken) { 655 | let value: number | string | boolean | null; 656 | switch (valueToken.tokenType) { 657 | case T.NUMBER: 658 | value = Number.parseFloat(valueToken.value); 659 | break; 660 | case T.STRING: 661 | value = valueToken.value; 662 | break; 663 | case T.FALSE: 664 | value = false; 665 | break; 666 | case T.TRUE: 667 | value = true; 668 | break; 669 | default: 670 | value = null; 671 | break; 672 | } 673 | return new Literal(value); 674 | } 675 | return new Literal(null); 676 | } 677 | 678 | function buildArrayExp(vtWrap: V_T_Wrap) { 679 | if (vtWrap.childNums === 2) { 680 | return new ArrayExp();//如果是一个空数组,则返回一个新建的ArrayExp 681 | } 682 | } 683 | 684 | function buildArrayItems(vtWrap: V_T_Wrap) { 685 | let arrayExp: ArrayExp; 686 | if (vtWrap.testChild(COMMA)) { 687 | //如果存在多个元素 688 | arrayExp = ASTStack.pop(); 689 | if (!(arrayExp instanceof ArrayExp)) { 690 | printBuildASTError("运行时错误,运行时栈中元素不匹配,无法匹配ArrayExp") 691 | } 692 | } else { 693 | //仅有一个 694 | arrayExp = new ArrayExp(); 695 | } 696 | arrayExp.pushElement(ASTStack.pop()); 697 | return arrayExp; 698 | } 699 | 700 | function buildArraySub(vtWrap: V_T_Wrap) { 701 | if (vtWrap.testChild(ARRAY_SUB)) { 702 | let exp: Exp = ASTStack.pop(); 703 | let arraySub: ArraySub = ASTStack.pop(); 704 | if (arraySub instanceof ArraySub) { 705 | if (exp instanceof Exp) { 706 | arraySub.pushSub(exp); 707 | return arraySub; 708 | } else { 709 | printBuildASTError("数据类型不匹配,需要匹配Exp", vtWrap.lineNo); 710 | } 711 | } else { 712 | printBuildASTError("数据类型不匹配,需要匹配ArraySub", vtWrap.lineNo); 713 | } 714 | } else { 715 | let exp: Exp = ASTStack.pop(); 716 | if (exp instanceof Exp) { 717 | let arraySub = new ArraySub(); 718 | arraySub.pushSub(exp); 719 | return arraySub; 720 | } else { 721 | printBuildASTError("数据类型不匹配,需要匹配Exp", vtWrap.lineNo); 722 | } 723 | } 724 | } 725 | 726 | function buildInnerFunDefStmt(vtWrap: V_T_Wrap) { 727 | if (preScope() === SCOPE_TYPE.STATIC_FUN) { 728 | //说明是内部函数 729 | let funDeclaration: FunDeclaration = ASTStack.pop(); 730 | if (funDeclaration) { 731 | const staticFun = funStack.peek() 732 | let innerFunDefStmt: InnerFunDefStmt = new InnerFunDefStmt(funDeclaration, qsModule.moduleName, staticFun.id); 733 | scopeStateStack.pop();//退出到静态作用域中 734 | return innerFunDefStmt; 735 | } else { 736 | printBuildASTError("运行时错误,函数定义节点丢失!"); 737 | } 738 | } else { 739 | printBuildASTError("内部函数必须在静态函数内部!", vtWrap.lineNo); 740 | } 741 | } 742 | 743 | function buildIfStmt(vtWrap: V_T_Wrap) { 744 | if (!vtWrap.testChild(ELSE)) { 745 | //如果不存在else,也就是说是一个全新的分支 746 | //弹出stmt与exp 747 | let ifStmtList = ASTStack.popX(2); 748 | if (!hasNull(ifStmtList)) { 749 | //如果都存在 750 | return new IfStmt(ifStmtList[0], ifStmtList[1]); 751 | } else { 752 | printBuildASTError("运行时错误,IF语句缺失条件或执行语句"); 753 | } 754 | } else { 755 | //如果存在else 756 | //需要寻找一个ifStmt与之匹配 757 | let ifElseStmtList = ASTStack.popX(2); 758 | let setAlternate = (ifStmt: IfStmt, alternateSTmt: Statement) => { 759 | //先找到可以放置alternate语句的位置,因为可能有多个if子句嵌套 760 | while (ifStmt.alternate) { 761 | //如果存在else子句 762 | let alternateStmt = ifStmt.alternate; 763 | if (alternateStmt.nodeType === NODE_TYPE.IF_STMT) { 764 | //如果子句是ifStmt,则继续向下查找 765 | ifStmt = alternateStmt; 766 | } else { 767 | //如果else子句不是ifStmt,那么就表明出现了语法错误,因为当前else已经有值了,无法再加上另一个else子句 768 | //该情况不可能出现。 769 | printBuildASTError("IF语句出现语法错误,else子句无法对应多个子语句", vtWrap.lineNo); 770 | } 771 | } 772 | ifStmt.alternate = alternateSTmt; 773 | }; 774 | if (!hasNull(ifElseStmtList)) { 775 | //如果都存在 776 | let ifStmt: IfStmt = ifElseStmtList[0]; 777 | setAlternate(ifStmt, ifElseStmtList[1]); 778 | return ifStmt; 779 | } else { 780 | printBuildASTError("运行时错误,IF语句缺失Else子句"); 781 | } 782 | } 783 | } 784 | --------------------------------------------------------------------------------