(270 lines)
1 -- Nomsu version 62 file <-3 {:curr_indent: ' '* :}4 (((methodchain / action / expression / inline_block) eol !.)5 / file_chunks / comment? blank_lines?)6 {:curr_indent: %nil :}7 !.9 shebang <- "#!" (!"nomsu" [^%nl])* "nomsu" ws+ "-V" ws* [0-9.]+ [^%nl]* (%nl / !.)11 file_chunks (FileChunks) <-12 {:shebang: shebang :}?13 (top_block (nl_nodent section_division top_block)*)14 blank_lines?15 unexpected_indent? unexpected_chunk?17 section_division <- ("~")^+3 eol19 eof <- !.20 eol <- ws* (&%nl / !.)21 nodent <- (unexpected_indent [^%nl]* / =curr_indent)22 indent <- { =curr_indent " " }23 blank_lines <- %nl ((nodent comment / ws*) %nl)*24 nl_nodent <- blank_lines nodent25 nl_indent <- blank_lines tab_error? {:curr_indent: indent :} (comment nl_nodent)*28 comment (Comment) <-29 "#" {~ [^%nl]* (%nl+ (indent -> '') [^%nl]*)* (%nl &%nl)* ~}32 top_block (Block) <-33 ((blank_lines nodent) / (comment nl_nodent))? statement (nl_nodent statement)*35 inline_block (Block) <-36 ":" ws* (inline_statement (ws* ";" ws* inline_statement)*)?37 (&eol !nl_indent / &(ws* ([)},;] / "]")))39 indented_block (Block) <-40 ":" eol nl_indent statement (nl_nodent statement)*41 (%nl (ws* %nl)* nodent (comment / eol / unexpected_code))*42 {:curr_indent: %nil :}44 statement_block (Block) <-45 ":" ws* (methodchain / action / expression)48 statement <-49 (methodchain / action / expression / statement_block) (eol / unexpected_code)51 inline_statement <-52 inline_methodchain / inline_action / inline_expression54 noindex_inline_expression <-55 number / variable / inline_text / inline_list / inline_dict / inline_nomsu /56 "("57 ws* (inline_block / inline_methodchain / inline_action / inline_expression) ws*58 (")" / eof / missing_paren_err / unexpected_code)60 inline_expression <- inline_index_chain / noindex_inline_expression / inline_index / inline_block62 indented_expression <-63 indented_text / indented_nomsu / indented_list / indented_dict / indented_block /64 indented_parens66 indented_parens <-67 "(" indented_naked_expression (nl_nodent ")" / missing_paren_err / unexpected_code)69 indented_naked_expression <-70 ({| nl_indent71 (methodchain / action / expression) (eol / unexpected_code)72 (%nl (ws* %nl)* nodent (comment / eol / unexpected_code))*73 {:curr_indent: %nil :}74 |} -> unpack)76 expression <-77 inline_expression / indented_index_chain / indented_expression / inline_index / indented_index79 inline_nomsu (EscapedNomsu) <- "\" inline_expression80 indented_nomsu (EscapedNomsu) <- "\" expression83 inline_index (Index) <-84 "." (hex_integer / integer / text_word / noindex_inline_expression)85 _inline_index (IndexChain) <- inline_index86 inline_index_chain <-87 (noindex_inline_expression _inline_index+) -> foldr89 indented_index (Index) <- "." indented_expression90 _indented_index (IndexChain) <- indented_index91 indented_index_chain <-92 (noindex_inline_expression inline_index* (inline_index / _indented_index)) -> foldr95 -- Actions need 1 argument and either another argument or a word.96 inline_action (Action) <-97 !section_division98 ( word (ws* inline_arg)*99 / inline_expression ((ws* inline_arg)+ / "(" ws* ")"))100 inline_arg <- inline_expression / word102 action (Action) <-103 !section_division104 ( word ((linesplit / ws*) arg)*105 / !statement_block arg (((linesplit / ws*) arg)+ / "(" ws* ")"))106 arg <- expression / indented_naked_expression / word107 linesplit <- eol nl_nodent ".." ws*110 inline_methodsuffix (MethodCall) <-111 inline_action112 / "(" ws* inline_action (ws* ";" ws* inline_action)* ")"113 inline_methodchain <-114 ((inline_action / inline_expression) (ws* "," ws* inline_methodsuffix)+) -> foldr116 methodsuffix (MethodCall) <-117 action118 / "(" ws* inline_action (ws* ";" ws* inline_action)* ws* ")"119 / eol ({| nl_indent120 (action eol) (nl_nodent action eol)*121 (%nl (ws* %nl)* nodent (comment / eol / unexpected_code))*122 {:curr_indent: %nil :}123 |} -> unpack)124 methodchain <-125 ((inline_action / expression) ((linesplit / ws*) "," ws* methodsuffix)+) -> foldr127 word <- !number { operator_char+ / ident_char+ }130 text_word (Text) <- word132 inline_text (Text) <-133 '"' !eol _inline_text* ('"' / eof / missing_quote_err / unexpected_code)134 _inline_text <-135 {~ (('\"' -> '"') / ('\\' -> '\') / escaped_char / text_char+)+ ~}136 / inline_text_interpolation / illegal_char137 inline_text_interpolation <-138 "\" (139 variable / inline_list / inline_dict140 / ("("141 ws* ((inline_methodchain / inline_action / inline_expression) ws*)?142 (")" / eof / missing_paren_err / unexpected_code))143 )145 text_char <- %utf8_char / !["\] %print / %tab147 indented_text (Text) <-148 '("' %nl {%nl*} ({|149 {:curr_indent: indent :}150 (indented_plain_text / text_interpolation / illegal_char / blank_text_lines)*151 {:curr_indent: %nil :}152 |} -> unpack)153 (nl_nodent '")' / eof / missing_indented_quote_err)155 -- Tracking text-lines-within-indented-text as separate objects allows for better debugging line info156 indented_plain_text (Text) <-157 {~158 ((("\" blank_lines =curr_indent "..") -> "") / ('\\' -> '\') / ('\"' -> '"') / ('\;' -> '')159 / (!text_interpolation ((!("\n") escaped_char) / '\'))160 / ('"' / text_char)+)+161 blank_text_lines?162 ~}163 blank_text_lines <-164 {~ (%nl ((ws* -> '') (&%nl / !.) / (=curr_indent -> '') &[^%nl]))+ ~}166 text_interpolation <-167 ({|168 -- %indentation will backtrack and match the actual indentation of the current line169 "\" {:curr_indent: %indentation :}170 (indented_block (blank_lines =curr_indent "..")? / indented_expression)171 |} -> unpack)172 / inline_text_interpolation175 number <-176 hex_integer / real_number / integer178 integer (Number) <-179 (("-"? [0-9]+)-> tonumber)181 hex_integer (Number) <-182 (("-"? "0x" [0-9a-fA-F]+)-> tonumber)183 {:hex: '' -> 'yes' :}185 real_number (Number) <-186 (("-"? [0-9]+ "." [0-9]+)-> tonumber)189 variable (Var) <- "$" ({ident_char+} / "(" ws* inline_action ws* ")" / {''})192 inline_list (List) <-193 "[" ws* !eol194 (inline_list_item (ws* ',' ws* inline_list_item)* (ws* ',')?)? ws*195 ("]" / eof / (","? (missing_bracket_error / unexpected_code)))196 inline_list_item <- inline_action / inline_expression198 indented_list (List) <-199 ({|200 "[" eol nl_indent201 list_line (nl_nodent list_line)*202 {:curr_indent: %nil :}203 |} -> unpack)204 (nl_nodent "]" / eof / missing_bracket_error / unexpected_code)205 list_line <-206 (inline_list_item ws* "," ws*)+ eol207 / (inline_list_item ws* "," ws*)* (action / statement_block / expression) eol210 inline_dict (Dict) <-211 "{" ws* !eol212 ((inline_action / inline_expression) (ws* ',' ws* (inline_action / inline_expression))*)? ws*213 ("}" / eof / (","? (missing_brace_error / unexpected_code)))215 indented_dict (Dict) <-216 ({|217 "{" eol nl_indent218 dict_line (nl_nodent dict_line)*219 (%nl (ws* %nl)* nodent (comment / eol / unexpected_code))*220 {:curr_indent: %nil :}221 |} -> unpack)222 (nl_nodent "}" / eof / missing_brace_error / unexpected_code)223 dict_line <-224 ((inline_action / inline_expression) ws* "," ws*)+ eol225 / ((inline_action / inline_expression) ws* "," ws*)* (action / statement_block / expression) eol227 operator_char <- [#'`~@^&*+=<>?/%!|-]228 ident_char <- [a-zA-Z0-9_] / %utf8_char229 ws <- " "231 escaped_char <-232 ("\"->'') (233 (([xX]->'') ((({[0-9a-fA-F]^2} %number_16) -> tonumber) -> tochar))234 / ((([0-9] [0-9]^-2) -> tonumber) -> tochar)235 / ("a"->ascii_7) / ("b"->ascii_8) / ("t"->ascii_9) / ("n"->ascii_10)236 / ("v"->ascii_11) / ("f"->ascii_12) / ("r"->ascii_13)237 )240 -- Errors241 unexpected_code <- ws* _unexpected_code242 _unexpected_code (Error) <-243 {:error: {~ [^%nl]+ -> "Couldn't parse this code." ~} :}244 unexpected_chunk (Error) <-245 {:error: {~ .+ -> "Couldn't parse this chunk of code." ~} :}246 unexpected_indent (Error) <-247 {:error: {~ (=curr_indent ws+) -> "This indentation is messed up." ~} :}248 {:hint: {~ '' -> 'This line should either have the same indentation as the line above it, or exactly 4 spaces more.' ~} :}249 missing_paren_err (Error) <-250 {:error: {~ eol -> 'This expression is missing a closing )-parenthesis.' ~} :}251 {:hint: {~ '' -> 'Put a ")" here' ~} :}252 missing_quote_err (Error) <-253 {:error: {~ eol -> "This text is missing a closing quotation mark." ~} :}254 {:hint: {~ "" -> "Put a quotation mark here." ~} :}255 missing_indented_quote_err (Error) <-256 {:error: {~ '' -> 'This text is missing a closing ")-quotation mark.' ~} :}257 {:hint: {~ "" -> 'Put a ") after this line, at the same level of indentation as the opening (".' ~} :}258 missing_bracket_error (Error) <-259 {:error: {~ eol -> "This list is missing a closing ]-bracket" ~} :}260 {:hint: {~ '' -> 'Put a "]" here' ~} :}261 missing_brace_error (Error) <-262 {:error: {~ eol -> "This dict is missing a closing }-brace" ~} :}263 {:hint: {~ '' -> 'Put a "}" here' ~} :}264 tab_error (Error) <-265 &(=curr_indent %tab)266 {:error: {~ '' -> 'Tabs are not allowed for indentation.' ~} :}267 {:hint: {~ '' -> 'Use spaces instead of tabs.' ~} :}268 illegal_char (Error) <-269 {:error: {~ (!(%nl / %tab / %print) .) -> "Illegal unprintable character here (it may not be visible, but it's there)" ~} :}270 {:hint: {~ '' -> "This sort of thing can happen when copying and pasting code. Try deleting and retyping the code." ~} :}