code / nomsu

Lines6.6K Lua5.1K PEG1.3K make117
2 others 83
Markdown60 Bourne Again Shell23
(232 lines)
1 -- Nomsu version 4
2 file <-
3 {:curr_indent: ' '* :}
4 (((action / expression / inline_block / indented_block) eol !.)
5 / file_chunks / empty_block)
6 {:curr_indent: %nil :}
7 !.
9 shebang <- "#!" (!"nomsu" [^%nl])* "nomsu" ws+ "-V" ws* [0-9.]+ [^%nl]* (%nl / !.)
11 eof <- !.
13 file_chunks (FileChunks) <-
14 {:shebang: shebang :}?
15 (top_block (nl_nodent section_division top_block)*)
16 blank_lines?
17 unexpected_indent? unexpected_chunk?
19 top_block (Block) <-
20 ((blank_lines nodent) / (comment nl_nodent))? statement (nl_nodent statement)*
22 empty_block (Block) <-
23 comment? blank_lines?
25 nodent <- (unexpected_indent [^%nl]* / =curr_indent)
26 indent <- {~ =curr_indent (ws / (%tab -> ' '))+ ~}
27 blank_lines <- %nl ((nodent comment / ws*) %nl)*
28 eol <- ws* eol_comment? (!. / &%nl)
30 nl_nodent <- blank_lines nodent
31 nl_indent <- blank_lines tab_error? {:curr_indent: indent :} (comment nl_nodent)*
33 comment (Comment) <-
34 "#" {~ [^%nl]* (%nl+ (indent -> '') [^%nl]*)* (%nl &%nl)* ~}
35 eol_comment (Comment) <-
36 "#" {[^%nl]*}
38 unexpected_code <- ws* _unexpected_code
39 _unexpected_code (Error) <-
40 {:error: {~ [^%nl]+ -> "Couldn't parse this code." ~} :}
41 unexpected_chunk (Error) <-
42 {:error: {~ .+ -> "Couldn't parse this chunk of code." ~} :}
43 unexpected_indent (Error) <-
44 {:error: {~ (=curr_indent ws+) -> "This indentation is messed up." ~} :}
45 {:hint: {~ '' -> 'This line should either have the same indentation as the line above it, or exactly 4 spaces more.' ~} :}
46 missing_paren_err (Error) <-
47 {:error: {~ eol -> 'Line ended without finding a closing )-parenthesis' ~} :}
48 {:hint: {~ '' -> 'Put a ")" here' ~} :}
49 missing_quote_err (Error) <-
50 {:error: {~ eol -> 'Line ended before finding a closing double quotation mark' ~} :}
51 {:hint: {~ "" -> "Put a quotation mark here" ~} :}
52 missing_bracket_error (Error) <-
53 {:error: {~ eol -> "Line ended before finding a closing ]-bracket" ~} :}
54 {:hint: {~ '' -> 'Put a "]" here' ~} :}
55 missing_brace_error (Error) <-
56 {:error: {~ eol -> "Line ended before finding a closing }-brace" ~} :}
57 {:hint: {~ '' -> 'Put a "}" here' ~} :}
58 disallowed_interpolation (Error) <-
59 {:error: {~ ("\" ('\:' / '(..)' / '[..]' / '{..}') (%nl (&(%nl) / =curr_indent ' ' [^%nl]*))*) ->
60 "Sorry, indented text interpolations are not currently supported on the first line of multi-line text." ~} :}
61 {:hint: {~ '' -> 'Move the code for the first line of text to the next line by ending this line with "\" and starting the next line indented with "..", followed by the code for the first line.' ~} :}
62 tab_error (Error) <-
63 &(=curr_indent %tab)
64 {:error: {~ '' -> 'Tabs are not allowed for indentation.' ~} :}
65 {:hint: {~ '' -> 'Use spaces instead of tabs.' ~} :}
67 section_division <- ("~")^+3 eol
69 inline_block <-
70 "(" ws* inline_block ws* (eof / ")") / raw_inline_block
71 raw_inline_block (Block) <-
72 (!"::") ":" ws* ((inline_statement (ws* ";" ws* inline_statement)*) / !(eol nl_indent))
73 indented_block (Block) <-
74 ":" eol nl_indent statement (nl_nodent statement)*
75 (%nl (ws* %nl)* nodent (comment / eol / unexpected_code))*
76 {:curr_indent: %nil :}
78 statement <-
79 (action / expression) (eol / unexpected_code)
81 inline_statement <- (inline_action / inline_expression)
83 noindex_inline_expression <-
84 number / variable / inline_text / inline_list / inline_dict / inline_nomsu
85 / ( "("
86 ws* (inline_action / inline_expression) ws*
87 (ws* ',' ws* (inline_action / inline_expression) ws*)*
88 (")" / eof / missing_paren_err / unexpected_code)
90 inline_expression <- index_chain / noindex_inline_expression
91 indented_expression <-
92 indented_text / indented_nomsu / indented_list / indented_dict / ({|
93 "(..)" eol nl_indent
94 (action / expression) (eol / unexpected_code)
95 (%nl (ws* %nl)* nodent (comment / eol / unexpected_code))*
96 {:curr_indent: %nil :}
97 |} -> unpack)
98 expression <-
99 inline_expression / indented_expression
101 inline_nomsu (EscapedNomsu) <- "\" (inline_expression / inline_block)
102 indented_nomsu (EscapedNomsu) <-
103 "\" (noindex_inline_expression / inline_block / indented_expression / indented_block)
105 index_chain (IndexChain) <-
106 noindex_inline_expression ("." (text_word / noindex_inline_expression))+
108 inline_action <- inline_methodcall / _inline_action
109 inline_methodcall (MethodCall) <-
110 (inline_expression / "(" inline_block ")") ws* "::" ws* _inline_action
111 -- Actions need either at least 1 word, or at least 2 tokens
112 _inline_action (Action) <-
113 !section_division
114 ( (inline_arg (ws* (inline_arg / word))+)
115 / (word (ws* (inline_arg / word))*))
116 (ws* inline_block)?
117 inline_arg <- inline_expression / inline_block / "(" ws* ")"
119 action <- methodcall / _action
120 methodcall (MethodCall) <-
121 (expression / "(" inline_block ")" / indented_block)
122 ((ws* "\")? eol nl_nodent "..")? ws* "::" ((ws* "\")? eol nl_nodent "..")? ws*
123 _action
124 _action (Action) <-
125 !section_division
126 ( (arg (((ws* "\")? eol nl_nodent "..")? ws* (arg / word))+)
127 / (word (((ws* "\")? eol nl_nodent "..")? ws* (arg / word))*))
128 arg <- expression / inline_block / indented_block / "(" ws* ")"
130 word <- !number { operator_char+ / ident_char+ }
132 text_word (Text) <- word
134 inline_text (Text) <-
135 !(indented_text)
136 '"' _inline_text* ('"' / eof / missing_quote_err / unexpected_code)
137 _inline_text <-
138 {~ (('\"' -> '"') / ('\\' -> '\') / escaped_char / text_char+)+ ~}
139 / inline_text_interpolation / illegal_char
140 inline_text_interpolation <-
141 "\" (
142 variable / inline_list / inline_dict
143 / ("("
144 ws* (inline_action / inline_expression) ws*
145 (ws* ',' ws* (inline_action / inline_expression) ws*)*
146 (")" / eof / missing_paren_err / unexpected_code))
149 text_char <- %utf8_char / !["\] %print / %tab
150 illegal_char (Error) <-
151 {:error: {~ (!(%nl / %tab / %print) .) -> "Illegal unprintable character here (it may not be visible, but it's there)" ~} :}
152 {:hint: {~ '' -> "This sort of thing can happen when copying and pasting code. Try deleting and retyping the code." ~} :}
154 nonterminal_quote <-
155 '"' &([^%nl] / %nl+ =curr_indent)
156 indented_text (Text) <-
157 '"'
158 _inline_text*
159 (('\' %nl+ {:curr_indent: indent :} ('..')?)
160 / disallowed_interpolation? {%nl+} {:curr_indent: indent :})
161 (indented_plain_text / text_interpolation / illegal_char / {~ %nl+ (=curr_indent -> "") [ ]* ~})*
162 ('"' eol / eof / missing_quote_err)
163 {:curr_indent: %nil :}
164 -- Tracking text-lines-within-indented-text as separate objects allows for better debugging line info
165 indented_plain_text (Text) <-
167 ((("\" blank_lines =curr_indent "..") -> "") / ('\\' -> '\')
168 / (!text_interpolation (escaped_char / '\'))
169 / (nonterminal_quote / text_char)+)+
172 text_interpolation <-
173 inline_text_interpolation / ("\" (indented_expression / indented_block) (blank_lines =curr_indent "..")?)
175 number (Number) <-
176 (&("-"? "0x" [0-9a-fA-F]+) {:hex: '' -> 'yes' :})?
177 (("-"? (([0-9]+ "." [0-9]+) / ("." [0-9]+) / "0x" [0-9a-fA-F]+ / ([0-9]+)))-> tonumber)
179 -- Variables can be nameless (i.e. just %) and can only contain identifier chars.
180 -- This ensures you don't get weird parsings of `%x+%y` or `%'s thing`.
181 variable (Var) <- "%" {ident_char*}
183 inline_list (List) <-
184 !('[..]')
185 "[" ws*
186 (inline_list_item (ws* ',' ws* inline_list_item)* (ws* ',')?)? ws*
187 ("]" / eof / (","? (missing_bracket_error / unexpected_code)))
188 indented_list (List) <-
189 "[..]" eol nl_indent
190 list_line (nl_nodent list_line)*
191 (%nl (ws* %nl)* nodent (comment / eol / unexpected_code))*
192 (","? unexpected_code)?
193 list_line <-
194 (inline_list_item ws* "," ws*)+ eol
195 / (inline_list_item ws* "," ws*)* (action / expression / inline_block / indented_block) eol
196 inline_list_item <- inline_action / inline_expression / inline_block
198 inline_dict (Dict) <-
199 !('{..}')
200 "{" ws*
201 (inline_dict_entry (ws* ',' ws* inline_dict_entry)*)? ws*
202 ("}" / eof / (","? (missing_brace_error / unexpected_code)))
203 indented_dict (Dict) <-
204 "{..}" eol nl_indent
205 dict_line (nl_nodent dict_line)*
206 (%nl (ws* %nl)* nodent (comment / eol / unexpected_code))*
207 (","? unexpected_code)?
208 dict_line <-
209 (inline_dict_entry ws* "," ws*)+ eol
210 / (inline_dict_entry ws* "," ws*)* dict_entry eol
211 _dict_entry(DictEntry) <-
212 dict_key (ws* ":" ws* (action / expression))?
213 dict_entry <-
214 _dict_entry / inline_block / indented_block
215 _inline_dict_entry(DictEntry) <-
216 dict_key (ws* ":" ws* (inline_action / inline_expression)?)?
217 inline_dict_entry <-
218 _inline_dict_entry / inline_block
219 dict_key <-
220 text_word / inline_expression
222 operator_char <- ['`~!@$^&*+=|<>?/-]
223 ident_char <- [a-zA-Z0-9_] / %utf8_char
224 ws <- " "
226 escaped_char <-
227 ("\"->'') (
228 (([xX]->'') ((({[0-9a-fA-F]^2} %number_16) -> tonumber) -> tochar))
229 / ((([0-9] [0-9]^-2) -> tonumber) -> tochar)
230 / ("a"->ascii_7) / ("b"->ascii_8) / ("t"->ascii_9) / ("n"->ascii_10)
231 / ("v"->ascii_11) / ("f"->ascii_12) / ("r"->ascii_13)