1@subheader """\
2from ast import literal_eval
3
4from pegen.grammar import (
5    Alt,
6    Cut,
7    Forced,
8    Gather,
9    Group,
10    Item,
11    Lookahead,
12    LookaheadOrCut,
13    MetaTuple,
14    MetaList,
15    NameLeaf,
16    NamedItem,
17    NamedItemList,
18    NegativeLookahead,
19    Opt,
20    Plain,
21    PositiveLookahead,
22    Repeat0,
23    Repeat1,
24    Rhs,
25    Rule,
26    RuleList,
27    RuleName,
28    Grammar,
29    StringLeaf,
30)
31"""
32
33start[Grammar]: grammar ENDMARKER { grammar }
34
35grammar[Grammar]:
36    | metas rules { Grammar(rules, metas) }
37    | rules { Grammar(rules, []) }
38
39metas[MetaList]:
40    | meta metas { [meta] + metas }
41    | meta { [meta] }
42
43meta[MetaTuple]:
44    | "@" NAME NEWLINE { (name.string, None) }
45    | "@" a=NAME b=NAME NEWLINE { (a.string, b.string) }
46    | "@" NAME STRING NEWLINE { (name.string, literal_eval(string.string)) }
47
48rules[RuleList]:
49    | rule rules { [rule] + rules }
50    | rule { [rule] }
51
52rule[Rule]:
53    | rulename memoflag? ":" alts NEWLINE INDENT more_alts DEDENT {
54          Rule(rulename[0], rulename[1], Rhs(alts.alts + more_alts.alts), memo=opt) }
55    | rulename memoflag? ":" NEWLINE INDENT more_alts DEDENT {
56          Rule(rulename[0], rulename[1], more_alts, memo=opt) }
57    | rulename memoflag? ":" alts NEWLINE { Rule(rulename[0], rulename[1], alts, memo=opt) }
58
59rulename[RuleName]:
60    | NAME annotation { (name.string, annotation) }
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 annotation '=' ~ item {NamedItem(name.string, item, annotation)}
87    | NAME '=' ~ item {NamedItem(name.string, item)}
88    | item {NamedItem(None, item)}
89    | forced=forced_atom {NamedItem(None, forced)}
90    | it=lookahead {NamedItem(None, it)}
91
92forced_atom[Forced]:
93    | '&''&' ~ atom {Forced(atom)}
94
95lookahead[LookaheadOrCut]:
96    | '&' ~ atom {PositiveLookahead(atom)}
97    | '!' ~ atom {NegativeLookahead(atom)}
98    | '~' {Cut()}
99
100item[Item]:
101    | '[' ~ alts ']' {Opt(alts)}
102    |  atom '?' {Opt(atom)}
103    |  atom '*' {Repeat0(atom)}
104    |  atom '+' {Repeat1(atom)}
105    |  sep=atom '.' node=atom '+' {Gather(sep, node)}
106    |  atom {atom}
107
108atom[Plain]:
109    | '(' ~ alts ')' {Group(alts)}
110    | NAME {NameLeaf(name.string) }
111    | STRING {StringLeaf(string.string)}
112
113# Mini-grammar for the actions and annotations
114
115action[str]: "{" ~ target_atoms "}" { target_atoms }
116annotation[str]: "[" ~ target_atoms "]" { target_atoms }
117
118target_atoms[str]:
119    | target_atom target_atoms { target_atom + " " + target_atoms }
120    | target_atom { target_atom }
121
122target_atom[str]:
123    | "{" ~ atoms=target_atoms? "}" { "{" + (atoms or "") + "}" }
124    | "[" ~ atoms=target_atoms? "]" { "[" + (atoms or "") + "]" }
125    | NAME "*" { name.string + "*" }
126    | NAME { name.string }
127    | NUMBER { number.string }
128    | STRING { string.string }
129    | "?" { "?" }
130    | ":" { ":" }
131    | !"}" !"]" OP { op.string }
132