# A Raku program conssts of statements, separated by end of expression. # End of expression is a period or a newline not escaped by a preceding \ PROGRAM ← STATEMENTS STATEMENTS ← (STATEMENT EOX)+ # A statement is a command, a block or a call, optionallly followed by comment, or a comment STATEMENT ← (COMMENT / COMMAND COMMENT? / BLOCK COMMENT? / CALL COMMENT?) # A comment starts with #, comment remark or rem ~COMMENT ← LONG_COMMENT / LINE_COMMENT # Reuse the string macro to absorb a long comment LONG_COMMENT ← RAWSM("#{", "}#") LINE_COMMENT ← ("#" / "comment" / "remark" / "rem") (!([\r\n]+).)* # A Commans starts with a word which is the verb, and is followed by optional arguments COMMAND ← VERB ARGUMENTS? ~BLOCK_KEYWORD ← < ( "do" / "sub" / "block") > WHITESPACE ~END_KEYWORD ← < ( "so" / "end" / "done" ) > WHITESPACE ~CALL_KEYWORD ← < ( "be" / "run" / "call" ) > WHITESPACE HAVING_KEYWORD ← < ( "having" / "given" ) > WHITESPACE BLOCK ← BLOCK_KEYWORD BODY END_KEYWORD / "{" BODY "}" CALL ← CALL_KEYWORD BODY END_KEYWORD / "(" BODY ")" BODY ← OPERATION / (EOX? STATEMENTS? STATEMENT?) TARGET ← ARGSEP? (EXPRESSION / BLOCK / CALL) ARGUMENTS ← TARGET ARGUMENT* ARGSEP ← ',' / ((PREPOSITION / ARTICLE)+) / ((HAVING_KEYWORD ARTICLE? WORD ARTICLE?)) PREPOSITION ← < ( "else" / "otherwise" / "aboard" / "about" / "above" / "across" / "after" / "against" / "alongside"/ "along" / "amidst" / "amidst" / "among" / "around" / "as" / "at" / "atop" / "before" / "behind"/ "below" / "beneath" / "besides" / "beside" / "between" / "beyond"/ "but" / "by" / "circa" / "despite" / "down" / "during"/ "except" / "for" / "from" / "inside" / "into" / "in" / "less" / "like" / "near" / "nothwithstanding" / "off" / "onto" / "on" / "opposite" / "outside" / "out" / "over" / "since" / "than" / "through" / "thru" / "towards" / "throughout" / "to" / "underneath"/ "under" / "unlike" / "until" / "upon" / "upside" / "up" / "versus" / "via" / "within" / "without" / "with" ) > WHITESPACE ~ARTICLE ← <("a" / "an" / "the")> WHITESPACE ARGUMENT ← ARGSEP EXPRESSION / ARGSEP? BLOCK / ARGSEP? CALL EXPRESSION ← ARRAY / STRING / NUMBER / SPECIALS / OPERATION / NAME OPERATION ← UNARY_OPERATION / BIN_OPERATION OPERAND ← UNOPER? (ARRAY/ STRING / NUMBER / SPECIALS / NAME / BLOCK / CALL ) BIN_OPERATION ← (OPERAND (BINOPER OPERAND)+) UNARY_OPERATION ← (UNOPER OPERAND) KWUNOPER ← "not" / "negate" / "complement" KWBINOPER ← "greater_or_equal" / "lesser_or_equal" / "plus" / "minus" / "times" / "divide" / "of" / "'s" / "'" / "and" / "or" / "equals" / "equal" / "differs" / "isn't" / "is" / "aint" / "greater" / "lesser" / "compare" / "xor" / "binand" / "binor" / "rshift" / "lshift" BINOPER ← < [-+/*] / "<-" / "->" / "&" / "|" / "&&"/ "||" / ":" / "==" / "!=" / "<=>" / "<<" / ">>" / ">=" / "<=" / ">" / "<" / "^" / KWBINOPER > UNOPER ← < [-!~] / KWUNOPER > CONJUNCTION ← < ( "and" / "or" ) > WHITESPACE ~ARRAY_KEYWORD ← < ( "list" / "array") > WHITESPACE ARRAY ← ("[" ACONTENTS? "]") / (ARRAY_KEYWORD ACONTENTS? END_KEYWORD) ARRAY_SEP ← (CONJUNCTION / ",") ACONTENTS ← (TARGET ARRAY_SEP)* TARGET ARRAY_SEP? SPECIALS ← "true" / "false" / "nil" / "nothing" / "me" / "my" / "parent" / "this" / "it" / "its" # Strings STRING ← ESCSTR / RAWSTR # Raw string macro RAWSM(O,C) ← O < (!(C).)* > C # Escaped string macro. ESCSM(O,C) ← O < (!(C)STRCHAR)* > C ESCSTR ← ESCSM("`", "`") / ESCSM('"', '"') RAWSTR ← RAWSM('<<', '>>') / RAWSM('«', '»') / RAWSM('‹', '›') / RAWSM('“', '”') STRESC1 ← "\\" [nrtfv\'\\"\[\]\\] STRESC2 ← "\\" [0-3] [0-7] [0-7] STRESC3 ← "\\" [0-7] [0-7]* STRESC4 ← "\\x" [0-9a-fA-F] [0-9a-fA-F]? STRESC5 ← "\\u" [0-9a-fA-F]+ STRNOESC ← (!('\\\\').) STRCHAR ← STRESC1 / STRESC2 / STRESC3 / STRESC4 / STRESC5 / STRNOESC NUMBER ← DECIMAL / INTEGER DECIMAL ← < [-]?[0-9]+[.][0-9]+ > INTEGER ← < [-]?[0-9]+ > KEYWORD ← BLOCK_KEYWORD / END_KEYWORD / CALL_KEYWORD / HAVING_KEYWORD / PREPOSITION / ARTICLE / SPECIALS / KWUNOPER / KWBINOPER NAME ← ARTICLE? WORD+ VERB ← WORD WORD ← !KEYWORD < [a-zA-Z_][a-zA-Z0-9_]* > ESC_EOX ← ([ \t]* "\\" ( "\r\n" / "\r" / "\n")) ~EOX ← (!ESC_EOX)([ \t]*[\r\n.]+[ \t]*)+ ~WHITESPACE ← < ESC_EOX / [ \t]* > %whitespace ← WHITESPACE %word ← [a-zA-Z_][a-zA-Z0-9_]* # --- # Expression parsing option # %expr = BINOPER # Rule to apply 'precedence climbing method' to # %binop = L && || and or # %binop = L == equals equal is # %binop = L + - plus minus # %binop = L * / times divide # %binop = L of 's <- -> '