I would like to write in (current) Typescript a general parser parameterized over symbols particular to language grammars.
Below is the simplest of several tried approaches of parameterizing Sym, the type for the symbols that varies per language grammar, but the first line in Parser.js fails type checking:
Type
Symdoes not satisfy the constraintstring | number | symbol.
Every way I tried to adjust the definition of GrammarRules<Sym> that resolved the issue unfortunately resulted in further downstream problems, only some of portion of which were themselves resolvable – couldn't find a full solution.
How can I define the symbol type, Sym, differently for each parser language and handle generically in Parser.js? I'm open to substantially re-working some or all of the declarations and code to get the cleanest overall solution.
Parser.ts
export type GrammarRules<Sym> = Record<Sym, GrammarRule<Sym>>
export type GrammarRule<Sym> = { lhs: Sym /* further uses of Sym type */ }
export class Parser<Sym> {
rules: GrammarRules<Sym>
private str: string
/* Various other datastructure declarations with types dependent on Sym */
constructor(rules: GrammarRules<Sym>) {
this.rules = rules
}
parse(startSym: Sym, str: string) {
this.str = str
console.log(this.rules[startSym].lhs)
// ...
}
}
ParserLangABC.ts
import { Parser, GrammarRules } from "./Parser"
type Sym = 'A' | 'B' | 'C'
const rulesABC: GrammarRules<Sym> = {
A: { lhs: 'A' /* rhs with further data of type Sym */ },
B: { lhs: 'B' /* rhs with further data of type Sym */ },
C: { lhs: 'C' /* rhs with further data of type Sym */ }
}
class ParserLangABC<Sym> extends Parser<Sym> {
static parse(str: string) {
const parser = new Parser(rulesABC)
parser.parse('A', str)
}
// Other supporting methods parameterized to Sym
}
ParserLangDEF.ts
import { Parser, GrammarRules } from "./Parser"
type Sym = 'D' | 'E' | 'F'
const rulesDEF: GrammarRules<Sym> = {
D: { lhs: 'D' /* rhs with further data of type Sym */ },
E: { lhs: 'E' /* rhs with further data of type Sym */ },
F: { lhs: 'F' /* rhs with further data of type Sym */ }
}
class ParserLangDEF<Sym> extends Parser<Sym> {
static parse(str: string) {
const parser = new Parser(rulesDEF)
parser.parse('D', str)
}
// Other supporting methods parameterized to Sym
}