This site describes solve-engine as it is on main: 2.43.0, which npm does not have yet. npm installs 2.40.0, so a page may show an answer that version does not give yet.
ParseletRegistry
Defined in: packages/engine/src/parser/registry/ParseletRegistry.ts:68
ParseletRegistry, which accepts both string token types and integer token type IDs, the integer form being the fast dispatch in the Parser hot path.
Providers call registerPrefix(“NUMBER”, …) with string token types. Parser.parseExpression() looks a parselet up by token.typeId (integer), while diagnostics and error messages use token.type (string).
One map per kind, keyed by the integer ID. A name and its ID are one to one
(the process-wide table in lexer/Token.ts hands each name one ID for
good), so a lookup by name translates the name and reads the same map, and
getAllPrefix translates back. This used to keep a second,
string-keyed copy of each map as well. The built-in packages register more
than 256 prefix parselets, past the size at which a Map doubles its
table, so the copy cost every engine about 14KB for prefix parselets alone
and answered nothing the integer map does not.
Performance: Integer Map.get() avoids string hashing, saving ~2-5ns per dispatch. With ~10-15 dispatches per expression, that’s ~20-75ns.
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new ParseletRegistry(): ParseletRegistry;Returns
Section titled “Returns”ParseletRegistry
Accessors
Section titled “Accessors”infixCount
Section titled “infixCount”Get Signature
Section titled “Get Signature”get infixCount(): number;Defined in: packages/engine/src/parser/registry/ParseletRegistry.ts:177
Number of registered infix parselets.
Returns
Section titled “Returns”number
prefixCount
Section titled “prefixCount”Get Signature
Section titled “Get Signature”get prefixCount(): number;Defined in: packages/engine/src/parser/registry/ParseletRegistry.ts:174
Number of registered prefix parselets.
Returns
Section titled “Returns”number
Methods
Section titled “Methods”clear()
Section titled “clear()”clear(): void;Defined in: packages/engine/src/parser/registry/ParseletRegistry.ts:211
Remove every registered parselet.
Returns
Section titled “Returns”void
getAllInfix()
Section titled “getAllInfix()”getAllInfix(): { associativity: "left" | "right"; category?: string; leftBindingPower: number; rightBindingPower: number; tokenType: string;}[];Defined in: packages/engine/src/parser/registry/ParseletRegistry.ts:157
Iterate all registered infix parselets for diagnostic display.
The field an InfixParselet actually declares is bindingPower. This
used to read leftBindingPower and rightBindingPower, which no
parselet in this codebase declares, so both reads were undefined, both
fell to the ?? 0 default, and the public getParseletRegistry()
reported a binding power of 0 for every one of the ~60 infix operators.
A host building a precedence table from it was told * and + bind
equally, and that neither binds at all.
The left/right split: bindingPower is the LEFT power, and the right is
one higher. That is the standard encoding for a left-associative
operator, and it is what the parser itself does, see
PrecedenceParser.parseExpression()’s bp + 1 for the right operand.
An operator that declares rightAssociative (^) is reported with the
right power one BELOW the left, which is how it parses its right operand
(see parseRightOperand), and associativity says which in words.
Returns
Section titled “Returns”{
associativity: "left" | "right";
category?: string;
leftBindingPower: number;
rightBindingPower: number;
tokenType: string;
}[]
getAllPrefix()
Section titled “getAllPrefix()”getAllPrefix(): { bindingPower: number; category?: string; tokenType: string;}[];Defined in: packages/engine/src/parser/registry/ParseletRegistry.ts:126
Iterate all registered prefix parselets for diagnostic display.
PrefixParselet declares no binding power, and this used to read a field
of that name and report 0 for every one of them. 0 is not a neutral
wrong answer: it is the value that means “not an operator, stop the
expression”, so a host drawing a table from this was told none of them
bind at all. A prefix parselet in this parser has no per-parselet power
to report, they all bind at the prefix level and each chooses for itself
at what power to parse its own operand, so that level is what is
reported. A parselet that does carry its own bindingPower still wins.
Returns
Section titled “Returns”{
bindingPower: number;
category?: string;
tokenType: string;
}[]
getInfix()
Section titled “getInfix()”getInfix(tokenType): | InfixParselet | undefined;Defined in: packages/engine/src/parser/registry/ParseletRegistry.ts:195
Get infix parselet by string token type OR integer typeId. Fast path for integer IDs (Parser hot path), fallback for strings.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
tokenType | string | number |
Returns
Section titled “Returns”| InfixParselet
| undefined
getPrefix()
Section titled “getPrefix()”getPrefix(tokenType): | PrefixParselet | undefined;Defined in: packages/engine/src/parser/registry/ParseletRegistry.ts:186
Get prefix parselet by string token type OR integer typeId. Fast path for integer IDs (Parser hot path), fallback for strings (diagnostics, error messages, backwards compatibility). A name no token type was ever registered under has no parselet, and asking does not register it.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
tokenType | string | number |
Returns
Section titled “Returns”| PrefixParselet
| undefined
hasInfix()
Section titled “hasInfix()”hasInfix(tokenType): boolean;Defined in: packages/engine/src/parser/registry/ParseletRegistry.ts:206
Whether an infix parselet is registered for the token type tokenType.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
tokenType | string |
Returns
Section titled “Returns”boolean
hasPrefix()
Section titled “hasPrefix()”hasPrefix(tokenType): boolean;Defined in: packages/engine/src/parser/registry/ParseletRegistry.ts:201
Whether a prefix parselet is registered for the token type tokenType.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
tokenType | string |
Returns
Section titled “Returns”boolean
registerInfix()
Section titled “registerInfix()”registerInfix(tokenType, parselet): void;Defined in: packages/engine/src/parser/registry/ParseletRegistry.ts:105
Register an infix parselet for tokenType. See registerPrefix for the collision-warning behavior this mirrors.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
tokenType | string |
parselet | InfixParselet |
Returns
Section titled “Returns”void
registerPrefix()
Section titled “registerPrefix()”registerPrefix(tokenType, parselet): void;Defined in: packages/engine/src/parser/registry/ParseletRegistry.ts:95
Register a prefix parselet for tokenType.
If another parselet is already registered for this token type, it is
silently overwritten by default (Map.set() semantics), the old
parselet is simply unreachable from then on, with no error. This is
a real footgun for third-party packages: two packages independently
choosing the same custom token type will collide with zero signal
about which one “won”. Mirrors ResolverRegistry.register()‘s and
ExpressionEngine.registerPackage()‘s existing “warn and replace”
pattern for the same class of problem at the resolver-namespace and
package-name levels.
Note: this warns about registry-level collisions only. It does NOT
detect the separate case where tokenType is one of PrecedenceParser’s
Tier-1 fast-path token types (NUMBER, STRING, IDENT, LPAREN, MINUS,
PLUS, and the Tier-1 infix operators), those are deliberately kept
registered here for introspection/diagnostics even though Tier-1
always intercepts them before this registry is consulted (see
PrecedenceParser.parsePrefix()‘s docs), so warning there would
misfire on that intentional, already-documented pattern.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
tokenType | string |
parselet | PrefixParselet |
Returns
Section titled “Returns”void