blob: b705de5067fe105c4b4697f8e88e67b9a975fb24 (
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
136
137
138
|
file:
shebang?
(ignored_line %nl)*
(block / action / expression)?
(%nl ignored_line)*
(!. / (({} (.* -> "Parse error") %userdata) => error))
shebang: "#!" [^%nl]* (!. / %nl)
inline_block (Block):
{| inline_statement (%ws* ";" %ws* inline_statement)+ |}
block (Block):
{| statement (nodent (statement / (({} ([^%nl]* -> "Error while parsing block line") %userdata) => error)))+ |}
statement: (action / expression) (eol / (({} ([^%nl]* -> "Error while parsing line") %userdata) => error))
inline_statement: inline_action / inline_expression
noindex_inline_expression:
number / variable / inline_text / inline_list / inline_dict / inline_nomsu
/ ( "("
%ws* (inline_block / inline_action / inline_expression) %ws*
(comma %ws* (inline_block / inline_action / inline_expression) %ws*)*
(")"
/ (({} ((!. / &%nl) -> 'Expected to find a ) before the end of the line') %userdata) => error)
/ (({} ([^%nl]* -> 'Error while parsing subexpression') %userdata) => 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") %userdata) => error))
)
expression:
inline_expression / (":" %ws* (inline_block / inline_action / inline_expression) eol) / indented_expression
inline_nomsu (EscapedNomsu): "\" {| inline_expression |}
indented_nomsu (EscapedNomsu):
"\" {| (noindex_inline_expression / (":" %ws* (inline_block / inline_action / inline_expression) eol) / indented_expression) |}
index_chain (IndexChain):
{| noindex_inline_expression ("." (text_word / noindex_inline_expression))+ |}
-- Actions 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))?
|}
action (Action):
{| (expression (dotdot? %ws*))* word ((dotdot? %ws*) (expression / word))* |}
word: { %operator / (!number plain_word) }
text_word (Text): {| {%operator / (!number plain_word)} |}
inline_text (Text):
!('".."' eol)
'"' {|
({~ (('\"' -> '"') / ('\\' -> '\') / %escaped_char / [^%nl\"])+ ~}
/ inline_text_interpolation)*
|} ('"' / (({} ([^%nl]*->'Failed to find a closing " mark on the same line') %userdata) => 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)*
|} (((!.) %dedent) / (&(%nl %dedent)) / (({} (non_dedent_error -> "Error while parsing Text") %userdata) => error))
inline_text_interpolation:
"\" (
variable / inline_list / inline_dict / inline_text
/ ("("
%ws* (inline_block / inline_action / inline_expression) %ws*
(comma %ws* (inline_block / inline_action / inline_expression) %ws*)*
(")"
/ (({} (&%nl -> 'Expected to find a ")" before the end of the line') %userdata) => error)
/ (({} ([^%nl]* -> 'Error while parsing text interpolation') %userdata) => 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 ((!"'" %operator) / plain_word)*)? }
inline_list (List):
!('[..]')
"[" %ws* {| (inline_list_item (comma inline_list_item)* comma?)? |} %ws*
("]" / (({} ([^%nl]*->"Failed to find a closing ] on the same line") %userdata) => error))
indented_list (List):
"[..]" indent
{| list_line (nodent list_line)* |}
(dedent / (({} (non_dedent_error -> "Error while parsing list") %userdata) => 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_entry (comma inline_dict_entry)*)? |} %ws*
("}"
/ (({} (%ws* comma? (!. / &%nl)->"Failed to find a closing } on the same line") %userdata) => error)
/ (({} ([^%nl]*->"Error while parsing dictionary") %userdata) => error))
indented_dict (Dict):
"{..}" indent
{| dict_line (nodent dict_line)* |}
(dedent / (({} (non_dedent_error -> "Error while parsing dict") %userdata) => error))
dict_line:
(dict_entry !comma) / (inline_dict_entry (comma dict_line?)?)
dict_entry(DictEntry):
{| dict_key %ws* ":" %ws* (action / expression) |}
inline_dict_entry(DictEntry):
{| dict_key %ws* (":" %ws* (inline_block / inline_action / inline_expression)?) |}
dict_key:
text_word / inline_expression
comment: "#" [^%nl]* (%nl+ %indent [^%nl]* (%nl+ %nodent [^%nl]*)* %dedent)?
eol_comment: "#" [^%nl]*
eol: %ws* eol_comment? (!. / &%nl)
ignored_line: (%nodent comment) / (%ws* (!. / &%nl))
indent: eol (%nl ignored_line)* %nl %indent (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 ".."
plain_word: ([a-zA-Z0-9_-] / %utf8_char)+
|