cast 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +6 -0
- data/doc/index.html +2513 -0
- data/install.rb +14 -0
- data/lib/c.tab.rb +3433 -0
- data/lib/c.y +935 -0
- data/lib/c_nodes.rb +1301 -0
- data/lib/cast.rb +9 -0
- data/lib/node.rb +744 -0
- data/lib/node_list.rb +842 -0
- data/lib/parse.rb +233 -0
- data/lib/to_debug.rb +59 -0
- data/lib/to_s.rb +538 -0
- data/test/common.rb +174 -0
- data/test/run.rb +5 -0
- data/test/test_c_nodes.rb +160 -0
- data/test/test_node.rb +1224 -0
- data/test/test_node_list.rb +2485 -0
- data/test/test_parse.rb +2014 -0
- data/test/test_parser.rb +2925 -0
- metadata +56 -0
data/lib/c.y
ADDED
@@ -0,0 +1,935 @@
|
|
1
|
+
class C::Parser
|
2
|
+
## shift/reduce conflict on "if (c) if (c) ; else ; else ;"
|
3
|
+
expect 1
|
4
|
+
rule
|
5
|
+
|
6
|
+
## A.2.4 External definitions
|
7
|
+
|
8
|
+
## Returns TranslationUnit
|
9
|
+
translation_unit
|
10
|
+
: external_declaration {result = TranslationUnit.new_at(val[0].pos, NodeChain[val[0]])}
|
11
|
+
| translation_unit external_declaration {result = val[0]; result.entities << val[1]}
|
12
|
+
|
13
|
+
## Returns Declaration|FunctionDef
|
14
|
+
external_declaration
|
15
|
+
: function_definition {result = val[0]}
|
16
|
+
| declaration {result = val[0]}
|
17
|
+
|
18
|
+
## Returns FunctionDef
|
19
|
+
function_definition
|
20
|
+
: declaration_specifiers declarator declaration_list compound_statement {result = make_function_def(val[0][0], val[0][1], val[1], val[2], val[3])}
|
21
|
+
| declaration_specifiers declarator compound_statement {result = make_function_def(val[0][0], val[0][1], val[1], nil , val[2])}
|
22
|
+
|
23
|
+
## Returns [Declaration]
|
24
|
+
declaration_list
|
25
|
+
: declaration {result = [val[0]]}
|
26
|
+
| declaration_list declaration {result = val[0] << val[1]}
|
27
|
+
|
28
|
+
## A.2.3 Statements
|
29
|
+
|
30
|
+
## Returns Statement
|
31
|
+
statement
|
32
|
+
: labeled_statement {result = val[0]}
|
33
|
+
| compound_statement {result = val[0]}
|
34
|
+
| expression_statement {result = val[0]}
|
35
|
+
| selection_statement {result = val[0]}
|
36
|
+
| iteration_statement {result = val[0]}
|
37
|
+
| jump_statement {result = val[0]}
|
38
|
+
|
39
|
+
## Returns Statement
|
40
|
+
labeled_statement
|
41
|
+
: identifier ':' statement {val[2].labels.unshift(PlainLabel.new_at(val[0].pos, val[0].val)); result = val[2]}
|
42
|
+
| 'case' constant_expression ':' statement {val[3].labels.unshift(Case .new_at(val[0].pos, val[1] )); result = val[3]}
|
43
|
+
| 'default' ':' statement {val[2].labels.unshift(Default .new_at(val[0].pos )); result = val[2]}
|
44
|
+
## type names can also be used as labels
|
45
|
+
| typedef_name ':' statement {val[2].labels.unshift(PlainLabel.new_at(val[0].pos, val[0].name)); result = val[2]}
|
46
|
+
|
47
|
+
## Returns Block
|
48
|
+
compound_statement
|
49
|
+
: '{' block_item_list '}' {result = Block.new_at(val[0].pos, val[1])}
|
50
|
+
| '{' '}' {result = Block.new_at(val[0].pos )}
|
51
|
+
|
52
|
+
## Returns NodeChain[Declaration|Statement]
|
53
|
+
block_item_list
|
54
|
+
: block_item {result = NodeChain[val[0]]}
|
55
|
+
| block_item_list block_item {result = val[0] << val[1]}
|
56
|
+
|
57
|
+
## Returns Declaration|Statement
|
58
|
+
block_item
|
59
|
+
: declaration {result = val[0]}
|
60
|
+
| statement {result = val[0]}
|
61
|
+
|
62
|
+
## Returns ExpressionStatement
|
63
|
+
expression_statement
|
64
|
+
: expression ';' {result = ExpressionStatement.new_at(val[0].pos, val[0])}
|
65
|
+
| ';' {result = ExpressionStatement.new_at(val[0].pos )}
|
66
|
+
|
67
|
+
## Returns Statement
|
68
|
+
selection_statement
|
69
|
+
: 'if' '(' expression ')' statement {result = If .new_at(val[0].pos, val[2], val[4] )}
|
70
|
+
| 'if' '(' expression ')' statement 'else' statement {result = If .new_at(val[0].pos, val[2], val[4], val[6])}
|
71
|
+
| 'switch' '(' expression ')' statement {result = Switch.new_at(val[0].pos, val[2], val[4] )}
|
72
|
+
|
73
|
+
## Returns Statement
|
74
|
+
iteration_statement
|
75
|
+
: 'while' '(' expression ')' statement {result = While.new_at(val[0].pos, val[2], val[4] )}
|
76
|
+
| 'do' statement 'while' '(' expression ')' ';' {result = While.new_at(val[0].pos, val[4], val[1], :do => true )}
|
77
|
+
| 'for' '(' expression ';' expression ';' expression ')' statement {result = For.new_at(val[0].pos, val[2], val[4], val[6], val[8])}
|
78
|
+
| 'for' '(' expression ';' expression ';' ')' statement {result = For.new_at(val[0].pos, val[2], val[4], nil , val[7])}
|
79
|
+
| 'for' '(' expression ';' ';' expression ')' statement {result = For.new_at(val[0].pos, val[2], nil , val[5], val[7])}
|
80
|
+
| 'for' '(' expression ';' ';' ')' statement {result = For.new_at(val[0].pos, val[2], nil , nil , val[6])}
|
81
|
+
| 'for' '(' ';' expression ';' expression ')' statement {result = For.new_at(val[0].pos, nil , val[3], val[5], val[7])}
|
82
|
+
| 'for' '(' ';' expression ';' ')' statement {result = For.new_at(val[0].pos, nil , val[3], nil , val[6])}
|
83
|
+
| 'for' '(' ';' ';' expression ')' statement {result = For.new_at(val[0].pos, nil , nil , val[4], val[6])}
|
84
|
+
| 'for' '(' ';' ';' ')' statement {result = For.new_at(val[0].pos, nil , nil , nil , val[5])}
|
85
|
+
| 'for' '(' declaration expression ';' expression ')' statement {result = For.new_at(val[0].pos, val[2], val[3], val[5], val[7])}
|
86
|
+
| 'for' '(' declaration expression ';' ')' statement {result = For.new_at(val[0].pos, val[2], val[3], nil , val[6])}
|
87
|
+
| 'for' '(' declaration ';' expression ')' statement {result = For.new_at(val[0].pos, val[2], nil , val[4], val[6])}
|
88
|
+
| 'for' '(' declaration ';' ')' statement {result = For.new_at(val[0].pos, val[2], nil , nil , val[5])}
|
89
|
+
|
90
|
+
## Returns Statement
|
91
|
+
jump_statement
|
92
|
+
: 'goto' identifier ';' {result = Goto .new_at(val[0].pos, val[1].val)}
|
93
|
+
| 'continue' ';' {result = Continue.new_at(val[0].pos )}
|
94
|
+
| 'break' ';' {result = Break .new_at(val[0].pos )}
|
95
|
+
| 'return' expression ';' {result = Return .new_at(val[0].pos, val[1] )}
|
96
|
+
| 'return' ';' {result = Return .new_at(val[0].pos )}
|
97
|
+
## type names can also be used as labels
|
98
|
+
| 'goto' typedef_name ';' {result = Goto .new_at(val[0].pos, val[1].name)}
|
99
|
+
|
100
|
+
## A.2.2 Declarations
|
101
|
+
|
102
|
+
## Returns Declaration
|
103
|
+
declaration
|
104
|
+
: declaration_specifiers init_declarator_list ';' {result = make_declaration(val[0][0], val[0][1], val[1])}
|
105
|
+
| declaration_specifiers ';' {result = make_declaration(val[0][0], val[0][1], NodeArray[])}
|
106
|
+
|
107
|
+
## Returns {Pos, [Symbol]}
|
108
|
+
declaration_specifiers
|
109
|
+
: storage_class_specifier declaration_specifiers {val[1][1] << val[0][1]; result = val[1]}
|
110
|
+
| storage_class_specifier {result = [val[0][0], [val[0][1]]]}
|
111
|
+
| type_specifier declaration_specifiers {val[1][1] << val[0][1]; result = val[1]}
|
112
|
+
| type_specifier {result = [val[0][0], [val[0][1]]]}
|
113
|
+
| type_qualifier declaration_specifiers {val[1][1] << val[0][1]; result = val[1]}
|
114
|
+
| type_qualifier {result = [val[0][0], [val[0][1]]]}
|
115
|
+
| function_specifier declaration_specifiers {val[1][1] << val[0][1]; result = val[1]}
|
116
|
+
| function_specifier {result = [val[0][0], [val[0][1]]]}
|
117
|
+
|
118
|
+
## Returns NodeArray[Declarator]
|
119
|
+
init_declarator_list
|
120
|
+
: init_declarator {result = NodeArray[val[0]]}
|
121
|
+
| init_declarator_list ',' init_declarator {result = val[0] << val[2]}
|
122
|
+
|
123
|
+
## Returns Declarator
|
124
|
+
init_declarator
|
125
|
+
: declarator {result = val[0]}
|
126
|
+
| declarator '=' initializer {val[0].init = val[2]; result = val[0]}
|
127
|
+
|
128
|
+
## Returns [Pos, Symbol]
|
129
|
+
storage_class_specifier
|
130
|
+
: 'typedef' {result = [val[0].pos, val[0].val]}
|
131
|
+
| 'extern' {result = [val[0].pos, val[0].val]}
|
132
|
+
| 'static' {result = [val[0].pos, val[0].val]}
|
133
|
+
| 'auto' {result = [val[0].pos, val[0].val]}
|
134
|
+
| 'register' {result = [val[0].pos, val[0].val]}
|
135
|
+
|
136
|
+
## Returns [Pos, Type|Symbol]
|
137
|
+
type_specifier
|
138
|
+
: 'void' {result = [val[0].pos, val[0].val]}
|
139
|
+
| 'char' {result = [val[0].pos, val[0].val]}
|
140
|
+
| 'short' {result = [val[0].pos, val[0].val]}
|
141
|
+
| 'int' {result = [val[0].pos, val[0].val]}
|
142
|
+
| 'long' {result = [val[0].pos, val[0].val]}
|
143
|
+
| 'float' {result = [val[0].pos, val[0].val]}
|
144
|
+
| 'double' {result = [val[0].pos, val[0].val]}
|
145
|
+
| 'signed' {result = [val[0].pos, val[0].val]}
|
146
|
+
| 'unsigned' {result = [val[0].pos, val[0].val]}
|
147
|
+
| '_Bool' {result = [val[0].pos, val[0].val]}
|
148
|
+
| '_Complex' {result = [val[0].pos, val[0].val]}
|
149
|
+
| '_Imaginary' {result = [val[0].pos, val[0].val]}
|
150
|
+
| struct_or_union_specifier {result = [val[0].pos, val[0] ]}
|
151
|
+
| enum_specifier {result = [val[0].pos, val[0] ]}
|
152
|
+
| typedef_name {result = [val[0].pos, val[0] ]}
|
153
|
+
|
154
|
+
## Returns Struct|Union
|
155
|
+
struct_or_union_specifier
|
156
|
+
: struct_or_union identifier '{' struct_declaration_list '}' {result = val[0][1].new_at(val[0][0], val[1].val, val[3])}
|
157
|
+
| struct_or_union '{' struct_declaration_list '}' {result = val[0][1].new_at(val[0][0], nil , val[2])}
|
158
|
+
| struct_or_union identifier {result = val[0][1].new_at(val[0][0], val[1].val, nil )}
|
159
|
+
## type names can also be used as struct identifiers
|
160
|
+
| struct_or_union typedef_name '{' struct_declaration_list '}' {result = val[0][1].new_at(val[0][0], val[1].name, val[3])}
|
161
|
+
| struct_or_union typedef_name {result = val[0][1].new_at(val[0][0], val[1].name, nil )}
|
162
|
+
|
163
|
+
## Returns [Pos, Class]
|
164
|
+
struct_or_union
|
165
|
+
: 'struct' {result = [val[0].pos, Struct]}
|
166
|
+
| 'union' {result = [val[0].pos, Union ]}
|
167
|
+
|
168
|
+
## Returns NodeArray[Declaration]
|
169
|
+
struct_declaration_list
|
170
|
+
: struct_declaration {result = NodeArray[val[0]]}
|
171
|
+
| struct_declaration_list struct_declaration {val[0] << val[1]; result = val[0]}
|
172
|
+
|
173
|
+
## Returns Declaration
|
174
|
+
struct_declaration
|
175
|
+
: specifier_qualifier_list struct_declarator_list ';' {result = make_declaration(val[0][0], val[0][1], val[1])}
|
176
|
+
|
177
|
+
## Returns {Pos, [Symbol]}
|
178
|
+
specifier_qualifier_list
|
179
|
+
: type_specifier specifier_qualifier_list {val[1][1] << val[0][1]; result = val[1]}
|
180
|
+
| type_specifier {result = [val[0][0], [val[0][1]]]}
|
181
|
+
| type_qualifier specifier_qualifier_list {val[1][1] << val[0][1]; result = val[1]}
|
182
|
+
| type_qualifier {result = [val[0][0], [val[0][1]]]}
|
183
|
+
|
184
|
+
## Returns NodeArray[Declarator]
|
185
|
+
struct_declarator_list
|
186
|
+
: struct_declarator {result = NodeArray[val[0]]}
|
187
|
+
| struct_declarator_list ',' struct_declarator {result = val[0] << val[2]}
|
188
|
+
|
189
|
+
## Returns Declarator
|
190
|
+
struct_declarator
|
191
|
+
: declarator {result = val[0]}
|
192
|
+
| declarator ':' constant_expression {result = val[0]; val[0].num_bits = val[2]}
|
193
|
+
| ':' constant_expression {result = Declarator.new_at(val[0].pos, :num_bits => val[1])}
|
194
|
+
|
195
|
+
## Returns Enum
|
196
|
+
enum_specifier
|
197
|
+
: 'enum' identifier '{' enumerator_list '}' {result = Enum.new_at(val[0].pos, val[1].val, val[3])}
|
198
|
+
| 'enum' '{' enumerator_list '}' {result = Enum.new_at(val[0].pos, nil , val[2])}
|
199
|
+
| 'enum' identifier '{' enumerator_list ',' '}' {result = Enum.new_at(val[0].pos, val[1].val, val[3])}
|
200
|
+
| 'enum' '{' enumerator_list ',' '}' {result = Enum.new_at(val[0].pos, nil , val[2])}
|
201
|
+
| 'enum' identifier {result = Enum.new_at(val[0].pos, val[1].val, nil )}
|
202
|
+
## type names can also be used as enum names
|
203
|
+
| 'enum' typedef_name '{' enumerator_list '}' {result = Enum.new_at(val[0].pos, val[1].name, val[3])}
|
204
|
+
| 'enum' typedef_name '{' enumerator_list ',' '}' {result = Enum.new_at(val[0].pos, val[1].name, val[3])}
|
205
|
+
| 'enum' typedef_name {result = Enum.new_at(val[0].pos, val[1].name, nil )}
|
206
|
+
|
207
|
+
## Returns NodeArray[Enumerator]
|
208
|
+
enumerator_list
|
209
|
+
: enumerator {result = NodeArray[val[0]]}
|
210
|
+
| enumerator_list ',' enumerator {result = val[0] << val[2]}
|
211
|
+
|
212
|
+
## Returns Enumerator
|
213
|
+
enumerator
|
214
|
+
: enumeration_constant {result = Enumerator.new_at(val[0].pos, val[0].val, nil )}
|
215
|
+
| enumeration_constant '=' constant_expression {result = Enumerator.new_at(val[0].pos, val[0].val, val[2])}
|
216
|
+
|
217
|
+
## Returns [Pos, Symbol]
|
218
|
+
type_qualifier
|
219
|
+
: 'const' {result = [val[0].pos, val[0].val]}
|
220
|
+
| 'restrict' {result = [val[0].pos, val[0].val]}
|
221
|
+
| 'volatile' {result = [val[0].pos, val[0].val]}
|
222
|
+
|
223
|
+
## Returns [Pos, Symbol]
|
224
|
+
function_specifier
|
225
|
+
: 'inline' {result = [val[0].pos, val[0].val]}
|
226
|
+
|
227
|
+
## Returns Declarator
|
228
|
+
declarator
|
229
|
+
: pointer direct_declarator {result = add_decl_type(val[1], val[0])}
|
230
|
+
| direct_declarator {result = val[0]}
|
231
|
+
|
232
|
+
## Returns Declarator
|
233
|
+
direct_declarator
|
234
|
+
: identifier {result = Declarator.new_at(val[0].pos, nil, val[0].val)}
|
235
|
+
| '(' declarator ')' {result = val[1]}
|
236
|
+
| direct_declarator '[' type_qualifier_list assignment_expression ']' {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
|
237
|
+
| direct_declarator '[' type_qualifier_list ']' {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
|
238
|
+
| direct_declarator '[' assignment_expression ']' {result = add_decl_type(val[0], Array.new_at(val[0].pos, nil, val[2]))}
|
239
|
+
| direct_declarator '[' ']' {result = add_decl_type(val[0], Array.new_at(val[0].pos ))}
|
240
|
+
| direct_declarator '[' 'static' type_qualifier_list assignment_expression ']' {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
|
241
|
+
| direct_declarator '[' 'static' assignment_expression ']' {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
|
242
|
+
| direct_declarator '[' type_qualifier_list 'static' assignment_expression ']' {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
|
243
|
+
| direct_declarator '[' type_qualifier_list '*' ']' {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
|
244
|
+
| direct_declarator '[' '*' ']' {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
|
245
|
+
| direct_declarator '(' parameter_type_list ')' {result = add_decl_type(val[0], Function.new_at(val[0].pos, nil, param_list(*val[2]), :var_args => val[2][1]))}
|
246
|
+
| direct_declarator '(' identifier_list ')' {result = add_decl_type(val[0], Function.new_at(val[0].pos, nil, val[2]))}
|
247
|
+
| direct_declarator '(' ')' {result = add_decl_type(val[0], Function.new_at(val[0].pos ))}
|
248
|
+
|
249
|
+
## Returns Pointer
|
250
|
+
pointer
|
251
|
+
: '*' type_qualifier_list {result = add_type_quals(Pointer.new_at(val[0].pos), val[1][1]) }
|
252
|
+
| '*' {result = Pointer.new_at(val[0].pos) }
|
253
|
+
| '*' type_qualifier_list pointer {p = add_type_quals(Pointer.new_at(val[0].pos), val[1][1]); val[2].direct_type = p; result = val[2]}
|
254
|
+
| '*' pointer {p = Pointer.new_at(val[0].pos) ; val[1].direct_type = p; result = val[1]}
|
255
|
+
|
256
|
+
## Returns {Pos, [Symbol]}
|
257
|
+
type_qualifier_list
|
258
|
+
: type_qualifier {result = [val[0][0], [val[0][1]]]}
|
259
|
+
| type_qualifier_list type_qualifier {val[0][1] << val[1][1]; result = val[0]}
|
260
|
+
|
261
|
+
## Returns [NodeArray[Parameter], var_args?]
|
262
|
+
parameter_type_list
|
263
|
+
: parameter_list {result = [val[0], false]}
|
264
|
+
| parameter_list ',' '...' {result = [val[0], true ]}
|
265
|
+
|
266
|
+
## Returns NodeArray[Parameter]
|
267
|
+
parameter_list
|
268
|
+
: parameter_declaration {result = NodeArray[val[0]]}
|
269
|
+
| parameter_list ',' parameter_declaration {result = val[0] << val[2]}
|
270
|
+
|
271
|
+
## Returns Parameter
|
272
|
+
parameter_declaration
|
273
|
+
: declaration_specifiers declarator {ind_type = val[1].indirect_type and ind_type.detach
|
274
|
+
result = make_parameter(val[0][0], val[0][1], ind_type, val[1].name)}
|
275
|
+
| declaration_specifiers abstract_declarator {result = make_parameter(val[0][0], val[0][1], val[1] , nil )}
|
276
|
+
| declaration_specifiers {result = make_parameter(val[0][0], val[0][1], nil , nil )}
|
277
|
+
|
278
|
+
## Returns NodeArray[Parameter]
|
279
|
+
identifier_list
|
280
|
+
: identifier {result = NodeArray[Parameter.new_at(val[0].pos, nil, val[0].val)]}
|
281
|
+
| identifier_list ',' identifier {result = val[0] << Parameter.new_at(val[2].pos, nil, val[2].val)}
|
282
|
+
|
283
|
+
## Returns Type
|
284
|
+
type_name
|
285
|
+
: specifier_qualifier_list abstract_declarator {val[1].direct_type = make_direct_type(val[0][0], val[0][1]); result = val[1]}
|
286
|
+
| specifier_qualifier_list {result = make_direct_type(val[0][0], val[0][1]) }
|
287
|
+
|
288
|
+
## Returns Type
|
289
|
+
abstract_declarator
|
290
|
+
: pointer {result = val[0]}
|
291
|
+
| pointer direct_abstract_declarator {val[1].direct_type = val[0]; result = val[1]}
|
292
|
+
| direct_abstract_declarator {result = val[0]}
|
293
|
+
|
294
|
+
## Returns Type
|
295
|
+
direct_abstract_declarator
|
296
|
+
: '(' abstract_declarator ')' {result = val[1]}
|
297
|
+
| direct_abstract_declarator '[' assignment_expression ']' {val[0].direct_type = Array.new_at(val[0].pos, nil, val[2]); result = val[0]}
|
298
|
+
| direct_abstract_declarator '[' ']' {val[0].direct_type = Array.new_at(val[0].pos, nil, nil ); result = val[0]}
|
299
|
+
| '[' assignment_expression ']' {result = Array.new_at(val[0].pos, nil, val[1])}
|
300
|
+
| '[' ']' {result = Array.new_at(val[0].pos )}
|
301
|
+
| direct_abstract_declarator '[' '*' ']' {val[0].direct_type = Array.new_at(val[0].pos); result = val[0]} # TODO
|
302
|
+
| '[' '*' ']' {result = Array.new_at(val[0].pos)} # TODO
|
303
|
+
| direct_abstract_declarator '(' parameter_type_list ')' {val[0].direct_type = Function.new_at(val[0].pos, nil, param_list(*val[2]), val[2][1]); result = val[0]}
|
304
|
+
| direct_abstract_declarator '(' ')' {val[0].direct_type = Function.new_at(val[0].pos ); result = val[0]}
|
305
|
+
| '(' parameter_type_list ')' {result = Function.new_at(val[0].pos, nil, param_list(*val[1]), val[1][1])}
|
306
|
+
| '(' ')' {result = Function.new_at(val[0].pos )}
|
307
|
+
|
308
|
+
## Returns CustomType
|
309
|
+
typedef_name
|
310
|
+
#: identifier -- insufficient since we must distinguish between type
|
311
|
+
# names and var names (otherwise we have a conflict)
|
312
|
+
: TYPE_ID {result = CustomType.new_at(val[0].pos, val[0].val)}
|
313
|
+
|
314
|
+
## Returns Expression
|
315
|
+
initializer
|
316
|
+
: assignment_expression {result = val[0]}
|
317
|
+
| '{' initializer_list '}' {result = CompoundLiteral.new_at(val[0].pos, nil, val[1])}
|
318
|
+
| '{' initializer_list ',' '}' {result = CompoundLiteral.new_at(val[0].pos, nil, val[1])}
|
319
|
+
|
320
|
+
## Returns NodeArray[MemberInit]
|
321
|
+
initializer_list
|
322
|
+
: designation initializer {result = NodeArray[MemberInit.new_at(val[0][0] , val[0][1], val[1])]}
|
323
|
+
| initializer {result = NodeArray[MemberInit.new_at(val[0].pos, nil , val[0])]}
|
324
|
+
| initializer_list ',' designation initializer {result = val[0] << MemberInit.new_at(val[2][0] , val[2][1], val[3])}
|
325
|
+
| initializer_list ',' initializer {result = val[0] << MemberInit.new_at(val[2].pos, nil , val[2])}
|
326
|
+
|
327
|
+
## Returns {Pos, NodeArray[Expression|Token]}
|
328
|
+
designation
|
329
|
+
: designator_list '=' {result = val[0]}
|
330
|
+
|
331
|
+
## Returns {Pos, NodeArray[Expression|Token]}
|
332
|
+
designator_list
|
333
|
+
: designator {result = val[0]; val[0][1] = NodeArray[val[0][1]]}
|
334
|
+
| designator_list designator {result = val[0]; val[0][1] << val[1][1]}
|
335
|
+
|
336
|
+
## Returns {Pos, Expression|Member}
|
337
|
+
designator
|
338
|
+
: '[' constant_expression ']' {result = [val[1].pos, val[1] ]}
|
339
|
+
| '.' identifier {result = [val[1].pos, Member.new_at(val[1].pos, val[1].val)]}
|
340
|
+
|
341
|
+
### A.2.1 Expressions
|
342
|
+
|
343
|
+
## Returns Expression
|
344
|
+
primary_expression
|
345
|
+
: identifier {result = Variable.new_at(val[0].pos, val[0].val)}
|
346
|
+
| constant {result = val[0]}
|
347
|
+
| string_literal {result = val[0]}
|
348
|
+
| '(' expression ')' {result = val[1]}
|
349
|
+
|
350
|
+
## Returns Expression
|
351
|
+
postfix_expression
|
352
|
+
: primary_expression {result = val[0]}
|
353
|
+
| postfix_expression '[' expression ']' {result = Index .new_at(val[0].pos, val[0], val[2])}
|
354
|
+
| postfix_expression '(' argument_expression_list ')' {result = Call .new_at(val[0].pos, val[0], val[2] )}
|
355
|
+
| postfix_expression '(' ')' {result = Call .new_at(val[0].pos, val[0], NodeArray[])}
|
356
|
+
| postfix_expression '.' identifier {result = Dot .new_at(val[0].pos, val[0], Member.new(val[2].val))}
|
357
|
+
| postfix_expression '->' identifier {result = Arrow .new_at(val[0].pos, val[0], Member.new(val[2].val))}
|
358
|
+
| postfix_expression '++' {result = PostInc .new_at(val[0].pos, val[0] )}
|
359
|
+
| postfix_expression '--' {result = PostDec .new_at(val[0].pos, val[0] )}
|
360
|
+
| '(' type_name ')' '{' initializer_list '}' {result = CompoundLiteral.new_at(val[0].pos, val[1], val[4])}
|
361
|
+
| '(' type_name ')' '{' initializer_list ',' '}' {result = CompoundLiteral.new_at(val[0].pos, val[1], val[4])}
|
362
|
+
|
363
|
+
## Returns [Expression]
|
364
|
+
argument_expression_list
|
365
|
+
: assignment_expression {result = NodeArray[val[0]]}
|
366
|
+
| argument_expression_list ',' assignment_expression {result = val[0] << val[2]}
|
367
|
+
|
368
|
+
## Returns Expression
|
369
|
+
unary_expression
|
370
|
+
: postfix_expression {result = val[0]}
|
371
|
+
| '++' unary_expression {result = PreInc.new_at(val[0].pos, val[1])}
|
372
|
+
| '--' unary_expression {result = PreDec.new_at(val[0].pos, val[1])}
|
373
|
+
| unary_operator cast_expression {result = val[0][0].new_at(val[0][1], val[1])}
|
374
|
+
| 'sizeof' unary_expression {result = Sizeof.new_at(val[0].pos, val[1])}
|
375
|
+
| 'sizeof' '(' type_name ')' {result = Sizeof.new_at(val[0].pos, val[2])}
|
376
|
+
|
377
|
+
## Returns [Class, Pos]
|
378
|
+
unary_operator
|
379
|
+
: '&' {result = [Address , val[0].pos]}
|
380
|
+
| '*' {result = [Dereference, val[0].pos]}
|
381
|
+
| '+' {result = [Positive , val[0].pos]}
|
382
|
+
| '-' {result = [Negative , val[0].pos]}
|
383
|
+
| '~' {result = [BitNot , val[0].pos]}
|
384
|
+
| '!' {result = [Not , val[0].pos]}
|
385
|
+
|
386
|
+
## Returns Expression
|
387
|
+
cast_expression
|
388
|
+
: unary_expression {result = val[0]}
|
389
|
+
| '(' type_name ')' cast_expression {result = Cast.new_at(val[0].pos, val[1], val[3])}
|
390
|
+
|
391
|
+
## Returns Expression
|
392
|
+
multiplicative_expression
|
393
|
+
: cast_expression {result = val[0]}
|
394
|
+
| multiplicative_expression '*' cast_expression {result = Multiply.new_at(val[0].pos, val[0], val[2])}
|
395
|
+
| multiplicative_expression '/' cast_expression {result = Divide .new_at(val[0].pos, val[0], val[2])}
|
396
|
+
| multiplicative_expression '%' cast_expression {result = Mod .new_at(val[0].pos, val[0], val[2])}
|
397
|
+
|
398
|
+
## Returns Expression
|
399
|
+
additive_expression
|
400
|
+
: multiplicative_expression {result = val[0]}
|
401
|
+
| additive_expression '+' multiplicative_expression {result = Add .new_at(val[0].pos, val[0], val[2])}
|
402
|
+
| additive_expression '-' multiplicative_expression {result = Subtract.new_at(val[0].pos, val[0], val[2])}
|
403
|
+
|
404
|
+
## Returns Expression
|
405
|
+
shift_expression
|
406
|
+
: additive_expression {result = val[0]}
|
407
|
+
| shift_expression '<<' additive_expression {result = ShiftLeft .new_at(val[0].pos, val[0], val[2])}
|
408
|
+
| shift_expression '>>' additive_expression {result = ShiftRight.new_at(val[0].pos, val[0], val[2])}
|
409
|
+
|
410
|
+
## Returns Expression
|
411
|
+
relational_expression
|
412
|
+
: shift_expression {result = val[0]}
|
413
|
+
| relational_expression '<' shift_expression {result = Less.new_at(val[0].pos, val[0], val[2])}
|
414
|
+
| relational_expression '>' shift_expression {result = More.new_at(val[0].pos, val[0], val[2])}
|
415
|
+
| relational_expression '<=' shift_expression {result = LessOrEqual.new_at(val[0].pos, val[0], val[2])}
|
416
|
+
| relational_expression '>=' shift_expression {result = MoreOrEqual.new_at(val[0].pos, val[0], val[2])}
|
417
|
+
|
418
|
+
## Returns Expression
|
419
|
+
equality_expression
|
420
|
+
: relational_expression {result = val[0]}
|
421
|
+
| equality_expression '==' relational_expression {result = Equal .new_at(val[0].pos, val[0], val[2])}
|
422
|
+
| equality_expression '!=' relational_expression {result = NotEqual.new_at(val[0].pos, val[0], val[2])}
|
423
|
+
|
424
|
+
## Returns Expression
|
425
|
+
and_expression
|
426
|
+
: equality_expression {result = val[0]}
|
427
|
+
| and_expression '&' equality_expression {result = BitAnd.new_at(val[0].pos, val[0], val[2])}
|
428
|
+
|
429
|
+
## Returns Expression
|
430
|
+
exclusive_or_expression
|
431
|
+
: and_expression {result = val[0]}
|
432
|
+
| exclusive_or_expression '^' and_expression {result = BitXor.new_at(val[0].pos, val[0], val[2])}
|
433
|
+
|
434
|
+
## Returns Expression
|
435
|
+
inclusive_or_expression
|
436
|
+
: exclusive_or_expression {result = val[0]}
|
437
|
+
| inclusive_or_expression '|' exclusive_or_expression {result = BitOr.new_at(val[0].pos, val[0], val[2])}
|
438
|
+
|
439
|
+
## Returns Expression
|
440
|
+
logical_and_expression
|
441
|
+
: inclusive_or_expression {result = val[0]}
|
442
|
+
| logical_and_expression '&&' inclusive_or_expression {result = And.new_at(val[0].pos, val[0], val[2])}
|
443
|
+
|
444
|
+
## Returns Expression
|
445
|
+
logical_or_expression
|
446
|
+
: logical_and_expression {result = val[0]}
|
447
|
+
| logical_or_expression '||' logical_and_expression {result = Or.new_at(val[0].pos, val[0], val[2])}
|
448
|
+
|
449
|
+
## Returns Expression
|
450
|
+
conditional_expression
|
451
|
+
: logical_or_expression {result = val[0]}
|
452
|
+
| logical_or_expression '?' expression ':' conditional_expression {result = Conditional.new_at(val[0].pos, val[0], val[2], val[4])}
|
453
|
+
|
454
|
+
## Returns Expression
|
455
|
+
assignment_expression
|
456
|
+
: conditional_expression {result = val[0]}
|
457
|
+
| unary_expression assignment_operator assignment_expression {result = val[1].new_at(val[0].pos, val[0], val[2])}
|
458
|
+
|
459
|
+
## Returns Class
|
460
|
+
assignment_operator
|
461
|
+
: '=' {result = Assign}
|
462
|
+
| '*=' {result = MultiplyAssign}
|
463
|
+
| '/=' {result = DivideAssign}
|
464
|
+
| '%=' {result = ModAssign}
|
465
|
+
| '+=' {result = AddAssign}
|
466
|
+
| '-=' {result = SubtractAssign}
|
467
|
+
| '<<=' {result = ShiftLeftAssign}
|
468
|
+
| '>>=' {result = ShiftRightAssign}
|
469
|
+
| '&=' {result = BitAndAssign}
|
470
|
+
| '^=' {result = BitXorAssign}
|
471
|
+
| '|=' {result = BitOrAssign}
|
472
|
+
|
473
|
+
## Returns Expression
|
474
|
+
expression
|
475
|
+
: assignment_expression {result = val[0]}
|
476
|
+
| expression ',' assignment_expression {
|
477
|
+
if val[0].is_a? Comma
|
478
|
+
if val[2].is_a? Comma
|
479
|
+
val[0].exprs.push(*val[2].exprs)
|
480
|
+
else
|
481
|
+
val[0].exprs << val[2]
|
482
|
+
end
|
483
|
+
result = val[0]
|
484
|
+
else
|
485
|
+
if val[2].is_a? Comma
|
486
|
+
val[2].exprs.unshift(val[0])
|
487
|
+
val[2].pos = val[0].pos
|
488
|
+
result = val[2]
|
489
|
+
else
|
490
|
+
result = Comma.new_at(val[0].pos, NodeArray[val[0], val[2]])
|
491
|
+
end
|
492
|
+
end
|
493
|
+
}
|
494
|
+
|
495
|
+
## Returns Expression
|
496
|
+
constant_expression
|
497
|
+
: conditional_expression {result = val[0]}
|
498
|
+
|
499
|
+
### A.1.1 -- Lexical elements
|
500
|
+
##
|
501
|
+
## token
|
502
|
+
## : keyword (raw string)
|
503
|
+
## | identifier expanded below
|
504
|
+
## | constant expanded below
|
505
|
+
## | string_literal expanded below
|
506
|
+
## | punctuator (raw string)
|
507
|
+
##
|
508
|
+
## preprocessing-token (skip)
|
509
|
+
|
510
|
+
## Returns Token
|
511
|
+
identifier
|
512
|
+
: ID {result = val[0]}
|
513
|
+
|
514
|
+
## Returns Literal
|
515
|
+
constant
|
516
|
+
: INT {result = IntLiteral.new_at(val[0].pos, val[0].val)}
|
517
|
+
| FLOAT {result = FloatLiteral.new_at(val[0].pos, val[0].val)}
|
518
|
+
#| enumeration_constant -- these are parsed as identifiers at all
|
519
|
+
# places the `constant' nonterminal appears
|
520
|
+
| CHAR {result = CharLiteral.new_at(val[0].pos, val[0].val)}
|
521
|
+
|
522
|
+
## Returns Token
|
523
|
+
enumeration_constant
|
524
|
+
: ID {result = val[0]}
|
525
|
+
|
526
|
+
## Returns StringLiteral
|
527
|
+
string_literal
|
528
|
+
: STRING {result = StringLiteral.new_at(val[0].pos, val[0].val)}
|
529
|
+
|
530
|
+
---- inner
|
531
|
+
## A.1.9 -- Preprocessing numbers -- skip
|
532
|
+
## A.1.8 -- Header names -- skip
|
533
|
+
|
534
|
+
## A.1.7 -- Puncuators -- we don't bother with {##,#,%:,%:%:} since
|
535
|
+
## we don't do preprocessing
|
536
|
+
@@punctuators = %r'\+\+|-[->]|&&|\|\||\.\.\.|(?:<<|>>|[<>=!*/%+\-&^|])=?|[\[\](){}.~?:;,]'
|
537
|
+
@@digraphs = %r'<[:%]|[:%]>'
|
538
|
+
|
539
|
+
## A.1.6 -- String Literals -- simple for us because we don't decode
|
540
|
+
## the string (and indeed accept some illegal strings)
|
541
|
+
@@string_literal = %r'L?"(?:[^\\]|\\.)*?"'m
|
542
|
+
|
543
|
+
## A.1.5 -- Constants
|
544
|
+
@@decimal_floating_constant = %r'(?:(?:\d*\.\d+|\d+\.)(?:e[-+]?\d+)?|\d+e[-+]?\d+)[fl]?'i
|
545
|
+
@@hexadecimal_floating_constant = %r'0x(?:(?:[0-9a-f]*\.[0-9a-f]+|[0-9a-f]+\.)|[0-9a-f]+)p[-+]?\d+[fl]?'i
|
546
|
+
|
547
|
+
@@integer_constant = %r'(?:[1-9][0-9]*|0x[0-9a-f]+|0[0-7]*)(?:ul?l?|ll?u?)?'i
|
548
|
+
@@floating_constant = %r'#{@@decimal_floating_constant}|#{@@hexadecimal_floating_constant}'
|
549
|
+
@@enumeration_constant = %r'[a-zA-Z_\\][a-zA-Z_\\0-9]*'
|
550
|
+
@@character_constant = %r"L?'(?:[^\\]|\\.)+?'"
|
551
|
+
## (note that as with string-literals, we accept some illegal
|
552
|
+
## character-constants)
|
553
|
+
|
554
|
+
## A.1.4 -- Universal character names -- skip
|
555
|
+
|
556
|
+
## A.1.3 -- Identifiers -- skip, since an identifier is lexically
|
557
|
+
## identical to an enumeration constant
|
558
|
+
|
559
|
+
## A.1.2 Keywords
|
560
|
+
keywords = %w'auto break case char const continue default do
|
561
|
+
double else enum extern float for goto if inline int long register
|
562
|
+
restrict return short signed sizeof static struct switch typedef union
|
563
|
+
unsigned void volatile while _Bool _Complex _Imaginary'
|
564
|
+
@@keywords = %r"#{keywords.join('|')}"
|
565
|
+
|
566
|
+
def initialize
|
567
|
+
@type_names = ::Set.new
|
568
|
+
|
569
|
+
@warning_proc = lambda{}
|
570
|
+
@pos = C::Node::Pos.new(nil, 1, 0)
|
571
|
+
end
|
572
|
+
def initialize_copy x
|
573
|
+
@pos = x.pos.dup
|
574
|
+
@type_names = x.type_names.dup
|
575
|
+
end
|
576
|
+
attr_accessor :pos, :type_names
|
577
|
+
|
578
|
+
def parse str
|
579
|
+
if str.respond_to? :read
|
580
|
+
str = str.read
|
581
|
+
end
|
582
|
+
@str = str
|
583
|
+
begin
|
584
|
+
return do_parse
|
585
|
+
rescue ParseError => e
|
586
|
+
e.set_backtrace(caller)
|
587
|
+
raise
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
### Obsolete? Todo? What was I thinking?
|
592
|
+
def on_error error_token_id, error_value, value_stack
|
593
|
+
if error_value == '$'
|
594
|
+
parse_error @pos, "unexpected EOF"
|
595
|
+
else
|
596
|
+
parse_error(error_value.pos,
|
597
|
+
"parse error on #{error_value.val.inspect}")
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
private
|
602
|
+
|
603
|
+
class Token
|
604
|
+
attr_accessor :pos, :val
|
605
|
+
def initialize pos, val
|
606
|
+
@pos = pos
|
607
|
+
@val = val
|
608
|
+
end
|
609
|
+
end
|
610
|
+
def eat str
|
611
|
+
lines = str.split(/\r\n|[\r\n]/, -1)
|
612
|
+
if lines.length == 1
|
613
|
+
@pos.col_num += lines[0].length
|
614
|
+
else
|
615
|
+
@pos.line_num += lines.length - 1
|
616
|
+
@pos.col_num = lines[-1].length
|
617
|
+
end
|
618
|
+
end
|
619
|
+
def next_token
|
620
|
+
return nil if @str == ''
|
621
|
+
case @str
|
622
|
+
when %r'\A\s+'
|
623
|
+
## whitespace
|
624
|
+
eat $&
|
625
|
+
@str[0...$&.length] = ''
|
626
|
+
return next_token
|
627
|
+
when %r'\A/\*.*?\*/'m
|
628
|
+
## comment
|
629
|
+
eat $&
|
630
|
+
@str[0...$&.length] = ''
|
631
|
+
return next_token
|
632
|
+
when %r'\A#{@@keywords}\b'
|
633
|
+
## keyword
|
634
|
+
ret = [$&, $&.to_sym]
|
635
|
+
when %r'\A#{@@enumeration_constant}'
|
636
|
+
## identifier, enumeration_constant, or typedef_name
|
637
|
+
case
|
638
|
+
when @type_names.include?($&)
|
639
|
+
ret = [:TYPE_ID, $&]
|
640
|
+
else
|
641
|
+
ret = [:ID, $&]
|
642
|
+
end
|
643
|
+
when %r'\A#{@@floating_constant}'
|
644
|
+
## floating-constant
|
645
|
+
ret = [:FLOAT, $&.to_f]
|
646
|
+
when %r'\A#{@@integer_constant}'
|
647
|
+
## integer-constant
|
648
|
+
ret = [:INT, $&.to_i]
|
649
|
+
when %r'\A#{@@character_constant}'
|
650
|
+
## character constant
|
651
|
+
ret = [:CHAR, $&[1...-1]]
|
652
|
+
when %r'\A#{@@string_literal}'
|
653
|
+
## string-literal
|
654
|
+
ret = [:STRING, $&[1...-1]]
|
655
|
+
when %r'\A#{@@punctuators}'
|
656
|
+
## punctuator
|
657
|
+
ret = [$&, $&]
|
658
|
+
when %r'\A#{@@digraphs}'
|
659
|
+
## digraph
|
660
|
+
case $&
|
661
|
+
when '<:'
|
662
|
+
ret = ['[', '[']
|
663
|
+
when ':>'
|
664
|
+
ret = [']', ']']
|
665
|
+
when '<%'
|
666
|
+
ret = ['{', '{']
|
667
|
+
when '%>'
|
668
|
+
ret = ['}', '}']
|
669
|
+
else
|
670
|
+
raise 'bug'
|
671
|
+
end
|
672
|
+
else
|
673
|
+
if @str.length > 40
|
674
|
+
s = @str[0...37] << '...'
|
675
|
+
else
|
676
|
+
s = @str
|
677
|
+
end
|
678
|
+
raise ParseError, "#{@pos}: invalid token: #{s.inspect}"
|
679
|
+
end
|
680
|
+
ret[1] = Token.new(@pos.dup, ret[1])
|
681
|
+
eat $&
|
682
|
+
@str[0...$&.length] = ''
|
683
|
+
return ret
|
684
|
+
end
|
685
|
+
|
686
|
+
private
|
687
|
+
|
688
|
+
#### Helper methods
|
689
|
+
|
690
|
+
## Make a Declaration from the given specs and declarators.
|
691
|
+
def make_declaration pos, specs, declarators
|
692
|
+
specs.all?{|x| x.is_a?(Symbol) || x.is_a?(Type)} or raise specs.map{|x| x.class}.inspect
|
693
|
+
decl = Declaration.new_at(pos, nil, declarators)
|
694
|
+
|
695
|
+
## set storage class
|
696
|
+
storage_classes = specs.find_all do |x|
|
697
|
+
[:typedef, :extern, :static, :auto, :register].include? x
|
698
|
+
end
|
699
|
+
## 6.7.1p2: at most, one storage-class specifier may be given in
|
700
|
+
## the declaration specifiers in a declaration
|
701
|
+
storage_classes.length <= 1 or
|
702
|
+
begin
|
703
|
+
if declarators.length == 0
|
704
|
+
for_name = ''
|
705
|
+
else
|
706
|
+
for_name = "for `#{declarators[0].name}'"
|
707
|
+
end
|
708
|
+
parse_error pos, "multiple or duplicate storage classes given #{for_name}'"
|
709
|
+
end
|
710
|
+
decl.storage = storage_classes[0]
|
711
|
+
|
712
|
+
## set type (specifiers, qualifiers)
|
713
|
+
decl.type = make_direct_type(pos, specs)
|
714
|
+
|
715
|
+
## set function specifiers
|
716
|
+
decl.inline = specs.include?(:inline)
|
717
|
+
|
718
|
+
## look for new type names
|
719
|
+
if decl.typedef?
|
720
|
+
decl.declarators.each do |d|
|
721
|
+
if d.name
|
722
|
+
@type_names << d.name
|
723
|
+
end
|
724
|
+
end
|
725
|
+
end
|
726
|
+
|
727
|
+
return decl
|
728
|
+
end
|
729
|
+
|
730
|
+
def make_function_def pos, specs, func_declarator, decl_list, defn
|
731
|
+
add_decl_type(func_declarator, make_direct_type(pos, specs))
|
732
|
+
|
733
|
+
## get types from decl_list if necessary
|
734
|
+
function = func_declarator.indirect_type
|
735
|
+
function.is_a? Function or
|
736
|
+
parse_error pos, "non function type for function `#{func_declarator.name}'"
|
737
|
+
params = function.params
|
738
|
+
if decl_list
|
739
|
+
params.all?{|p| p.type.nil?} or
|
740
|
+
parse_error pos, "both prototype and declaration list given for `#{func_declarator.name}'"
|
741
|
+
decl_list.each do |declaration|
|
742
|
+
declaration.declarators.each do |declarator|
|
743
|
+
param = params.find{|p| p.name == declarator.name} or
|
744
|
+
parse_error pos, "no parameter named #{declarator.name}"
|
745
|
+
if declarator.indirect_type
|
746
|
+
param.type = declarator.indirect_type
|
747
|
+
param.type.direct_type = declaration.type.dup
|
748
|
+
else
|
749
|
+
param.type = declaration.type.dup
|
750
|
+
end
|
751
|
+
end
|
752
|
+
end
|
753
|
+
params.all?{|p| p.type} or
|
754
|
+
begin
|
755
|
+
s = params.find_all{|p| p.type.nil?}.map{|p| "`#{p.name}'"}.join(' and ')
|
756
|
+
parse_error pos, "types missing for parameters #{s}"
|
757
|
+
end
|
758
|
+
end
|
759
|
+
|
760
|
+
fd = FunctionDef.new_at(pos,
|
761
|
+
function.detach,
|
762
|
+
func_declarator.name,
|
763
|
+
defn,
|
764
|
+
:no_prototype => !decl_list.nil?)
|
765
|
+
|
766
|
+
## set storage class
|
767
|
+
## 6.9.1p4: only extern or static allowed
|
768
|
+
specs.each do |s|
|
769
|
+
[:typedef, :auto, :register].include?(s) and
|
770
|
+
"`#{s}' illegal for function"
|
771
|
+
end
|
772
|
+
storage_classes = specs.find_all do |s|
|
773
|
+
s == :extern || s == :static
|
774
|
+
end
|
775
|
+
## 6.7.1p2: at most, one storage-class specifier may be given in
|
776
|
+
## the declaration specifiers in a declaration
|
777
|
+
storage_classes.length <= 1 or
|
778
|
+
"multiple or duplicate storage classes given for `#{declarator.name}'"
|
779
|
+
fd.storage = storage_classes[0] if storage_classes[0]
|
780
|
+
|
781
|
+
## set function specifiers
|
782
|
+
## 6.7.4p5 'inline' can be repeated
|
783
|
+
fd.inline = specs.include?(:inline)
|
784
|
+
|
785
|
+
return fd
|
786
|
+
end
|
787
|
+
|
788
|
+
## Make a direct type from the list of type specifiers and type
|
789
|
+
## qualifiers.
|
790
|
+
def make_direct_type pos, specs
|
791
|
+
specs_order = [:signed, :unsigned, :short, :long, :double, :void,
|
792
|
+
:char, :int, :float, :_Bool, :_Complex, :_Imaginary]
|
793
|
+
|
794
|
+
type_specs = specs.find_all do |x|
|
795
|
+
specs_order.include?(x) || !x.is_a?(Symbol)
|
796
|
+
end
|
797
|
+
type_specs.sort! do |a, b|
|
798
|
+
(specs_order.index(a)||100) <=> (specs_order.index(b)||100)
|
799
|
+
end
|
800
|
+
|
801
|
+
## set type specifiers
|
802
|
+
## 6.7.2p2: the specifier list should be one of these
|
803
|
+
type =
|
804
|
+
case type_specs
|
805
|
+
when [:void]
|
806
|
+
Void.new
|
807
|
+
when [:char]
|
808
|
+
Char.new
|
809
|
+
when [:signed, :char]
|
810
|
+
Char.new :signed => true
|
811
|
+
when [:unsigned, :char]
|
812
|
+
Char.new :signed => false
|
813
|
+
when [:short], [:signed, :short], [:short, :int],
|
814
|
+
[:signed, :short, :int]
|
815
|
+
Int.new :longness => -1
|
816
|
+
when [:unsigned, :short], [:unsigned, :short, :int]
|
817
|
+
Int.new :unsigned => true, :longness => -1
|
818
|
+
when [:int], [:signed], [:signed, :int]
|
819
|
+
Int.new
|
820
|
+
when [:unsigned], [:unsigned, :int]
|
821
|
+
Int.new :unsigned => true
|
822
|
+
when [:long], [:signed, :long], [:long, :int],
|
823
|
+
[:signed, :long, :int]
|
824
|
+
Int.new :longness => 1
|
825
|
+
when [:unsigned, :long], [:unsigned, :long, :int]
|
826
|
+
Int.new :longness => 1, :unsigned => true
|
827
|
+
when [:long, :long], [:signed, :long, :long],
|
828
|
+
[:long, :long, :int], [:signed, :long, :long, :int]
|
829
|
+
Int.new :longness => 2
|
830
|
+
when [:unsigned, :long, :long], [:unsigned, :long, :long, :int]
|
831
|
+
Int.new :longness => 2, :unsigned => true
|
832
|
+
when [:float]
|
833
|
+
Float.new
|
834
|
+
when [:double]
|
835
|
+
Float.new :longness => 1
|
836
|
+
when [:long, :double]
|
837
|
+
Float.new :longness => 2
|
838
|
+
when [:_Bool]
|
839
|
+
Bool.new
|
840
|
+
when [:float, :_Complex]
|
841
|
+
Complex.new
|
842
|
+
when [:double, :_Complex]
|
843
|
+
Complex.new :longness => 1
|
844
|
+
when [:long, :double, :_Complex]
|
845
|
+
Complex.new :longness => 2
|
846
|
+
when [:float, :_Imaginary]
|
847
|
+
Imaginary.new
|
848
|
+
when [:double, :_Imaginary]
|
849
|
+
Imaginary.new :longness => 1
|
850
|
+
when [:long, :double, :_Imaginary]
|
851
|
+
Imaginary.new :longness => 2
|
852
|
+
else
|
853
|
+
if type_specs.length == 1 &&
|
854
|
+
[CustomType, Struct, Union, Enum].any?{|c| type_specs[0].is_a? c}
|
855
|
+
type_specs[0]
|
856
|
+
else
|
857
|
+
if type_specs == []
|
858
|
+
parse_error pos, "no type specifiers given"
|
859
|
+
else
|
860
|
+
parse_error pos, "invalid type specifier combination: #{type_specs.join(' ')}"
|
861
|
+
end
|
862
|
+
end
|
863
|
+
end
|
864
|
+
type.pos ||= pos
|
865
|
+
|
866
|
+
## set type qualifiers
|
867
|
+
## 6.7.3p4: type qualifiers can be repeated
|
868
|
+
type.const = specs.any?{|x| x.equal? :const }
|
869
|
+
type.restrict = specs.any?{|x| x.equal? :restrict}
|
870
|
+
type.volatile = specs.any?{|x| x.equal? :volatile}
|
871
|
+
|
872
|
+
return type
|
873
|
+
end
|
874
|
+
|
875
|
+
def make_parameter pos, specs, indirect_type, name
|
876
|
+
type = indirect_type
|
877
|
+
if type
|
878
|
+
type.direct_type = make_direct_type(pos, specs)
|
879
|
+
else
|
880
|
+
type = make_direct_type(pos, specs)
|
881
|
+
end
|
882
|
+
[:typedef, :extern, :static, :auto, :inline].each do |sym|
|
883
|
+
specs.include? sym and
|
884
|
+
parse_error pos, "parameter `#{declarator.name}' declared `#{sym}'"
|
885
|
+
end
|
886
|
+
return Parameter.new_at(pos, type, name,
|
887
|
+
:register => specs.include?(:register))
|
888
|
+
end
|
889
|
+
|
890
|
+
def add_type_quals type, quals
|
891
|
+
type.const = quals.include?(:const )
|
892
|
+
type.restrict = quals.include?(:restrict)
|
893
|
+
type.volatile = quals.include?(:volatile)
|
894
|
+
return type
|
895
|
+
end
|
896
|
+
|
897
|
+
## Add te given type as the "most direct" type to the given
|
898
|
+
## declarator. Return the declarator.
|
899
|
+
def add_decl_type declarator, type
|
900
|
+
if declarator.indirect_type
|
901
|
+
declarator.indirect_type.direct_type = type
|
902
|
+
else
|
903
|
+
declarator.indirect_type = type
|
904
|
+
end
|
905
|
+
return declarator
|
906
|
+
end
|
907
|
+
|
908
|
+
def param_list params, var_args
|
909
|
+
if params.length == 1 &&
|
910
|
+
params[0].type.is_a?(Void) &&
|
911
|
+
params[0].name.nil?
|
912
|
+
return NodeArray[]
|
913
|
+
elsif params.empty?
|
914
|
+
return nil
|
915
|
+
else
|
916
|
+
return params
|
917
|
+
end
|
918
|
+
end
|
919
|
+
|
920
|
+
def parse_error pos, str
|
921
|
+
raise ParseError, "#{pos}: #{str}"
|
922
|
+
end
|
923
|
+
|
924
|
+
---- header
|
925
|
+
|
926
|
+
require 'set'
|
927
|
+
|
928
|
+
#### Error classes
|
929
|
+
module C
|
930
|
+
class ParseError < StandardError; end
|
931
|
+
end
|
932
|
+
|
933
|
+
### Local variables:
|
934
|
+
### mode: ruby
|
935
|
+
### end:
|