|
|
@@ -0,0 +1,604 @@
|
|
|
+{
|
|
|
+ /*global parse, options, offset, line, column, text, SyntaxError*/
|
|
|
+ //TODO: the 'MP2-parser.rig' takes a scope and bakes it into the output we will do that elsewhere
|
|
|
+ //TODO: the 'MP2-parser.rig' checks for various error scenarios that we might bake into this
|
|
|
+ //TODO: when we get to bool_expr might look into using the `ast-types` npm to make any code generation easier (escodegen)
|
|
|
+ var opts = arguments[2] || options,
|
|
|
+ fileName = opts.fileName || "NOFILENAME",
|
|
|
+ locations = opts.locations !== undefined ? opts.locations : false,
|
|
|
+ comments = opts.comments !== undefined ? opts.comments : false;
|
|
|
+
|
|
|
+ var uniqueNumber = 0,
|
|
|
+ getUniqueNumber = function getUniqueNumber() {
|
|
|
+ return uniqueNumber++;
|
|
|
+ };
|
|
|
+
|
|
|
+ var err = function err(msg, suffix) {
|
|
|
+ if (typeof msg === "number") msg = "ERR" + msg + ": " + errors[msg];
|
|
|
+ if (suffix) msg += suffix;
|
|
|
+ return new SyntaxError(msg, null, null, offset(), line(), column());
|
|
|
+ };
|
|
|
+
|
|
|
+ var ast = {
|
|
|
+
|
|
|
+ errors: [], // tracks all of the non-grammatical errors
|
|
|
+
|
|
|
+ rulesById: {}, // track all of the rules by their ID
|
|
|
+
|
|
|
+ Base: function Base(type) {
|
|
|
+ this.type = type;
|
|
|
+ if (locations) {
|
|
|
+ this.location = {
|
|
|
+ pos: offset(),
|
|
|
+ line: line(),
|
|
|
+ col: column(),
|
|
|
+ len: text().length,
|
|
|
+ };
|
|
|
+ }
|
|
|
+ if (comments && type !== "Comment") {
|
|
|
+ //TODO: not attached in right place
|
|
|
+ this.comments = ast._comments;
|
|
|
+ ast._comments = [];
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ _comments: [],
|
|
|
+ Comment: function Comment(block, text) {
|
|
|
+ ast.Base.call(this, "Comment");
|
|
|
+ this.block = block;
|
|
|
+ this.text = text;
|
|
|
+ ast._comments.push(this);
|
|
|
+ },
|
|
|
+
|
|
|
+ Id: function Id(type, id) {
|
|
|
+ ast.Base.call(this, type);
|
|
|
+ this.id = id;
|
|
|
+ },
|
|
|
+
|
|
|
+ Schema: function Schema(includes, statements) {
|
|
|
+ ast.Id.call(this, "Schema", fileName);
|
|
|
+ this.includes = includes;
|
|
|
+ this.statements = statements;
|
|
|
+ },
|
|
|
+
|
|
|
+ Include: function Include(id) {
|
|
|
+ throw err(12, "INCLUDE");
|
|
|
+ ast.Id.call(this, "Include", id);
|
|
|
+ },
|
|
|
+
|
|
|
+ Rule: function Rule(id, ruleType, patterns, buildBlock) {
|
|
|
+ ast.Id.call(this, "Rule", id);
|
|
|
+ this.ruleType = ruleType;
|
|
|
+ // this.refId = "Comp_" + getUniqueNumber(); // aka "work_name" in RIGAL code
|
|
|
+ this.patterns = patterns;
|
|
|
+ // this.buildBlock = buildBlock;
|
|
|
+ },
|
|
|
+
|
|
|
+ RootRule: function RootRule(id, patterns, buildBlock) {
|
|
|
+ ast.Rule.call(this, id, "RootRule", patterns, buildBlock);
|
|
|
+ },
|
|
|
+
|
|
|
+ CompositeRule: function CompositeRule(id, patterns, buildBlock) {
|
|
|
+ ast.Rule.call(this, id, "CompositeRule", patterns, buildBlock);
|
|
|
+ },
|
|
|
+
|
|
|
+ Event: function Event(id) {
|
|
|
+ ast.Id.call(this, "Event", id);
|
|
|
+ },
|
|
|
+
|
|
|
+ Sequence: function Sequence(body) { // aka pattern_list
|
|
|
+ ast.Base.call(this, "Sequence");
|
|
|
+ // this.refId = "Sq_" + getUniqueNumber(); // aka "name" in RIGAL code
|
|
|
+ this.body = body;
|
|
|
+ },
|
|
|
+
|
|
|
+ Alternative: function Alternative(body) {
|
|
|
+ ast.Base.call(this, "Alternative");
|
|
|
+ // this.refId = "Alt_" + getUniqueNumber(); // aka "name" in RIGAL code
|
|
|
+ this.body = body; // aka "patterns" in the RIGAL codye
|
|
|
+ },
|
|
|
+
|
|
|
+ Probability: function Probability(p) {
|
|
|
+ throw err(12, "PROBABILITY");
|
|
|
+ ast.Base.call(this, "Probability");
|
|
|
+ this.p = p;
|
|
|
+ },
|
|
|
+
|
|
|
+ MinMax: function MinMax(min, max) {
|
|
|
+ ast.Base.call(this, "MinMax");
|
|
|
+ this.min = min;
|
|
|
+ this.max = max;
|
|
|
+ },
|
|
|
+
|
|
|
+ Iterator: function Iterator(scope, body) {
|
|
|
+ ast.Base.call(this, "Iterator");
|
|
|
+ // this.refId = "Itr_" + getUniqueNumber(); // aka "name" in RIGAL code
|
|
|
+ this.scope = scope;
|
|
|
+ this.body = body;
|
|
|
+ },
|
|
|
+
|
|
|
+ Set: function Set(body) {
|
|
|
+ ast.Base.call(this, "Set");
|
|
|
+ // this.refId = "Set_" + getUniqueNumber(); // aka "name" in RIGAL code
|
|
|
+ this.body = body;
|
|
|
+ },
|
|
|
+
|
|
|
+ SetIterator: function SetIterator(scope, body) {
|
|
|
+ ast.Base.call(this, "SetIterator");
|
|
|
+ // this.refId = "SetIterator_" + getUniqueNumber(); // aka "name" in RIGAL code
|
|
|
+ this.scope = scope;
|
|
|
+ this.body = body;
|
|
|
+ },
|
|
|
+
|
|
|
+ Optional: function Optional(body) {
|
|
|
+ ast.Base.call(this, "Optional");
|
|
|
+ // this.refId = "Opt_" + getUniqueNumber(); // aka "name" in RIGAL code
|
|
|
+ this.body = body;
|
|
|
+ },
|
|
|
+
|
|
|
+ Coordinate: function Coordinate(async, srcs, body) {
|
|
|
+ ast.Base.call(this, "Coordinate");
|
|
|
+ // this.refId = "Coordinate_" + getUniqueNumber(); // aka "work" in RIGAL code
|
|
|
+ this.async = async;
|
|
|
+ this.srcs = srcs;
|
|
|
+ this.body = body;
|
|
|
+ },
|
|
|
+
|
|
|
+ CoordinateSource: function CoordinateSource(id, select, from) {
|
|
|
+ ast.Id.call(this, "CoordinateSource", id);
|
|
|
+ this.select = select;
|
|
|
+ this.from = from || "<this>";
|
|
|
+ },
|
|
|
+
|
|
|
+ ShareAll: function ShareAll(hosts, events) {
|
|
|
+ ast.Base.call(this, "ShareAll");
|
|
|
+ // this.refId = "ShareAll_" + getUniqueNumber(); // aka "work" in RIGAL code
|
|
|
+ this.hosts = hosts;
|
|
|
+ this.events = events;
|
|
|
+ },
|
|
|
+
|
|
|
+ Relationship: function Relationship(src, relType, dst) {
|
|
|
+ ast.Base.call(this, "Relationship");
|
|
|
+ this.relType = relType;
|
|
|
+ this.src = src;
|
|
|
+ this.dst = dst;
|
|
|
+ },
|
|
|
+
|
|
|
+ AddOperation: function AddOperation(rels) {
|
|
|
+ ast.Base.call(this, "Add");
|
|
|
+ this.relationships = rels;
|
|
|
+ },
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ parse.ast = ast;
|
|
|
+
|
|
|
+ if (opts.ast) {
|
|
|
+ /*TODO: setup overrides from opts.ast on top of ast*/
|
|
|
+ }
|
|
|
+
|
|
|
+ var errors = {
|
|
|
+ // 1: "wrong schema name $a identifier expected/ !", //NOTE: probably not applicable if we make SCHEMA go away (or at least optional silliness)
|
|
|
+ // 2: "wrong event pattern $a / !", //NOTE: errors handled by our generated parser
|
|
|
+ 3: "trigger event $a should not appear in WHEN pattern list / !",
|
|
|
+ //// 4: "detected around token $a/ !", //NOTE: errors handled by our generated parser
|
|
|
+ 5: "defined event name should not appear in rule body: ",
|
|
|
+ //TODO: 6: "recursion for event $a is detected/ !", //TODO: check for this
|
|
|
+ // 7: "syntax error in probability definition detected at $a/ !", //NOTE: just took out of parser for now
|
|
|
+ // 8: "schema name $a should be the same as input parameter/ !", //NOTE: disabled this restriction
|
|
|
+ // 9: "keyword 'DO' is expected in COORDINATE when actual token is $a / !", //NOTE: errors handled by our generated parser
|
|
|
+ // 10: "keyword 'OD' is expected in COORDINATE when actual token is $a / !", //NOTE: errors handled by our generated parser
|
|
|
+ // 11: "semicolon is expected when actual token is $a / !", //NOTE: errors handled by our generated parser
|
|
|
+ 12: "not implemented yet: ",
|
|
|
+ // 13: "':' is expected when actual token is $a / !", //NOTE: errors handled by our generated parser
|
|
|
+ // 14: "incorrect variable name $a in the COORDINATE source / !", //NOTE: errors handled by our generated parser
|
|
|
+ // 15: "derivation for root $a should be completed before composition/ !", //NOTE: handled by 21
|
|
|
+ // 16: "wrong relation name $a in the ADD composition/ !", //NOTE: errors handled by our generated parser
|
|
|
+ 17: "variable is not defined: ",
|
|
|
+ //TODO: 18: "shared event $a has not been defined in any grammar rule / !", //TODO: not sure how to recreate to test this
|
|
|
+ 19: "variable has been defined twice: ",
|
|
|
+ //NOTE: additional errors added by us
|
|
|
+ 20: "rule defined more than once: ",
|
|
|
+ 21: "reference to undefined item: ",
|
|
|
+ 22: "reference to non-root event: ",
|
|
|
+ };
|
|
|
+
|
|
|
+} //jshint ignore:start
|
|
|
+
|
|
|
+// GRAMMAR
|
|
|
+start
|
|
|
+ =
|
|
|
+ !{ ast.errors = []; }
|
|
|
+ m:model
|
|
|
+ {
|
|
|
+ m.errors = ast.errors;
|
|
|
+ return m;
|
|
|
+ }
|
|
|
+
|
|
|
+model
|
|
|
+ = schema
|
|
|
+ /*TODO:NOT_YET: ( ( assertion / query ) __ semi )* */
|
|
|
+
|
|
|
+schema
|
|
|
+ =
|
|
|
+ (SCHEMA schema_id semi?)? /*NOTE: optional in ours for now*/
|
|
|
+ includes:schema_include*
|
|
|
+ statements:schema_statement*
|
|
|
+ /*TODO:NOT_YET: build_block?*/
|
|
|
+ EOF
|
|
|
+ { return new ast.Schema(includes, statements); }
|
|
|
+schema_include "INCLUDE statement" /*NOTE: renamed from 'include_clause' in 'MP2-parser.rig' file*/
|
|
|
+ = INCLUDE id:schema_id semi
|
|
|
+ { return new ast.Include(id); }
|
|
|
+schema_statement
|
|
|
+ =
|
|
|
+ s:(
|
|
|
+ rule
|
|
|
+ / composition_operation
|
|
|
+ /*TODO:NOT_YET: / new_schema*/
|
|
|
+ )
|
|
|
+ semi
|
|
|
+ { return s }
|
|
|
+
|
|
|
+rule
|
|
|
+ = r:ROOT? id:root_id !{ ast.ruleId = id.id; } colon pl:pattern_list? /*TODO:NOT_YET:build_block?*/
|
|
|
+ {
|
|
|
+ var rule = new (r ? ast.RootRule : ast.CompositeRule)(id, pl);
|
|
|
+ if (id.id in ast.rulesById) ast.errors.push(err(20, id.id));
|
|
|
+ ast.rulesById[rule.id.id] = rule;
|
|
|
+ return rule;
|
|
|
+ }
|
|
|
+
|
|
|
+pattern_list
|
|
|
+ = list:pattern_unit+
|
|
|
+ { return new ast.Sequence(list); }
|
|
|
+
|
|
|
+pattern_unit
|
|
|
+ =
|
|
|
+ id:event_id
|
|
|
+ {
|
|
|
+ if (id.id === ast.ruleId) ast.errors.push(err(5,id));
|
|
|
+ return id;
|
|
|
+ }
|
|
|
+ / alternative
|
|
|
+ / iterator
|
|
|
+ / iterator_plus
|
|
|
+ / set
|
|
|
+ / set_iterator
|
|
|
+ / set_iterator_plus
|
|
|
+ / optional
|
|
|
+ /*TODO:NOT_YET: / "<|" pattern_list when_clause "|>" */
|
|
|
+ /*NOTE: empty handled by using optional pattern lists*/
|
|
|
+
|
|
|
+alternative
|
|
|
+ // = parenL list:alternative_list+ parenR
|
|
|
+ = parenL /*probability*/ item:pattern_list tail:(pipe /*probability*/ item:pattern_list {return item})* parenR
|
|
|
+ { return new ast.Alternative([item].concat(tail)); }
|
|
|
+
|
|
|
+probability /*TODO:NOT_YET:*/
|
|
|
+ = ltlt f:float gtgt
|
|
|
+ { return new ast.Probability(f); }
|
|
|
+
|
|
|
+
|
|
|
+iterator_scope_any /*iteration_scope iff min>=0*/
|
|
|
+ = lt a:(integer to)? b:integer gt
|
|
|
+ { return new ast.MinMax(a !== null ? a[0] : b, b); }
|
|
|
+
|
|
|
+iterator_scope_some /*iteration_scope iff min>=1*/
|
|
|
+ = lt a:(integer_gt0 to)? b:integer_gt0 gt
|
|
|
+ { return new ast.MinMax(a !== null ? a[0] : b, b); }
|
|
|
+
|
|
|
+iterator
|
|
|
+ = begin_iter s:iterator_scope_any? pl:pattern_list end_iter
|
|
|
+ { return new ast.Iterator(s !== null ? s : new ast.MinMax(0, null), pl); }
|
|
|
+
|
|
|
+iterator_plus
|
|
|
+ = begin_itpl s:iterator_scope_some? pl:pattern_list end_itpl
|
|
|
+ { return new ast.Iterator(s !== null ? s : new ast.MinMax(1, null), pl); }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+set
|
|
|
+ = braceL pl:pattern_lists_by_comma? braceR
|
|
|
+ { return new ast.Set(pl); }
|
|
|
+
|
|
|
+pattern_lists_by_comma
|
|
|
+ = item:pattern_list tail:(comma item:pattern_list { return item; })*
|
|
|
+ { return [item].concat(tail); }
|
|
|
+
|
|
|
+
|
|
|
+set_iterator
|
|
|
+ = begin_seti s:iterator_scope_any? pl:pattern_list end_seti
|
|
|
+ { return new ast.SetIterator(s !== null ? s : new ast.MinMax(0, null), pl); }
|
|
|
+
|
|
|
+set_iterator_plus
|
|
|
+ = begin_setp s:iterator_scope_some? pl:pattern_list end_setp
|
|
|
+ { return new ast.SetIterator(s !== null ? s : new ast.MinMax(1, null), pl); }
|
|
|
+
|
|
|
+optional
|
|
|
+ = bracketL /*TODO:NOT_YET:probability?*/ pl:pattern_list bracketR
|
|
|
+ { return new ast.Optional(pl); }
|
|
|
+
|
|
|
+/*
|
|
|
+NOTE: not yet...
|
|
|
+when_clause
|
|
|
+ = "WHEN" when_units_by_comma
|
|
|
+when_unit
|
|
|
+ = probability? event_id "==>" pattern_list
|
|
|
+*/
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * COMPOSITION OPERATIONS
|
|
|
+ */
|
|
|
+
|
|
|
+composition_operation
|
|
|
+ = shared_composition
|
|
|
+ / coordinate_composition
|
|
|
+ /*TODO:NOT_YET:/ ENSURE bool_expr*/
|
|
|
+
|
|
|
+
|
|
|
+shared_composition
|
|
|
+ = share:root_or_var_by_exunionstr_by_comma SHARE_ALL on:event_id_by_comma
|
|
|
+ { return new ast.ShareAll(share, on); }
|
|
|
+
|
|
|
+root_or_var
|
|
|
+ = id:root_id
|
|
|
+ {
|
|
|
+ if (!(id.id in ast.rulesById)) ast.errors.push(err(21, id.id)); //TODO: move to errors
|
|
|
+ else if (ast.rulesById[id.id].ruleType !== "RootRule") ast.errors.push(err(22, id.id)); //TODO: move to errors
|
|
|
+ return id;
|
|
|
+ }
|
|
|
+ / variable
|
|
|
+
|
|
|
+root_or_var_by_exunionstr
|
|
|
+ = item:root_or_var tail:(exunionstr item:root_or_var { return item; })*
|
|
|
+ { return [item].concat(tail); }
|
|
|
+
|
|
|
+root_or_var_by_exunionstr_by_comma
|
|
|
+ = item:root_or_var_by_exunionstr tail:(comma item:root_or_var_by_exunionstr { return item; })*
|
|
|
+ { return [item].concat(tail); }
|
|
|
+
|
|
|
+event_id_by_comma
|
|
|
+ = item:event_id tail:(comma item:event_id)*
|
|
|
+ { return [item].concat(tail); }
|
|
|
+
|
|
|
+
|
|
|
+coordinate_composition
|
|
|
+ =
|
|
|
+ COORDINATE async:asyncstr?
|
|
|
+ srcs:coordination_source_by_comma
|
|
|
+ DO
|
|
|
+ body:do_body_statement+
|
|
|
+ OD
|
|
|
+ { return new ast.Coordinate(Boolean(async), srcs, body); }
|
|
|
+
|
|
|
+coordination_source_by_comma
|
|
|
+ =
|
|
|
+ head:(
|
|
|
+ item:coordination_source
|
|
|
+ {
|
|
|
+ ast._srcs = {};
|
|
|
+ ast._srcs[item.id] = 1;
|
|
|
+ return [item];
|
|
|
+ }
|
|
|
+ )
|
|
|
+ tail:(
|
|
|
+ comma item:coordination_source
|
|
|
+ {
|
|
|
+ if (item.id in ast._srcs) ast.errors.push(err(19, item.id));
|
|
|
+ ast._srcs[item.id] = 1;
|
|
|
+ return item;
|
|
|
+ }
|
|
|
+ )*
|
|
|
+ { return head.concat(tail); }
|
|
|
+
|
|
|
+do_body_statement
|
|
|
+ = item:(
|
|
|
+ /*TODO:NOT_YET: variable colon new_instance*/
|
|
|
+ add_relation
|
|
|
+ /*TODO:NOT_YET:/ MAP_composition*/
|
|
|
+ / shared_composition
|
|
|
+ / coordinate_composition
|
|
|
+ )
|
|
|
+ semi
|
|
|
+ { return item }
|
|
|
+
|
|
|
+coordination_source
|
|
|
+ = v:variable colon s:selection_pattern f:(FROM (THIS / root_or_var))?
|
|
|
+ {
|
|
|
+ var frm = f ? f[1] : null;
|
|
|
+ if (frm && frm[0] === "$" && !(frm in ast._srcs)) ast.errors.push(err(17, frm));
|
|
|
+ return new ast.CoordinateSource(v, s, frm);
|
|
|
+ }
|
|
|
+
|
|
|
+add_relation
|
|
|
+ = ADD rels:relationships_by_comma
|
|
|
+ { return new ast.AddOperation(rels); }
|
|
|
+relationships_by_comma
|
|
|
+ =
|
|
|
+ head:(
|
|
|
+ item:relationship
|
|
|
+ {
|
|
|
+ if (!(item.src in ast._srcs)) ast.errors.push(err(17, item.src));
|
|
|
+ if (!(item.dst in ast._srcs)) ast.errors.push(err(17, item.dst));
|
|
|
+ return [item];
|
|
|
+ }
|
|
|
+ )
|
|
|
+ tail:(
|
|
|
+ comma item:relationship
|
|
|
+ {
|
|
|
+ if (!(item.src in ast._srcs)) ast.errors.push(err(17, item.src));
|
|
|
+ if (!(item.dst in ast._srcs)) ast.errors.push(err(17, item.dst));
|
|
|
+ return item;
|
|
|
+ }
|
|
|
+ )*
|
|
|
+ { return head.concat(tail); }
|
|
|
+
|
|
|
+relationship
|
|
|
+ = start:variable relType:(IN / PRECEDES / CONTAINS / FOLLOWS) second:variable
|
|
|
+ { return new ast.Relationship(start, relType, second); }
|
|
|
+
|
|
|
+selection_pattern
|
|
|
+ = event_id
|
|
|
+ / alternative_of_event_names
|
|
|
+
|
|
|
+alternative_of_event_names
|
|
|
+ = parenL alts:event_id_by_pipe parenR
|
|
|
+ { return new ast.Alternative(alts); }
|
|
|
+event_id_by_pipe
|
|
|
+ = item:event_id tail:(pipe item:event_id {return item;})*
|
|
|
+ { return [item].concat(tail); }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/*TODO:NOT_YET:
|
|
|
+MAP_composition
|
|
|
+ = MAP
|
|
|
+ { throw err(12, "MAP"); }
|
|
|
+*/
|
|
|
+
|
|
|
+
|
|
|
+/*TODO:NOT_YET:
|
|
|
+build_block "BUILD block"
|
|
|
+ =
|
|
|
+ BUILD braceL
|
|
|
+ (
|
|
|
+ (
|
|
|
+ composition_operation
|
|
|
+ / plain_attribute_declaration
|
|
|
+ / event_attribute_declaration
|
|
|
+ )
|
|
|
+ semi
|
|
|
+ )*
|
|
|
+ braceR
|
|
|
+ { throw err(12, "BUILD"); }
|
|
|
+plain_attribute_declaration
|
|
|
+ = !{ throw err(12, "BUILD"); }
|
|
|
+event_attribute_declaration
|
|
|
+ = !{ throw err(12, "BUILD"); }
|
|
|
+*/
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+//LEX
|
|
|
+
|
|
|
+schema_id "SCHEMA identifier"
|
|
|
+ = id
|
|
|
+
|
|
|
+keyword /*NOTE: list from the MP2-parser.rig definition of "keyword", though it seems incomplete*/
|
|
|
+ = "WHEN" / "COORDINATE" / "ENSURE" / "DO" / "OD" / "FROM"
|
|
|
+
|
|
|
+root_id "ROOT identifier"
|
|
|
+ = !keyword id:id
|
|
|
+ { return new ast.Event(id); }
|
|
|
+
|
|
|
+event_id "EVENT identifier"
|
|
|
+ = !keyword id:id
|
|
|
+ { return new ast.Event(id); }
|
|
|
+
|
|
|
+variable "VARIABLE"
|
|
|
+ = _ "$" id:id _
|
|
|
+ { return "$" + id; }
|
|
|
+
|
|
|
+id
|
|
|
+ = _ a:[A-Za-z] b:[a-zA-Z0-9_]* _
|
|
|
+ { return a + b.join(""); }
|
|
|
+
|
|
|
+integer
|
|
|
+ = _ a:[0-9]+ _
|
|
|
+ { return a.join(""); }
|
|
|
+
|
|
|
+integer_gt0
|
|
|
+ = _ a:[1-9] b:[0-9]* _
|
|
|
+ { return a + b.join(""); }
|
|
|
+
|
|
|
+float
|
|
|
+ = _ a:[0-9]+ b:("." b:[0-9]+)?
|
|
|
+ { return parseFloat(b ? a.join("") + "." + b[1].join("") : a.join("")); }
|
|
|
+ / _ "." b:[0-9]+
|
|
|
+ { return parseFloat("." + b.join("")); }
|
|
|
+
|
|
|
+begin_iter = _ "(*" _
|
|
|
+end_iter = _ "*)" _
|
|
|
+begin_itpl = _ "(+" _
|
|
|
+end_itpl = _ "+)" _
|
|
|
+begin_seti = _ "{*" _
|
|
|
+end_seti = _ "*}" _
|
|
|
+begin_setp = _ "{+" _
|
|
|
+end_setp = _ "+}" _
|
|
|
+
|
|
|
+asyncstr = _ "<!>" _
|
|
|
+exunionstr = _ "|+|" _
|
|
|
+to = _ ".." _
|
|
|
+
|
|
|
+parenL = _ "(" _
|
|
|
+parenR = _ ")" _
|
|
|
+braceL = _ "{" _
|
|
|
+braceR = _ "}" _
|
|
|
+bracketL = _ "[" _
|
|
|
+bracketR = _ "]" _
|
|
|
+lt = _ "<" _
|
|
|
+gt = _ ">" _
|
|
|
+ltlt = _ "<<" _
|
|
|
+gtgt = _ ">>" _
|
|
|
+colon = _ ":" _
|
|
|
+semi = _ ";" _
|
|
|
+comma = _ "," _
|
|
|
+pipe = _ "|" _
|
|
|
+
|
|
|
+SCHEMA = _ "SCHEMA" __
|
|
|
+INCLUDE = _ "INCLUDE" __
|
|
|
+ROOT = _ "ROOT" __
|
|
|
+SHARE_ALL = _ "SHARE" __ "ALL" __
|
|
|
+COORDINATE = _ "COORDINATE" __
|
|
|
+FROM = _ "FROM" __
|
|
|
+
|
|
|
+ADD = _ "ADD" __
|
|
|
+IN = _ "IN" __ { return "IN"; }
|
|
|
+CONTAINS = _ "CONTAINS" __ { return "CONTAINS"; }
|
|
|
+PRECEDES = _ "PRECEDES" __ { return "PRECEDES"; }
|
|
|
+FOLLOWS = _ "FOLLOWS" __ { return "FOLLOWS"; }
|
|
|
+THIS = _ "this" _ { return "this"; }
|
|
|
+
|
|
|
+DO = _ "DO" _
|
|
|
+OD = _ "OD" _
|
|
|
+
|
|
|
+BUILD = _ "BUILD" _
|
|
|
+NEW = _ "NEW" _
|
|
|
+MAP = _ "MAP" _
|
|
|
+ENSURE = _ "ENSURE" _
|
|
|
+
|
|
|
+EOF
|
|
|
+ = !.
|
|
|
+
|
|
|
+
|
|
|
+_ "optional whitespace"
|
|
|
+ = ([ \t\n\r] / comment)*
|
|
|
+ { return null; }
|
|
|
+
|
|
|
+__ "required whitespace"
|
|
|
+ = [ \t\n\r] _?
|
|
|
+ { return null; }
|
|
|
+
|
|
|
+nl "newline"
|
|
|
+ = [\n]
|
|
|
+ { return null; }
|
|
|
+
|
|
|
+comment
|
|
|
+ = c:comment_line nl?
|
|
|
+ { return c }
|
|
|
+ / c:comment_block nl?
|
|
|
+ { return c }
|
|
|
+comment_line "comment line"
|
|
|
+ = "//" c:[^\n]*
|
|
|
+ { return new ast.Comment(false, c.join("")); }
|
|
|
+comment_block "comment block"
|
|
|
+ = "/*" c:comment_block_char* "*/"
|
|
|
+ { return new ast.Comment(true, c.join("")); }
|
|
|
+comment_block_char
|
|
|
+ = !"*/" c:.
|
|
|
+ { return c; }
|