export class OpcodeCompiler {private lines: Array<string> //结果列表private symbolTable: SymbolTable //对应的符号表constructor() { }//通过寄存器+偏移量寻址private offset(register: string, lexeme: ITable, argc: number = 0): string {if (lexeme.index < argc) {return `${register}+${4 * (argc - lexeme.index + 1)}`} else if (lexeme.index > argc) {return `${register}-${4 * (lexeme.index - 1)}`} else {return `${register}`}}//获取地址private addr(curScope: SymbolTable, x: string, register = 'R0'): string {// 数字if (x[0].match(/[0-9]/)) {return '#' + x}//消除%else if (x.indexOf('%') !== -1) {return x.replace(/%/g, '')}//else {// const argc = currentScop// console.log(curScope, curScope.children[0].table)const argc = curScope.type === 'function' ? curScope.argc : 0const lexeme = curScope.find(x)// 分case讨论// case1: 变量在当前作用域// case2:变量不在当前作用域// case3: 当前作用域是变量作用域的子节点// case4: 当前作用域不是变量作用域的子节点if (curScope.id === lexeme.scopeId) {return `${this.offset('TOP', lexeme, argc)}`} else {if (curScope.isParent(lexeme.scopeId)) {const levelDiff = curScope.level - lexeme.levelthis.lines.push(`mov TOP ${register}`)for (let i = 0; i < levelDiff; i++) {this.lines.push(`mov @${register}${register}`)}this.lines.push(`mov ${this.offset(register, lexeme, argc)}${register}`)} else {// 这种情况下TOP肯定指向父作用域this.lines.push(`mov TOP ${register}`)this.lines.push(`mov @${register}${register}`)this.lines.push(`mov ${this.offset(register, lexeme, argc)}${register}`)}}}}//翻译Passprivate translatePass(curScope: SymbolTable, params: Array<string>): void {const v = params[0]this.lines.push(`push ${this.addr(curScope, v, 'TOP')}`)}//翻译Branchprivate translateBranch(curScope: SymbolTable, params: Array<string>): void {const v = params[0]const lb1 = params[1]this.lines.push(`jz ${lb1}`)}//翻译Callprivate translateCall(curScope: SymbolTable, params: Array<string>): void {const func = params[0]this.lines.push(`push PC`)this.lines.push(`jump ${func}`)}//翻译setprivate translateSet(curScope: SymbolTable, params: Array<string>): void {const assignee: string = params[0] //临时变量const op: string = params[2]//操作符const l: string = params[1] //左值const r: string = params[3]//右值//存在操作符时if (op) {//拿到左值的地址const a = this.addr(curScope, l, 'R0')//拿到右值的地址const b = this.addr(curScope, r, 'R1')switch (op) {case "==": {this.lines.push(`cmp ${a}${b}`)this.lines.push(`mov ZF ${this.addr(curScope, assignee, 'TOP')}`)break}case "||": {this.lines.push(`mov ${a} R0`)this.lines.push(`or R0 ${b}`)this.lines.push(`mov R0 ${this.addr(curScope, assignee, 'TOP')}`)break}case '-': {this.lines.push(`mov ${a} R0`)this.lines.push(`sub R0 ${b}`)this.lines.push(`mov R0 ${this.addr(curScope, assignee, 'TOP')}`)break}case '+': {this.lines.push(`mov ${a} R0`)this.lines.push(`add R0 ${b}`)this.lines.push(`mov R0 ${this.addr(curScope, assignee, 'TOP')}`)}}} else {const a: string = this.addr(curScope, assignee, 'R0')const b: string = this.addr(curScope, l, 'R1')this.lines.push(`mov ${b}${a}`)if (assignee.indexOf('%') === -1) {this.lines.push(`sub #-4 SP`)}}}public parse(sourceCode: string, symbols: ISymbols): void {this.lines = [] //初始化结果列表this.symbolTable = new SymbolTable(symbols) //创建符号表const ilLines: Array<string> = sourceCode.split('\n') //将每行中间码数据拆成单个数组元素let sectionScope: SymbolTable = null //当前section作用域下的符号表//逐条解析单个三地址码for (let iline of ilLines) {if (iline.trim()) {let label = ''if (iline.indexOf(':') !== -1) {[label, iline] = iline.split(':')}const prts: Array<string> = iline.split('').filter(x => x)/*** codeName:指令名称* params:指令参数列表*/const [codeName, ...params] = prtsswitch (codeName) {case 'section': {const [name, id] = params[0].split('@')sectionScope = this.symbolTable.findScope(id)break}case 'set': {this.translateSet(sectionScope, params)break}case 'branch': {this.translateBranch(sectionScope, params)break}case 'pass': {this.translatePass(sectionScope, params)break}case 'call': {this.translateCall(sectionScope, params)break}}}}}public print(): void {for (let line of this.lines) {console.log(line)}}}interface ISymbols {id: numbertable: objectchildren: Array<ISymbols>type?: stringargc?: number}interface IHash {id?: SymbolTable}interface ITable {index: number //在table中的索引位置level: number //层级scopeId: number //作用域IDtype: string //数据类型}//符号表类class SymbolTable {private hash: IHash //全局hash,存放各级符号表private table: ITable //本级符号表public children: Array<SymbolTable> //子符号表public id: number //本级符号表idpublic type: string //类型public argc: number //type为function时,参数个数constructor(private symbols: ISymbols, private parent?: SymbolTable, public level: number = 0) {if (this.level === 0) {this.hash = {}}if (this.parent) {this.hash = this.parent.hash}for (let key in this.symbols) {this[key] = this.symbols[key]}this.hash[this.id] = this//本机符号表中补充层级和作用域信息for (let key in this.table) {this.table[key].level = this.levelthis.table[key].scopeId = this.id}//子符号表this.children = symbols.children ? symbols.children.map(x => new SymbolTable(x, this, level + 1)) : null}//根据id寻找符号表findScope(id): SymbolTable {return this.hash[id]}//根据id查找详情信息find(id) {//判断id是否带作用域if (id.indexOf('@') !== -1) {const [vid, scopeId] = id.split('@')const scope = this.hash[scopeId]return scope.table[vid]} else {//判断本级符号表是否存在id,没有的话则去父表中找if (this.table[id]) {return this.table[id]}return this.parent.find(id)}}//判断当前符号表是不是scopeId表的父表isParent(scopeId: string): boolean {if (this.findScope(scopeId).parent.id === this.id) {return true} else {return false}}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。