UNPKG

ohm-js

Version:

An object-oriented language for parsing and pattern matching

189 lines (148 loc) 3.85 kB
import {UnicodeCategories} from './UnicodeCategories.js'; import * as common from './common.js'; // -------------------------------------------------------------------- // Private stuff // -------------------------------------------------------------------- // General stuff export class PExpr { constructor() { if (this.constructor === PExpr) { throw new Error("PExpr cannot be instantiated -- it's abstract"); } } // Set the `source` property to the interval containing the source for this expression. withSource(interval) { if (interval) { this.source = interval.trimmed(); } return this; } } // Any export const any = Object.create(PExpr.prototype); // End export const end = Object.create(PExpr.prototype); // Terminals export class Terminal extends PExpr { constructor(obj) { super(); this.obj = obj; } } // Ranges export class Range extends PExpr { constructor(from, to) { super(); this.from = from; this.to = to; // If either `from` or `to` is made up of multiple code units, then // the range should consume a full code point, not a single code unit. this.matchCodePoint = from.length > 1 || to.length > 1; } } // Parameters export class Param extends PExpr { constructor(index) { super(); this.index = index; } } // Alternation export class Alt extends PExpr { constructor(terms) { super(); this.terms = terms; } } // Extend is an implementation detail of rule extension export class Extend extends Alt { constructor(superGrammar, name, body) { const origBody = superGrammar.rules[name].body; super([body, origBody]); this.superGrammar = superGrammar; this.name = name; this.body = body; } } // Splice is an implementation detail of rule overriding with the `...` operator. export class Splice extends Alt { constructor(superGrammar, ruleName, beforeTerms, afterTerms) { const origBody = superGrammar.rules[ruleName].body; super([...beforeTerms, origBody, ...afterTerms]); this.superGrammar = superGrammar; this.ruleName = ruleName; this.expansionPos = beforeTerms.length; } } // Sequences export class Seq extends PExpr { constructor(factors) { super(); this.factors = factors; } } // Iterators and optionals export class Iter extends PExpr { constructor(expr) { super(); this.expr = expr; } } export class Star extends Iter {} export class Plus extends Iter {} export class Opt extends Iter {} Star.prototype.operator = '*'; Plus.prototype.operator = '+'; Opt.prototype.operator = '?'; Star.prototype.minNumMatches = 0; Plus.prototype.minNumMatches = 1; Opt.prototype.minNumMatches = 0; Star.prototype.maxNumMatches = Number.POSITIVE_INFINITY; Plus.prototype.maxNumMatches = Number.POSITIVE_INFINITY; Opt.prototype.maxNumMatches = 1; // Predicates export class Not extends PExpr { constructor(expr) { super(); this.expr = expr; } } export class Lookahead extends PExpr { constructor(expr) { super(); this.expr = expr; } } // "Lexification" export class Lex extends PExpr { constructor(expr) { super(); this.expr = expr; } } // Rule application export class Apply extends PExpr { constructor(ruleName, args = []) { super(); this.ruleName = ruleName; this.args = args; } isSyntactic() { return common.isSyntactic(this.ruleName); } // This method just caches the result of `this.toString()` in a non-enumerable property. toMemoKey() { if (!this._memoKey) { Object.defineProperty(this, '_memoKey', {value: this.toString()}); } return this._memoKey; } } // Unicode character export class UnicodeChar extends PExpr { constructor(category) { super(); this.category = category; this.pattern = UnicodeCategories[category]; } }