UNPKG

@parser-generator/core

Version:

A Parser Generator that supports LL,SLR,LR1,LALR

213 lines (204 loc) 8.38 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const shim_1 = require("@light0x00/shim"); const definition_1 = require("@parser-generator/definition"); const definition_2 = require("./definition"); const debug_1 = __importDefault(require("debug")); const first_follow_1 = require("../first-follow"); const automata_1 = require("./automata"); const parsing_table_1 = require("./parsing-table"); let debug = debug_1.default("PG:LR1"); /* 构造自动机所需要的方法 */ class LR1AutomataTools { constructor(firstSetCalculator) { this.getFirstSet = firstSetCalculator; } GOTO(I, inputSymbol) { let nextItemSet = new definition_2.ItemSet(); for (let item of I) { if (!item.hasNext()) continue; if (item.nextSymbol() == inputSymbol) { nextItemSet.push(item.nextItem()); } } return this.closure(nextItemSet); } closure(itemSet) { let itemSetClosure = itemSet; //项集的每一个项 item for (let processedIdx = 0; processedIdx < itemSetClosure.length; processedIdx++) { let item = itemSetClosure[processedIdx]; if (!item.hasNext()) //issue 1.1 continue; let expandSym = item.nextSymbol(); if (!(expandSym instanceof definition_1.NonTerminal)) //issue 1.2 continue; if (item.prod.body[0] == item.prod.head && item.dotPos == 0) { //issue 1.4 debug(`Stop expanding left recursion production ${expandSym}`); continue; } let lrps = this.getLeftRecursiveProds(expandSym); //issue 2.1.1.1 左递归产生式 let nlrlookSet = this.determineNonLeftRecursionLookSet(item); //issue 2.1.1 展开符包含 if (lrps.length > 0) { let lrLookSet = this.determineLeftRecursionLookSet(item); //由所有左递归项带来的展望符集 for (let lrp of expandSym.prods) { let unionLookSet = new Set(); shim_1.addAll_Set(unionLookSet, lrLookSet); shim_1.addAll_Set(unionLookSet, nlrlookSet); itemSetClosure.pushOrMerge(new definition_2.Item(lrp, 0, unionLookSet)); } } //issue 2.1.2 展开符不包含递归产生式的情况 else { for (let prod of expandSym.prods) { let newItem = new definition_2.Item(prod, 0, nlrlookSet); itemSetClosure.pushOrMerge(newItem); } } } return itemSetClosure; } /** ========展开符包含左递归产生式的处理======== 文法: S->A A->A𝜶 | A𝜷 | 𝝲 状态: S->·A ,$ A->·A𝜶,$ A->·A𝜷,$ A->·𝝲, ? 如何求「 A->𝝲 」的展望集? 若𝜶,𝜷不能推出𝝴,则 lookSet(A->·𝝲) = {𝜶,𝜷} 否则 lookSet(A->·𝝲) ={𝜶,𝜷,$} 形式化: 加入在A中的每一个左递归产生式中的「第一非A的符号的First集」,记为First(!A), 如果该集内存在𝝴,则一路向后直到末尾,如果仍存在𝝴,则加入 Look(A) 伪代码: for each lr-prod in A for each sym in lr-prod if sym != A add First(sym) if 𝝴 ∉ First(sym) break else if sym is rightmost add lookSet(S) 注: Look(S) 表示S的lookeheadSet * @param curItem */ determineLeftRecursionLookSet(curItem) { let target = curItem.nextSymbol(); shim_1.assert(target instanceof definition_1.NonTerminal); let lookaheadSet = new Set(); //目标的所有左递归产生式 let lrProds = this.getLeftRecursiveProds(target); //每一个左递归产生式 for (let lr_prod of lrProds) { //每一个符号 let searching = false; for (let j = 0; j < lr_prod.body.length; j++) { if (lr_prod.body[j] != target && !searching) { continue; } // right-most if (j == lr_prod.body.length - 1) { shim_1.addAll_Set(lookaheadSet, curItem.lookaheadSet); } else { let follower = lr_prod.body[j + 1]; let follower_first_set = this.getFirstSet(follower); shim_1.addAll_Set(lookaheadSet, follower_first_set); // 𝝴 ∉ First(follower) if (!follower_first_set.has(definition_1.NIL)) { break; } // 𝝴 ∈ First(follower) scan next one else { lookaheadSet.delete(definition_1.NIL); searching = true; } } } } return lookaheadSet; } /** ========展开符不包含左递归产生式的处理======== 约定 - 将闭包项记为 closureItem ,例如S->·As - 将展开项计为 expandItem , 例如由展开符A得到的项 A->·a 形式化计算规则如下: 展开符位于item末端,形如A->·B lookSet(expandItem)=lookSet(prevItem) next非末端,形如A->·B𝜶𝜷 lookSet(expandItem)=First(𝜶) , 如果𝜶可推出𝝴,则继续向后寻找𝜷,重复这个过程, 如果𝜷为最末尾符号,且𝜷仍可推出𝝴,那么将lookSet(prevItem)放入lookSet(next) * @param prevItem */ determineNonLeftRecursionLookSet(prevItem) { let expandSym = prevItem.nextSymbol(); shim_1.assert(expandSym instanceof definition_1.NonTerminal); let lookaheadSet = new Set(); for (let i = prevItem.dotPos; i < prevItem.prod.body.length; i++) { if (i == prevItem.prod.body.length - 1) { shim_1.addAll_Set(lookaheadSet, prevItem.lookaheadSet); break; } else { let firstSetOfFollow = this.getFirstSet(prevItem.prod.body[i + 1]); shim_1.addAll_Set(lookaheadSet, firstSetOfFollow); if (firstSetOfFollow.has(definition_1.NIL)) { lookaheadSet.delete(definition_1.NIL); } else { break; } } } return lookaheadSet; } getLeftRecursiveProds(non_terminal) { let lr_prods = []; //每一个产生式 for (let prod of non_terminal.prods) { //产生式中的每一个符号 for (let symbol of prod.body) { //若相等,,则表示prod存在左递归 if (symbol == non_terminal) { lr_prods.push(prod); break; } //若不相等 且First(symbol)不存在𝝴则中断,则表示prod没有左递归 else if (!this.getFirstSet(symbol).has(definition_1.NIL)) { break; } } } debug(lr_prods.join(",")); return lr_prods; } getStartState(grammar) { return new definition_2.State(0, this.closure(new definition_2.ItemSet(new definition_2.Item(grammar.startNT().prods[0], 0, new Set([definition_1.EOF]))))); } } exports.LR1AutomataTools = LR1AutomataTools; function getLR1Automata(grammar, fristGetter) { if (fristGetter == undefined) { let firstCalculator = new first_follow_1.FirstCalculator(grammar); fristGetter = (i) => firstCalculator.getFirstSet(i); } return automata_1.getAutomata(grammar, new LR1AutomataTools(fristGetter)); } exports.getLR1Automata = getLR1Automata; function getLR1ParsingTable(grammar, autotama) { if (autotama == undefined) autotama = getLR1Automata(grammar); return parsing_table_1.getParsingTable(autotama, grammar.startNT(), (i) => i.lookaheadSet); } exports.getLR1ParsingTable = getLR1ParsingTable; //# sourceMappingURL=lr1.js.map