consys
Version:
consys is a flexible tool to evaluate models using generic and readable constraints.
270 lines (269 loc) • 8.11 kB
TypeScript
import Token from './Token';
import { Expression } from './Expression';
/**
* This class transforms a given list of tokens into an abstract syntax tree mirroring the dsl grammar.
* Syntax definition for constraints:
*
* constraint -> activation ( ":" | "THEN" ) assertion ;
* activation -> "ALWAYS" | "WHEN" | "IF" expression | functionExpr ;
* assertion -> expression ;
*
* expression -> disjunction ;
* disjunction -> conjunction ( ( "||" | "OR" ) conjunction )* ;
* conjunction -> equality ( ( "&&" | "AND" ) equality )* ;
* equality -> comparison ( ( "==" | "!=" ) comparison )? ;
* comparison -> term ( ( "<" | "<=" | ">=" | ">" ) term )? ;
* term -> factor ( ( "+" | "-" ) factor )* ;
* factor -> unary ( ( "*" | "/" | "%" ) unary )* ;
* unary -> ( "!" | "-" | "NOT" ) unary | primary ;
* primary -> number | string | variable | function | "(" expression ")" ;
*
* variable -> model | state ;
* model -> "$" ( nested )? ;
* state -> "#" ( nested )? ;
* nested -> identifier ( "." identifier )* ;
*
* function -> functionExpr | identifier "(" ( arguments )? ")" ;
* arguments -> expression ( "," expression )* ;
* functionExpr -> identifier ;
*
* number -> natural ( digit )* ( "." ( digit )+ )? ;
* string -> "'" ( character )* "'" ;
* identifier -> alpha ( alpha | digit | "_" )* ;
*
* digit -> zero | natural ;
* character -> digit | alpha ;
* zero -> "0" ;
* natural -> "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
* alpha -> "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" |
* "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" |
* "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "a" |
* "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" |
* "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" |
* "t" | "u" | "v" | "w" | "x" | "y" | "z" ;
*/
export default class Parser {
private readonly source;
private readonly tokens;
private current;
private statistics;
/**
* Creates a new parser instance from a given string of source code and a list of tokens.
*
* @param source source code
* @param tokens list of tokens
*/
constructor(source: string, tokens: Token[]);
/**
* Returns the ast for the given token list for a constraint.
*/
parse(): Expression.AST;
/**
* Returns the ast for the given token list for a model.
*/
parseModel(): Expression.AST;
/**
* Returns the ast for the given token list for a state.
*/
parseState(): Expression.AST;
/**
* Returns the ast for the given token list for a function.
*/
parseFunction(): Expression.AST;
/**
* Returns the ast for the given token list for a function expression.
*/
parseFunctionExpr(): Expression.AST;
/**
* Starts the parsing algorithm with a given starting rule.
*
* @param start starting rule
* @param emptyMessage error message if an empty list is given (single eof token)
* @private
*/
private run;
/**
* Matches this rule:
* constraint -> activation ( ":" | "THEN" ) assertion ;
* @private
*/
private constraint;
/**
* Matches this rule:
* activation -> "ALWAYS" | "WHEN" | "IF" expression | functionExpr ;
* @private
*/
private activation;
/**
* Matches this rule:
* assertion -> expression ;
* @private
*/
private assertion;
/**
* Matches this rule:
* expression -> disjunction ;
* @private
*/
private expression;
/**
* Matches this rule:
* disjunction -> conjunction ( ( "||" | "OR" ) conjunction )* ;
* @private
*/
private disjunction;
/**
* Matches this rule:
* conjunction -> equality ( ( "&&" | "AND" ) equality )* ;
* @private
*/
private conjunction;
/**
* Matches this rule:
* equality -> comparison ( ( "==" | "!=" ) comparison )? ;
* @private
*/
private equality;
/**
* Matches this rule:
* comparison -> term ( ( "<" | "<=" | ">=" | ">" ) term )? ;
* @private
*/
private comparison;
/**
* Matches this rule:
* term -> factor ( ( "+" | "-" ) factor )* ;
* @private
*/
private term;
/**
* Matches this rule:
* factor -> unary ( ( "*" | "/" | "%" ) unary )* ;
* @private
*/
private factor;
/**
* Matches this rule:
* unary -> ( "!" | "-" | "NOT" ) unary | primary ;
* @private
*/
private unary;
/**
* Matches this rule:
* primary -> number | string | variable | function | "(" expression ")" ;
* @private
*/
private primary;
/**
* Matches this rule:
* variable -> model | state ;
* model -> "$" ( nested )? ;
* state -> "#" ( nested )? ;
* nested -> identifier ( "." identifier )* ;
* @private
*/
private variable;
/**
* Matches this rule:
* function -> functionExpr | identifier "(" ( arguments )? ")" ;
* @private
*/
private functionCall;
/**
* Matches this rule:
* arguments -> expression ( "," expression )* ;
* @private
*/
private args;
/**
* Matches this rule:
* functionExpr -> identifier ;
* @private
*/
private functionExpr;
/**
* Parses a rule with the following format:
* rule -> production ( ( operators[0] | operators[1] | ... ) production )* ;
*
* @param logical true if currently parsing a logical expression
* @param production production function pointer
* @param operators binary operators of this rule
* @private
*/
private parseLeftAssociativeBinaryOperator;
/**
* Parses a rule with the following format:
* rule -> production ( ( operators[0] | operators[1] | ... ) production )? ;
*
* @param production production function pointer
* @param operators binary operators of this rule
* @private
*/
private parseLeftAssociativeOptionalBinaryOperator;
/**
* Adds a variable of given type (model or state) to the statistics counts.
*
* @param type variable type
* @param name variable name
* @private
*/
private addStatisticsVariable;
/**
* Consumes the current token if any of the given token types matches the current token.
*
* @param types token types to match
* @private
*/
private matchAny;
/**
* Consumes the current token.
*
* @param type token type
* @param message error message if current token is not of given type
* @private
*/
private consume;
/**
* Consumes the current token if it matches any of the given token types.
*
* @param message error message if current token is not of any given type
* @param types token types
* @private
*/
private consumeAny;
/**
* Check if the current token is of the given type.
*
* @param type token type to check
* @private
*/
private check;
/**
* Consumes the current token.
* @private
*/
private advance;
/**
* Checks if the parser is done.
* @private
*/
private isAtEnd;
/**
* Returns the current token.
* @private
*/
private peek;
/**
* Returns the previous token.
* @private
*/
private previous;
/**
* Prints an error message and then throws an error.
*
* @param token token where the error occurred
* @param message error message
* @private
*/
private syntaxErrorOnToken;
}