-
Notifications
You must be signed in to change notification settings - Fork 2
/
parser_c_preproc.ebnf
216 lines (167 loc) · 4.25 KB
/
parser_c_preproc.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*
Grammar originally from https://sourceforge.net/projects/libparser/
files test/grammar/parser_c_preproc.bnf and test/grammar/scanner_c_preproc.bnf
Manually converted (correctnes is not the priority now) to be viewd by
(IPV6) https://www.bottlecaps.de/rr/ui
(IPV4) https://rr.red-dove.com/ui
*/
PREPROCESSOR ::= CODE CONTROL_LINE PREPROCESSOR
| CODE
// accept anything that is not a control line or a directive end
CODE_WITHOUT_DIRECTEND ::= CODE_WITHOUT_DIRECTEND CODE_TOKEN_WITHOUT_DIRECTEND
| /* empty */
// accept anything that is not a control line
CODE ::= CODE CODE_TOKEN
| /* empty */
CODE_TOKEN ::= CODE_TOKEN_WITHOUT_DIRECTEND
| DIRECTIVE_END
CODE_TOKEN_WITHOUT_DIRECTEND ::= DEFINED
| IDENTIFIER
| MACRO
| CONSTANT
| FILENAME_SYSTEM
| STRING_LITERAL
| COMMA
| P_OPEN
| P_CLOSE
| RIGHT_OP
| LEFT_OP
| AND_OP
| OR_OP
| LE_OP
| GE_OP
| EQ_OP
| NE_OP
| DOT
| AND
| NOT
| NEG
| LESS_SIG
| PLUS_SIG
| MUL
| DIV
| MOD
| LESS
| GREATER
| XOR
| OR
| TEXT
CONTROL_LINE ::= DEFINE_LINE
| UNDEF_LINE
| INCLUDE_LINE
| CONDITIONAL
| LINE_LINE
| ERROR_LINE
| WARNING_LINE
| PRAGMA_LINE
DEFINE_LINE ::= DEFINE IDENTIFIER CODE_WITHOUT_DIRECTEND DIRECTIVE_END
| DEFINE MACRO IDENTIFIER_LIST P_CLOSE CODE_WITHOUT_DIRECTEND DIRECTIVE_END
| DEFINE MACRO P_CLOSE CODE_WITHOUT_DIRECTEND DIRECTIVE_END
UNDEF_LINE ::= UNDEF IDENTIFIER DIRECTIVE_END
INCLUDE_LINE ::= INCLUDE FILENAME_SYSTEM DIRECTIVE_END
| INCLUDE STRING_LITERAL DIRECTIVE_END
| INCLUDE IDENTIFIER DIRECTIVE_END
LINE_LINE ::= LINE CONSTANT STRING_LITERAL DIRECTIVE_END
| LINE CONSTANT DIRECTIVE_END
ERROR_LINE ::= ERROR STRING_LITERAL DIRECTIVE_END
WARNING_LINE ::= WARNING STRING_LITERAL DIRECTIVE_END
PRAGMA_LINE ::= PRAGMA STRING_LITERAL DIRECTIVE_END
CONDITIONAL ::= IF_LINE PREPROCESSOR ELIF_PARTS
IF_LINE ::= IF CODE_WITHOUT_DIRECTEND DIRECTIVE_END
| IFDEF IDENTIFIER DIRECTIVE_END
| IFNDEF IDENTIFIER DIRECTIVE_END
ENDIF_LINE ::= ENDIF DIRECTIVE_END
ELIF_PARTS ::= ELIF_LINE PREPROCESSOR ELIF_PARTS
| ELSE_PART
ELSE_PART ::= ELSE_LINE PREPROCESSOR ENDIF_LINE
| ENDIF_LINE
ELIF_LINE ::= ELIF CODE_WITHOUT_DIRECTEND DIRECTIVE_END
ELSE_LINE ::= ELSE DIRECTIVE_END
IDENTIFIER_LIST ::= IDENTIFIER COMMA IDENTIFIER_LIST
| IDENTIFIER
/* scanner */
/*ignore*/ COMMENT ::= ("/*"([^\*]|("*"+[^\*/]))*"*"+"/")|("//"[^\n]*)
/*ignore*/ DIRECTIVE_CONTINUE ::= "\\\n"
DIRECTIVE_END ::= "\n"
DEFINE ::= "#define"
DEFINED ::= "defined"
UNDEF ::= "#undef"
INCLUDE ::= "#include"
IF ::= "#if"
IFDEF ::= "#ifdef"
IFNDEF ::= "#ifndef"
ELSE ::= "#else"
ELIF ::= "#elif"
ENDIF ::= "#endif"
LINE ::= "#line"
ERROR ::= "#error"
WARNING ::= "#warning"
PRAGMA ::= "#pragma"
IDENTIFIER ::= [_a-zA-Z][_a-zA-Z0-9]*
/*
* MACRO is a workaround becouse in the expression
* #define a (b) c
* if there is a whitespace between a and (b), it is a ordinary define
* if there is no whitespace, then it's a macro,
* as our lexer ignores whitespaces, we define the token MACRO
* that is an identifier with a '(' in the end
*/
MACRO ::= [_a-zA-Z][_a-zA-Z0-9]*
CONSTANT ::= "0"[xX]([0-9a-fA-F])+[uUlL]?
CONSTANT ::= [0-9]+[uUlL]?
CONSTANT ::= "'"([^\']|"\'")+"'"
CONSTANT ::= [0-9]+[eE][\+-]?[0-9]+[fFlL]?
CONSTANT ::= [0-9]+'.'[0-9]*([eE][\+-]?)?[0-9]+[fFlL]?
CONSTANT ::= [0-9]*'.'[0-9]+([eE][\+-]?)?[0-9]+[fFlL]?
FILENAME_SYSTEM ::= "<" [^>]* ">"
STRING_LITERAL ::= '"' ([^\"]|'\"')* '"'
ELLIPSIS ::= "..."
RIGHT_ASSIGN ::= ">>="
LEFT_ASSIGN ::= "<<="
ADD_ASSIGN ::= "+="
SUB_ASSIGN ::= "-="
MUL_ASSIGN ::= "*="
DIV_ASSIGN ::= "/="
MOD_ASSIGN ::= "%="
AND_ASSIGN ::= "&="
XOR_ASSIGN ::= "^="
OR_ASSIGN ::= "|="
RIGHT_OP ::= ">>"
LEFT_OP ::= "<<"
INC_OP ::= "++"
DEC_OP ::= "--"
PTR_OP ::= "->"
AND_OP ::= "&&"
OR_OP ::= "||"
LE_OP ::= "<="
GE_OP ::= ">="
EQ_OP ::= "=="
NE_OP ::= "!="
INST_END ::= ";"
BEGIN ::= "{"
END ::= "}"
COMMA ::= ","
COLUMN ::= ":"
EQ ::= "="
P_OPEN ::= "("
P_CLOSE ::= ")"
B_OPEN ::= "["
B_CLOSE ::= "]"
DOT ::= "."
AND ::= "&"
NOT ::= "!"
NEG ::= "~"
LESS_SIG ::= "-"
PLUS_SIG ::= "+"
MUL ::= "*"
DIV ::= "/"
MOD ::= "%"
LESS ::= "<"
GREATER ::= ">"
XOR ::= "^"
OR ::= "|"
QUESTION ::= "?"
/*ignore*/ WHITESPCE ::= "[ \t\f\r]+"
// the text will be generated by PreprocessorScanner.
// define it's regex to be never used here
TEXT ::= " "