-
Notifications
You must be signed in to change notification settings - Fork 0
SyntaxParser
HC uses a version of applicative-parsing, which is similar to monadic parsing. The core idea is to define a generic combinator that consumes and aggregates elements that get chained together to form the Abstract Syntax Tree (AST). Of course, since Frame is fully homoiconic, the AST is simply a tree of Frames, including FrameExpr's that can be directly evaluated to product a result.
The core class is SyntaxCombinator.
We initialize them as an array, since we can extract the key from an instantiated object.
export const terminals = [
SyntaxNest(FrameGroup),
SyntaxNest(FrameArray),
SyntaxNest(FrameLazyGroup),
SyntaxFinish(FrameExpr, ","),
SyntaxFinish(FrameStatement, ";"),
SyntaxEnd(Frame.kEND)
];Those methods all return factory functions which instantiate those classes using the current Array<Frame> state.
Tokens operate similarly, but each item constructed from a string (at this level, every Frame is a character represented as FrameSymbol, so Array<FrameSymbol> can be concatenated into a JavaScript string).
export const tokens = [
SyntaxQuote(FrameString),
SyntaxQuote(FrameComment),
SyntaxQuote(FrameBlob),
SyntaxItem(FrameSymbol),
SyntaxItem(FrameName),
SyntaxItem(FrameNumber),
SyntaxItem(FrameReference),
SyntaxItem(FrameControl)
];Those are used to create a lexer, which feeds into the pipeline. const lex_pipe = make_lexer(tokens, terminals);
export const evaluate = (input: string, context = Void): Frame => {
const result = new FrameArray([], context); // store the result
const evaluator = new EvalPipe(result); // evaluate lists into results
const grouper = new GroupPipe(evaluator); // group expressions into lists
const parser = new ParsePipe(grouper); // parse tokens into expressions
const lexer = lex_pipe(parser); // lex characters into tokens
lexer.lex_string(input);
return result;
};