@parser-generator/core
Version:
A Parser Generator that supports LL,SLR,LR1,LALR
213 lines (204 loc) • 8.38 kB
JavaScript
;
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