1@subheader """\
2from ast import literal_eval
3
4from pegen.grammar import (
5    Alt,
6    Cut,
7    Gather,
8    Group,
9    Item,
10    Lookahead,
11    LookaheadOrCut,
12    MetaTuple,
13    MetaList,
14    NameLeaf,
15    NamedItem,
16    NamedItemList,
17    NegativeLookahead,
18    Opt,
19    Plain,
20    PositiveLookahead,
21    Repeat0,
22    Repeat1,
23    Rhs,
24    Rule,
25    RuleList,
26    RuleName,
27    Grammar,
28    StringLeaf,
29)
30"""
31
32start[Grammar]: grammar ENDMARKER { grammar }
33
34grammar[Grammar]:
35    | metas rules { Grammar(rules, metas) }
36    | rules { Grammar(rules, []) }
37
38metas[MetaList]:
39    | meta metas { [meta] + metas }
40    | meta { [meta] }
41
42meta[MetaTuple]:
43    | "@" NAME NEWLINE { (name.string, None) }
44    | "@" a=NAME b=NAME NEWLINE { (a.string, b.string) }
45    | "@" NAME STRING NEWLINE { (name.string, literal_eval(string.string)) }
46
47rules[RuleList]:
48    | rule rules { [rule] + rules }
49    | rule { [rule] }
50
51rule[Rule]:
52    | rulename memoflag? ":" alts NEWLINE INDENT more_alts DEDENT {
53          Rule(rulename[0], rulename[1], Rhs(alts.alts + more_alts.alts), memo=opt) }
54    | rulename memoflag? ":" NEWLINE INDENT more_alts DEDENT {
55          Rule(rulename[0], rulename[1], more_alts, memo=opt) }
56    | rulename memoflag? ":" alts NEWLINE { Rule(rulename[0], rulename[1], alts, memo=opt) }
57
58rulename[RuleName]:
59    | NAME '[' type=NAME '*' ']' { (name.string, type.string+"*") }
60    | NAME '[' type=NAME ']' { (name.string, type.string) }
61    | NAME { (name.string, None) }
62
63# In the future this may return something more complicated
64memoflag[str]:
65    | '(' 'memo' ')' { "memo" }
66
67alts[Rhs]:
68    | alt "|" alts { Rhs([alt] + alts.alts)}
69    | alt { Rhs([alt]) }
70
71more_alts[Rhs]:
72    | "|" alts NEWLINE more_alts { Rhs(alts.alts + more_alts.alts) }
73    | "|" alts NEWLINE { Rhs(alts.alts) }
74
75alt[Alt]:
76    | items '$' action { Alt(items + [NamedItem(None, NameLeaf('ENDMARKER'))], action=action) }
77    | items '$' { Alt(items + [NamedItem(None, NameLeaf('ENDMARKER'))], action=None) }
78    | items action { Alt(items, action=action) }
79    | items { Alt(items, action=None) }
80
81items[NamedItemList]:
82    | named_item items { [named_item] + items }
83    | named_item { [named_item] }
84
85named_item[NamedItem]:
86    | NAME '=' ~ item {NamedItem(name.string, item)}
87    | item {NamedItem(None, item)}
88    | it=lookahead {NamedItem(None, it)}
89
90lookahead[LookaheadOrCut]:
91    | '&' ~ atom {PositiveLookahead(atom)}
92    | '!' ~ atom {NegativeLookahead(atom)}
93    | '~' {Cut()}
94
95item[Item]:
96    | '[' ~ alts ']' {Opt(alts)}
97    |  atom '?' {Opt(atom)}
98    |  atom '*' {Repeat0(atom)}
99    |  atom '+' {Repeat1(atom)}
100    |  sep=atom '.' node=atom '+' {Gather(sep, node)}
101    |  atom {atom}
102
103atom[Plain]:
104    | '(' ~ alts ')' {Group(alts)}
105    | NAME {NameLeaf(name.string) }
106    | STRING {StringLeaf(string.string)}
107
108# Mini-grammar for the actions
109
110action[str]: "{" ~ target_atoms "}" { target_atoms }
111
112target_atoms[str]:
113    | target_atom target_atoms { target_atom + " " + target_atoms }
114    | target_atom { target_atom }
115
116target_atom[str]:
117    | "{" ~ target_atoms "}" { "{" + target_atoms + "}" }
118    | NAME { name.string }
119    | NUMBER { number.string }
120    | STRING { string.string }
121    | "?" { "?" }
122    | ":" { ":" }
123    | !"}" OP { op.string }
124