@parser-generator/definition
Version:
A Parser Generator that supports LL,SLR,LR1,LALR
112 lines (97 loc) • 2.53 kB
text/typescript
import { Queue, assert } from "@light0x00/shim";
import { SSymbol, Terminal } from "./syntax";
export interface TableKey {
key(): SSymbol;
}
export interface IToken {
key(): Terminal
// pos(): { lineNo: number, colNo: number }
}
export interface ILexer {
peek(): IToken
next(): IToken
}
export type TokenPatterns<T> = Array<{ regexp: RegExp, type: T }>
export abstract class CommonAbstractRegexpLexer<T, A>{
private patterns: TokenPatterns<A>;
private lastIndex = 0
private text: string
private hasMore = true
private buffer = new Queue<T>();
constructor(text: string, patterns: TokenPatterns<A>) {
assert(text!=undefined);
this.text = text;
this.patterns = patterns;
}
peek(): T {
return this.peekFor(0);
}
peekFor(i: number): T {
if (this.fill(i)) {
return this.buffer.get(i)!;
} else {
return this.getEOF();
}
}
next(): T {
if (this.fill(0))
return this.buffer.removeFirst()!;
else
return this.getEOF();
}
/**
* 填充直到队列达到指定数量,或没有足够的输入符号.
* 如果填充达到要求的数量,返回true,否则false
* @param i
*/
private fill(i: number) {
while (this.buffer.size() < i + 1 && this.hasMore) {
this.addToken();
}
return i < this.buffer.size();
}
/**
* 填充
*/
private addToken() {
assert(this.hasMore);
//determine lexeme and type
let type: A | undefined;
let lexeme: string | undefined;
let match: RegExpExecArray | null = null;
for (let p of this.patterns) {
p.regexp.lastIndex = this.lastIndex;
match = p.regexp.exec(this.text);
if (match != null) {
type = p.type;
lexeme = match[0];
this.lastIndex = p.regexp.lastIndex;
//reach the end
if (this.lastIndex >= this.text.length) {
this.hasMore = false;
}
break;
}
}
if (type == undefined || lexeme == undefined || match == null) {
this.hasMore = false;
this.onMatchFaild(this.text, this.lastIndex);
return;
}
//create token
let t = this.createToken(lexeme, type, match);
if (t == undefined) {
return false;
} else {
this.buffer.addLast(t);
return true;
}
}
protected abstract createToken(lexeme: string, type: A, match: RegExpExecArray): T | undefined
protected onMatchFaild(text: string, lastIndex: number): void {
throw new Error(`Unrecognized charactor(${lastIndex}):${text[lastIndex]} `);
}
protected abstract getEOF(): T
}
export abstract class AbstractRegexpLexer<T extends IToken, A> extends CommonAbstractRegexpLexer<T, A> implements ILexer {
}