/* @desc PEG.js grammar file for Siebbel Query Language (forked from https://github.com/pegjs/pegjs/blob/master/examples/javascript.pegjs) @author VB @version 1.1 (2019.02.24) */ // ----- functions ----- { function filledArray(count, value) { return Array.apply(null, new Array(count)) .map(function() { return value; }); } function extractOptional(optional, index) { return optional ? optional[index] : null; } function extractList(list, index) { return list.map(function(element) { return element[index]; }); } function buildList(head, tail, index) { return [head].concat(extractList(tail, index)); } function buildExpression(head, tail, type, par) { return tail.reduce(function(result, element) { return { type: type, operator: element[1], left: result, right: element[3], par: par ? par : false }; }, head); } function optionalList(value) { return value !== null ? value : []; } } Start = __ expression:ExpressionStatement __ { return expression; } // ----- Lexical Grammar ----- WhiteSpace "whitespace" = "\t" / "\v" / "\f" / " " / "\u00A0" / "\uFEFF" / Zs LineTerminator = [\n\r\u2028\u2029] LineTerminatorSequence "end of line" = "\n" / "\r\n" / "\r" / "\u2028" / "\u2029" Identifier = name:IdentifierName { return name; } IdentifierName "identifier" = head:IdentifierStart tail:IdentifierPart* { return head + tail.join("") } IdentifierStart = UnicodeLetter / "_" IdentifierPart = IdentifierStart / UnicodeCombiningMark / Nd / Pc / "\u200C" / "\u200D" UnicodeLetter = Lu / Ll / Nl UnicodeCombiningMark = Mn / Mc Literal = NumericLiteral / StringLiteral NumericLiteral "number" = literal:DecimalLiteral !(IdentifierStart / DecimalDigit) { return literal; } DecimalLiteral = DecimalIntegerLiteral "." DecimalDigit* ExponentPart? { return { type: "num", value: parseFloat(text()) }; } / "." DecimalDigit+ ExponentPart? { return { type: "num", value: parseFloat(text()) }; } / DecimalIntegerLiteral ExponentPart? { return { type: "num", value: parseFloat(text()) }; } DecimalIntegerLiteral = "0" / NonZeroDigit DecimalDigit* DecimalDigit = [0-9] NonZeroDigit = [1-9] ExponentPart = ExponentIndicator SignedInteger ExponentIndicator = "e"i SignedInteger = [+-]? DecimalDigit+ StringLiteral "string" = '"' chars:DoubleStringCharacter* '"' { return { type: "str", value: chars.join(""), quote:'"' }; } / "'" chars:SingleStringCharacter* "'" { return { type: "str", value: chars.join(""), quote:"'" }; } DoubleStringCharacter = !('"' / LineTerminator) . { return text(); } SingleStringCharacter = !("'" / LineTerminator) . { return text(); } // Letter, Lowercase Ll = [a-z] // Letter, Uppercase Lu = [A-Z] // Mark, Spacing Combining Mc = [\u0903\u093B\u093E-\u0940\u0949-\u094C\u094E-\u094F\u0982-\u0983\u09BE-\u09C0\u09C7-\u09C8\u09CB-\u09CC\u09D7\u0A03\u0A3E-\u0A40\u0A83\u0ABE-\u0AC0\u0AC9\u0ACB-\u0ACC\u0B02-\u0B03\u0B3E\u0B40\u0B47-\u0B48\u0B4B-\u0B4C\u0B57\u0BBE-\u0BBF\u0BC1-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCC\u0BD7\u0C01-\u0C03\u0C41-\u0C44\u0C82-\u0C83\u0CBE\u0CC0-\u0CC4\u0CC7-\u0CC8\u0CCA-\u0CCB\u0CD5-\u0CD6\u0D02-\u0D03\u0D3E-\u0D40\u0D46-\u0D48\u0D4A-\u0D4C\u0D57\u0D82-\u0D83\u0DCF-\u0DD1\u0DD8-\u0DDF\u0DF2-\u0DF3\u0F3E-\u0F3F\u0F7F\u102B-\u102C\u1031\u1038\u103B-\u103C\u1056-\u1057\u1062-\u1064\u1067-\u106D\u1083-\u1084\u1087-\u108C\u108F\u109A-\u109C\u17B6\u17BE-\u17C5\u17C7-\u17C8\u1923-\u1926\u1929-\u192B\u1930-\u1931\u1933-\u1938\u1A19-\u1A1A\u1A55\u1A57\u1A61\u1A63-\u1A64\u1A6D-\u1A72\u1B04\u1B35\u1B3B\u1B3D-\u1B41\u1B43-\u1B44\u1B82\u1BA1\u1BA6-\u1BA7\u1BAA\u1BE7\u1BEA-\u1BEC\u1BEE\u1BF2-\u1BF3\u1C24-\u1C2B\u1C34-\u1C35\u1CE1\u1CF2-\u1CF3\u1CF7\u302E-\u302F\uA823-\uA824\uA827\uA880-\uA881\uA8B4-\uA8C3\uA952-\uA953\uA983\uA9B4-\uA9B5\uA9BA-\uA9BB\uA9BD-\uA9C0\uAA2F-\uAA30\uAA33-\uAA34\uAA4D\uAA7B\uAA7D\uAAEB\uAAEE-\uAAEF\uAAF5\uABE3-\uABE4\uABE6-\uABE7\uABE9-\uABEA\uABEC] // Mark, Nonspacing Mn = [\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D3-\u08E1\u08E3-\u0902\u093A\u093C\u0941-\u0948\u094D\u0951-\u0957\u0962-\u0963\u0981\u09BC\u09C1-\u09C4\u09CD\u09E2-\u09E3\u09FE\u0A01-\u0A02\u0A3C\u0A41-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A51\u0A70-\u0A71\u0A75\u0A81-\u0A82\u0ABC\u0AC1-\u0AC5\u0AC7-\u0AC8\u0ACD\u0AE2-\u0AE3\u0AFA-\u0AFF\u0B01\u0B3C\u0B3F\u0B41-\u0B44\u0B4D\u0B56\u0B62-\u0B63\u0B82\u0BC0\u0BCD\u0C00\u0C04\u0C3E-\u0C40\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56\u0C62-\u0C63\u0C81\u0CBC\u0CBF\u0CC6\u0CCC-\u0CCD\u0CE2-\u0CE3\u0D00-\u0D01\u0D3B-\u0D3C\u0D41-\u0D44\u0D4D\u0D62-\u0D63\u0DCA\u0DD2-\u0DD4\u0DD6\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19\u0F35\u0F37\u0F39\u0F71-\u0F7E\u0F80-\u0F84\u0F86-\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102D-\u1030\u1032-\u1037\u1039-\u103A\u103D-\u103E\u1058-\u1059\u105E-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108D\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17B4-\u17B5\u17B7-\u17BD\u17C6\u17C9-\u17D3\u17DD\u180B-\u180D\u1885-\u1886\u18A9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193B\u1A17-\u1A18\u1A1B\u1A56\u1A58-\u1A5E\u1A60\u1A62\u1A65-\u1A6C\u1A73-\u1A7C\u1A7F\u1AB0-\u1ABD\u1B00-\u1B03\u1B34\u1B36-\u1B3A\u1B3C\u1B42\u1B6B-\u1B73\u1B80-\u1B81\u1BA2-\u1BA5\u1BA8-\u1BA9\u1BAB-\u1BAD\u1BE6\u1BE8-\u1BE9\u1BED\u1BEF-\u1BF1\u1C2C-\u1C33\u1C36-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE0\u1CE2-\u1CE8\u1CED\u1CF4\u1CF8-\u1CF9\u1DC0-\u1DF9\u1DFB-\u1DFF\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302D\u3099-\u309A\uA66F\uA674-\uA67D\uA69E-\uA69F\uA6F0-\uA6F1\uA802\uA806\uA80B\uA825-\uA826\uA8C4-\uA8C5\uA8E0-\uA8F1\uA8FF\uA926-\uA92D\uA947-\uA951\uA980-\uA982\uA9B3\uA9B6-\uA9B9\uA9BC\uA9E5\uAA29-\uAA2E\uAA31-\uAA32\uAA35-\uAA36\uAA43\uAA4C\uAA7C\uAAB0\uAAB2-\uAAB4\uAAB7-\uAAB8\uAABE-\uAABF\uAAC1\uAAEC-\uAAED\uAAF6\uABE5\uABE8\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F] // Number, Decimal Digit Nd = [0-9] // Number, Letter Nl = [\u16EE-\u16F0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303A\uA6E6-\uA6EF] // Punctuation, Connector Pc = [\u005F\u203F-\u2040\u2054\uFE33-\uFE34\uFE4D-\uFE4F\uFF3F] // Separator, Space Zs = [\u0020\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000] __ = (WhiteSpace / LineTerminatorSequence)* _ = (WhiteSpace)* EOS = _ LineTerminatorSequence / __ EOF EOF = !. // ----- Expressions ----- PrimaryExpression = Literal / Field / Parameter / NULL / NOTNULL / NOT __ expression:Expression { expression.not = true; return expression; } / "(" __ expression:Expression __ ")" { expression.par = true; return expression; } NOT = "NOT"i __ {return "NOT"} NULL = "NULL"i {return "NULL"} NOTNULL = "NOT"i __ "NULL"i {return "NOT NULL"} Field = "[" __ field:[A-Za-z _0-9.\-]* "]" { return { type: "field", field: field.join("") }; } Parameter = "[&" __ param:[A-Za-z _0-9.\-]* "]" { return { type: "param", param: param.join("") }; } Elision = "," commas:(__ ",")* { return filledArray(commas.length + 1, null); } CallExpression = !(NOT __ Arguments) name:Identifier __ args:Arguments { return { type: "func", name: name, arguments: args }; } Arguments = "(" __ args:(ArgumentList __)? ")" { return optionalList(extractOptional(args, 0)); } ArgumentList = head:Expression tail:(__ "," __ Expression)* { return buildList(head, tail, 3); } LeftHandSideExpression = CallExpression / PrimaryExpression MultiplicativeExpression = head:LeftHandSideExpression tail:(__ MultiplicativeOperator __ LeftHandSideExpression)* { return buildExpression(head, tail, "bin"); } MultiplicativeOperator = $("*" !"=") / $("/" !"=") / $("^" !"=") AdditiveExpression = head:MultiplicativeExpression tail:(__ AdditiveOperator __ MultiplicativeExpression)* { return buildExpression(head, tail, "bin"); } AdditiveOperator = $("+" ![+=]) / $("-" ![-=]) RelationalExpression = head:AdditiveExpression tail:(__ RelationalOperator __ AdditiveExpression)* { return buildExpression(head, tail, "bin"); } RelationalOperator = "<=" / ">=" / $("<" !"<") / $(">" !">") EqualityExpression = head:RelationalExpression tail:(__ EqualityOperator __ RelationalExpression)* { return buildExpression(head, tail, "bin"); } EqualityOperator = "=" / "<>" / Is / Like / NotLike Is = "is"i {return "IS"} Like = "LIKE"i {return "LIKE"} NotLike = "NOT "i __ "LIKE"i {return "NOT LIKE"} LogicalANDExpression = head:EqualityExpression tail:(__ "AND"i __ EqualityExpression)* { return buildExpression(head, tail, "log"); } LogicalORExpression = head:LogicalANDExpression tail:(__ "OR"i __ LogicalANDExpression)* { return buildExpression(head, tail, "log"); } Expression = LogicalORExpression ExpressionStatement = expression:Expression EOS { return { type: "Expression", expression: expression }; }