@parser-generator/core
Version:
A Parser Generator that supports LL,SLR,LR1,LALR
179 lines (177 loc) • 8.19 kB
JavaScript
import rootDebug from "debug";
import { NIL, isNonTerminal, isTerminal, EOF } from "@parser-generator/definition";
import { CyclicDepsDector } from "./utils";
let debug = rootDebug("PG:first&follow");
export class FirstCalculator {
constructor(grammar) {
this.firstMapCache = new Map();
this.cyclicDector = new CyclicDepsDector();
this.grammar = grammar;
}
getFirstSet(target) {
if ((isTerminal(target))) { //终结符的first集就是本身
return new Set([target]);
}
else {
let map = this.getFirstMap(target);
return new Set(map.keys());
}
}
/**
* 「指定非终结符号对frist集中的每个符号所选用的产生式」
* @param target
*/
getFirstMap(target) {
if (this.firstMapCache.has(target))
return this.firstMapCache.get(target);
let result = new Map();
//每一个子产生式
for (let i = 0; i < target.prods.length; i++) {
let prod = target.prods[i];
//产生式的每一个符号
for (let lmIdx = 0; lmIdx < prod.body.length; lmIdx++) {
let leftmost = prod.body[lmIdx];
/*
推导得到First(leftMost),加入 First(leftMost)-ε
- 如果First(leftMost)不包含ε,中断.
- 如果First(leftMost)包含ε,leftMost指向后一个符号,继续推导的First(leftMost),重复同样的过程直到到产生式末尾.
- 当到产生式达末尾时,如果还有ε,则将ε加入First(S)
*/
if (leftmost == target) { //issue 1.自递归
if (lmIdx == 0) //对于左递归文法 给出提示
debug(`Found the left recursive production ${prod}`);
break;
}
if (isNonTerminal(leftmost)) {
if (this.cyclicDector.registerAndCheckCycl(target, leftmost)) { //issue 3.循环依赖 跳过
debug(`Cyclic dependencies are detected between the non-terminal ${target} and ${leftmost} when calculating the first set of ${target}!`);
continue;
}
}
//加入 First(leftMost)-ε
let leftmostFSet = this.getFirstSet(leftmost);
for (let a of leftmostFSet) {
if (a != NIL)
result.set(a, prod);
}
//不包含ε
if (!leftmostFSet.has(NIL)) {
break;
}
//包含ε
else {
//到达最后一个仍包含ε 加入ε
if (lmIdx == prod.body.length - 1)
result.set(NIL, prod);
}
}
}
this.firstMapCache.set(target, result);
return result;
}
getFirstTable() {
let firstTable = new Map();
for (let nt of this.grammar.nonTerminals()) {
let firstMap = this.getFirstMap(nt);
firstTable.set(nt, firstMap);
}
return firstTable;
}
}
import { addAll_Set as addAll } from "@light0x00/shim";
export class FollowCalculator {
constructor(grammar, FirstCalculator) {
this.cyclicDector = new CyclicDepsDector(); // issue: 9.循环依赖
this.cache = new Map();
this.grammar = grammar;
this.FirstCalculator = FirstCalculator;
}
throwError(holder, other) {
throw new Error(`Cyclic dependencies are detected between the non-terminal ${holder} and ${other} when calculating the follow set of ${holder}!`);
}
/*
约定:
j表示当前正在处理的产生式(prod)
k表示当前正在处理的符号(j中的一个符号)
k+n表示当前符号k后的n个符号
伪代码:
k是否为j末尾符号
- 是, 加入Follow(j)
- 不是,加入 (First(k+1)-{ε})
- 如果 ε ∈ First(k+1) 则继续加入 First(k+2)).
并重复这一过程,直到第n个满足ε ∉ First(k+n),
如果符号(k+n)直到j的最后一个符号还仍旧存在 ε ∈ First(k+n), 则加入Follow(j)
注:伪代码仅供参考,一切以实物为准!
*/
getFollowSet(target) {
if (this.cache.has(target)) {
debug(`cache hit:${target}`);
return this.cache.get(target);
}
let non_terminals = this.grammar.nonTerminals();
let follow_set = new Set();
let whichHaveAddedFristSet = new Set(); //记录已经添加过哪些符号的First集
let whichHaveAddedFollowSet = new Set(); //记录已经添加过哪些符号的Follow集
if (non_terminals[0] == target) { // if start symbol
follow_set.add(EOF);
debug(`+EOF is added because ${target} is the beginning symbol`);
}
//每一个非终结符i
for (let i = 0; i < non_terminals.length; i++) {
let non_terminal = non_terminals[i];
//终结符中的每一个产生式j
for (let j = 0; j < non_terminal.prods.length; j++) {
let prod = non_terminal.prods[j];
debug(`Scanning ${target} in production:${prod}`);
let searching = false; //标记是否处于搜索状态 issue: 5. 连续重复
//每一个符号k
for (let k = 0; k < prod.body.length; k++) {
if (prod.body[k] != target && !searching) { //非搜索状态,且非target,则跳过 issue: 5. 连续重复
continue;
}
//k为j的末尾符号
if (k == prod.body.length - 1) {
if (non_terminal != target && !whichHaveAddedFollowSet.has(non_terminal)) { //issue: 6,7 自递归 && 重复添加
if (this.cyclicDector.registerAndCheckCycl(target, non_terminal)) // issue: 9.循环依赖 跳过
continue;
debug(`+Since ${target.name} is at the end of production ${prod.head},add Follow(${non_terminal.name})`);
addAll(follow_set, this.getFollowSet(non_terminal));
whichHaveAddedFollowSet.add(non_terminal); //标记Follow(p)已添加
}
break;
}
searching = true;
//处理k+1
let follower = prod.body[k + 1];
if (whichHaveAddedFristSet.has(follower)) //issue: 6. 重复添加
continue;
let followerFirstSet = this.FirstCalculator.getFirstSet(follower);
whichHaveAddedFristSet.add(follower); //标记 First(k+1)为已添加
//如果: ε ∈ First(k+1)
if (followerFirstSet.has(NIL)) {
addAll(follow_set, followerFirstSet);
follow_set.delete(NIL);
debug(`+The symbol ${follower} follows ${target},add First(${follower})-{𝝴}, due ${follower} contains 𝝴 ,scan the following symbol of ${follower} `);
}
//如果 ε ∉ First(k+1)
else {
addAll(follow_set, followerFirstSet);
debug(`+The symbol ${follower} follows ${target},add First(${follower})`);
searching = false; //k+1不可推出𝝴 则结束搜索状态 issue: 5. 连续重复
}
}
}
}
this.cache.set(target, follow_set);
return follow_set;
}
getFollowTable() {
let followTable = new Map();
for (let non_terminal of this.grammar.nonTerminals()) {
let followSet = this.getFollowSet(non_terminal);
followTable.set(non_terminal, followSet);
}
return followTable;
}
}
//# sourceMappingURL=first-follow.js.map