cast 0.0.1 → 0.3.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.
@@ -0,0 +1,340 @@
1
+ /* -*- mode: c -*- */
2
+ /* Given to re2c to generate the lexer `yylex'.
3
+ *
4
+ * Based on c.re in the exmaples distributed with re2c.
5
+ */
6
+ #include <stdio.h>
7
+ #include <string.h>
8
+ #include "cast.h"
9
+
10
+ /*
11
+ * -------------------------------------------------------------------
12
+ * Helpers
13
+ * -------------------------------------------------------------------
14
+ */
15
+
16
+ #define new_func(Foo) \
17
+ VALUE cast_new_##Foo##_at(long pos) { \
18
+ VALUE c##Foo; \
19
+ c##Foo = rb_const_get(cast_mC, rb_intern(#Foo)); \
20
+ return rb_funcall2(c##Foo, rb_intern("new"), 0, NULL); \
21
+ }
22
+ #define set_func(Foo, field) \
23
+ VALUE cast_##Foo##_set_##field(VALUE self, VALUE value) { \
24
+ return rb_funcall2(self, rb_intern(#field "="), 1, &value); \
25
+ }
26
+
27
+ new_func(IntLiteral);
28
+ set_func(IntLiteral, format);
29
+ set_func(IntLiteral, val);
30
+ set_func(IntLiteral, suffix);
31
+
32
+ new_func(FloatLiteral);
33
+ set_func(FloatLiteral, format);
34
+ set_func(FloatLiteral, val);
35
+ set_func(FloatLiteral, exponent);
36
+ set_func(FloatLiteral, suffix);
37
+
38
+ new_func(CharLiteral);
39
+ set_func(CharLiteral, prefix);
40
+ set_func(CharLiteral, val);
41
+
42
+ new_func(StringLiteral);
43
+ set_func(StringLiteral, prefix);
44
+ set_func(StringLiteral, val);
45
+
46
+ /*
47
+ * -------------------------------------------------------------------
48
+ * yylex
49
+ * -------------------------------------------------------------------
50
+ */
51
+ #define BSIZE 8192
52
+
53
+ #define YYLTYPE VALUE
54
+
55
+ #define YYCTYPE char
56
+ #define YYCURSOR cursor
57
+ #define YYLIMIT p->lim
58
+ #define YYMARKER p->ptr
59
+ #define YYFILL(n) {}
60
+
61
+ #define RET(sym) {p->cur = cursor; rb_ary_store(p->token, 0, sym); rb_ary_store(p->token, 1, sym ); return;}
62
+ #define RETVALUE(sym) {p->cur = cursor; rb_ary_store(p->token, 0, sym); rb_ary_store(p->token, 1, value); return;}
63
+
64
+ /* Raise a ParseError. `s' is the format string for the exception
65
+ * message, which must contain exactly one '%s', which is replaced by
66
+ * the string delimited by `b' and `e'.
67
+ */
68
+ static void error1(char *s, char *b, char *e) {
69
+ char *str;
70
+ str = ALLOCA_N(char, e - b + 1);
71
+ memcpy(str, b, e-b);
72
+ str[e-b] = '\0';
73
+ rb_raise(cast_eParseError, s, str);
74
+ }
75
+
76
+ /* `token' is assumed to be a two element array, which is filled in.
77
+ */
78
+ void yylex(VALUE self, cast_Parser *p) {
79
+ char *cursor = p->cur;
80
+ char *cp, *ep;
81
+ VALUE value;
82
+ std:
83
+ p->tok = cursor;
84
+ /*!re2c
85
+ any = [\000-\377];
86
+ O = [0-7];
87
+ D = [0-9];
88
+ H = [a-fA-F0-9];
89
+ N = [1-9];
90
+ L = [a-zA-Z_];
91
+ E = [Ee] [+-]? D+;
92
+ P = [Pp] [+-]? D+;
93
+ FS = [fFlL];
94
+ IS = [uU] ([lL] | "ll" | "LL")? | ([lL] | "ll" | "LL") [uU]?;
95
+ ESC = [\\] ([abfnrtv?'"\\] | O (O O?)? | "x" H+);
96
+ */
97
+ /*!re2c
98
+ "/*" { goto comment; }
99
+ "//" { goto comment2; }
100
+
101
+ "auto" { RET(cast_sym_AUTO); }
102
+ "break" { RET(cast_sym_BREAK); }
103
+ "case" { RET(cast_sym_CASE); }
104
+ "char" { RET(cast_sym_CHAR); }
105
+ "const" { RET(cast_sym_CONST); }
106
+ "continue" { RET(cast_sym_CONTINUE); }
107
+ "default" { RET(cast_sym_DEFAULT); }
108
+ "do" { RET(cast_sym_DO); }
109
+ "double" { RET(cast_sym_DOUBLE); }
110
+ "else" { RET(cast_sym_ELSE); }
111
+ "enum" { RET(cast_sym_ENUM); }
112
+ "extern" { RET(cast_sym_EXTERN); }
113
+ "float" { RET(cast_sym_FLOAT); }
114
+ "for" { RET(cast_sym_FOR); }
115
+ "goto" { RET(cast_sym_GOTO); }
116
+ "if" { RET(cast_sym_IF); }
117
+ "int" { RET(cast_sym_INT); }
118
+ "long" { RET(cast_sym_LONG); }
119
+ "register" { RET(cast_sym_REGISTER); }
120
+ "return" { RET(cast_sym_RETURN); }
121
+ "short" { RET(cast_sym_SHORT); }
122
+ "signed" { RET(cast_sym_SIGNED); }
123
+ "sizeof" { RET(cast_sym_SIZEOF); }
124
+ "static" { RET(cast_sym_STATIC); }
125
+ "struct" { RET(cast_sym_STRUCT); }
126
+ "switch" { RET(cast_sym_SWITCH); }
127
+ "typedef" { RET(cast_sym_TYPEDEF); }
128
+ "union" { RET(cast_sym_UNION); }
129
+ "unsigned" { RET(cast_sym_UNSIGNED); }
130
+ "void" { RET(cast_sym_VOID); }
131
+ "volatile" { RET(cast_sym_VOLATILE); }
132
+ "while" { RET(cast_sym_WHILE); }
133
+ "inline" { RET(cast_sym_INLINE); }
134
+ "restrict" { RET(cast_sym_RESTRICT); }
135
+ "_Bool" { RET(cast_sym_BOOL); }
136
+ "_Complex" { RET(cast_sym_COMPLEX); }
137
+ "_Imaginary" { RET(cast_sym_IMAGINARY); }
138
+
139
+ L (L|D)* {
140
+ value = rb_str_new(p->tok, cursor - p->tok);
141
+ if (rb_funcall2(rb_funcall2(self, rb_intern("type_names"), 0, NULL),
142
+ rb_intern("include?"), 1, &value) == Qtrue) {
143
+ RETVALUE(cast_sym_TYPENAME);
144
+ } else {
145
+ RETVALUE(cast_sym_ID);
146
+ }
147
+ }
148
+
149
+ "0" [xX] H+ IS? {
150
+ value = cast_new_IntLiteral_at(p->lineno);
151
+ cast_IntLiteral_set_format(value, ID2SYM(rb_intern("hex")));
152
+ cast_IntLiteral_set_val(value, LONG2NUM(strtol(p->tok, (char **)&cp, 16)));
153
+ if (cp < cursor)
154
+ cast_IntLiteral_set_suffix(value, rb_str_new(cp, cursor - cp));
155
+ RETVALUE(cast_sym_ICON);
156
+ }
157
+ "0" D+ IS? {
158
+ value = cast_new_IntLiteral_at(p->lineno);
159
+ cast_IntLiteral_set_format(value, ID2SYM(rb_intern("oct")));
160
+ cast_IntLiteral_set_val(value, LONG2NUM(strtol(p->tok, (char **)&cp, 8)));
161
+ if (cp < cursor) {
162
+ if (cp[0] == '8' || cp[0] == '9')
163
+ rb_raise(cast_eParseError, "bad octal digit: %c", cp[0]);
164
+ cast_IntLiteral_set_suffix(value, rb_str_new(cp, cursor - cp));
165
+ }
166
+ RETVALUE(cast_sym_ICON);
167
+ }
168
+ ( "0" | [1-9] D* ) IS? {
169
+ value = cast_new_IntLiteral_at(p->lineno);
170
+ cast_IntLiteral_set_format(value, ID2SYM(rb_intern("dec")));
171
+ cast_IntLiteral_set_val(value, LONG2NUM(strtol(p->tok, (char **)&cp, 10)));
172
+ if (cp < cursor)
173
+ cast_IntLiteral_set_suffix(value, rb_str_new(cp, cursor - cp));
174
+ RETVALUE(cast_sym_ICON);
175
+ }
176
+
177
+ ( D+ E | D* "." D+ E? | D+ "." D* E? ) FS? {
178
+ value = cast_new_FloatLiteral_at(p->lineno);
179
+ cast_FloatLiteral_set_format(value, ID2SYM(rb_intern("dec")));
180
+ cast_FloatLiteral_set_val(value, rb_float_new(strtod(p->tok, (char **)&cp)));
181
+ if (cp < cursor)
182
+ cast_FloatLiteral_set_suffix(value, rb_str_new(cp, cursor - cp));
183
+
184
+ ep = (char *)memchr(p->tok, 'e', cp - p->tok);
185
+ if (!ep)
186
+ ep = (char *)memchr(p->tok, 'E', cp - p->tok);
187
+ if (ep)
188
+ cast_FloatLiteral_set_exponent(value, LONG2NUM(strtod(ep + 1, NULL)));
189
+
190
+ RETVALUE(cast_sym_FCON);
191
+ }
192
+ ( "0" [Xx] (H+ P | H* "." H+ P | H+ "." H* P) ) FS? {
193
+ value = cast_new_FloatLiteral_at(p->lineno);
194
+ cast_FloatLiteral_set_format(value, ID2SYM(rb_intern("hex")));
195
+ cast_FloatLiteral_set_val(value, rb_float_new(strtod(p->tok, (char **)&cp)));
196
+ if (cp < cursor)
197
+ cast_FloatLiteral_set_suffix(value, rb_str_new(cp, cursor - cp));
198
+
199
+ ep = (char *)memchr(p->tok, 'p', cp - p->tok);
200
+ if (!ep)
201
+ ep = (char *)memchr(p->tok, 'P', cp - p->tok);
202
+ if (ep)
203
+ cast_FloatLiteral_set_exponent(value, LONG2NUM(strtod(ep + 1, NULL)));
204
+
205
+ RETVALUE(cast_sym_FCON);
206
+ }
207
+
208
+ L? ['] (ESC|any\[\\'])+ ['] {
209
+ value = cast_new_CharLiteral_at(p->lineno);
210
+ if (p->tok[0] == '\'') {
211
+ cp = p->tok;
212
+ } else {
213
+ cast_CharLiteral_set_prefix(value, rb_str_new(p->tok, 1));
214
+ cp = p->tok + 1;
215
+ }
216
+ cast_CharLiteral_set_val(value, rb_str_new(cp + 1, cursor - cp - 2));
217
+ RETVALUE(cast_sym_CCON);
218
+ }
219
+ L? ["] (ESC|any\[\\"])* ["] {
220
+ value = cast_new_StringLiteral_at(p->lineno);
221
+ if (p->tok[0] == '"') {
222
+ cp = p->tok;
223
+ } else {
224
+ cast_StringLiteral_set_prefix(value, rb_str_new(p->tok, 1));
225
+ cp = p->tok + 1;
226
+ }
227
+ cast_StringLiteral_set_val(value, rb_str_new(cp + 1, cursor - cp - 2));
228
+ RETVALUE(cast_sym_SCON);
229
+ }
230
+
231
+ "..." { RET(cast_sym_ELLIPSIS); }
232
+ ">>=" { RET(cast_sym_RSHIFTEQ); }
233
+ "<<=" { RET(cast_sym_LSHIFTEQ); }
234
+ "+=" { RET(cast_sym_ADDEQ); }
235
+ "-=" { RET(cast_sym_SUBEQ); }
236
+ "*=" { RET(cast_sym_MULEQ); }
237
+ "/=" { RET(cast_sym_DIVEQ); }
238
+ "%=" { RET(cast_sym_MODEQ); }
239
+ "&=" { RET(cast_sym_ANDEQ); }
240
+ "^=" { RET(cast_sym_XOREQ); }
241
+ "|=" { RET(cast_sym_OREQ); }
242
+ ">>" { RET(cast_sym_RSHIFT); }
243
+ "<<" { RET(cast_sym_LSHIFT); }
244
+ "++" { RET(cast_sym_INC); }
245
+ "--" { RET(cast_sym_DEC); }
246
+ "->" { RET(cast_sym_ARROW); }
247
+ "&&" { RET(cast_sym_ANDAND); }
248
+ "||" { RET(cast_sym_OROR); }
249
+ "<=" { RET(cast_sym_LEQ); }
250
+ ">=" { RET(cast_sym_GEQ); }
251
+ "==" { RET(cast_sym_EQEQ); }
252
+ "!=" { RET(cast_sym_NEQ); }
253
+ ";" { RET(cast_sym_SEMICOLON); }
254
+ "{" { RET(cast_sym_LBRACE); }
255
+ "}" { RET(cast_sym_RBRACE); }
256
+ "," { RET(cast_sym_COMMA); }
257
+ ":" { RET(cast_sym_COLON); }
258
+ "=" { RET(cast_sym_EQ); }
259
+ "(" { RET(cast_sym_LPAREN); }
260
+ ")" { RET(cast_sym_RPAREN); }
261
+ "[" { RET(cast_sym_LBRACKET); }
262
+ "]" { RET(cast_sym_RBRACKET); }
263
+ "." { RET(cast_sym_DOT); }
264
+ "&" { RET(cast_sym_AND); }
265
+ "!" { RET(cast_sym_BANG); }
266
+ "~" { RET(cast_sym_NOT); }
267
+ "-" { RET(cast_sym_SUB); }
268
+ "+" { RET(cast_sym_ADD); }
269
+ "*" { RET(cast_sym_MUL); }
270
+ "/" { RET(cast_sym_DIV); }
271
+ "%" { RET(cast_sym_MOD); }
272
+ "<" { RET(cast_sym_LT); }
273
+ ">" { RET(cast_sym_GT); }
274
+ "^" { RET(cast_sym_XOR); }
275
+ "|" { RET(cast_sym_OR); }
276
+ "?" { RET(cast_sym_QUESTION); }
277
+
278
+ "<:" { RET(cast_sym_LBRACKET); }
279
+ "<%" { RET(cast_sym_LBRACE); }
280
+ ":>" { RET(cast_sym_RBRACKET); }
281
+ "%>" { RET(cast_sym_RBRACE); }
282
+
283
+ [ \t\v\f]+ { goto std; }
284
+
285
+ [\000]
286
+ {
287
+ if(cursor == p->eof) RET(Qnil);
288
+ goto std;
289
+ }
290
+
291
+ "\n"
292
+ {
293
+ p->pos = cursor; ++p->lineno;
294
+ goto std;
295
+ }
296
+
297
+ any
298
+ {
299
+ rb_raise(cast_eParseError, "%ld: unexpected character: %c (ASCII %d)\n", p->lineno, *p->tok, (int)*p->tok);
300
+ goto std;
301
+ }
302
+ */
303
+
304
+ comment:
305
+ /*!re2c
306
+ "*" "/" { goto std; }
307
+ "\n"
308
+ {
309
+ p->tok = p->pos = cursor; ++p->lineno;
310
+ goto comment;
311
+ }
312
+
313
+ [\000]
314
+ {
315
+ if (cursor == p->eof)
316
+ rb_raise(cast_eParseError,
317
+ "%ld: unclosed multiline comment",
318
+ p->lineno);
319
+ }
320
+
321
+ any { goto comment; }
322
+ */
323
+
324
+ comment2:
325
+ /*!re2c
326
+ "\n"
327
+ {
328
+ p->tok = p->pos = cursor; ++p->lineno;
329
+ goto std;
330
+ }
331
+
332
+ [\000]
333
+ {
334
+ if (cursor == p->eof) RET(Qnil);
335
+ goto std;
336
+ }
337
+
338
+ any { goto comment2; }
339
+ */
340
+ }
@@ -1,9 +1,11 @@
1
- dir = File.dirname(File.expand_path(__FILE__))
2
-
3
- require "#{dir}/node.rb"
4
- require "#{dir}/node_list.rb"
5
- require "#{dir}/c_nodes.rb"
6
- require "#{dir}/c.tab.rb"
7
- require "#{dir}/parse.rb"
8
- require "#{dir}/to_s.rb"
9
- require "#{dir}/to_debug.rb"
1
+ require "cast/cast"
2
+ require "cast/tempfile"
3
+ require "cast/preprocessor"
4
+ require "cast/node"
5
+ require "cast/node_list"
6
+ require "cast/c_nodes"
7
+ require "cast/c.tab"
8
+ require "cast/parse"
9
+ require "cast/to_s"
10
+ require "cast/inspect"
11
+ require "cast/version"
@@ -0,0 +1,904 @@
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 COLON statement {val[2].labels.unshift(PlainLabel.new_at(val[0].pos, val[0].val)); result = val[2]}
42
+ | CASE constant_expression COLON statement {val[3].labels.unshift(Case .new_at(val[0].pos, val[1] )); result = val[3]}
43
+ | DEFAULT COLON 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 COLON 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
+ : LBRACE block_item_list RBRACE {result = Block.new_at(val[0].pos, val[1])}
50
+ | LBRACE RBRACE {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 SEMICOLON {result = ExpressionStatement.new_at(val[0].pos, val[0])}
65
+ | SEMICOLON {result = ExpressionStatement.new_at(val[0].pos )}
66
+
67
+ # Returns Statement
68
+ selection_statement
69
+ : IF LPAREN expression RPAREN statement {result = If .new_at(val[0].pos, val[2], val[4] )}
70
+ | IF LPAREN expression RPAREN statement ELSE statement {result = If .new_at(val[0].pos, val[2], val[4], val[6])}
71
+ | SWITCH LPAREN expression RPAREN statement {result = Switch.new_at(val[0].pos, val[2], val[4] )}
72
+
73
+ # Returns Statement
74
+ iteration_statement
75
+ : WHILE LPAREN expression RPAREN statement {result = While.new_at(val[0].pos, val[2], val[4] )}
76
+ | DO statement WHILE LPAREN expression RPAREN SEMICOLON {result = While.new_at(val[0].pos, val[4], val[1], :do => true )}
77
+ | FOR LPAREN expression SEMICOLON expression SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, val[2], val[4], val[6], val[8])}
78
+ | FOR LPAREN expression SEMICOLON expression SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, val[2], val[4], nil , val[7])}
79
+ | FOR LPAREN expression SEMICOLON SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, val[2], nil , val[5], val[7])}
80
+ | FOR LPAREN expression SEMICOLON SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, val[2], nil , nil , val[6])}
81
+ | FOR LPAREN SEMICOLON expression SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, nil , val[3], val[5], val[7])}
82
+ | FOR LPAREN SEMICOLON expression SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, nil , val[3], nil , val[6])}
83
+ | FOR LPAREN SEMICOLON SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, nil , nil , val[4], val[6])}
84
+ | FOR LPAREN SEMICOLON SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, nil , nil , nil , val[5])}
85
+ | FOR LPAREN declaration expression SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, val[2], val[3], val[5], val[7])}
86
+ | FOR LPAREN declaration expression SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, val[2], val[3], nil , val[6])}
87
+ | FOR LPAREN declaration SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, val[2], nil , val[4], val[6])}
88
+ | FOR LPAREN declaration SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, val[2], nil , nil , val[5])}
89
+
90
+ # Returns Statement
91
+ jump_statement
92
+ : GOTO identifier SEMICOLON {result = Goto .new_at(val[0].pos, val[1].val)}
93
+ | CONTINUE SEMICOLON {result = Continue.new_at(val[0].pos )}
94
+ | BREAK SEMICOLON {result = Break .new_at(val[0].pos )}
95
+ | RETURN expression SEMICOLON {result = Return .new_at(val[0].pos, val[1] )}
96
+ | RETURN SEMICOLON {result = Return .new_at(val[0].pos )}
97
+ # type names can also be used as labels
98
+ | GOTO typedef_name SEMICOLON {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 SEMICOLON {result = make_declaration(val[0][0], val[0][1], val[1])}
105
+ | declaration_specifiers SEMICOLON {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 COMMA init_declarator {result = val[0] << val[2]}
122
+
123
+ # Returns Declarator
124
+ init_declarator
125
+ : declarator {result = val[0]}
126
+ | declarator EQ initializer {val[0].init = val[2]; result = val[0]}
127
+
128
+ # Returns [Pos, Symbol]
129
+ storage_class_specifier
130
+ : TYPEDEF {result = [val[0].pos, :typedef ]}
131
+ | EXTERN {result = [val[0].pos, :extern ]}
132
+ | STATIC {result = [val[0].pos, :static ]}
133
+ | AUTO {result = [val[0].pos, :auto ]}
134
+ | REGISTER {result = [val[0].pos, :register]}
135
+
136
+ # Returns [Pos, Type|Symbol]
137
+ type_specifier
138
+ : VOID {result = [val[0].pos, :void ]}
139
+ | CHAR {result = [val[0].pos, :char ]}
140
+ | SHORT {result = [val[0].pos, :short ]}
141
+ | INT {result = [val[0].pos, :int ]}
142
+ | LONG {result = [val[0].pos, :long ]}
143
+ | FLOAT {result = [val[0].pos, :float ]}
144
+ | DOUBLE {result = [val[0].pos, :double ]}
145
+ | SIGNED {result = [val[0].pos, :signed ]}
146
+ | UNSIGNED {result = [val[0].pos, :unsigned ]}
147
+ | BOOL {result = [val[0].pos, :_Bool ]}
148
+ | COMPLEX {result = [val[0].pos, :_Complex ]}
149
+ | IMAGINARY {result = [val[0].pos, :_Imaginary]}
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 LBRACE struct_declaration_list RBRACE {result = val[0][1].new_at(val[0][0], val[1].val, val[3])}
157
+ | struct_or_union LBRACE struct_declaration_list RBRACE {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 LBRACE struct_declaration_list RBRACE {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 SEMICOLON {result = make_declaration(val[0][0], val[0][1], val[1])}
176
+ | specifier_qualifier_list SEMICOLON {result = make_declaration(val[0][0], val[0][1], NodeArray[])}
177
+
178
+ # Returns {Pos, [Symbol]}
179
+ specifier_qualifier_list
180
+ : type_specifier specifier_qualifier_list {val[1][1] << val[0][1]; result = val[1]}
181
+ | type_specifier {result = [val[0][0], [val[0][1]]]}
182
+ | type_qualifier specifier_qualifier_list {val[1][1] << val[0][1]; result = val[1]}
183
+ | type_qualifier {result = [val[0][0], [val[0][1]]]}
184
+
185
+ # Returns NodeArray[Declarator]
186
+ struct_declarator_list
187
+ : struct_declarator {result = NodeArray[val[0]]}
188
+ | struct_declarator_list COMMA struct_declarator {result = val[0] << val[2]}
189
+
190
+ # Returns Declarator
191
+ struct_declarator
192
+ : declarator {result = val[0]}
193
+ | declarator COLON constant_expression {result = val[0]; val[0].num_bits = val[2]}
194
+ | COLON constant_expression {result = Declarator.new_at(val[0].pos, :num_bits => val[1])}
195
+
196
+ # Returns Enum
197
+ enum_specifier
198
+ : ENUM identifier LBRACE enumerator_list RBRACE {result = Enum.new_at(val[0].pos, val[1].val, val[3])}
199
+ | ENUM LBRACE enumerator_list RBRACE {result = Enum.new_at(val[0].pos, nil , val[2])}
200
+ | ENUM identifier LBRACE enumerator_list COMMA RBRACE {result = Enum.new_at(val[0].pos, val[1].val, val[3])}
201
+ | ENUM LBRACE enumerator_list COMMA RBRACE {result = Enum.new_at(val[0].pos, nil , val[2])}
202
+ | ENUM identifier {result = Enum.new_at(val[0].pos, val[1].val, nil )}
203
+ # type names can also be used as enum names
204
+ | ENUM typedef_name LBRACE enumerator_list RBRACE {result = Enum.new_at(val[0].pos, val[1].name, val[3])}
205
+ | ENUM typedef_name LBRACE enumerator_list COMMA RBRACE {result = Enum.new_at(val[0].pos, val[1].name, val[3])}
206
+ | ENUM typedef_name {result = Enum.new_at(val[0].pos, val[1].name, nil )}
207
+
208
+ # Returns NodeArray[Enumerator]
209
+ enumerator_list
210
+ : enumerator {result = NodeArray[val[0]]}
211
+ | enumerator_list COMMA enumerator {result = val[0] << val[2]}
212
+
213
+ # Returns Enumerator
214
+ enumerator
215
+ : enumeration_constant {result = Enumerator.new_at(val[0].pos, val[0].val, nil )}
216
+ | enumeration_constant EQ constant_expression {result = Enumerator.new_at(val[0].pos, val[0].val, val[2])}
217
+
218
+ # Returns [Pos, Symbol]
219
+ type_qualifier
220
+ : CONST {result = [val[0].pos, :const ]}
221
+ | RESTRICT {result = [val[0].pos, :restrict]}
222
+ | VOLATILE {result = [val[0].pos, :volatile]}
223
+
224
+ # Returns [Pos, Symbol]
225
+ function_specifier
226
+ : INLINE {result = [val[0].pos, :inline]}
227
+
228
+ # Returns Declarator
229
+ declarator
230
+ : pointer direct_declarator {result = add_decl_type(val[1], val[0])}
231
+ | direct_declarator {result = val[0]}
232
+
233
+ # Returns Declarator
234
+ direct_declarator
235
+ : identifier {result = Declarator.new_at(val[0].pos, nil, val[0].val)}
236
+ | LPAREN declarator RPAREN {result = val[1]}
237
+ | direct_declarator LBRACKET type_qualifier_list assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
238
+ | direct_declarator LBRACKET type_qualifier_list RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
239
+ | direct_declarator LBRACKET assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos, nil, val[2]))}
240
+ | direct_declarator LBRACKET RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))}
241
+ | direct_declarator LBRACKET STATIC type_qualifier_list assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
242
+ | direct_declarator LBRACKET STATIC assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
243
+ | direct_declarator LBRACKET type_qualifier_list STATIC assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
244
+ | direct_declarator LBRACKET type_qualifier_list MUL RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
245
+ | direct_declarator LBRACKET MUL RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
246
+ | direct_declarator LPAREN parameter_type_list RPAREN {result = add_decl_type(val[0], Function.new_at(val[0].pos, nil, param_list(*val[2]), :var_args => val[2][1]))}
247
+ | direct_declarator LPAREN identifier_list RPAREN {result = add_decl_type(val[0], Function.new_at(val[0].pos, nil, val[2]))}
248
+ | direct_declarator LPAREN RPAREN {result = add_decl_type(val[0], Function.new_at(val[0].pos ))}
249
+
250
+ # Returns Pointer
251
+ pointer
252
+ : MUL type_qualifier_list {result = add_type_quals(Pointer.new_at(val[0].pos), val[1][1]) }
253
+ | MUL {result = Pointer.new_at(val[0].pos) }
254
+ | MUL 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]}
255
+ | MUL pointer {p = Pointer.new_at(val[0].pos) ; val[1].direct_type = p; result = val[1]}
256
+
257
+ # Returns {Pos, [Symbol]}
258
+ type_qualifier_list
259
+ : type_qualifier {result = [val[0][0], [val[0][1]]]}
260
+ | type_qualifier_list type_qualifier {val[0][1] << val[1][1]; result = val[0]}
261
+
262
+ # Returns [NodeArray[Parameter], var_args?]
263
+ parameter_type_list
264
+ : parameter_list {result = [val[0], false]}
265
+ | parameter_list COMMA ELLIPSIS {result = [val[0], true ]}
266
+
267
+ # Returns NodeArray[Parameter]
268
+ parameter_list
269
+ : parameter_declaration {result = NodeArray[val[0]]}
270
+ | parameter_list COMMA parameter_declaration {result = val[0] << val[2]}
271
+
272
+ # Returns Parameter
273
+ parameter_declaration
274
+ : declaration_specifiers declarator {ind_type = val[1].indirect_type and ind_type.detach
275
+ result = make_parameter(val[0][0], val[0][1], ind_type, val[1].name)}
276
+ | declaration_specifiers abstract_declarator {result = make_parameter(val[0][0], val[0][1], val[1] , nil )}
277
+ | declaration_specifiers {result = make_parameter(val[0][0], val[0][1], nil , nil )}
278
+
279
+ # Returns NodeArray[Parameter]
280
+ identifier_list
281
+ : identifier {result = NodeArray[Parameter.new_at(val[0].pos, nil, val[0].val)]}
282
+ | identifier_list COMMA identifier {result = val[0] << Parameter.new_at(val[2].pos, nil, val[2].val)}
283
+
284
+ # Returns Type
285
+ type_name
286
+ : specifier_qualifier_list abstract_declarator {val[1].direct_type = make_direct_type(val[0][0], val[0][1]); result = val[1]}
287
+ | specifier_qualifier_list {result = make_direct_type(val[0][0], val[0][1]) }
288
+
289
+ # Returns Type
290
+ abstract_declarator
291
+ : pointer {result = val[0]}
292
+ | pointer direct_abstract_declarator {val[1].direct_type = val[0]; result = val[1]}
293
+ | direct_abstract_declarator {result = val[0]}
294
+
295
+ # Returns Type
296
+ direct_abstract_declarator
297
+ : LPAREN abstract_declarator RPAREN {result = val[1]}
298
+ | direct_abstract_declarator LBRACKET assignment_expression RBRACKET {val[0].direct_type = Array.new_at(val[0].pos, nil, val[2]); result = val[0]}
299
+ | direct_abstract_declarator LBRACKET RBRACKET {val[0].direct_type = Array.new_at(val[0].pos, nil, nil ); result = val[0]}
300
+ | LBRACKET assignment_expression RBRACKET {result = Array.new_at(val[0].pos, nil, val[1])}
301
+ | LBRACKET RBRACKET {result = Array.new_at(val[0].pos )}
302
+ | direct_abstract_declarator LBRACKET MUL RBRACKET {val[0].direct_type = Array.new_at(val[0].pos); result = val[0]} # TODO
303
+ | LBRACKET MUL RBRACKET {result = Array.new_at(val[0].pos)} # TODO
304
+ | direct_abstract_declarator LPAREN parameter_type_list RPAREN {val[0].direct_type = Function.new_at(val[0].pos, nil, param_list(*val[2]), val[2][1]); result = val[0]}
305
+ | direct_abstract_declarator LPAREN RPAREN {val[0].direct_type = Function.new_at(val[0].pos ); result = val[0]}
306
+ | LPAREN parameter_type_list RPAREN {result = Function.new_at(val[0].pos, nil, param_list(*val[1]), val[1][1])}
307
+ | LPAREN RPAREN {result = Function.new_at(val[0].pos )}
308
+
309
+ # Returns CustomType
310
+ typedef_name
311
+ #: identifier -- insufficient since we must distinguish between type
312
+ # names and var names (otherwise we have a conflict)
313
+ : TYPENAME {result = CustomType.new_at(val[0].pos, val[0].val)}
314
+
315
+ # Returns Expression
316
+ initializer
317
+ : assignment_expression {result = val[0]}
318
+ | LBRACE initializer_list RBRACE {result = CompoundLiteral.new_at(val[0].pos, nil, val[1])}
319
+ | LBRACE initializer_list COMMA RBRACE {result = CompoundLiteral.new_at(val[0].pos, nil, val[1])}
320
+
321
+ # Returns NodeArray[MemberInit]
322
+ initializer_list
323
+ : designation initializer {result = NodeArray[MemberInit.new_at(val[0][0] , val[0][1], val[1])]}
324
+ | initializer {result = NodeArray[MemberInit.new_at(val[0].pos, nil , val[0])]}
325
+ | initializer_list COMMA designation initializer {result = val[0] << MemberInit.new_at(val[2][0] , val[2][1], val[3])}
326
+ | initializer_list COMMA initializer {result = val[0] << MemberInit.new_at(val[2].pos, nil , val[2])}
327
+
328
+ # Returns {Pos, NodeArray[Expression|Token]}
329
+ designation
330
+ : designator_list EQ {result = val[0]}
331
+
332
+ # Returns {Pos, NodeArray[Expression|Token]}
333
+ designator_list
334
+ : designator {result = val[0]; val[0][1] = NodeArray[val[0][1]]}
335
+ | designator_list designator {result = val[0]; val[0][1] << val[1][1]}
336
+
337
+ # Returns {Pos, Expression|Member}
338
+ designator
339
+ : LBRACKET constant_expression RBRACKET {result = [val[1].pos, val[1] ]}
340
+ | DOT identifier {result = [val[1].pos, Member.new_at(val[1].pos, val[1].val)]}
341
+
342
+ # A.2.1 Expressions
343
+
344
+ # Returns Expression
345
+ primary_expression
346
+ : identifier {result = Variable.new_at(val[0].pos, val[0].val)}
347
+ | constant {result = val[0]}
348
+ | string_literal {result = val[0]}
349
+ # GCC EXTENSION: allow a compound statement in parentheses as an expression
350
+ | LPAREN expression RPAREN {result = val[1]}
351
+ | LPAREN compound_statement RPAREN {block_expressions_enabled? or parse_error val[0].pos, "compound statement found where expression expected"
352
+ result = BlockExpression.new(val[1]); result.pos = val[0].pos}
353
+
354
+ # Returns Expression
355
+ postfix_expression
356
+ : primary_expression {result = val[0]}
357
+ | postfix_expression LBRACKET expression RBRACKET {result = Index .new_at(val[0].pos, val[0], val[2])}
358
+ | postfix_expression LPAREN argument_expression_list RPAREN {result = Call .new_at(val[0].pos, val[0], val[2] )}
359
+ | postfix_expression LPAREN RPAREN {result = Call .new_at(val[0].pos, val[0], NodeArray[])}
360
+ | postfix_expression DOT identifier {result = Dot .new_at(val[0].pos, val[0], Member.new(val[2].val))}
361
+ | postfix_expression ARROW identifier {result = Arrow .new_at(val[0].pos, val[0], Member.new(val[2].val))}
362
+ | postfix_expression INC {result = PostInc .new_at(val[0].pos, val[0] )}
363
+ | postfix_expression DEC {result = PostDec .new_at(val[0].pos, val[0] )}
364
+ | LPAREN type_name RPAREN LBRACE initializer_list RBRACE {result = CompoundLiteral.new_at(val[0].pos, val[1], val[4])}
365
+ | LPAREN type_name RPAREN LBRACE initializer_list COMMA RBRACE {result = CompoundLiteral.new_at(val[0].pos, val[1], val[4])}
366
+
367
+ # Returns [Expression|Type]
368
+ argument_expression_list
369
+ : argument_expression {result = NodeArray[val[0]]}
370
+ | argument_expression_list COMMA argument_expression {result = val[0] << val[2]}
371
+
372
+ # Returns Expression|Type -- EXTENSION: allow type names here too, to support some standard library macros (e.g., va_arg [7.15.1.1])
373
+ argument_expression
374
+ : assignment_expression {result = val[0]}
375
+ | type_name {result = val[0]}
376
+
377
+ # Returns Expression
378
+ unary_expression
379
+ : postfix_expression {result = val[0]}
380
+ | INC unary_expression {result = PreInc.new_at(val[0].pos, val[1])}
381
+ | DEC unary_expression {result = PreDec.new_at(val[0].pos, val[1])}
382
+ | unary_operator cast_expression {result = val[0][0].new_at(val[0][1], val[1])}
383
+ | SIZEOF unary_expression {result = Sizeof.new_at(val[0].pos, val[1])}
384
+ | SIZEOF LPAREN type_name RPAREN {result = Sizeof.new_at(val[0].pos, val[2])}
385
+
386
+ # Returns [Class, Pos]
387
+ unary_operator
388
+ : AND {result = [Address , val[0].pos]}
389
+ | MUL {result = [Dereference, val[0].pos]}
390
+ | ADD {result = [Positive , val[0].pos]}
391
+ | SUB {result = [Negative , val[0].pos]}
392
+ | NOT {result = [BitNot , val[0].pos]}
393
+ | BANG {result = [Not , val[0].pos]}
394
+
395
+ # Returns Expression
396
+ cast_expression
397
+ : unary_expression {result = val[0]}
398
+ | LPAREN type_name RPAREN cast_expression {result = Cast.new_at(val[0].pos, val[1], val[3])}
399
+
400
+ # Returns Expression
401
+ multiplicative_expression
402
+ : cast_expression {result = val[0]}
403
+ | multiplicative_expression MUL cast_expression {result = Multiply.new_at(val[0].pos, val[0], val[2])}
404
+ | multiplicative_expression DIV cast_expression {result = Divide .new_at(val[0].pos, val[0], val[2])}
405
+ | multiplicative_expression MOD cast_expression {result = Mod .new_at(val[0].pos, val[0], val[2])}
406
+
407
+ # Returns Expression
408
+ additive_expression
409
+ : multiplicative_expression {result = val[0]}
410
+ | additive_expression ADD multiplicative_expression {result = Add .new_at(val[0].pos, val[0], val[2])}
411
+ | additive_expression SUB multiplicative_expression {result = Subtract.new_at(val[0].pos, val[0], val[2])}
412
+
413
+ # Returns Expression
414
+ shift_expression
415
+ : additive_expression {result = val[0]}
416
+ | shift_expression LSHIFT additive_expression {result = ShiftLeft .new_at(val[0].pos, val[0], val[2])}
417
+ | shift_expression RSHIFT additive_expression {result = ShiftRight.new_at(val[0].pos, val[0], val[2])}
418
+
419
+ # Returns Expression
420
+ relational_expression
421
+ : shift_expression {result = val[0]}
422
+ | relational_expression LT shift_expression {result = Less.new_at(val[0].pos, val[0], val[2])}
423
+ | relational_expression GT shift_expression {result = More.new_at(val[0].pos, val[0], val[2])}
424
+ | relational_expression LEQ shift_expression {result = LessOrEqual.new_at(val[0].pos, val[0], val[2])}
425
+ | relational_expression GEQ shift_expression {result = MoreOrEqual.new_at(val[0].pos, val[0], val[2])}
426
+
427
+ # Returns Expression
428
+ equality_expression
429
+ : relational_expression {result = val[0]}
430
+ | equality_expression EQEQ relational_expression {result = Equal .new_at(val[0].pos, val[0], val[2])}
431
+ | equality_expression NEQ relational_expression {result = NotEqual.new_at(val[0].pos, val[0], val[2])}
432
+
433
+ # Returns Expression
434
+ and_expression
435
+ : equality_expression {result = val[0]}
436
+ | and_expression AND equality_expression {result = BitAnd.new_at(val[0].pos, val[0], val[2])}
437
+
438
+ # Returns Expression
439
+ exclusive_or_expression
440
+ : and_expression {result = val[0]}
441
+ | exclusive_or_expression XOR and_expression {result = BitXor.new_at(val[0].pos, val[0], val[2])}
442
+
443
+ # Returns Expression
444
+ inclusive_or_expression
445
+ : exclusive_or_expression {result = val[0]}
446
+ | inclusive_or_expression OR exclusive_or_expression {result = BitOr.new_at(val[0].pos, val[0], val[2])}
447
+
448
+ # Returns Expression
449
+ logical_and_expression
450
+ : inclusive_or_expression {result = val[0]}
451
+ | logical_and_expression ANDAND inclusive_or_expression {result = And.new_at(val[0].pos, val[0], val[2])}
452
+
453
+ # Returns Expression
454
+ logical_or_expression
455
+ : logical_and_expression {result = val[0]}
456
+ | logical_or_expression OROR logical_and_expression {result = Or.new_at(val[0].pos, val[0], val[2])}
457
+
458
+ # Returns Expression
459
+ conditional_expression
460
+ : logical_or_expression {result = val[0]}
461
+ | logical_or_expression QUESTION expression COLON conditional_expression {result = Conditional.new_at(val[0].pos, val[0], val[2], val[4])}
462
+
463
+ # Returns Expression
464
+ assignment_expression
465
+ : conditional_expression {result = val[0]}
466
+ | unary_expression assignment_operator assignment_expression {result = val[1].new_at(val[0].pos, val[0], val[2])}
467
+
468
+ # Returns Class
469
+ assignment_operator
470
+ : EQ {result = Assign}
471
+ | MULEQ {result = MultiplyAssign}
472
+ | DIVEQ {result = DivideAssign}
473
+ | MODEQ {result = ModAssign}
474
+ | ADDEQ {result = AddAssign}
475
+ | SUBEQ {result = SubtractAssign}
476
+ | LSHIFTEQ {result = ShiftLeftAssign}
477
+ | RSHIFTEQ {result = ShiftRightAssign}
478
+ | ANDEQ {result = BitAndAssign}
479
+ | XOREQ {result = BitXorAssign}
480
+ | OREQ {result = BitOrAssign}
481
+
482
+ # Returns Expression
483
+ expression
484
+ : assignment_expression {result = val[0]}
485
+ | expression COMMA assignment_expression {
486
+ if val[0].is_a? Comma
487
+ if val[2].is_a? Comma
488
+ val[0].exprs.push(*val[2].exprs)
489
+ else
490
+ val[0].exprs << val[2]
491
+ end
492
+ result = val[0]
493
+ else
494
+ if val[2].is_a? Comma
495
+ val[2].exprs.unshift(val[0])
496
+ val[2].pos = val[0].pos
497
+ result = val[2]
498
+ else
499
+ result = Comma.new_at(val[0].pos, NodeArray[val[0], val[2]])
500
+ end
501
+ end
502
+ }
503
+
504
+ # Returns Expression
505
+ constant_expression
506
+ : conditional_expression {result = val[0]}
507
+
508
+ # A.1.1 -- Lexical elements
509
+ #
510
+ # token
511
+ # : keyword (raw string)
512
+ # | identifier expanded below
513
+ # | constant expanded below
514
+ # | string_literal expanded below
515
+ # | punctuator (raw string)
516
+ #
517
+ # preprocessing-token (skip)
518
+
519
+ # Returns Token
520
+ identifier
521
+ : ID {result = val[0]}
522
+
523
+ # Returns Literal
524
+ constant
525
+ : ICON {result = val[0].val; result.pos = val[0].pos}
526
+ | FCON {result = val[0].val; result.pos = val[0].pos}
527
+ #| enumeration_constant -- these are parsed as identifiers at all
528
+ # places the `constant' nonterminal appears
529
+ | CCON {result = val[0].val; result.pos = val[0].pos}
530
+
531
+ # Returns Token
532
+ enumeration_constant
533
+ : ID {result = val[0]}
534
+
535
+ # Returns StringLiteral
536
+ # Also handles string literal concatenation (6.4.5.4)
537
+ string_literal
538
+ : string_literal SCON {val[0].val << val[1].val.val; result = val[0]}
539
+ | SCON { result = val[0].val; result.pos = val[0].pos }
540
+
541
+ ---- inner
542
+ # A.1.9 -- Preprocessing numbers -- skip
543
+ # A.1.8 -- Header names -- skip
544
+
545
+ # A.1.7 -- Puncuators -- we don't bother with {##,#,%:,%:%:} since
546
+ # we don't do preprocessing
547
+ @@punctuators = %r'\+\+|-[->]|&&|\|\||\.\.\.|(?:<<|>>|[<>=!*/%+\-&^|])=?|[\[\](){}.~?:;,]'
548
+ @@digraphs = %r'<[:%]|[:%]>'
549
+
550
+ # A.1.6 -- String Literals -- simple for us because we don't decode
551
+ # the string (and indeed accept some illegal strings)
552
+ @@string_literal = %r'L?"(?:[^\\]|\\.)*?"'m
553
+
554
+ # A.1.5 -- Constants
555
+ @@decimal_floating_constant = %r'(?:(?:\d*\.\d+|\d+\.)(?:e[-+]?\d+)?|\d+e[-+]?\d+)[fl]?'i
556
+ @@hexadecimal_floating_constant = %r'0x(?:(?:[0-9a-f]*\.[0-9a-f]+|[0-9a-f]+\.)|[0-9a-f]+)p[-+]?\d+[fl]?'i
557
+
558
+ @@integer_constant = %r'(?:[1-9][0-9]*|0x[0-9a-f]+|0[0-7]*)(?:ul?l?|ll?u?)?'i
559
+ @@floating_constant = %r'#{@@decimal_floating_constant}|#{@@hexadecimal_floating_constant}'
560
+ @@enumeration_constant = %r'[a-zA-Z_\\][a-zA-Z_\\0-9]*'
561
+ @@character_constant = %r"L?'(?:[^\\]|\\.)+?'"
562
+ # (note that as with string-literals, we accept some illegal
563
+ # character-constants)
564
+
565
+ # A.1.4 -- Universal character names -- skip
566
+
567
+ # A.1.3 -- Identifiers -- skip, since an identifier is lexically
568
+ # identical to an enumeration constant
569
+
570
+ # A.1.2 Keywords
571
+ keywords = %w'auto break case char const continue default do
572
+ double else enum extern float for goto if inline int long register
573
+ restrict return short signed sizeof static struct switch typedef union
574
+ unsigned void volatile while _Bool _Complex _Imaginary'
575
+ @@keywords = %r"#{keywords.join('|')}"
576
+
577
+ def initialize
578
+ @type_names = ::Set.new
579
+
580
+ @warning_proc = lambda{}
581
+ @pos = C::Node::Pos.new(nil, 1, 0)
582
+ end
583
+ def initialize_copy(x)
584
+ @pos = x.pos.dup
585
+ @type_names = x.type_names.dup
586
+ end
587
+ attr_accessor :pos, :type_names
588
+
589
+ def parse(str)
590
+ if str.respond_to? :read
591
+ str = str.read
592
+ end
593
+ @str = str
594
+ begin
595
+ prepare_lexer(str)
596
+ return do_parse
597
+ rescue ParseError => e
598
+ e.set_backtrace(caller)
599
+ raise
600
+ end
601
+ end
602
+
603
+ #
604
+ # Error handler, as used by racc.
605
+ #
606
+ def on_error(error_token_id, error_value, value_stack)
607
+ if error_value == '$'
608
+ parse_error @pos, "unexpected EOF"
609
+ else
610
+ parse_error(error_value.pos,
611
+ "parse error on #{token_to_str(error_token_id)} (#{error_value.val})")
612
+ end
613
+ end
614
+
615
+ def self.feature(name)
616
+ attr_writer "#{name}_enabled"
617
+ class_eval <<-EOS
618
+ def enable_#{name}
619
+ @#{name}_enabled = true
620
+ end
621
+ def #{name}_enabled?
622
+ @#{name}_enabled
623
+ end
624
+ EOS
625
+ end
626
+ private_class_method :feature
627
+
628
+ #
629
+ # Allow blocks in parentheses as expressions, as per the gcc
630
+ # extension. [http://rubyurl.com/iB7]
631
+ #
632
+ feature :block_expressions
633
+
634
+ private # ---------------------------------------------------------
635
+
636
+ class Token
637
+ attr_accessor :pos, :val
638
+ def initialize(pos, val)
639
+ @pos = pos
640
+ @val = val
641
+ end
642
+ end
643
+ def eat(str)
644
+ lines = str.split(/\r\n|[\r\n]/, -1)
645
+ if lines.length == 1
646
+ @pos.col_num += lines[0].length
647
+ else
648
+ @pos.line_num += lines.length - 1
649
+ @pos.col_num = lines[-1].length
650
+ end
651
+ end
652
+
653
+ #
654
+ # Make a Declaration from the given specs and declarators.
655
+ #
656
+ def make_declaration(pos, specs, declarators)
657
+ specs.all?{|x| x.is_a?(Symbol) || x.is_a?(Type)} or raise specs.map{|x| x.class}.inspect
658
+ decl = Declaration.new_at(pos, nil, declarators)
659
+
660
+ # set storage class
661
+ storage_classes = specs.find_all do |x|
662
+ [:typedef, :extern, :static, :auto, :register].include? x
663
+ end
664
+ # 6.7.1p2: at most, one storage-class specifier may be given in
665
+ # the declaration specifiers in a declaration
666
+ storage_classes.length <= 1 or
667
+ begin
668
+ if declarators.length == 0
669
+ for_name = ''
670
+ else
671
+ for_name = "for `#{declarators[0].name}'"
672
+ end
673
+ parse_error pos, "multiple or duplicate storage classes given #{for_name}'"
674
+ end
675
+ decl.storage = storage_classes[0]
676
+
677
+ # set type (specifiers, qualifiers)
678
+ decl.type = make_direct_type(pos, specs)
679
+
680
+ # set function specifiers
681
+ decl.inline = specs.include?(:inline)
682
+
683
+ # look for new type names
684
+ if decl.typedef?
685
+ decl.declarators.each do |d|
686
+ if d.name
687
+ @type_names << d.name
688
+ end
689
+ end
690
+ end
691
+
692
+ return decl
693
+ end
694
+
695
+ def make_function_def(pos, specs, func_declarator, decl_list, defn)
696
+ add_decl_type(func_declarator, make_direct_type(pos, specs))
697
+
698
+ # get types from decl_list if necessary
699
+ function = func_declarator.indirect_type
700
+ function.is_a? Function or
701
+ parse_error pos, "non function type for function `#{func_declarator.name}'"
702
+ params = function.params
703
+ if decl_list
704
+ params.all?{|p| p.type.nil?} or
705
+ parse_error pos, "both prototype and declaration list given for `#{func_declarator.name}'"
706
+ decl_list.each do |declaration|
707
+ declaration.declarators.each do |declarator|
708
+ param = params.find{|p| p.name == declarator.name} or
709
+ parse_error pos, "no parameter named #{declarator.name}"
710
+ if declarator.indirect_type
711
+ param.type = declarator.indirect_type
712
+ param.type.direct_type = declaration.type.dup
713
+ else
714
+ param.type = declaration.type.dup
715
+ end
716
+ end
717
+ end
718
+ params.all?{|p| p.type} or
719
+ begin
720
+ s = params.find_all{|p| p.type.nil?}.map{|p| "`#{p.name}'"}.join(' and ')
721
+ parse_error pos, "types missing for parameters #{s}"
722
+ end
723
+ end
724
+
725
+ fd = FunctionDef.new_at(pos,
726
+ function.detach,
727
+ func_declarator.name,
728
+ defn,
729
+ :no_prototype => !decl_list.nil?)
730
+
731
+ # set storage class
732
+ # 6.9.1p4: only extern or static allowed
733
+ specs.each do |s|
734
+ [:typedef, :auto, :register].include?(s) and
735
+ "`#{s}' illegal for function"
736
+ end
737
+ storage_classes = specs.find_all do |s|
738
+ s == :extern || s == :static
739
+ end
740
+ # 6.7.1p2: at most, one storage-class specifier may be given in
741
+ # the declaration specifiers in a declaration
742
+ storage_classes.length <= 1 or
743
+ "multiple or duplicate storage classes given for `#{func_declarator.name}'"
744
+ fd.storage = storage_classes[0] if storage_classes[0]
745
+
746
+ # set function specifiers
747
+ # 6.7.4p5 'inline' can be repeated
748
+ fd.inline = specs.include?(:inline)
749
+
750
+ return fd
751
+ end
752
+
753
+ #
754
+ # Make a direct type from the list of type specifiers and type
755
+ # qualifiers.
756
+ #
757
+ def make_direct_type(pos, specs)
758
+ specs_order = [:signed, :unsigned, :short, :long, :double, :void,
759
+ :char, :int, :float, :_Bool, :_Complex, :_Imaginary]
760
+
761
+ type_specs = specs.find_all do |x|
762
+ specs_order.include?(x) || !x.is_a?(Symbol)
763
+ end
764
+ type_specs.sort! do |a, b|
765
+ (specs_order.index(a)||100) <=> (specs_order.index(b)||100)
766
+ end
767
+
768
+ # set type specifiers
769
+ # 6.7.2p2: the specifier list should be one of these
770
+ type =
771
+ case type_specs
772
+ when [:void]
773
+ Void.new
774
+ when [:char]
775
+ Char.new
776
+ when [:signed, :char]
777
+ Char.new :signed => true
778
+ when [:unsigned, :char]
779
+ Char.new :signed => false
780
+ when [:short], [:signed, :short], [:short, :int],
781
+ [:signed, :short, :int]
782
+ Int.new :longness => -1
783
+ when [:unsigned, :short], [:unsigned, :short, :int]
784
+ Int.new :unsigned => true, :longness => -1
785
+ when [:int], [:signed], [:signed, :int]
786
+ Int.new
787
+ when [:unsigned], [:unsigned, :int]
788
+ Int.new :unsigned => true
789
+ when [:long], [:signed, :long], [:long, :int],
790
+ [:signed, :long, :int]
791
+ Int.new :longness => 1
792
+ when [:unsigned, :long], [:unsigned, :long, :int]
793
+ Int.new :longness => 1, :unsigned => true
794
+ when [:long, :long], [:signed, :long, :long],
795
+ [:long, :long, :int], [:signed, :long, :long, :int]
796
+ Int.new :longness => 2
797
+ when [:unsigned, :long, :long], [:unsigned, :long, :long, :int]
798
+ Int.new :longness => 2, :unsigned => true
799
+ when [:float]
800
+ Float.new
801
+ when [:double]
802
+ Float.new :longness => 1
803
+ when [:long, :double]
804
+ Float.new :longness => 2
805
+ when [:_Bool]
806
+ Bool.new
807
+ when [:float, :_Complex]
808
+ Complex.new
809
+ when [:double, :_Complex]
810
+ Complex.new :longness => 1
811
+ when [:long, :double, :_Complex]
812
+ Complex.new :longness => 2
813
+ when [:float, :_Imaginary]
814
+ Imaginary.new
815
+ when [:double, :_Imaginary]
816
+ Imaginary.new :longness => 1
817
+ when [:long, :double, :_Imaginary]
818
+ Imaginary.new :longness => 2
819
+ else
820
+ if type_specs.length == 1 &&
821
+ [CustomType, Struct, Union, Enum].any?{|c| type_specs[0].is_a? c}
822
+ type_specs[0]
823
+ else
824
+ if type_specs == []
825
+ parse_error pos, "no type specifiers given"
826
+ else
827
+ parse_error pos, "invalid type specifier combination: #{type_specs.join(' ')}"
828
+ end
829
+ end
830
+ end
831
+ type.pos ||= pos
832
+
833
+ # set type qualifiers
834
+ # 6.7.3p4: type qualifiers can be repeated
835
+ type.const = specs.any?{|x| x.equal? :const }
836
+ type.restrict = specs.any?{|x| x.equal? :restrict}
837
+ type.volatile = specs.any?{|x| x.equal? :volatile}
838
+
839
+ return type
840
+ end
841
+
842
+ def make_parameter(pos, specs, indirect_type, name)
843
+ type = indirect_type
844
+ if type
845
+ type.direct_type = make_direct_type(pos, specs)
846
+ else
847
+ type = make_direct_type(pos, specs)
848
+ end
849
+ [:typedef, :extern, :static, :auto, :inline].each do |sym|
850
+ specs.include? sym and
851
+ parse_error pos, "parameter `#{declarator.name}' declared `#{sym}'"
852
+ end
853
+ return Parameter.new_at(pos, type, name,
854
+ :register => specs.include?(:register))
855
+ end
856
+
857
+ def add_type_quals(type, quals)
858
+ type.const = quals.include?(:const )
859
+ type.restrict = quals.include?(:restrict)
860
+ type.volatile = quals.include?(:volatile)
861
+ return type
862
+ end
863
+
864
+ #
865
+ # Add te given type as the "most direct" type to the given
866
+ # declarator. Return the declarator.
867
+ #
868
+ def add_decl_type(declarator, type)
869
+ if declarator.indirect_type
870
+ declarator.indirect_type.direct_type = type
871
+ else
872
+ declarator.indirect_type = type
873
+ end
874
+ return declarator
875
+ end
876
+
877
+ def param_list(params, var_args)
878
+ if params.length == 1 &&
879
+ params[0].type.is_a?(Void) &&
880
+ params[0].name.nil?
881
+ return NodeArray[]
882
+ elsif params.empty?
883
+ return nil
884
+ else
885
+ return params
886
+ end
887
+ end
888
+
889
+ def parse_error(pos, str)
890
+ raise ParseError, "#{pos}: #{str}"
891
+ end
892
+
893
+ ---- header
894
+
895
+ require 'set'
896
+
897
+ # Error classes
898
+ module C
899
+ class ParseError < StandardError; end
900
+ end
901
+
902
+ # Local variables:
903
+ # mode: ruby
904
+ # end: