• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2015 PLUMgrid, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17%skeleton "lalr1.cc"
18%defines
19%define namespace "ebpf::cc"
20%define parser_class_name "BisonParser"
21%parse-param { ebpf::cc::Lexer &lexer }
22%parse-param { ebpf::cc::Parser &parser }
23%lex-param { ebpf::cc::Lexer &lexer }
24%locations
25
26%code requires {
27    #include <memory>
28    #include <vector>
29    #include <string>
30    #include "node.h"
31    // forward declaration
32    namespace ebpf { namespace cc {
33        class Lexer;
34        class Parser;
35    } }
36}
37
38%code {
39    static int yylex(ebpf::cc::BisonParser::semantic_type *yylval,
40                     ebpf::cc::BisonParser::location_type *yylloc,
41                     ebpf::cc::Lexer &lexer);
42}
43
44%{
45    #include "node.h"
46    #include "parser.h"
47    using std::unique_ptr;
48    using std::vector;
49    using std::string;
50    using std::move;
51%}
52
53%union {
54    Scopes::StateScope *state_scope;
55    Scopes::VarScope *var_scope;
56    BlockStmtNode *block;
57    ExprNode *expr;
58    MethodCallExprNode *call;
59    StmtNode *stmt;
60    IdentExprNode *ident;
61    IntegerExprNode *numeric;
62    BitopExprNode *bitop;
63    ExprNodeList *args;
64    IdentExprNodeList *ident_args;
65    StmtNodeList *stmts;
66    FormalList *formals;
67    VariableDeclStmtNode *decl;
68    StructVariableDeclStmtNode *type_decl;
69    TableIndexExprNode *table_index;
70    std::vector<int> *type_specifiers;
71    std::string* string;
72    int token;
73}
74
75/* Define the terminal symbols. */
76%token <string> TIDENTIFIER TINTEGER THEXINTEGER TPRAGMA TSTRING
77%token <token> TU8 TU16 TU32 TU64
78%token <token> TEQUAL TCEQ TCNE TCLT TCLE TCGT TCGE TAND TOR
79%token <token> TLPAREN TRPAREN TLBRACE TRBRACE TLBRACK TRBRACK
80%token <token> TDOT TARROW TCOMMA TPLUS TMINUS TMUL TDIV TMOD TXOR TDOLLAR TCOLON TSCOPE TNOT TSEMI TCMPL TLAND TLOR
81%token <token> TSTRUCT TSTATE TFUNC TGOTO TCONTINUE TNEXT TTRUE TFALSE TRETURN
82%token <token> TIF TELSE TSWITCH TCASE
83%token <token> TMATCH TMISS TFAILURE TVALID
84%token <token> TAT
85
86/* Define non-terminal symbols as defined in the above union */
87%type <ident> ident scoped_ident dotted_ident any_ident
88%type <expr> expr assign_expr return_expr init_arg_kv
89%type <numeric> numeric
90%type <bitop> bitop
91%type <args> call_args /*init_args*/ init_args_kv
92%type <ident_args> table_decl_args
93%type <formals> struct_decl_stmts formals
94%type <block> program block prog_decls
95%type <decl> decl_stmt int_decl ref_stmt
96%type <type_decl> type_decl ptr_decl
97%type <stmt> stmt prog_decl var_decl struct_decl state_decl func_decl
98%type <stmt> table_decl table_result_stmt if_stmt switch_stmt case_stmt onvalid_stmt
99%type <var_scope> enter_varscope exit_varscope
100%type <state_scope> enter_statescope exit_statescope
101%type <stmts> stmts table_result_stmts case_stmts
102%type <call> call_expr
103%type <table_index> table_index_expr
104%type <type_specifiers> type_specifiers
105%type <stmt> pragma_decl
106%type <token> type_specifier
107
108/* taken from C++ operator precedence wiki page */
109%nonassoc TSCOPE
110%left TDOT TLBRACK TLBRACE TLPAREN TINCR TDECR
111%right TNOT TCMPL
112%left TMUL
113%left TDIV
114%left TMOD
115%left TPLUS
116%left TMINUS
117%left TCLT TCLE TCGT TCGE
118%left TCEQ
119%left TCNE
120%left TXOR
121%left TAND
122%left TOR
123%left TLAND
124%left TLOR
125%right TEQUAL
126
127%start program
128
129%%
130
131program
132  : enter_statescope enter_varscope prog_decls exit_varscope exit_statescope
133    { parser.root_node_ = $3; $3->scope_ = $2; }
134  ;
135
136/* program is a list of declarations */
137prog_decls
138  : prog_decl
139    { $$ = new BlockStmtNode; $$->stmts_.push_back(StmtNode::Ptr($1)); }
140  | prog_decls prog_decl
141    { $1->stmts_.push_back(StmtNode::Ptr($2)); }
142  ;
143
144/*
145 possible program declarations are:
146  "struct {}"
147  "state|on_miss|on_match|on_valid {}"
148  "var <var_decl>"
149  "Table <...> <ident>(size)"
150 */
151prog_decl
152  : var_decl TSEMI
153  | struct_decl TSEMI
154  | state_decl
155  | table_decl TSEMI
156  | pragma_decl
157  | func_decl
158  ;
159
160pragma_decl
161  : TPRAGMA TIDENTIFIER TIDENTIFIER
162    { $$ = new BlockStmtNode; parser.add_pragma(*$2, *$3); delete $2; delete $3; }
163  | TPRAGMA TIDENTIFIER TSTRING
164    { $$ = new BlockStmtNode; parser.add_pragma(*$2, *$3); delete $2; delete $3; }
165  ;
166
167stmts
168  : stmt
169    { $$ = new StmtNodeList; $$->push_back(StmtNode::Ptr($1)); }
170  | stmts stmt
171    { $1->push_back(StmtNode::Ptr($2)); }
172  ;
173
174stmt
175  : expr TSEMI
176    { $$ = new ExprStmtNode(ExprNode::Ptr($1));
177      parser.set_loc($$, @$); }
178  | assign_expr TSEMI
179    { $$ = new ExprStmtNode(ExprNode::Ptr($1));
180      parser.set_loc($$, @$); }
181  | return_expr TSEMI
182    { $$ = new ExprStmtNode(ExprNode::Ptr($1));
183      parser.set_loc($$, @$); }
184  | call_expr TLBRACE enter_varscope table_result_stmts exit_varscope TRBRACE TSEMI
185    { $$ = new ExprStmtNode(ExprNode::Ptr($1));
186      $1->block_->stmts_ = move(*$4); delete $4;
187      $1->block_->scope_ = $3;
188      parser.set_loc($$, @$); }
189  | call_expr TLBRACE TRBRACE TSEMI  // support empty curly braces
190    { $$ = new ExprStmtNode(ExprNode::Ptr($1));
191      parser.set_loc($$, @$); }
192  | if_stmt
193  | switch_stmt
194  | var_decl TSEMI
195    { $$ = $1; }
196  | state_decl
197  | onvalid_stmt
198  ;
199
200call_expr
201  : any_ident TLPAREN call_args TRPAREN
202    { $$ = new MethodCallExprNode(IdentExprNode::Ptr($1), move(*$3), lexer.lineno()); delete $3;
203      parser.set_loc($$, @$); }
204  ;
205
206block
207  : TLBRACE stmts TRBRACE
208    { $$ = new BlockStmtNode; $$->stmts_ = move(*$2); delete $2;
209      parser.set_loc($$, @$); }
210  | TLBRACE TRBRACE
211    { $$ = new BlockStmtNode;
212      parser.set_loc($$, @$); }
213  ;
214
215enter_varscope : /* empty */ { $$ = parser.scopes_->enter_var_scope(); } ;
216exit_varscope : /* emtpy */ { $$ = parser.scopes_->exit_var_scope(); } ;
217enter_statescope : /* empty */ { $$ = parser.scopes_->enter_state_scope(); } ;
218exit_statescope : /* emtpy */ { $$ = parser.scopes_->exit_state_scope(); } ;
219
220struct_decl
221  : TSTRUCT ident TLBRACE struct_decl_stmts TRBRACE
222    { $$ = parser.struct_add($2, $4); delete $4;
223      parser.set_loc($$, @$); }
224  ;
225
226struct_decl_stmts
227  : type_specifiers decl_stmt TSEMI
228    { $$ = new FormalList; $$->push_back(VariableDeclStmtNode::Ptr($2)); }
229  | struct_decl_stmts type_specifiers decl_stmt TSEMI
230    { $1->push_back(VariableDeclStmtNode::Ptr($3)); }
231  ;
232
233table_decl
234  : ident TCLT table_decl_args TCGT ident TLPAREN TINTEGER TRPAREN
235    { $$ = parser.table_add($1, $3, $5, $7); delete $3;
236      parser.set_loc($$, @$); }
237  ;
238
239table_decl_args
240  : ident
241    { $$ = new IdentExprNodeList; $$->push_back(IdentExprNode::Ptr($1)); }
242  | table_decl_args TCOMMA ident
243    { $$->push_back(IdentExprNode::Ptr($3)); }
244  ;
245
246state_decl
247  : TSTATE scoped_ident enter_statescope enter_varscope block exit_varscope exit_statescope
248    { $$ = parser.state_add($3, $2, $5); $5->scope_ = $4;
249      if (!$$) YYERROR;
250      parser.set_loc($$, @$); }
251  | TSTATE scoped_ident TCOMMA TMUL enter_statescope enter_varscope block exit_varscope exit_statescope
252    { $$ = parser.state_add($5, $2, new IdentExprNode(""), $7); $7->scope_ = $6;
253      if (!$$) YYERROR;
254      parser.set_loc($$, @$); }
255  | TSTATE scoped_ident TCOMMA scoped_ident enter_statescope enter_varscope block exit_varscope exit_statescope
256    { $$ = parser.state_add($5, $2, $4, $7); $7->scope_ = $6;
257      if (!$$) YYERROR;
258      parser.set_loc($$, @$); }
259  ;
260
261func_decl
262  : type_specifiers ident enter_statescope enter_varscope TLPAREN formals TRPAREN block exit_varscope exit_statescope
263    { $$ = parser.func_add($1, $3, $2, $6, $8); $8->scope_ = $4;
264      if (!$$) YYERROR;
265      parser.set_loc($$, @$); }
266  ;
267
268table_result_stmts
269  : table_result_stmt
270    { $$ = new StmtNodeList; $$->push_back(StmtNode::Ptr($1)); }
271  | table_result_stmts table_result_stmt
272    { $$->push_back(StmtNode::Ptr($2)); }
273  ;
274
275table_result_stmt
276  : TMATCH ident enter_varscope TLPAREN formals TRPAREN block exit_varscope TSEMI
277    { $$ = parser.result_add($1, $2, $5, $7); delete $5; $7->scope_ = $3;
278      if (!$$) YYERROR;
279      parser.set_loc($$, @$); }
280  | TMISS ident enter_varscope TLPAREN TRPAREN block exit_varscope TSEMI
281    { $$ = parser.result_add($1, $2, new FormalList, $6); $6->scope_ = $3;
282      if (!$$) YYERROR;
283      parser.set_loc($$, @$); }
284  | TFAILURE ident enter_varscope TLPAREN formals TRPAREN block exit_varscope TSEMI
285    { $$ = parser.result_add($1, $2, $5, $7); delete $5; $7->scope_ = $3;
286      if (!$$) YYERROR;
287      parser.set_loc($$, @$); }
288  ;
289
290formals
291  : TSTRUCT ptr_decl
292    { $$ = new FormalList; $$->push_back(VariableDeclStmtNode::Ptr(parser.variable_add(nullptr, $2))); }
293  | formals TCOMMA TSTRUCT ptr_decl
294    { $1->push_back(VariableDeclStmtNode::Ptr(parser.variable_add(nullptr, $4))); }
295  ;
296
297type_specifier
298  : TU8
299  | TU16
300  | TU32
301  | TU64
302  ;
303
304type_specifiers
305  : type_specifier { $$ = new std::vector<int>; $$->push_back($1); }
306  | type_specifiers type_specifier { $$->push_back($2); }
307  ;
308
309var_decl
310  : type_specifiers decl_stmt
311    { $$ = parser.variable_add($1, $2);
312      if (!$$) YYERROR;
313      parser.set_loc($$, @$); }
314  | type_specifiers int_decl TEQUAL expr
315    { $$ = parser.variable_add($1, $2, $4);
316      if (!$$) YYERROR;
317      parser.set_loc($$, @$); }
318  | TSTRUCT type_decl TEQUAL TLBRACE init_args_kv TRBRACE
319    { $$ = parser.variable_add($2, $5, true);
320      if (!$$) YYERROR;
321      parser.set_loc($$, @$); }
322  /*| TSTRUCT type_decl TEQUAL TLBRACE init_args TRBRACE
323    { $$ = parser.variable_add($2, $5, false);
324      parser.set_loc($$, @$); }*/
325  | TSTRUCT ref_stmt
326    { $$ = parser.variable_add(nullptr, $2);
327      if (!$$) YYERROR;
328      parser.set_loc($$, @$); }
329  ;
330
331/* "id":"bitsize" or "type" "id" */
332decl_stmt : int_decl { $$ = $1; } | type_decl { $$ = $1; };
333int_decl : ident TCOLON TINTEGER
334    { $$ = new IntegerVariableDeclStmtNode(IdentExprNode::Ptr($1), *$3); delete $3;
335      parser.set_loc($$, @$); }
336  ;
337
338type_decl : scoped_ident ident
339    { $$ = new StructVariableDeclStmtNode(IdentExprNode::Ptr($1), IdentExprNode::Ptr($2));
340      parser.set_loc($$, @$); }
341  ;
342
343/* "type" "*" "id" */
344ref_stmt : ptr_decl { $$ = $1; };
345ptr_decl : scoped_ident TMUL ident
346    { $$ = new StructVariableDeclStmtNode(IdentExprNode::Ptr($1), IdentExprNode::Ptr($3),
347                                          VariableDeclStmtNode::STRUCT_REFERENCE);
348      parser.set_loc($$, @$); }
349  ;
350
351/* normal initializer */
352/* init_args
353  : expr { $$ = new ExprNodeList; $$->push_back(ExprNode::Ptr($1)); }
354  | init_args TCOMMA expr { $$->push_back(ExprNode::Ptr($3)); }
355  ;*/
356
357/* one or more of "field" = "expr" */
358init_args_kv
359  : init_arg_kv { $$ = new ExprNodeList; $$->push_back(ExprNode::Ptr($1)); }
360  | init_args_kv TCOMMA init_arg_kv { $$->push_back(ExprNode::Ptr($3)); }
361  ;
362init_arg_kv
363  : TDOT ident TEQUAL expr
364    { $$ = new AssignExprNode(IdentExprNode::Ptr($2), ExprNode::Ptr($4));
365      parser.set_loc($$, @$); }
366  | TDOT ident bitop TEQUAL expr
367    { $$ = new AssignExprNode(IdentExprNode::Ptr($2), ExprNode::Ptr($5)); $$->bitop_ = BitopExprNode::Ptr($3);
368      parser.set_loc($$, @$); }
369  ;
370
371if_stmt
372  : TIF expr enter_varscope block exit_varscope
373    { $$ = new IfStmtNode(ExprNode::Ptr($2), StmtNode::Ptr($4));
374      $4->scope_ = $3;
375      parser.set_loc($$, @$); }
376  | TIF expr enter_varscope block exit_varscope TELSE enter_varscope block exit_varscope
377    { $$ = new IfStmtNode(ExprNode::Ptr($2), StmtNode::Ptr($4), StmtNode::Ptr($8));
378      $4->scope_ = $3; $8->scope_ = $7;
379      parser.set_loc($$, @$); }
380  | TIF expr enter_varscope block exit_varscope TELSE if_stmt
381    { $$ = new IfStmtNode(ExprNode::Ptr($2), StmtNode::Ptr($4), StmtNode::Ptr($7));
382      $4->scope_ = $3;
383      parser.set_loc($$, @$); }
384  ;
385
386onvalid_stmt
387  : TVALID TLPAREN ident TRPAREN enter_varscope block exit_varscope
388    { $$ = new OnValidStmtNode(IdentExprNode::Ptr($3), StmtNode::Ptr($6));
389      $6->scope_ = $5;
390      parser.set_loc($$, @$); }
391  | TVALID TLPAREN ident TRPAREN enter_varscope block exit_varscope TELSE enter_varscope block exit_varscope
392    { $$ = new OnValidStmtNode(IdentExprNode::Ptr($3), StmtNode::Ptr($6), StmtNode::Ptr($10));
393      $6->scope_ = $5; $10->scope_ = $9;
394      parser.set_loc($$, @$); }
395  ;
396
397switch_stmt
398  : TSWITCH expr TLBRACE case_stmts TRBRACE
399    { $$ = new SwitchStmtNode(ExprNode::Ptr($2), make_unique<BlockStmtNode>(move(*$4))); delete $4;
400      parser.set_loc($$, @$); }
401  ;
402
403case_stmts
404  : case_stmt
405    { $$ = new StmtNodeList; $$->push_back(StmtNode::Ptr($1)); }
406  | case_stmts case_stmt
407    { $$->push_back(StmtNode::Ptr($2)); }
408  ;
409
410case_stmt
411  : TCASE numeric block TSEMI
412    { $$ = new CaseStmtNode(IntegerExprNode::Ptr($2), BlockStmtNode::Ptr($3));
413      parser.set_loc($$, @$); }
414  | TCASE TMUL block TSEMI
415    { $$ = new CaseStmtNode(BlockStmtNode::Ptr($3));
416      parser.set_loc($$, @$); }
417  ;
418
419numeric
420  : TINTEGER
421    { $$ = new IntegerExprNode($1);
422      parser.set_loc($$, @$); }
423  | THEXINTEGER
424    { $$ = new IntegerExprNode($1);
425      parser.set_loc($$, @$); }
426  | TINTEGER TCOLON TINTEGER
427    { $$ = new IntegerExprNode($1, $3);
428      parser.set_loc($$, @$); }
429  | THEXINTEGER TCOLON TINTEGER
430    { $$ = new IntegerExprNode($1, $3);
431      parser.set_loc($$, @$); }
432  | TTRUE
433    { $$ = new IntegerExprNode(new string("1"), new string("1"));
434      parser.set_loc($$, @$); }
435  | TFALSE
436    { $$ = new IntegerExprNode(new string("0"), new string("1"));
437      parser.set_loc($$, @$); }
438  ;
439
440assign_expr
441  : expr TEQUAL expr
442    { $$ = new AssignExprNode(ExprNode::Ptr($1), ExprNode::Ptr($3));
443      parser.set_loc($$, @$); }
444  /* The below has a reduce/reduce conflict.
445     TODO: ensure the above is handled in the type check properly */
446  /*| dotted_ident TEQUAL expr
447    { $$ = new AssignExprNode(IdentExprNode::Ptr($1), ExprNode::Ptr($3));
448      parser.set_loc($$, @$); }
449  | dotted_ident bitop TEQUAL expr
450    { $$ = new AssignExprNode(IdentExprNode::Ptr($1), ExprNode::Ptr($4)); $$->bitop_ = BitopExprNode::Ptr($2);
451      parser.set_loc($$, @$); }*/
452  ;
453
454return_expr
455  : TRETURN expr
456    { $$ = new ReturnExprNode(ExprNode::Ptr($2));
457      parser.set_loc($$, @$); }
458  ;
459
460expr
461  : call_expr
462    { $$ = $1; }
463  | call_expr bitop
464    { $$ = $1; $$->bitop_ = BitopExprNode::Ptr($2); }
465  | table_index_expr
466    { $$ = $1; }
467  | table_index_expr TDOT ident
468    { $$ = $1; $1->sub_ = IdentExprNode::Ptr($3); }
469  | any_ident
470    { $$ = $1; }
471  | TAT dotted_ident
472    { $$ = new PacketExprNode(IdentExprNode::Ptr($2));
473      $$->flags_[ExprNode::IS_REF] = true;
474      parser.set_loc($$, @$); }
475  | TDOLLAR dotted_ident
476    { $$ = new PacketExprNode(IdentExprNode::Ptr($2));
477      $$->flags_[ExprNode::IS_PKT] = true;
478      parser.set_loc($$, @$); }
479  | TDOLLAR dotted_ident bitop
480    { $$ = new PacketExprNode(IdentExprNode::Ptr($2)); $$->bitop_ = BitopExprNode::Ptr($3);
481      $$->flags_[ExprNode::IS_PKT] = true;
482      parser.set_loc($$, @$); }
483  | TGOTO scoped_ident
484    { $$ = new GotoExprNode(IdentExprNode::Ptr($2), false);
485      parser.set_loc($$, @$); }
486  | TNEXT scoped_ident
487    { $$ = new GotoExprNode(IdentExprNode::Ptr($2), false);
488      parser.set_loc($$, @$); }
489  | TCONTINUE scoped_ident
490    { $$ = new GotoExprNode(IdentExprNode::Ptr($2), true);
491      parser.set_loc($$, @$); }
492  | TLPAREN expr TRPAREN
493    { $$ = $2; }
494  | TLPAREN expr TRPAREN bitop
495    { $$ = $2; $$->bitop_ = BitopExprNode::Ptr($4); }
496  | TSTRING
497    { $$ = new StringExprNode($1);
498      parser.set_loc($$, @$); }
499  | numeric
500    { $$ = $1; }
501  | numeric bitop
502    { $$ = $1; $$->bitop_ = BitopExprNode::Ptr($2); }
503  | expr TCLT expr
504    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
505      parser.set_loc($$, @$); }
506  | expr TCGT expr
507    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
508      parser.set_loc($$, @$); }
509  | expr TCGE expr
510    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
511      parser.set_loc($$, @$); }
512  | expr TCLE expr
513    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
514      parser.set_loc($$, @$); }
515  | expr TCNE expr
516    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
517      parser.set_loc($$, @$); }
518  | expr TCEQ expr
519    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
520      parser.set_loc($$, @$); }
521  | expr TPLUS expr
522    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
523      parser.set_loc($$, @$); }
524  | expr TMINUS expr
525    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
526      parser.set_loc($$, @$); }
527  | expr TMUL expr
528    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
529      parser.set_loc($$, @$); }
530  | expr TDIV expr
531    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
532      parser.set_loc($$, @$); }
533  | expr TMOD expr
534    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
535      parser.set_loc($$, @$); }
536  | expr TXOR expr
537    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
538      parser.set_loc($$, @$); }
539  | expr TAND expr
540    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
541      parser.set_loc($$, @$); }
542  | expr TOR expr
543    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
544      parser.set_loc($$, @$); }
545  | expr TLAND expr
546    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
547      parser.set_loc($$, @$); }
548  | expr TLOR expr
549    { $$ = new BinopExprNode(ExprNode::Ptr($1), $2, ExprNode::Ptr($3));
550      parser.set_loc($$, @$); }
551  /*| expr bitop
552    { $$ = $1; $$->bitop_ = BitopExprNode::Ptr($2); }*/
553  | TNOT expr
554    { $$ = new UnopExprNode($1, ExprNode::Ptr($2));
555      parser.set_loc($$, @$); }
556  | TCMPL expr
557    { $$ = new UnopExprNode($1, ExprNode::Ptr($2));
558      parser.set_loc($$, @$); }
559  ;
560
561call_args
562  : /* empty */
563    { $$ = new ExprNodeList; }
564  | expr
565    { $$ = new ExprNodeList; $$->push_back(ExprNode::Ptr($1)); }
566  | call_args TCOMMA expr
567    { $$->push_back(ExprNode::Ptr($3)); }
568  ;
569
570bitop
571  : TLBRACK TCOLON TPLUS TINTEGER TRBRACK
572    { $$ = new BitopExprNode(string("0"), *$4); delete $4;
573      parser.set_loc($$, @$); }
574  | TLBRACK TINTEGER TCOLON TPLUS TINTEGER TRBRACK
575    { $$ = new BitopExprNode(*$2, *$5); delete $2; delete $5;
576      parser.set_loc($$, @$); }
577  ;
578
579table_index_expr
580  : dotted_ident TLBRACK ident TRBRACK
581    { $$ = new TableIndexExprNode(IdentExprNode::Ptr($1), IdentExprNode::Ptr($3));
582      parser.set_loc($$, @$); }
583  ;
584
585scoped_ident
586  : ident
587    { $$ = $1; }
588  | scoped_ident TSCOPE TIDENTIFIER
589    { $$->append_scope(*$3); delete $3; }
590  ;
591
592dotted_ident
593  : ident
594    { $$ = $1; }
595  | dotted_ident TDOT TIDENTIFIER
596    { $$->append_dot(*$3); delete $3; }
597  ;
598
599any_ident
600  : ident
601    { $$ = $1; }
602  | dotted_ident TARROW TIDENTIFIER
603    { $$->append_dot(*$3); delete $3; }
604  | dotted_ident TDOT TIDENTIFIER
605    { $$->append_dot(*$3); delete $3; }
606  | scoped_ident TSCOPE TIDENTIFIER
607    { $$->append_scope(*$3); delete $3; }
608  ;
609
610ident
611  : TIDENTIFIER
612    { $$ = new IdentExprNode(*$1); delete $1;
613      parser.set_loc($$, @$); }
614  ;
615
616%%
617
618void ebpf::cc::BisonParser::error(const ebpf::cc::BisonParser::location_type &loc,
619                            const string& msg) {
620    std::cerr << "Error: " << loc << " " << msg << std::endl;
621}
622
623#include "lexer.h"
624static int yylex(ebpf::cc::BisonParser::semantic_type *yylval,
625                 ebpf::cc::BisonParser::location_type *yylloc,
626                 ebpf::cc::Lexer &lexer) {
627    return lexer.yylex(yylval, yylloc);
628}
629
630