Spaces:
Runtime error
Runtime error
| module.exports = grammar({ | |
| name: 'ql', | |
| conflicts: $ => [ | |
| [$.simpleId, $.className], | |
| [$.simpleId, $.literalId], | |
| [$.moduleName, $.varName], | |
| [$.simpleId, $.moduleInstantiation], | |
| [$.className, $.moduleInstantiation], | |
| ], | |
| extras: $ => [ | |
| /[ \t\r\n]/, | |
| $.line_comment, | |
| $.block_comment, | |
| ], | |
| word: $ => $._lower_id, | |
| rules: { | |
| ql: $ => repeat($.moduleMember), | |
| module: $ => seq( | |
| 'module', | |
| field("name", $.moduleName), | |
| optional( | |
| seq( | |
| "<", | |
| sep1(field('parameter', $.moduleParam), ","), | |
| ">" | |
| ) | |
| ), | |
| optional(seq( | |
| "implements", | |
| sep1(field('implements', $.signatureExpr), ",") | |
| )), | |
| choice( | |
| seq( | |
| "{", | |
| repeat($.moduleMember), | |
| "}" | |
| ), | |
| $.moduleAliasBody | |
| ) | |
| ), | |
| moduleMember: $ => choice( | |
| seq( | |
| repeat($.annotation), | |
| choice($.importDirective, $.classlessPredicate, $.dataclass, $.datatype, $.select, $.module) | |
| ), | |
| $.qldoc | |
| ), | |
| importDirective: $ => seq( | |
| 'import', | |
| $.importModuleExpr, | |
| optional(seq('as', $.moduleName)) | |
| ), | |
| moduleAliasBody: $ => seq('=', $.moduleExpr, ";"), | |
| predicateAliasBody: $ => seq('=', $.predicateExpr, ";"), | |
| typeAliasBody: $ => seq('=', $.typeExpr, ";"), | |
| typeUnionBody: $ => seq('=', $.typeExpr, "or", sep($.typeExpr, "or"), ";"), | |
| classlessPredicate: $ => seq( | |
| field("returnType", choice($.predicate, $.typeExpr)), | |
| field("name", $.predicateName), | |
| choice( | |
| seq("(", sep($.varDecl, ","), ")", $._optbody), | |
| $.predicateAliasBody | |
| ) | |
| ), | |
| datatype: $ => seq( | |
| 'newtype', | |
| field("name", $.className), | |
| '=', | |
| $.datatypeBranches | |
| ), | |
| datatypeBranches: $ => sep1($.datatypeBranch, "or"), | |
| datatypeBranch: $ => seq( | |
| optional($.qldoc), | |
| optional($.annotation), | |
| field("name", $.className), | |
| "(", | |
| sep($.varDecl, ","), | |
| ")", | |
| optional($.body) | |
| ), | |
| select: $ => seq( | |
| optional(seq("from", sep($.varDecl, ","))), | |
| optional(seq("where", $._exprOrTerm)), | |
| seq('select', $.asExprs, optional($.orderBys)) | |
| ), | |
| dataclass: $ => seq( | |
| 'class', | |
| field("name", $.className), | |
| choice( | |
| seq( | |
| optional(field("extends", seq('extends', sep1($.typeExpr, ",")))), | |
| optional(field("instanceof", seq('instanceof', sep1($.typeExpr, ",")))), | |
| choice( | |
| seq( | |
| "{", | |
| repeat($.classMember), | |
| "}" | |
| ), | |
| ";" | |
| ) | |
| ), | |
| $.typeAliasBody, | |
| $.typeUnionBody | |
| ) | |
| ), | |
| classMember: $ => choice( | |
| seq( | |
| repeat($.annotation), | |
| choice($.charpred, $.memberPredicate, $.field) | |
| ), | |
| $.qldoc | |
| ), | |
| charpred: $ => seq($.className, "(", ")", "{", field('body', $._exprOrTerm), "}"), | |
| memberPredicate: $ => seq( | |
| field("returnType", choice($.predicate, $.typeExpr)), | |
| field("name", $.predicateName), | |
| "(", | |
| sep($.varDecl, ","), | |
| ")", | |
| $._optbody | |
| ), | |
| field: $ => seq($.varDecl, ";"), | |
| _optbody: $ => choice( | |
| $.empty, | |
| $.body, | |
| $.higherOrderTerm | |
| ), | |
| empty: $ => ";", | |
| body: $ => seq("{", $._exprOrTerm, "}"), | |
| higherOrderTerm: $ => seq( | |
| '=', | |
| field("name", $.literalId), | |
| "(", | |
| sep($.predicateExpr, ","), | |
| ")", | |
| "(", | |
| sep($._call_arg, ","), | |
| ")" | |
| ), | |
| special_call: $ => seq($.specialId, "(", ")"), | |
| prefix_cast: $ => prec.dynamic(10, seq("(", $.typeExpr, ")", $._exprOrTerm)), | |
| unary_expr: $ => prec.left(9, seq($.unop, $._exprOrTerm)), | |
| mul_expr: $ => prec.left(9, seq( | |
| field('left', $._exprOrTerm), | |
| $.mulop, | |
| field('right', $._exprOrTerm) | |
| )), | |
| add_expr: $ => prec.left(8, seq( | |
| field('left', $._exprOrTerm), | |
| $.addop, | |
| field('right', $._exprOrTerm) | |
| )), | |
| in_expr: $ => prec.left(7, seq( | |
| field('left', $._exprOrTerm), | |
| 'in', | |
| field('right', $._primary) | |
| )), | |
| comp_term: $ => prec.left(6, seq( | |
| field('left', $._exprOrTerm), | |
| $.compop, | |
| field('right', $._exprOrTerm) | |
| )), | |
| instance_of: $ => prec.left(5, seq($._exprOrTerm, 'instanceof', $.typeExpr)), | |
| negation: $ => prec.left(4, seq('not', $._exprOrTerm)), | |
| if_term: $ => prec.left(3, seq( | |
| "if", field('cond', $._exprOrTerm), | |
| "then", field('first', $._exprOrTerm), | |
| "else", field('second', $._exprOrTerm) | |
| )), | |
| conjunction: $ => prec.left(3, seq( | |
| field('left', $._exprOrTerm), | |
| "and", | |
| field('right', $._exprOrTerm) | |
| )), | |
| disjunction: $ => prec.left(2, seq( | |
| field('left', $._exprOrTerm), | |
| "or", | |
| field('right', $._exprOrTerm) | |
| )), | |
| implication: $ => prec.left(1, seq( | |
| field('left', $._exprOrTerm), | |
| "implies", | |
| field('right', $._exprOrTerm) | |
| )), | |
| quantified: $ => seq($.quantifier, "(", | |
| choice( | |
| seq( | |
| sep($.varDecl, ","), | |
| optional(seq("|", field('range', $._exprOrTerm), optional(seq("|", field('formula', $._exprOrTerm))))) | |
| ), | |
| field('expr', $._exprOrTerm) | |
| ), | |
| ")"), | |
| specialId: $ => 'none', | |
| quantifier: $ => choice('exists', 'forall', 'forex'), | |
| _call_arg: $ => choice( | |
| $._exprOrTerm, // ExprArg | |
| $.underscore // DontCare | |
| ), | |
| underscore: $ => '_', | |
| qualifiedRhs: $ => choice( | |
| seq( // QualCall | |
| field("name", $.predicateName), | |
| optional($.closure), | |
| "(", | |
| sep($._call_arg, ","), | |
| ")" | |
| ), | |
| seq( // QualCast | |
| "(", | |
| $.typeExpr, | |
| ")" | |
| ) | |
| ), | |
| call_body: $ => seq("(", sep($._call_arg, ","), ")"), | |
| unqual_agg_body: $ => seq( | |
| "(", | |
| sep($.varDecl, ","), | |
| "|", | |
| field('guard', optional($._exprOrTerm)), | |
| field('asExprs', optional(seq("|", $.asExprs))), | |
| ")" | |
| ), | |
| _call_or_unqual_agg_body: $ => choice($.call_body, $.unqual_agg_body), | |
| call_or_unqual_agg_expr: $ => prec.dynamic(10, seq($.aritylessPredicateExpr, optional($.closure), $._call_or_unqual_agg_body)), | |
| qualified_expr: $ => seq($._primary, ".", $.qualifiedRhs), | |
| super_ref: $ => seq(optional(seq($.typeExpr, ".")), $.super), | |
| // The split here is to ensure that the node is non-empty | |
| full_aggregate_body: $ => choice( | |
| seq(sep($.varDecl, ","), | |
| seq( | |
| "|", | |
| field('guard', optional($._exprOrTerm)), | |
| optional(seq("|", field('asExprs', $.asExprs), field('orderBys', optional($.orderBys)))) | |
| ) | |
| ), | |
| sep1($.varDecl, ","), | |
| ), | |
| expr_aggregate_body: $ => seq(field('asExprs', $.asExprs), field('orderBys', optional($.orderBys))), | |
| aggregate: $ => seq($.aggId, // Agg | |
| optional( | |
| seq("[", sep1($._exprOrTerm, ","), "]") | |
| ), | |
| "(", | |
| optional( | |
| choice($.full_aggregate_body, $.expr_aggregate_body) | |
| ), | |
| ")" | |
| ), | |
| range: $ => seq( // Range | |
| "[", | |
| field('lower', $._exprOrTerm), "..", field('upper', $._exprOrTerm), | |
| "]" | |
| ), | |
| set_literal: $ => seq( | |
| "[", | |
| sep($._exprOrTerm, ','), | |
| optional(','), | |
| "]" | |
| ), | |
| par_expr: $ => seq("(", $._exprOrTerm, ")"), | |
| expr_annotation: $ => seq( | |
| field('name', $.annotName), | |
| "[", | |
| field('annot_arg', $.annotName), | |
| "]", | |
| "(", | |
| $._exprOrTerm, | |
| ")", | |
| ), | |
| _exprOrTerm: $ => choice( | |
| $.special_call, | |
| $.prefix_cast, | |
| $._primary, | |
| $.unary_expr, | |
| $.mul_expr, | |
| $.add_expr, | |
| $.in_expr, | |
| $.comp_term, | |
| $.instance_of, | |
| $.negation, | |
| $.if_term, | |
| $.conjunction, | |
| $.disjunction, | |
| $.implication, | |
| $.quantified, // QuantifiedTerm | |
| ), | |
| _primary: $ => choice( | |
| $.call_or_unqual_agg_expr, // | |
| $.qualified_expr, // QualifiedExpr | |
| $.literal, // Lit | |
| $.variable, // Var | |
| $.super_ref, | |
| $.aggregate, | |
| $.range, | |
| $.set_literal, | |
| $.par_expr, // ParExpr | |
| $.expr_annotation, // ExprAnnotation | |
| ), | |
| literal: $ => choice( | |
| $.integer, // IntLit | |
| $.float, // FloatLit | |
| $.bool, // BoolLit | |
| $.string // StringLit | |
| ), | |
| bool: $ => choice($.true, $.false), | |
| variable: $ => choice($.this, $.result, $.varName), | |
| compop: $ => choice('=', '!=', '<', '>', '<=', '>='), | |
| unop: $ => choice('+', '-'), | |
| mulop: $ => choice('*', '/', '%'), | |
| addop: $ => choice('+', '-'), | |
| closure: $ => choice('*', '+'), | |
| direction: $ => choice('asc', 'desc'), | |
| varDecl: $ => seq($.typeExpr, $.varName), | |
| moduleParam: $ => seq( | |
| field('signature', $.signatureExpr), | |
| field('parameter', $.simpleId) | |
| ), | |
| asExprs: $ => sep1($.asExpr, ","), | |
| asExpr: $ => seq($._exprOrTerm, optional(seq('as', $.varName))), | |
| orderBys: $ => seq("order", "by", sep1($.orderBy, ",")), | |
| orderBy: $ => seq($._exprOrTerm, optional($.direction)), | |
| qldoc: $ => /\/\*\*[^*]*\*+([^/*][^*]*\*+)*\//, | |
| literalId: $ => choice($._lower_id, $._upper_id), | |
| annotation: $ => choice( | |
| field('name', $.annotName), // SimpleAnnotation | |
| seq( // ArgsAnnotation | |
| field('name', $.annotName), | |
| "[", | |
| field('args', sep1($.annotArg, ",")), | |
| "]" | |
| ) | |
| ), | |
| annotName: $ => $._lower_id, | |
| annotArg: $ => choice($.simpleId, $.this, $.result), | |
| moduleName: $ => $.simpleId, | |
| importModuleExpr: $ => seq( | |
| repeat(seq(field("qualName", $.simpleId), ".")), | |
| $.moduleExpr | |
| ), | |
| moduleExpr: $ => choice( | |
| $.simpleId, | |
| $.moduleInstantiation, | |
| seq($.moduleExpr, "::", field("name", choice($.simpleId, $.moduleInstantiation))) | |
| ), | |
| moduleInstantiation: $ => seq( | |
| field("name", $.moduleName), | |
| "<", | |
| sep1($.signatureExpr, ","), | |
| ">" | |
| ), | |
| primitiveType: $ => choice('boolean', 'date', 'float', 'int', 'string'), | |
| simpleId: $ => choice($._lower_id, $._upper_id), | |
| className: $ => $._upper_id, | |
| dbtype: $ => /@[a-z][A-Za-z0-9_]*/, | |
| typeExpr: $ => choice( | |
| seq(optional(seq(field("qualifier", $.moduleExpr), "::")), field("name", $.className)), | |
| $.dbtype, | |
| $.primitiveType | |
| ), | |
| signatureExpr: $ => choice( | |
| field("type_expr", $.typeExpr), | |
| field("mod_expr", $.moduleExpr), | |
| field("predicate", $.predicateExpr) | |
| ), | |
| predicateName: $ => $._lower_id, | |
| aritylessPredicateExpr: $ => seq(optional(seq(field('qualifier', $.moduleExpr), "::")), field("name", $.literalId)), | |
| predicateExpr: $ => seq($.aritylessPredicateExpr, '/', $.integer), | |
| varName: $ => $.simpleId, | |
| aggId: $ => choice('avg', 'concat', 'strictconcat', 'count', 'max', 'min', 'rank', 'strictcount', 'strictsum', 'sum', 'any', 'unique'), | |
| _upper_id: $ => /[A-Z][A-Za-z0-9_]*/, | |
| _lower_id: $ => /[a-z][A-Za-z0-9_]*/, | |
| integer: $ => /[0-9]+/, | |
| float: $ => /[0-9]+\.[0-9]+/, | |
| string: $ => /"([^"\\\r\n\t]|\\["\\nrt])*"/, | |
| line_comment: $ => /\/\/[^\r\n]*/, | |
| block_comment: $ => /\/\*([^*]+\*+([^/*][^*]*\*+)*|\*)\//, | |
| false: $ => 'false', | |
| predicate: $ => 'predicate', | |
| result: $ => 'result', | |
| super: $ => 'super', | |
| this: $ => 'this', | |
| true: $ => 'true', | |
| } | |
| }); | |
| function sep(rule, s) { | |
| return optional(sep1(rule, s)) | |
| } | |
| function sep1(rule, s) { | |
| return seq(rule, repeat(seq(s, rule))) | |
| } | |