casty 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,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: