UNPKG

jaycc

Version:

### the Javascript C Compiler

179 lines (146 loc) 4.51 kB
// Regular EXception // type Char = // 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' // | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' // | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' // | 'y' | 'z' | '?'; import type { Token } from './lexer.js'; type QM = Symbol; type Star = Symbol; type $ = Symbol; type $$ = Symbol; type Ex = QM | Star | $ | $$; // type ValidTypes = Char | Ex; type ValidTypes = Ex | Token; type Equality = (x:ValidTypes,y:ValidTypes)=>boolean; let QM:Ex; let Star:Ex; let $:Ex; let $$:Ex; QM = Symbol(); Star = Symbol(); $ = Symbol(); $$ = Symbol(); export { QM, Star, $, $$ }; export type { ValidTypes }; let wildcard:(x:ValidTypes)=>boolean; wildcard = (x:ValidTypes) => ( (x == QM) || (x == Star) || (x == $) || (x == $$) ); interface Irex<a> { constructor:Function; match:(xs:a[])=>boolean; match_:(xs:a[],cap_:a[])=>boolean; es:a[]; caps:a[][]; capidx:number|null; capturing:boolean; equality:Equality; } export class REX<a extends ValidTypes> implements Irex<a> { es:a[]; caps:a[][]; capidx:number|null; capturing:boolean; equality:Equality; constructor(input:ValidTypes[], eq:Equality) { // add sanity checks this.es = input as a[]; this.caps = []; this.capidx = null; this.capturing = false; this.equality = eq; } match(xs:a[]): boolean { return this.match_(xs, []); } match_(xs:a[],cap_:a[]): boolean { let x:a|null; let e:a|null; let cap:a[]; cap = cap_; // console.log('-- xs=', xs); // console.log('-- cap=', cap); x = xs.shift() || null; e = this.es.shift() || null; if (!x) if (!this.es.length) return true; else return false; else if (!e) return false; if ((this.capidx !== null) && (this.capturing)) { // console.log(' * adding cap ', x, 'e=', e, 'x=', x); cap = cap.concat([x]); } if (!wildcard(e)) { if (this.equality(e,x)) return this.match_(xs, cap); else return false; } else { switch (e) { case QM: // console.log('[?]'); return this.match_(xs, cap); break; case Star: // console.log('[*]'); if ((this.es[0] == x)) void 0; else if ((wildcard(this.es[0]) && (this.equality(this.es[1],x)))) { if (this.es[0] == $$) { cap.pop(); if (this.capidx === null) throw "Syntax error"; this.caps[this.capidx] = cap; this.capturing = false; this.es.shift(); return this.match_( xs, [] ); } this.es.shift() && this.match_(xs, cap); } else this.es = [e].concat(this.es); return this.match_(xs, cap); break; case $: // console.log('[$]'); if (this.capidx === null) this.capidx = 0; else this.capidx++; this.capturing = true; return this.match_( [x].concat(xs), [] ); break; case $$: console.log('[$$]'); if (this.capidx === null) throw "Syntax error"; cap.pop(); this.caps[this.capidx] = cap; this.capturing = false; // console.log(' cap=', cap); return this.match_( [x].concat(xs), [] ); break; } } return false; } }