code / nomsu

Lines6.6K Lua5.1K PEG1.3K make117
2 others 83
Markdown60 Bourne Again Shell23
(276 lines)
1 -- Nomsu version 7
2 file <-
3 {:curr_indent: ' '* :}
4 (((comment / methodchain / action / expression / inline_block) eol !.)
5 / file_chunks / comment? blank_lines?)
6 {:curr_indent: %nil :}
7 !.
9 shebang <- "#!" [^%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 eol
19 eof <- !.
20 eol <- ws* (&%nl / !.)
21 nodent <- (unexpected_indent [^%nl]* / =curr_indent)
22 indent <- { =curr_indent " " }
23 blank_lines <- %nl ((tab_error / nodent comment / ws*) %nl)*
24 nl_nodent <- blank_lines nodent
25 nl_indent <- blank_lines {: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_expression
54 noindex_inline_expression <-
55 number / variable / inline_text / inline_list / inline_dict / inline_unary_action /
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_block
62 indented_expression <-
63 indented_text / indented_list / indented_dict / indented_block /
64 indented_parens / unary_action
66 indented_parens <-
67 "(" indented_naked_expression (nl_nodent ")" / missing_paren_err / unexpected_code)
69 indented_naked_expression <-
70 ({| nl_indent
71 (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_index
80 inline_index (Index) <-
81 "." (hex_integer / integer / text_word / noindex_inline_expression)
82 _inline_index (IndexChain) <- inline_index
83 inline_index_chain <-
84 (noindex_inline_expression _inline_index+) -> foldr
86 indented_index (Index) <- "." indented_expression
87 _indented_index (IndexChain) <- indented_index
88 indented_index_chain <-
89 (noindex_inline_expression inline_index* (inline_index / _indented_index)) -> foldr
92 -- Actions need 1 argument and either another argument or a word.
93 inline_action (Action) <-
94 !section_division
95 ( inline_expression ((ws* inline_arg)+ / "(" ws* ")")
96 / word (ws* inline_arg)*)
97 inline_arg <- inline_expression / word
99 inline_unary_action (Action) <-
100 !section_division %at_break operator !":" inline_expression
102 action (Action) <-
103 !section_division
104 ( !statement_block (expression / indented_naked_expression) (((linesplit / ws*) arg)+ / "(" ws* ")")
105 / word ((linesplit / ws*) arg)*)
106 arg <- expression / indented_naked_expression / word
107 linesplit <- eol nl_nodent ".." ws*
109 unary_action (Action) <-
110 !section_division %at_break operator !":" !eol (expression / indented_naked_expression)
113 inline_methodsuffix (MethodCall) <-
114 inline_action
115 / "(" ws* inline_action (ws* ";" ws* inline_action)* ")"
116 inline_methodchain <-
117 ((inline_action / inline_expression) (ws* "," ws* inline_methodsuffix)+) -> foldr
119 methodsuffix (MethodCall) <-
120 action
121 / "(" ws* inline_action (ws* ";" ws* inline_action)* ws* ")"
122 / eol ({| nl_indent
123 (action eol) (nl_nodent action eol)*
124 (%nl (ws* %nl)* nodent (comment / eol / unexpected_code))*
125 {:curr_indent: %nil :}
126 |} -> unpack)
127 methodchain <-
128 ((unary_action / inline_action / expression) ((linesplit / ws*) "," ws* methodsuffix)+) -> foldr
130 word <- !number { %operator_char+ / ident_char+ }
131 operator <- !"###" {%operator_char+}
134 text_word (Text) <- word
136 inline_text (Text) <-
137 '"' !eol _inline_text* ('"' / eof / missing_quote_err / unexpected_code)
138 _inline_text <-
139 {~ (('\"' -> '"') / ('\\' -> '\') / escaped_char / text_char+)+ ~}
140 / inline_text_interpolation / illegal_char
141 inline_text_interpolation <-
142 "\" (
143 variable / inline_list / inline_dict
144 / ("("
145 ws* ((inline_methodchain / inline_action / inline_expression) ws*)?
146 (")" / eof / missing_paren_err / unexpected_code))
149 text_char <- %utf8_char / !["\] %print / %tab
151 indented_text (Text) <-
152 '("' %nl {%nl*} ({|
153 {:curr_indent: indent :}
154 (indented_plain_text / text_interpolation / illegal_char / blank_text_lines)*
155 {:curr_indent: %nil :}
156 |} -> unpack)
157 (nl_nodent '")' / eof / missing_indented_quote_err)
159 -- Tracking text-lines-within-indented-text as separate objects allows for better debugging line info
160 indented_plain_text (Text) <-
162 ((("\" blank_lines =curr_indent "..") -> "") / ('\\' -> '\') / ('\"' -> '"') / ('\;' -> '')
163 / (!text_interpolation ((!("\n") escaped_char) / '\'))
164 / ('"' / text_char)+)+
165 blank_text_lines?
167 blank_text_lines <-
168 {~ (%nl ((ws* -> '') (&%nl / !.) / (=curr_indent -> '') &[^%nl]))+ ~}
170 text_interpolation <-
171 ({|
172 -- %indentation will backtrack and match the actual indentation of the current line
173 "\" {:curr_indent: %indentation :}
174 (indented_block (blank_lines =curr_indent "..")? / indented_expression)
175 |} -> unpack)
176 / inline_text_interpolation
179 number <-
180 hex_integer / real_number / integer
182 integer (Number) <-
183 { (%at_break "-")? [0-9]+ (("_"+->"") [0-9]+)* }
185 hex_integer (Number) <-
186 { (%at_break "-")? "0x" [0-9a-fA-F]+ (("_"+->"") [0-9a-fA-F]+)* }
188 real_number (Number) <-
189 { (%at_break "-")? [0-9]+ (("_"+->"") [0-9]+)* "." [0-9]+ (("_"+->"") [0-9]+)* }
192 variable (Var) <- "$" ({ident_char+} / "(" ws* (inline_methodchain / inline_action / variable) ws* ")" / {''})
195 inline_list (List) <-
196 !indented_list
197 "[" ws* !eol
198 (inline_list_item (ws* ',' ws* inline_list_item)* (ws* ',')?)? ws*
199 ("]" / eof / (","? (missing_bracket_error / unexpected_code)))
200 inline_list_item <- inline_action / inline_expression
202 indented_list (List) <-
203 ({|
204 "[" (
205 (ws* indented_block)
206 / (eol nl_indent list_line (nl_nodent list_line)*))
207 {:curr_indent: %nil :}
208 |} -> unpack)
209 (nl_nodent "]" / eof / missing_bracket_error / unexpected_code)
210 list_line <-
211 (inline_list_item ws* "," ws*)+ eol
212 / (inline_list_item ws* "," ws*)* (action / statement_block / expression) eol
215 inline_dict (Dict) <-
216 !indented_dict
217 "{" ws* !eol
218 ((inline_action / inline_expression) (ws* ',' ws* (inline_action / inline_expression))*)? ws*
219 ("}" / eof / (","? (missing_brace_error / unexpected_code)))
221 indented_dict (Dict) <-
222 ({|
223 "{" (
224 (ws* indented_block)
225 / (eol nl_indent dict_line (nl_nodent dict_line)*
226 (%nl (ws* %nl)* nodent (comment / eol / unexpected_code))*))
227 {:curr_indent: %nil :}
228 |} -> unpack)
229 (nl_nodent "}" / eof / missing_brace_error / unexpected_code)
230 dict_line <-
231 ((inline_action / inline_expression) ws* "," ws*)+ eol
232 / ((inline_action / inline_expression) ws* "," ws*)* (action / statement_block / expression) eol
234 ident_char <- [a-zA-Z0-9_] / (!%operator_char %utf8_char)
235 ws <- " "
237 escaped_char <-
238 ("\"->'') (
239 (([xX]->'') ((({[0-9a-fA-F]^2} %number_16) -> tonumber) -> tochar))
240 / ((([0-9] [0-9]^-2) -> tonumber) -> tochar)
241 / ("a"->ascii_7) / ("b"->ascii_8) / ("t"->ascii_9) / ("n"->ascii_10)
242 / ("v"->ascii_11) / ("f"->ascii_12) / ("r"->ascii_13)
246 -- Errors
247 unexpected_code <- ws* _unexpected_code
248 _unexpected_code (Error) <-
249 {:error: {~ [^%nl]+ -> "Couldn't parse this code." ~} :}
250 unexpected_chunk (Error) <-
251 {:error: {~ .+ -> "Couldn't parse this chunk of code." ~} :}
252 unexpected_indent (Error) <-
253 {:error: {~ (=curr_indent ws+) -> "This indentation is messed up." ~} :}
254 {:hint: {~ '' -> 'This line should either have the same indentation as the line above it, or exactly 4 spaces more.' ~} :}
255 missing_paren_err (Error) <-
256 {:error: {~ eol -> 'This expression is missing a closing )-parenthesis.' ~} :}
257 {:hint: {~ '' -> 'Put a ")" here' ~} :}
258 missing_quote_err (Error) <-
259 {:error: {~ eol -> "This text is missing a closing quotation mark." ~} :}
260 {:hint: {~ "" -> "Put a quotation mark here." ~} :}
261 missing_indented_quote_err (Error) <-
262 {:error: {~ '' -> 'This text is missing a closing ")-quotation mark.' ~} :}
263 {:hint: {~ "" -> 'Put a ") after this line, at the same level of indentation as the opening (".' ~} :}
264 missing_bracket_error (Error) <-
265 {:error: {~ eol -> "This list is missing a closing ]-bracket" ~} :}
266 {:hint: {~ '' -> 'Put a "]" here' ~} :}
267 missing_brace_error (Error) <-
268 {:error: {~ eol -> "This dict is missing a closing }-brace" ~} :}
269 {:hint: {~ '' -> 'Put a "}" here' ~} :}
270 tab_error <- ws* _tab_error [^%nl]*
271 _tab_error (Error) <-
272 {:error: {~ %tab+ -> 'Tabs are not allowed for indentation.' ~} :}
273 {:hint: {~ '' -> 'Use 4-space indentation instead of tabs.' ~} :}
274 illegal_char (Error) <-
275 {:error: {~ (!(%nl / %tab / %print) .) -> "Illegal unprintable character here (it may not be visible, but it's there)" ~} :}
276 {:hint: {~ '' -> "This sort of thing can happen when copying and pasting code. Try deleting and retyping the code." ~} :}