Methods
cloneWithEvaluatorSync
-
Parameters
-
handleSubexpr: evaluatorSync
evalCommand
- evalCommand(handleSubexpr: evaluator): Promise<string>
-
Parameters
Returns Promise<string>
evalCommandSync
- evalCommandSync(handleSubexpr: evaluatorSync): string
-
Parameters
-
handleSubexpr: evaluatorSync
Returns string
evalEachFlag
- evalEachFlag(handleSubexpr: evaluatorSync, f: (name: string, payload: string, idx: number) => void): void
-
Parameters
-
handleSubexpr: evaluatorSync
-
f: (name: string, payload: string, idx: number) => void
-
- (name: string, payload: string, idx: number): void
-
Parameters
-
name: string
-
payload: string
-
idx: number
Returns void
Returns void
evalFlag
- evalFlag(handleSubexpr: evaluator, flag: string): Promise<string>
-
Parameters
-
handleSubexpr: evaluator
-
flag: string
Returns Promise<string>
evalFlagSync
- evalFlagSync(handleSubexpr: evaluatorSync, flag: string): string
-
Parameters
-
handleSubexpr: evaluatorSync
-
flag: string
Returns string
evalPositionals
- evalPositionals(handleSubexpr: evaluator): Promise<string[]>
-
Parameters
Returns Promise<string[]>
evalPositionalsSync
- evalPositionalsSync(handleSubexpr: evaluatorSync): string[]
-
Parameters
-
handleSubexpr: evaluatorSync
Returns string[]
forEachFlag
- forEachFlag(f: (name: string, payload: word<Expression>, idx: number) => void): void
-
Parameters
-
f: (name: string, payload: word<Expression>, idx: number) => void
-
- (name: string, payload: word<Expression>, idx: number): void
Returns void
hasFlag
- hasFlag(flag: string): boolean
-
Parameters
Returns boolean
The core type of my AST, this data-structure represents a single (sub-)command in an excmd script; and is the product of entry-points like [[Parser.expressionOfString]].
Construction
This JavaScript class, like most in my interface, cannot be constructed directly (i.e.
new Expression()
is going to throw an error); instead, you must invoke the parser via the functions in the exported Parser module.Evaluation
The language accepted by this parser allows for "sub-expressions" — runs of code that may remain unevaluated, to be executed at a later point.
The most direct method of interacting with these, is manually testing whether a particular method has produced a [[Literal]] or a [[Sub]]-expression, and proceeding as appropriate:
However, this can be tedious, if you only wish to evaluate simple expressions. For these situations, I provide a simplified "recursive evaluation" interface: by inverting control, you can allow the parser to become responsible for recursively evaluating [[Sub]] and [[Literal]] values into simple
string
s, as long as you can provide the parser with a simplified handler-callback that will attempt to reduce a single, given sub-expression into astring
.The entry-point to this auto-evaluation interface is either cloneWithEvaluator, or as a further convenience, the various
eval*
methods below: evalCommand, evalPositionals, and so on.Each of these takes a function — matching the [["index".evaluator | evaluator]] signature — that takes an expression, and mechanistically reduces it into a simple string:
(Note, additionally, that within the body of the evaluator above, I've only had to compare
expr.command
to a string, directly. As evaluators receive ExpressionEvals instead of plain expressions, their bodies need no further shenanigans; any requested expression-properties will recursively evaluate further subexpressions as-needed.)Finally, if you want to access multiple elements of an expression thusly, it may be easier to pre-associate an evaluator with the expression using cloneWithEvaluator, producing an ExpressionEval directly:
Mutation
Importantly, these
Expression
s are mutable views onto the underlying AST. They're designed to ensure you don't access the data-structure in an unsafe way. In particular, a givenword
in the original input-string can only be either a flag-payload, or a positional argument — not both.Consider the following:
Does that command have one flag, with the payload
world
? Or an empty (boolean) flag, and a single positional-argument,world
? My answer, in this interface, is “whichever you observe first”. To be more specific, any method of either Expression or ExpressionEval that produces flag-payloads or positional arguments, will mutate the data-structure such that subsequent accesses don't see an inconsistent state.Let's look at some examples:
Here, getFlag mutated
expr1
; and so a subsequent getPositionals produced a consistent result: there were no remaining positional arguments.Here, getPositionals mutated
expr2
; and so a subsequent getFlag, again, produced a consistent result: there was no value available to become the payload of-f
.This interface is intended to be used in a form wherein the invocations of these methods acts as the specification of the parser's behaviour. For example, one command might expect a flag
-d
or--dest
, and demand a payload for that flag; whereas another might use-d
as a boolean, and expect positionals. This way, the behaviour of the parser is flexible enough to handle both of those situations.Finally, note that at least for flags, there's also non-mutative accessors: you can always check whether a flag exists using hasFlag.