-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathgrammar.ebnf
151 lines (114 loc) · 3.41 KB
/
grammar.ebnf
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
139
140
141
142
143
144
145
146
147
148
149
150
151
# Copyright (C) 2022, Alex Badics
# This file is part of peginator
# Licensed under the MIT license. See LICENSE file in the project root for details.
@export
Grammar = {(rules:Rule | rules:CharRule | rules:ExternRule) ";"} $ ;
Rule = {directives:DirectiveExpression} name:Identifier "=" definition:Choice;
CharRule = {directives:CheckDirective} CharDirective {directives:CheckDirective} name:Identifier "=" choices:CharRulePart {"|" choices:CharRulePart };
CharRulePart = @:CharacterRange | @:CharRangePart | @:Identifier;
ExternRule = directive:ExternDirective name:Identifier;
Choice = choices:Sequence {"|" choices:Sequence};
Sequence = { parts:DelimitedExpression };
Group = "(" body:Choice ")";
Optional = "[" body:Choice "]";
Closure = "{" body:Choice "}" [at_least_one:AtLeastOneMarker];
AtLeastOneMarker = '+';
NegativeLookahead = "!" expr:*DelimitedExpression;
PositiveLookahead = "&" expr:*DelimitedExpression;
CharacterRange = from:CharRangePart ".." to:CharRangePart;
@no_skip_ws
CharRangePart = "'" @:StringItem "'";
@no_skip_ws
StringLiteral =
[insensitive:CaseInsensitiveMarker]
(
'"' {!'"' body:StringItem } '"' |
"'" {!"'" body:StringItem } "'"
)
;
CaseInsensitiveMarker = 'i';
Field = [(name:Identifier | name:OverrideMarker) ":" [boxed:BoxMarker]] typ:Identifier;
BoxMarker = '*';
OverrideMarker = "@";
IncludeRule = ">" rule:Identifier;
DelimitedExpression =
@:Group |
@:Optional |
@:Closure |
@:NegativeLookahead |
@:PositiveLookahead |
@:CharacterRange |
@:StringLiteral |
@:EndOfInput |
@:IncludeRule |
@:Field
;
@string
@no_skip_ws
Identifier = {IdentifierChar}+;
@char
IdentifierChar = 'a'..'z' | 'A'..'Z' | '0'..'9' | '_';
@no_skip_ws
StringItem = '\\' (@:SimpleEscape | @:HexaEscape | @:Utf8Escape) | !'\\' @:char ;
@no_skip_ws
SimpleEscape =
@:SimpleEscapeNewline |
@:SimpleEscapeCarriageReturn |
@:SimpleEscapeTab |
@:SimpleEscapeBackslash |
@:SimpleEscapeQuote |
@:SimpleEscapeDQuote
;
@no_skip_ws
SimpleEscapeNewline = 'n';
@no_skip_ws
SimpleEscapeCarriageReturn = 'r';
@no_skip_ws
SimpleEscapeTab = 't';
@no_skip_ws
SimpleEscapeBackslash = '\\';
@no_skip_ws
SimpleEscapeQuote = "'";
@no_skip_ws
SimpleEscapeDQuote = '"';
@no_skip_ws
HexaEscape = 'x' c1:HexChar c2:HexChar;
@char
HexChar = '0'..'9' | 'a'..'f' | 'A'..'F';
@no_skip_ws
Utf8Escape =
'u' '{' c1:HexChar [c2:HexChar [c3:HexChar [c4:HexChar [c5:HexChar [c6:HexChar ]]]]] '}' |
'u' c1:HexChar c2:HexChar c3:HexChar c4:HexChar |
'U' '0' '0' c1:HexChar c2:HexChar c3:HexChar c4:HexChar c5:HexChar c6:HexChar
;
DirectiveExpression =
@:StringDirective |
@:NoSkipWsDirective |
@:ExportDirective |
@:PositionDirective |
@:MemoizeDirective |
@:LeftrecDirective |
@:CheckDirective
;
StringDirective = "@string";
CharDirective = "@char";
NoSkipWsDirective = "@no_skip_ws";
ExportDirective = "@export";
PositionDirective = "@position";
MemoizeDirective = "@memoize";
LeftrecDirective = "@leftrec";
CheckDirective = "@check" "(" function:NamespacedRustName ")";
ExternDirective =
"@extern" "("
function:NamespacedRustName
[ '->' return_type:NamespacedRustName ]
")"
;
NamespacedRustName = @:RustNamePart { '::' @:RustNamePart };
@string
RustNamePart = {!( '-' | ')' |':' ) char}+;
EndOfInput = '$';
@no_skip_ws
Whitespace = {Comment | '\t' | '\n' | '\x0C' | '\r' | ' '};
@no_skip_ws
Comment = '#' {!'\n' char} '\n';