blob: 82886d3107816c4fbff94af6f0e5562f79ba8c94 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
file (File):
{| shebang?
(ignored_line %nl)*
statement ((nodent (statement / (({} ([^%nl]* -> "Error while parsing line")) => error)))
/ (({} ((%nl %dedent) ->"Indentation error")) => error))*
(%nl ignored_line)*
|} -> Tuple
(!. / (({} (.* -> "Parse error")) => error))
shebang: "#!" [^%nl]* (!. / %nl)
statement: (action / expression) (eol / (({} ([^%nl]* -> "Error while parsing line")) => error))
inline_statement: inline_action / inline_expression
inline_block (Block):
{| inline_statement (%ws* ";" %ws* inline_statement)+ |} -> Tuple
block (Block):
{| statement (nodent statement)+ |} -> Tuple
inline_nomsu (Nomsu): "\" noindex_inline_expression
indented_nomsu (Nomsu):
"\" (noindex_inline_expression / (":" %ws* (inline_block / inline_action / inline_expression) eol) / indented_expression)
index_chain (IndexChain):
{| noindex_inline_expression ("." ((({} ({|{%operator / (!number plain_word)}|} -> Tuple) {}) -> Text) / noindex_inline_expression))+ |} -> Tuple
noindex_inline_expression:
number / variable / inline_text / inline_list / inline_dict / inline_nomsu
/ (
"(" %ws* (inline_block / inline_action / inline_expression) %ws*
(")"
/ (({} ((!. / &%nl) -> 'Expected to find a ) before the end of the line')) => error)
/ (({} ([^%nl]* -> 'Error while parsing subexpression')) => error))
)
inline_expression:
index_chain / noindex_inline_expression
indented_expression:
indented_text / indented_nomsu / indented_list / indented_dict
/ ("(..)"? indent
(block / action / expression)
(dedent / (({} (non_dedent_error -> "Error while parsing indented expression")) => error))
)
expression:
inline_expression / (":" %ws* (inline_block / inline_action / inline_expression) eol) / indented_expression
-- Function calls need at least one word in them
inline_action (Action):
{| (inline_expression %ws*)* word (%ws* (inline_expression / word))*
(%ws* ":" %ws* (inline_block / inline_action / inline_expression))?|} -> Tuple
action (Action):
{| (expression (dotdot / %ws*))* word ((dotdot / %ws*) (expression / word))* |} -> Tuple
word (Word): { %operator / (!number plain_word) }
inline_text (Text):
!('".."' eol)
'"' ({|
({~ (('\"' -> '"') / ('\\' -> '\') / %escaped_char / [^%nl\"])+ ~}
/ inline_text_interpolation)*
|} -> Tuple) ('"' / (({} ([^%nl]*->'Failed to find a closing " mark on the same line')) => error))
-- Have to use "%indent" instead of "indent" etc. to avoid messing up text lines that start with "#"
indented_text (Text):
'".."' eol %nl ({|
{~ (%nl*) (%indent -> "") ~}
({~
(("\\" -> "\") / (("\" nodent "..") -> "")/ (%nl+ {~ %nodent -> "" ~}) / [^%nl\] / (!text_interpolation "\"))+
~} / text_interpolation)*
|} -> Tuple) (((!.) &%dedent) / (&(%nl %dedent)) / (({} (non_dedent_error -> "Error while parsing Text")) => error))
inline_text_interpolation:
"\" (
variable / inline_list / inline_dict / inline_text
/ ("("
%ws* (inline_block / inline_action / inline_expression) %ws*
(")"
/ (({} (&%nl -> 'Expected to find a ")" before the end of the line')) => error)
/ (({} ([^%nl]* -> 'Error while parsing text interpolation')) => error))
)
)
text_interpolation:
inline_text_interpolation /
("\" indented_expression nodent "..")
number (Number): (("-"? (([0-9]+ "." [0-9]+) / ("." [0-9]+) / ([0-9]+)))-> tonumber)
-- Variables can be nameless (i.e. just %) and can't contain operators like apostrophe
-- which is a hack to allow %'s to parse as "%" and "' s" separately
variable (Var): "%" { plain_word? }
inline_list (List):
!('[..]')
"[" %ws* ({| (inline_list_item (comma inline_list_item)* comma?)? |} -> Tuple) %ws*
("]" / (({} ([^%nl]*->"Failed to find a closing ] on the same line")) => error))
indented_list (List):
"[..]" indent ({|
list_line (nodent list_line)*
|} -> Tuple)
(dedent / (({} (non_dedent_error -> "Error while parsing list")) => error))
list_line:
((action / expression) !comma)
/ (inline_list_item (comma list_line?)?)
inline_list_item: inline_block / inline_action / inline_expression
inline_dict (Dict):
!('{..}')
"{" %ws* ({| (inline_dict_item (comma inline_dict_item)*)? |} -> Tuple) %ws*
("}"
/ (({} (%ws* comma? (!. / &%nl)->"Failed to find a closing } on the same line")) => error)
/ (({} ([^%nl]*->"Error while parsing dictionary")) => error))
indented_dict (Dict):
"{..}" indent ({|
dict_line (nodent dict_line)*
|} -> Tuple)
(dedent / (({} (non_dedent_error -> "Error while parsing dict")) => error))
dict_line:
((dict_key %ws* ":" %ws* (action / expression)) -> DictEntry !comma)
/ (inline_dict_item (comma dict_line?)?)
inline_dict_item:
((dict_key %ws* (":" %ws* (inline_block / inline_action / inline_expression)?)?)-> DictEntry)
dict_key:
(({} ({|{%operator / (!number plain_word)}|} -> Tuple) {}) -> Text) / inline_expression
block_comment: "#.." [^%nl]* (%nl+ %indent [^%nl]* (%nl+ %nodent [^%nl]*)* %dedent)?
line_comment: "#" [^%nl]*
eol: %ws* line_comment? (!. / &%nl)
ignored_line: (%nodent (block_comment / line_comment)) / (%ws* (!. / &%nl))
indent: eol (%nl ignored_line)* %nl %indent ((block_comment/line_comment) (%nl ignored_line)* nodent)?
nodent: eol (%nl ignored_line)* %nl %nodent
dedent: eol (%nl ignored_line)* (((!.) &%dedent) / (&(%nl %dedent)))
non_dedent_error: (!dedent .)* eol (%nl ignored_line)* (!. / &%nl)
comma: %ws* "," %ws*
dotdot: nodent ".." %ws*
plain_word: ([a-zA-Z0-9_] / %utf8_char)+
|