@parser-generator/definition
Version:
A Parser Generator that supports LL,SLR,LR1,LALR
363 lines • 9.64 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const shim_1 = require("@light0x00/shim");
/*******************************************************************************************************
符号的原型
符号原型的作用是用于建立一种逻辑上的匹配关系.
对于终结符而言:
1. 值类型符号,对应于 比较值的token,比如 '==' ,没有原型, 分析过程中直接使用词素值匹配
2. 原型类型符号,对应于 比较类型的token, 比如 NUMBER ,其原型是一个TerminalPro对象, 分析过程中使用该对象匹配
对于非终结符:
3. 文法中左侧符号都会对应一个NonterminalPro对象,而产生式体中出现的非终结符,比如 A->aA ,第二个
例:
E->E1+F1
F->digit
- 终结符‘+’没有原型,分析时匹配词素值.
- 终结符 digit 的实例则不可枚举,1、2都digit,分析时不能以词素值为准,而是以原型为准,1、2的词素值不一样,但其原型一致,
这是一种逻辑相等关系.
- 非终结符E1的原型是E,F1的原型是F.
*******************************************************************************************************/
/**
* 非终结符符号原型
*/
class NonTerminal {
constructor(name, isStart = false, prods = []) {
this._name = name;
this._isStart = isStart;
this._prods = prods;
}
get name() {
return this._name;
}
get prods() {
return this._prods;
}
set prods(ps) {
this._prods = ps;
}
get isStart() {
return this._isStart;
}
toString() {
return this._name;
}
key() {
return this;
}
}
exports.NonTerminal = NonTerminal;
/**
* token原型
*/
class TokenPro {
constructor(name) {
this.name = name;
}
toString() {
return this.name;
}
key() {
return this;
}
}
exports.TokenPro = TokenPro;
exports.NIL = new TokenPro("NIL");
exports.EOF = new TokenPro("EOF");
function isNonTerminal(sym) {
return sym instanceof NonTerminal;
}
exports.isNonTerminal = isNonTerminal;
function isTerminal(sym) {
return sym instanceof TokenPro || typeof sym === "string";
}
exports.isTerminal = isTerminal;
class SymbolWrapper {
constructor(sym, action) {
this._value = sym;
this._action = action;
}
get value() {
return this._value;
}
get action() {
return this.action;
}
isNonTerminal() {
return isNonTerminal(this._value);
}
isTerminal() {
return isTerminal(this._value);
}
isNIL() {
return this._value == exports.NIL;
}
toString() {
return this._value.toString() + (this._action == undefined ? "" : `<%${this._action}%>`);
}
}
exports.SymbolWrapper = SymbolWrapper;
/**
* 产生式
*/
class Production {
constructor(id, nt, body, preAction, postAction, leftAssoc = false, prec = -1) {
this._id = id;
this._nt = nt;
this._actionBody = body;
this._preAction = preAction;
this._postAction = postAction;
this._body = new Array();
this._leftAssoc = leftAssoc;
this._prec = prec;
for (let asym of body) {
this._body.push(asym.value);
}
}
get id() {
return this._id;
}
get head() {
return this._nt;
}
get body() {
return this._body;
}
get actionBody() {
return this._actionBody;
}
get preAction() {
return this._preAction;
}
get postAction() {
if (this._postAction == undefined)
console.warn(`production(${this.id}) doesn't have post action, it is required for Parser`);
return this._postAction; //TODO
}
get action() {
return this.postAction;
}
get prec() { return this._prec; }
set prec(val) {
this._prec = val;
}
get leftAssoc() {
return this._leftAssoc;
}
set leftAssoc(val) {
this._leftAssoc = val;
}
isEpsilon() {
return this._body.length == 1 && this._body[0] === exports.NIL;
}
toString() {
return (this._preAction == undefined ? "" : "<%" + this.preAction + "%>") +
`(${this._id}) ${this._nt}->${this._actionBody.map(o => o.toString()).join("")}`
+ (this._postAction == undefined ? "" : "<%" + this.postAction + "%>");
}
}
exports.Production = Production;
/**
* 符号优先级、结合性
*/
class SymbolTrait {
constructor(prec, leftAssoc) {
this._prec = prec;
this._leftAssoc = leftAssoc;
}
get prec() {
return this._prec;
}
get leftAssoc() {
return this._leftAssoc;
}
compareTo(other) {
//TODO
return false;
}
}
exports.SymbolTrait = SymbolTrait;
class Grammar {
constructor(nts, prods, startSymbol, traits = new Map()) {
this.nts = nts;
this.prods = prods;
this.startSym = startSymbol;
this.traits = traits;
//处理产生式的优先级与结合性
for (let p of prods) {
if (traits.has(p.head)) {
let trait = traits.get(p.head);
p.prec = trait.prec;
p.leftAssoc = trait.leftAssoc;
}
let prec = p.prec;
let leftAssoc = p.leftAssoc;
for (let s of p.body) {
if (traits.has(s)) {
let trait = traits.get(s);
if (trait.prec > prec) {
prec = trait.prec;
leftAssoc = trait.leftAssoc;
}
}
}
p.prec = prec;
p.leftAssoc = leftAssoc;
}
this.validate();
}
validate() {
}
nonTerminals() {
return this.nts;
}
productions() {
return this.prods;
}
startNT() {
return this.startSym;
}
toString() {
return this.prods.join("\n");
}
}
exports.Grammar = Grammar;
/*************************************** LR相关 ****************************************/
class AugmentedGrammar extends Grammar {
validate() {
shim_1.assert(this.startSym.prods.length == 1, `The start symbol of an augmented grammar has one and only one production! but ${this.startSym} has ${this.startSym.prods.length}:\n${this.startSym.prods.join("\n")}`);
}
}
exports.AugmentedGrammar = AugmentedGrammar;
/* 表示LR语法分析表格的操作 */
class Operation {
isReduce() {
return false;
}
isShift() {
return false;
}
isGoto() {
return false;
}
isAccept() {
return false;
}
}
exports.Operation = Operation;
class Shift extends Operation {
constructor(nextStateId) {
super();
this._nextStateId = nextStateId;
}
get nextStateId() {
return this._nextStateId;
}
toString() {
return `shift ${this._nextStateId}`;
}
equals(obj) {
return obj instanceof Shift && obj._nextStateId == this._nextStateId;
}
isShift() {
return true;
}
}
exports.Shift = Shift;
class Goto extends Operation {
constructor(nextStateId) {
super();
this._nextStateId = nextStateId;
}
get nextStateId() {
return this._nextStateId;
}
toString() {
return `goto ${this._nextStateId}`;
}
equals(obj) {
return obj instanceof Goto && obj._nextStateId == this._nextStateId;
}
isGoto() {
return true;
}
}
exports.Goto = Goto;
class Reduce extends Operation {
constructor(prod) {
super();
this._prod = prod;
}
get prod() {
return this._prod;
}
toString() {
return `reduce ${this._prod.id}`;
}
equals(obj) {
return obj instanceof Reduce && obj._prod == this._prod;
}
isReduce() {
return true;
}
}
exports.Reduce = Reduce;
class Accept extends Operation {
constructor() {
super();
}
equals(obj) {
return obj instanceof Accept;
}
toString() {
return `accept`;
}
isAccept() {
return true;
}
}
exports.Accept = Accept;
/* TODO 考虑是否应该包装 Map */
// export type LRParsingTable = Map<number, Map<SSymbol, Operation>>;
class ParsingTable {
constructor() {
this.parsingTable = new Map();
}
get table() {
return this.parsingTable;
}
put(state, symbol, op) {
let row = this.parsingTable.get(state);
if (row == undefined) {
row = new Map();
this.parsingTable.set(state, row);
}
row.set(symbol, op);
}
has(state, symbol, op) {
let row = this.parsingTable.get(state);
if (row == undefined)
return false;
let exstingOp = row.get(symbol);
if (exstingOp == null)
return false;
return exstingOp.equals(op);
}
get(state, symbol) {
let row = this.parsingTable.get(state);
if (row == undefined)
return undefined;
return row.get(symbol);
}
getExpectedSymbols(state) {
let row = this.parsingTable.get(state);
if (row == undefined)
return [];
return Array.from(row.keys());
}
getExpectedTokens(state) {
let expS = this.getExpectedSymbols(state);
return expS.filter(s => !(s instanceof NonTerminal));
}
}
exports.ParsingTable = ParsingTable;
//# sourceMappingURL=syntax.js.map