formula-fields-parser
This repository contains the WIP Formula Fields Parser. Currently implemented:
- Lexer
- Parser
- Visitor
- Symbol Table
- Semantic Analysis
Exports
Parser
- The formula fields parservisit
- The formula fields AST Visitorerrors
- Built in errors for use with the
visitorvalidate
- The formula fields semantic analysiswithPostProcessors
- A function to add post-processors to the parse and
validate logic, similar to redux middleware. See the detailed explanation
for more information
default
The default export is a convenience function that takes the text of a formula,
parses it, and runs semantic validation. It takes the following parameters:
formulaText
- The formula textoptions
- An object containing options for parsing. Note that this object
is also passed to all post-processors, so it can
contain additional options if needed.
parseOptions
- An object containing the options to give to the parserrecordType
- The type schema for the record this formula is bound to. If
provided, it will be used during validation to ensure all fields referenced in
the formula exist on the given type.optimizations
- An object containing flags turning optimizations on or off
Result
It returns an object with the following properties:
ast
- The formula abstract syntax tree. This may
be undefined if there are errors during the lexing or parsing phases.errors
- An array of any lex,
parse, or semantic
errors that occurred when validating the formula.
All errors are guaranteed to have the following properties, although some may
have additional:
name
- The name of the error type (e.g. MismatchedTokenException)message
- The error messagelocation
- The location where the error occurred
Parse Example
import parse from '@lanetix/formula-fields-parser'
const { ast, errors } = parse('CONCAT($first_name, $last_name)')
const recordType = ...
const { ast, errors } = parse('CONCAT($first_name, $last_name)', { recordType })
const { ast, errors } = parse('CONCAT("Hello ", "World")', { optimizations: { constantFold: false } })
import parse, { Parser } from '@lanetix/formula-fields-parser'
const { ast, errors } = parse('"Hello World"', { parseOptions: { rule: Parser.stringLiteral } })
withPostProcessors
In addition to the normal parse -> optimize -> validate pipeline provided by the
default export, additional post processors can be specified. Post-
processors are extremely similar to Redux middleware,
and it is advised to be familiar with such before continuing.
Post-Processor Explanation
Post processors have the following signature:
next => (parseResult, options) => { /* Implementation Logic */ }
-
next
- The next post processor in the chain. If not called, the post-
processing chain will be aborted here. It must be called with parseResult
and options
, although the implementation logic is free to modify both objects
-
parseResult
- The parse result. Additional
properties may be added, but ast
and errors
must always conform to the
parse result standard format
-
options
- The options object given. If none are given, this
will be an empty object, rather than undefined
.
withPostProcessors
Examples
Logs out the ast when the logAst
option is set to true
import { withPostProcessors } from '@lanetix/formula-fields-parser'
const logAst = next => (parseResult, options) => {
if (options.logAst) {
console.log(parseResult.ast)
}
return next(parseResult, options)
}
const parse = withPostProcessors(logAst)
const { ast, errors } = parse('CONCAT("Hello ", $name)')
const { ast, errors } = parse('CONCAT("Hello ", $name)', { logAst: true })
const options = {
logAst: true,
optimizations: {
constantFold: false
}
}
const { ast, errors } = parse('CONCAT("Hello ", "World")', options)
Conditionally return either the ast or the errors
import { withPostProcessors } from '@lanetix/formula-fields-parser'
const astOrError = next => (parseResult, options) => {
if (parseResult.errors.length > 0) {
return errors
} else {
return parseResult.ast
}
}
const parse = withPostProcessors(astOrError)
const result = parse('CONCAT("Hello ", $name)')
const result = parse('CONCAT(')