UNPKG

@parser-generator/definition

Version:

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

363 lines 9.64 kB
"use strict"; 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