casty 0.3.1

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