summaryrefslogtreecommitdiff
path: root/cmake/elfinfo/GnuLd.g4
diff options
context:
space:
mode:
Diffstat (limited to 'cmake/elfinfo/GnuLd.g4')
-rw-r--r--cmake/elfinfo/GnuLd.g41500
1 files changed, 1500 insertions, 0 deletions
diff --git a/cmake/elfinfo/GnuLd.g4 b/cmake/elfinfo/GnuLd.g4
new file mode 100644
index 0000000..da7b01f
--- /dev/null
+++ b/cmake/elfinfo/GnuLd.g4
@@ -0,0 +1,1500 @@
+grammar GnuLd;
+
+/*
+TODO: check right associative annotations
+*/
+
+/*
+%token <bigint> INT
+%token <name> NAME LNAME
+*/
+
+/*
+%right UNARY
+%token END
+%left <token> '('
+*/
+
+
+file:
+ /*INPUT_SCRIPT*/ script_file
+ | /*INPUT_MRI_SCRIPT*/ mri_script_file
+ | /*INPUT_VERSION_SCRIPT*/ version_script_file
+ | /*INPUT_DYNAMIC_LIST*/ dynamic_list_file
+ | /*INPUT_DEFSYM*/ defsym_expr
+ ;
+
+filename: NAME;
+
+
+defsym_expr:
+// { ldlex_defsym(); }
+ NAME '=' exp
+// {
+// ldlex_popstate();
+// lang_add_assignment (exp_defsym ($2, $4));
+// }
+ ;
+
+/* SYNTAX WITHIN AN MRI SCRIPT FILE */
+mri_script_file:
+// {
+// ldlex_mri_script ();
+// PUSH_ERROR (_("MRI style script"));
+// }
+ mri_script_lines
+// {
+// ldlex_popstate ();
+// mri_draw_tree ();
+// POP_ERROR ();
+// }
+ ;
+
+mri_script_lines:
+ mri_script_lines mri_script_command NEWLINE
+ |
+ ;
+
+mri_script_command:
+ CHIP exp
+ | CHIP exp ',' exp
+ | NAME /*{
+ einfo(_("%P%F: unrecognised keyword in MRI style script '%s'\n"),$1);
+ }*/
+ | LIST /*{
+ config.map_filename = "-";
+ }*/
+ | ORDER ordernamelist
+ | ENDWORD
+ | PUBLIC NAME '=' exp
+ // { mri_public($2, $4); }
+ | PUBLIC NAME ',' exp
+ // { mri_public($2, $4); }
+ | PUBLIC NAME exp
+ // { mri_public($2, $3); }
+ | FORMAT NAME
+ // { mri_format($2); }
+ | SECT NAME ',' exp
+ // { mri_output_section($2, $4);}
+ | SECT NAME exp
+ // { mri_output_section($2, $3);}
+ | SECT NAME '=' exp
+ // { mri_output_section($2, $4);}
+ | ALIGN_K NAME '=' exp
+ // { mri_align($2,$4); }
+ | ALIGN_K NAME ',' exp
+ // { mri_align($2,$4); }
+ | ALIGNMOD NAME '=' exp
+ // { mri_alignmod($2,$4); }
+ | ALIGNMOD NAME ',' exp
+ // { mri_alignmod($2,$4); }
+ | ABSOLUTE mri_abs_name_list
+ | LOAD mri_load_name_list
+ | NAMEWORD NAME
+ // { mri_name($2); }
+ | ALIAS NAME ',' NAME
+ // { mri_alias($2,$4,0);}
+ | ALIAS NAME ',' INT
+ // { mri_alias ($2, 0, (int) $4.integer); }
+ | BASE exp
+ // { mri_base($2); }
+ | TRUNCATE INT
+ // { mri_truncate ((unsigned int) $2.integer); }
+ | CASE casesymlist
+ | EXTERN extern_name_list
+ | INCLUDE filename
+ // { ldlex_script (); ldfile_open_command_file($2); }
+ mri_script_lines END
+ // { ldlex_popstate (); }
+ | START NAME
+ // { lang_add_entry ($2, FALSE); }
+ |
+ ;
+
+ordernamelist:
+ ordernamelist ',' NAME // { mri_order($3); }
+ | ordernamelist NAME // { mri_order($2); }
+ |
+ ;
+
+mri_load_name_list:
+ NAME
+ // { mri_load($1); }
+ | mri_load_name_list ',' NAME // { mri_load($3); }
+ ;
+
+mri_abs_name_list:
+ NAME
+ // { mri_only_load($1); }
+ | mri_abs_name_list ',' NAME
+ // { mri_only_load($3); }
+ ;
+
+casesymlist:
+ /* empty */ // { $$ = NULL; }
+ | NAME
+ | casesymlist ',' NAME
+ ;
+
+/* Parsed as expressions so that commas separate entries */
+extern_name_list:
+ // { ldlex_expression (); }
+ extern_name_list_body
+ // { ldlex_popstate (); }
+ ;
+
+extern_name_list_body:
+ NAME
+ // { ldlang_add_undef ($1, FALSE); }
+ | extern_name_list_body NAME
+ // { ldlang_add_undef ($2, FALSE); }
+ | extern_name_list_body ',' NAME
+ // { ldlang_add_undef ($3, FALSE); }
+ ;
+
+script_file:
+ // { ldlex_both(); }
+ ifile_list
+ // { ldlex_popstate(); }
+ ;
+
+ifile_list:
+ ifile_list ifile_p1
+ |
+ ;
+
+
+ifile_p1:
+ memory
+ | sections
+ | phdrs
+ | startup
+ | high_level_library
+ | low_level_library
+ | floating_point_support
+ | statement_anywhere
+ | version
+ | ';'
+ | TARGET_K '(' NAME ')'
+ // { lang_add_target($3); }
+ | SEARCH_DIR '(' filename ')'
+ // { ldfile_add_library_path ($3, FALSE); }
+ | OUTPUT '(' filename ')'
+ // { lang_add_output($3, 1); }
+ | OUTPUT_FORMAT '(' NAME ')'
+ // { lang_add_output_format ($3, (char *) NULL,
+ // (char *) NULL, 1); }
+ | OUTPUT_FORMAT '(' NAME ',' NAME ',' NAME ')'
+ // { lang_add_output_format ($3, $5, $7, 1); }
+ | OUTPUT_ARCH '(' NAME ')'
+ // { ldfile_set_output_arch ($3, bfd_arch_unknown); }
+ | FORCE_COMMON_ALLOCATION
+ // { command_line.force_common_definition = TRUE ; }
+ | INHIBIT_COMMON_ALLOCATION
+ // { command_line.inhibit_common_definition = TRUE ; }
+ | INPUT '(' input_list ')'
+ | GROUP
+ // { lang_enter_group (); }
+ '(' input_list ')'
+ // { lang_leave_group (); }
+ | MAP '(' filename ')'
+ // { lang_add_map($3); }
+ | INCLUDE filename
+ // { ldlex_script (); ldfile_open_command_file($2); }
+ ifile_list END
+ // { ldlex_popstate (); }
+ | NOCROSSREFS '(' nocrossref_list ')'
+ // {
+ // lang_add_nocrossref ($3);
+ // }
+ | NOCROSSREFS_TO '(' nocrossref_list ')'
+ // {
+ // lang_add_nocrossref_to ($3);
+ // }
+ | EXTERN '(' extern_name_list ')'
+ | INSERT_K AFTER NAME
+ // { lang_add_insert ($3, 0); }
+ | INSERT_K BEFORE NAME
+ // { lang_add_insert ($3, 1); }
+ | REGION_ALIAS '(' NAME ',' NAME ')'
+ // { lang_memory_region_alias ($3, $5); }
+ | LD_FEATURE '(' NAME ')'
+ // { lang_ld_feature ($3); }
+ ;
+
+input_list:
+ // { ldlex_inputlist(); }
+ input_list1
+ // { ldlex_popstate(); }
+ ;
+
+input_list1:
+ NAME
+ // { lang_add_input_file($1,lang_input_file_is_search_file_enum,
+ // (char *)NULL); }
+ | input_list1 ',' NAME
+ // { lang_add_input_file($3,lang_input_file_is_search_file_enum,
+ // (char *)NULL); }
+ | input_list1 NAME
+ // { lang_add_input_file($2,lang_input_file_is_search_file_enum,
+ // (char *)NULL); }
+ | LNAME
+ // { lang_add_input_file($1,lang_input_file_is_l_enum,
+ // (char *)NULL); }
+ | input_list1 ',' LNAME
+ // { lang_add_input_file($3,lang_input_file_is_l_enum,
+ // (char *)NULL); }
+ | input_list1 LNAME
+ // { lang_add_input_file($2,lang_input_file_is_l_enum,
+ // (char *)NULL); }
+ | AS_NEEDED '('
+ // { $<integer>$ = input_flags.add_DT_NEEDED_for_regular;
+ // input_flags.add_DT_NEEDED_for_regular = TRUE; }
+ // input_list1 ')'
+ // { input_flags.add_DT_NEEDED_for_regular = $<integer>3; }
+ | input_list1 ',' AS_NEEDED '('
+ // { $<integer>$ = input_flags.add_DT_NEEDED_for_regular;
+ // input_flags.add_DT_NEEDED_for_regular = TRUE; }
+ // input_list1 ')'
+ // { input_flags.add_DT_NEEDED_for_regular = $<integer>5; }
+ | input_list1 AS_NEEDED '('
+ // { $<integer>$ = input_flags.add_DT_NEEDED_for_regular;
+ // input_flags.add_DT_NEEDED_for_regular = TRUE; }
+ // input_list1 ')'
+ // { input_flags.add_DT_NEEDED_for_regular = $<integer>4; }
+ ;
+
+sections:
+ SECTIONS '{' sec_or_group_p1 '}'
+ ;
+
+sec_or_group_p1:
+ sec_or_group_p1 section
+ | sec_or_group_p1 statement_anywhere
+ |
+ ;
+
+statement_anywhere:
+ ENTRY '(' NAME ')'
+ // { lang_add_entry ($3, FALSE); }
+ | assignment end
+ | ASSERT_K /*{ldlex_expression ();}*/ '(' exp ',' NAME ')'
+ // { ldlex_popstate ();
+ // lang_add_assignment (exp_assert ($4, $6)); }
+ ;
+
+/* The '*' and '?' cases are there because the lexer returns them as
+ separate tokens rather than as NAME. */
+wildcard_name:
+ NAME
+ // {
+ // $$ = $1;
+ // }
+ | '*'
+ // {
+ // $$ = "*";
+ // }
+ | '?'
+ // {
+ // $$ = "?";
+ // }
+ ;
+
+wildcard_spec:
+ wildcard_name
+// {
+// $$.name = $1;
+// $$.sorted = none;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name
+// {
+// $$.name = $5;
+// $$.sorted = none;
+// $$.exclude_name_list = $3;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_NAME '(' wildcard_name ')'
+// {
+// $$.name = $3;
+// $$.sorted = by_name;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_ALIGNMENT '(' wildcard_name ')'
+// {
+// $$.name = $3;
+// $$.sorted = by_alignment;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_NONE '(' wildcard_name ')'
+// {
+// $$.name = $3;
+// $$.sorted = by_none;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_NAME '(' SORT_BY_ALIGNMENT '(' wildcard_name ')' ')'
+// {
+// $$.name = $5;
+// $$.sorted = by_name_alignment;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_NAME '(' SORT_BY_NAME '(' wildcard_name ')' ')'
+// {
+// $$.name = $5;
+// $$.sorted = by_name;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_ALIGNMENT '(' SORT_BY_NAME '(' wildcard_name ')' ')'
+// {
+// $$.name = $5;
+// $$.sorted = by_alignment_name;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_ALIGNMENT '(' SORT_BY_ALIGNMENT '(' wildcard_name ')' ')'
+// {
+// $$.name = $5;
+// $$.sorted = by_alignment;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_NAME '(' EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name ')'
+// {
+// $$.name = $7;
+// $$.sorted = by_name;
+// $$.exclude_name_list = $5;
+// $$.section_flag_list = NULL;
+// }
+ | SORT_BY_INIT_PRIORITY '(' wildcard_name ')'
+// {
+// $$.name = $3;
+// $$.sorted = by_init_priority;
+// $$.exclude_name_list = NULL;
+// $$.section_flag_list = NULL;
+// }
+ ;
+
+sect_flag_list: NAME
+// {
+// struct flag_info_list *n;
+// n = ((struct flag_info_list *) xmalloc (sizeof *n));
+// if ($1[0] == '!')
+// {
+// n->with = without_flags;
+// n->name = &$1[1];
+// }
+// else
+// {
+// n->with = with_flags;
+// n->name = $1;
+// }
+// n->valid = FALSE;
+// n->next = NULL;
+// $$ = n;
+// }
+ | sect_flag_list '&' NAME
+// {
+// struct flag_info_list *n;
+// n = ((struct flag_info_list *) xmalloc (sizeof *n));
+// if ($3[0] == '!')
+// {
+// n->with = without_flags;
+// n->name = &$3[1];
+// }
+// else
+// {
+// n->with = with_flags;
+// n->name = $3;
+// }
+// n->valid = FALSE;
+// n->next = $1;
+// $$ = n;
+// }
+ ;
+
+sect_flags:
+ /*not used by antlr: INPUT_SECTION_FLAGS*/ '(' sect_flag_list ')'
+// {
+// struct flag_info *n;
+// n = ((struct flag_info *) xmalloc (sizeof *n));
+// n->flag_list = $3;
+// n->flags_initialized = FALSE;
+// n->not_with_flags = 0;
+// n->only_with_flags = 0;
+// $$ = n;
+// }
+ ;
+
+exclude_name_list:
+ exclude_name_list wildcard_name
+// {
+// struct name_list *tmp;
+// tmp = (struct name_list *) xmalloc (sizeof *tmp);
+// tmp->name = $2;
+// tmp->next = $1;
+// $$ = tmp;
+// }
+ |
+ wildcard_name
+// {
+// struct name_list *tmp;
+// tmp = (struct name_list *) xmalloc (sizeof *tmp);
+// tmp->name = $1;
+// tmp->next = NULL;
+// $$ = tmp;
+// }
+ ;
+
+file_NAME_list:
+ file_NAME_list opt_comma wildcard_spec
+// {
+// struct wildcard_list *tmp;
+// tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
+// tmp->next = $1;
+// tmp->spec = $3;
+// $$ = tmp;
+// }
+ |
+ wildcard_spec
+// {
+// struct wildcard_list *tmp;
+// tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
+// tmp->next = NULL;
+// tmp->spec = $1;
+// $$ = tmp;
+// }
+ ;
+
+input_section_spec_no_keep:
+ NAME
+// {
+// struct wildcard_spec tmp;
+// tmp.name = $1;
+// tmp.exclude_name_list = NULL;
+// tmp.sorted = none;
+// tmp.section_flag_list = NULL;
+// lang_add_wild (&tmp, NULL, ldgram_had_keep);
+// }
+ | sect_flags NAME
+// {
+// struct wildcard_spec tmp;
+// tmp.name = $2;
+// tmp.exclude_name_list = NULL;
+// tmp.sorted = none;
+// tmp.section_flag_list = $1;
+// lang_add_wild (&tmp, NULL, ldgram_had_keep);
+// }
+ | '[' file_NAME_list ']'
+// {
+// lang_add_wild (NULL, $2, ldgram_had_keep);
+// }
+ | sect_flags '[' file_NAME_list ']'
+// {
+// struct wildcard_spec tmp;
+// tmp.name = NULL;
+// tmp.exclude_name_list = NULL;
+// tmp.sorted = none;
+// tmp.section_flag_list = $1;
+// lang_add_wild (&tmp, $3, ldgram_had_keep);
+// }
+ | wildcard_spec '(' file_NAME_list ')'
+// {
+// lang_add_wild (&$1, $3, ldgram_had_keep);
+// }
+ | sect_flags wildcard_spec '(' file_NAME_list ')'
+// {
+// $2.section_flag_list = $1;
+// lang_add_wild (&$2, $4, ldgram_had_keep);
+// }
+ ;
+
+input_section_spec:
+ input_section_spec_no_keep
+ | KEEP '('
+// { ldgram_had_keep = TRUE; }
+ input_section_spec_no_keep ')'
+// { ldgram_had_keep = FALSE; }
+ ;
+
+statement:
+ assignment end
+ | CREATE_OBJECT_SYMBOLS
+// {
+// lang_add_attribute(lang_object_symbols_statement_enum);
+// }
+ | ';'
+ | CONSTRUCTORS
+// {
+//
+// lang_add_attribute(lang_constructors_statement_enum);
+// }
+ | SORT_BY_NAME '(' CONSTRUCTORS ')'
+// {
+// constructors_sorted = TRUE;
+// lang_add_attribute (lang_constructors_statement_enum);
+// }
+ | input_section_spec
+ | length '(' mustbe_exp ')'
+// {
+// lang_add_data ((int) $1, $3);
+// }
+
+ | FILL '(' fill_exp ')'
+// {
+// lang_add_fill ($3);
+// }
+ | ASSERT_K /*{ldlex_expression ();}*/ '(' exp ',' NAME ')' end
+// { ldlex_popstate ();
+// lang_add_assignment (exp_assert ($4, $6)); }
+ | INCLUDE filename
+// { ldlex_script (); ldfile_open_command_file($2); }
+ statement_list_opt END
+// { ldlex_popstate (); }
+ ;
+
+statement_list:
+ statement_list statement
+ | statement
+ ;
+
+statement_list_opt:
+ /* empty */
+ | statement_list
+ ;
+
+length:
+ QUAD
+// { $$ = $1; }
+ | SQUAD
+// { $$ = $1; }
+ | LONG
+// { $$ = $1; }
+ | SHORT
+// { $$ = $1; }
+ | BYTE
+// { $$ = $1; }
+ ;
+
+fill_exp:
+ mustbe_exp
+// {
+// $$ = exp_get_fill ($1, 0, "fill value");
+// }
+ ;
+
+fill_opt:
+ '=' fill_exp
+ // { $$ = $2; }
+ | // { $$ = (fill_type *) 0; }
+ ;
+
+assign_op:
+ PLUSEQ
+// { $$ = '+'; }
+ | MINUSEQ
+// { $$ = '-'; }
+ | MULTEQ
+// { $$ = '*'; }
+ | DIVEQ
+// { $$ = '/'; }
+ | LSHIFTEQ
+// { $$ = LSHIFT; }
+ | RSHIFTEQ
+// { $$ = RSHIFT; }
+ | ANDEQ
+// { $$ = '&'; }
+ | OREQ
+// { $$ = '|'; }
+
+ ;
+
+end: ';' | ','
+ ;
+
+
+assignment:
+ NAME '=' mustbe_exp
+// {
+// lang_add_assignment (exp_assign ($1, $3, FALSE));
+// }
+ | NAME assign_op mustbe_exp
+// {
+// lang_add_assignment (exp_assign ($1,
+// exp_binop ($2,
+// exp_nameop (NAME,
+// $1),
+// $3), FALSE));
+// }
+ | HIDDEN_ '(' NAME '=' mustbe_exp ')'
+// {
+// lang_add_assignment (exp_assign ($3, $5, TRUE));
+// }
+ | PROVIDE '(' NAME '=' mustbe_exp ')'
+// {
+// lang_add_assignment (exp_provide ($3, $5, FALSE));
+// }
+ | PROVIDE_HIDDEN '(' NAME '=' mustbe_exp ')'
+// {
+// lang_add_assignment (exp_provide ($3, $5, TRUE));
+// }
+ ;
+
+
+opt_comma:
+ ',' | ;
+
+
+memory:
+ MEMORY '{' memory_spec_list_opt '}'
+ ;
+
+memory_spec_list_opt: memory_spec_list | ;
+
+memory_spec_list:
+ memory_spec_list opt_comma memory_spec
+ | memory_spec
+ ;
+
+
+memory_spec: NAME
+// { region = lang_memory_region_lookup ($1, TRUE); }
+ attributes_opt ':'
+ origin_spec opt_comma length_spec
+// {}
+ | INCLUDE filename
+// { ldlex_script (); ldfile_open_command_file($2); }
+ memory_spec_list_opt END
+// { ldlex_popstate (); }
+ ;
+
+origin_spec:
+ ORIGIN '=' mustbe_exp
+// {
+// region->origin_exp = $3;
+// region->current = region->origin;
+// }
+ ;
+
+length_spec:
+ LENGTH '=' mustbe_exp
+// {
+// region->length_exp = $3;
+// }
+ ;
+
+attributes_opt:
+ /* empty */
+ /* { *//* dummy action to avoid bison 1.25 error message *//* }
+ |*/ '(' attributes_list ')'
+ ;
+
+attributes_list:
+ attributes_string
+ | attributes_list attributes_string
+ ;
+
+attributes_string:
+ NAME # attributeNormal
+// { lang_set_flags (region, $1, 0); }
+ | '!' NAME # attributeInverted
+// { lang_set_flags (region, $2, 1); }
+ ;
+
+/*
+This would be best but the tokenizer would have to be made context sensitive which is too much work given how
+easy it is to check the flags after parsing.
+
+attributes_string :
+ attribute
+ | '!' attribute # attributeInverted
+ ;
+
+attribute: 'r' | 'w' | 'x' | 'a' | 'i' | 'l' ;
+*/
+startup:
+ STARTUP '(' filename ')'
+// { lang_startup($3); }
+ ;
+
+high_level_library:
+ HLL '(' high_level_library_NAME_list ')'
+ | HLL '(' ')'
+// { ldemul_hll((char *)NULL); }
+ ;
+
+high_level_library_NAME_list:
+ high_level_library_NAME_list opt_comma filename
+// { ldemul_hll($3); }
+ | filename
+// { ldemul_hll($1); }
+
+ ;
+
+low_level_library:
+ SYSLIB '(' low_level_library_NAME_list ')'
+ ; low_level_library_NAME_list:
+ low_level_library_NAME_list opt_comma filename
+// { ldemul_syslib($3); }
+ |
+ ;
+
+floating_point_support:
+ FLOAT
+// { lang_float(TRUE); }
+ | NOFLOAT
+// { lang_float(FALSE); }
+ ;
+
+nocrossref_list:
+ /* empty */
+// {
+// $$ = NULL;
+// }
+ | NAME nocrossref_list
+// {
+// struct lang_nocrossref *n;
+//
+// n = (struct lang_nocrossref *) xmalloc (sizeof *n);
+// n->name = $1;
+// n->next = $2;
+// $$ = n;
+// }
+ | NAME ',' nocrossref_list
+// {
+// struct lang_nocrossref *n;
+//
+// n = (struct lang_nocrossref *) xmalloc (sizeof *n);
+// n->name = $1;
+// n->next = $3;
+// $$ = n;
+// }
+ ;
+
+mustbe_exp: // { ldlex_expression (); }
+ exp
+ // { ldlex_popstate (); $$=$2;}
+ ;
+
+exp :
+ '-' exp # expNegate // TODO: %prec UNARY
+// { $$ = exp_unop ('-', $2); }
+ | '(' exp ')' # expParen
+// { $$ = $2; }
+ | NEXT '(' exp ')' # expNextParen // TODO: %prec UNARY
+// { $$ = exp_unop ((int) $1,$3); }
+ | '!' exp # expInvert // TODO: %prec UNARY
+// { $$ = exp_unop ('!', $2); }
+ | '+' exp # expPlus // TODO: %prec UNARY
+// { $$ = $2; }
+ | '~' exp # expMinus // TODO: %prec UNARY
+// { $$ = exp_unop ('~', $2);}
+ | exp '*' exp # expMul
+// { $$ = exp_binop ('*', $1, $3); }
+ | exp '/' exp # expDiv
+// { $$ = exp_binop ('/', $1, $3); }
+ | exp '%' exp # expMod
+// { $$ = exp_binop ('%', $1, $3); }
+ | exp '+' exp # expAdd
+// { $$ = exp_binop ('+', $1, $3); }
+ | exp '-' exp # expSub
+// { $$ = exp_binop ('-' , $1, $3); }
+ | exp LSHIFT exp # expLshift
+// { $$ = exp_binop (LSHIFT , $1, $3); }
+ | exp RSHIFT exp # expRshift
+// { $$ = exp_binop (RSHIFT , $1, $3); }
+ | exp EQ exp # expEq
+// { $$ = exp_binop (EQ , $1, $3); }
+ | exp NE exp # expNe
+// { $$ = exp_binop (NE , $1, $3); }
+ | exp LE exp # expLe
+// { $$ = exp_binop (LE , $1, $3); }
+ | exp GE exp # expGe
+// { $$ = exp_binop (GE , $1, $3); }
+ | exp '<' exp # expGt
+// { $$ = exp_binop ('<' , $1, $3); }
+ | exp '>' exp # expLt
+// { $$ = exp_binop ('>' , $1, $3); }
+ | exp '&' exp # expAnd
+// { $$ = exp_binop ('&' , $1, $3); }
+ | exp '^' exp # expXor
+// { $$ = exp_binop ('^' , $1, $3); }
+ | exp '|' exp # expOr
+// { $$ = exp_binop ('|' , $1, $3); }
+ | exp '?' exp ':' exp # expTrinary
+// { $$ = exp_trinop ('?' , $1, $3, $5); }
+ | exp ANDAND exp # expAndand
+// { $$ = exp_binop (ANDAND , $1, $3); }
+ | exp OROR exp # expOror
+// { $$ = exp_binop (OROR , $1, $3); }
+ | DEFINED '(' NAME ')' # expDefined
+// { $$ = exp_nameop (DEFINED, $3); }
+ | INT # expInt
+// { $$ = exp_bigintop ($1.integer, $1.str); }
+ | SIZEOF_HEADERS # expSizeofHeaders
+// { $$ = exp_nameop (SIZEOF_HEADERS,0); }
+ | ALIGNOF '(' NAME ')' # expAlignof
+// { $$ = exp_nameop (ALIGNOF,$3); }
+ | SIZEOF '(' NAME ')' # expSizeof
+// { $$ = exp_nameop (SIZEOF,$3); }
+ | ADDR '(' NAME ')' # expAddr
+// { $$ = exp_nameop (ADDR,$3); }
+ | LOADADDR '(' NAME ')' # expLoadaddr
+// { $$ = exp_nameop (LOADADDR,$3); }
+ | CONSTANT '(' NAME ')' # expConstant
+// { $$ = exp_nameop (CONSTANT,$3); }
+ | ABSOLUTE '(' exp ')' # expAbsolute
+// { $$ = exp_unop (ABSOLUTE, $3); }
+ | ALIGN_K '(' exp ')' # expAlign
+// { $$ = exp_unop (ALIGN_K,$3); }
+ | ALIGN_K '(' exp ',' exp ')' # expAlign2
+// { $$ = exp_binop (ALIGN_K,$3,$5); }
+ | DATA_SEGMENT_ALIGN '(' exp ',' exp ')' # expDataSegmentAlign
+// { $$ = exp_binop (DATA_SEGMENT_ALIGN, $3, $5); }
+ | DATA_SEGMENT_RELRO_END '(' exp ',' exp ')' # expDataSegmentRelRoEnd
+// { $$ = exp_binop (DATA_SEGMENT_RELRO_END, $5, $3);
+ | DATA_SEGMENT_END '(' exp ')' # expDataSegmentEnd
+// { $$ = exp_unop (DATA_SEGMENT_END, $3); }
+ | SEGMENT_START '(' NAME ',' exp ')' # expSegmentStart
+// { /* The operands to the expression node are
+// placed in the opposite order from the way
+// in which they appear in the script as
+// that allows us to reuse more code in
+// fold_binary. */
+// $$ = exp_binop (SEGMENT_START,
+// $5,
+// exp_nameop (NAME, $3)); }
+ | BLOCK '(' exp ')' # expBlock
+// { $$ = exp_unop (ALIGN_K,$3); }
+ | NAME # expName
+// { $$ = exp_nameop (NAME,$1); }
+ | MAX_K '(' exp ',' exp ')' # expMax
+// { $$ = exp_binop (MAX_K, $3, $5 ); }
+ | MIN_K '(' exp ',' exp ')' # expMin
+// { $$ = exp_binop (MIN_K, $3, $5 ); }
+ | ASSERT_K '(' exp ',' NAME ')' # expAssert
+// { $$ = exp_assert ($3, $5); }
+ | ORIGIN '(' NAME ')' # expOrigin
+// { $$ = exp_nameop (ORIGIN, $3); }
+ | LENGTH '(' NAME ')' # expLengthExp
+// { $$ = exp_nameop (LENGTH, $3); }
+ | LOG2CEIL '(' exp ')' # expLog2ceil
+// { $$ = exp_unop (LOG2CEIL, $3); }
+ ;
+
+
+memspec_at_opt:
+ AT '>' NAME // { $$ = $3; }
+ | // { $$ = 0; }
+ ;
+
+opt_at:
+ AT '(' exp ')' // { $$ = $3; }
+ | // { $$ = 0; }
+ ;
+
+opt_align:
+ ALIGN_K '(' exp ')' // { $$ = $3; }
+ | // { $$ = 0; }
+ ;
+
+opt_align_with_input:
+ ALIGN_WITH_INPUT // { $$ = ALIGN_WITH_INPUT; }
+ | // { $$ = 0; }
+ ;
+
+opt_subalign:
+ SUBALIGN '(' exp ')' // { $$ = $3; }
+ | // { $$ = 0; }
+ ;
+
+sect_constraint:
+ ONLY_IF_RO // { $$ = ONLY_IF_RO; }
+ | ONLY_IF_RW // { $$ = ONLY_IF_RW; }
+ | SPECIAL // { $$ = SPECIAL; }
+ | // { $$ = 0; }
+ ;
+
+section: NAME // { ldlex_expression(); }
+ opt_exp_with_type
+ opt_at
+ opt_align
+ opt_align_with_input
+ opt_subalign // { ldlex_popstate (); ldlex_script (); }
+ sect_constraint
+ '{'
+// {
+// lang_enter_output_section_statement($1, $3,
+// sectype,
+// $5, $7, $4, $9, $6);
+// }
+ statement_list_opt
+ '}' // { ldlex_popstate (); ldlex_expression (); }
+ memspec_opt memspec_at_opt phdr_opt fill_opt
+// {
+// ldlex_popstate ();
+// lang_leave_output_section_statement ($18, $15, $17, $16);
+// }
+ opt_comma
+ {}
+ | OVERLAY
+// { ldlex_expression (); }
+ opt_exp_without_type opt_nocrossrefs opt_at opt_subalign
+// { ldlex_popstate (); ldlex_script (); }
+ '{'
+// {
+// lang_enter_overlay ($3, $6);
+// }
+ overlay_section
+ '}'
+// { ldlex_popstate (); ldlex_expression (); }
+ memspec_opt memspec_at_opt phdr_opt fill_opt
+// {
+// ldlex_popstate ();
+// lang_leave_overlay ($5, (int) $4,
+// $16, $13, $15, $14);
+// }
+ opt_comma
+ | /* The GROUP case is just enough to support the gcc
+ svr3.ifile script. It is not intended to be full
+ support. I'm not even sure what GROUP is supposed
+ to mean. */
+ GROUP // { ldlex_expression (); }
+ opt_exp_with_type
+// {
+// ldlex_popstate ();
+// lang_add_assignment (exp_assign (".", $3, FALSE));
+// }
+ '{' sec_or_group_p1 '}'
+ | INCLUDE filename
+ // { ldlex_script (); ldfile_open_command_file($2); }
+ sec_or_group_p1 END
+ // { ldlex_popstate (); }
+ ;
+
+type:
+ NOLOAD // { sectype = noload_section; }
+ | DSECT // { sectype = noalloc_section; }
+ | COPY // { sectype = noalloc_section; }
+ | INFO // { sectype = noalloc_section; }
+ | OVERLAY // { sectype = noalloc_section; }
+ ;
+
+atype:
+ '(' type ')'
+ | /* EMPTY */ // { sectype = normal_section; }
+ | '(' ')' // { sectype = normal_section; }
+ ;
+
+opt_exp_with_type:
+ exp atype ':' // { $$ = $1; }
+ | atype ':' // { $$ = (etree_type *)NULL; }
+ | /* The BIND cases are to support the gcc svr3.ifile
+ script. They aren't intended to implement full
+ support for the BIND keyword. I'm not even sure
+ what BIND is supposed to mean. */
+ BIND '(' exp ')' atype ':' // { $$ = $3; }
+ | BIND '(' exp ')' BLOCK '(' exp ')' atype ':'
+ // { $$ = $3; }
+ ;
+
+opt_exp_without_type:
+ exp ':' // { $$ = $1; }
+ | ':' // { $$ = (etree_type *) NULL; }
+ ;
+
+opt_nocrossrefs:
+ /* empty */
+// { $$ = 0; }
+ | NOCROSSREFS
+// { $$ = 1; }
+ ;
+
+memspec_opt:
+ '>' NAME
+ // { $$ = $2; }
+ | // { $$ = DEFAULT_MEMORY_REGION; }
+ ;
+
+phdr_opt:
+ /* empty */
+// {
+// $$ = NULL;
+// }
+ | phdr_opt ':' NAME
+// {
+// struct lang_output_section_phdr_list *n;
+//
+// n = ((struct lang_output_section_phdr_list *)
+// xmalloc (sizeof *n));
+// n->name = $3;
+// n->used = FALSE;
+// n->next = $1;
+// $$ = n;
+// }
+ ;
+
+overlay_section:
+ /* empty */
+ | overlay_section
+ NAME
+// {
+// ldlex_script ();
+// lang_enter_overlay_section ($2);
+// }
+ '{' statement_list_opt '}'
+// { ldlex_popstate (); ldlex_expression (); }
+ phdr_opt fill_opt
+// {
+// ldlex_popstate ();
+// lang_leave_overlay_section ($9, $8);
+// }
+ opt_comma
+ ;
+
+phdrs:
+ PHDRS '{' phdr_list '}'
+ ;
+
+phdr_list:
+ /* empty */
+ | phdr_list phdr
+ ;
+
+phdr:
+ NAME // { ldlex_expression (); }
+ phdr_type phdr_qualifiers // { ldlex_popstate (); }
+ ';'
+// {
+// lang_new_phdr ($1, $3, $4.filehdr, $4.phdrs, $4.at,
+// $4.flags);
+// }
+ ;
+
+phdr_type:
+ exp
+// {
+// $$ = $1;
+//
+// if ($1->type.node_class == etree_name
+// && $1->type.node_code == NAME)
+// {
+// const char *s;
+// unsigned int i;
+// static const char * const phdr_types[] =
+// {
+// "PT_NULL", "PT_LOAD", "PT_DYNAMIC",
+// "PT_INTERP", "PT_NOTE", "PT_SHLIB",
+// "PT_PHDR", "PT_TLS"
+// };
+//
+// s = $1->name.name;
+// for (i = 0;
+// i < sizeof phdr_types / sizeof phdr_types[0];
+// i++)
+// if (strcmp (s, phdr_types[i]) == 0)
+// {
+// $$ = exp_intop (i);
+// break;
+// }
+// if (i == sizeof phdr_types / sizeof phdr_types[0])
+// {
+// if (strcmp (s, "PT_GNU_EH_FRAME") == 0)
+// $$ = exp_intop (0x6474e550);
+// else if (strcmp (s, "PT_GNU_STACK") == 0)
+// $$ = exp_intop (0x6474e551);
+// else
+// {
+// einfo (_("\
+//%X%P:%S: unknown phdr type `%s' (try integer literal)\n"),
+// NULL, s);
+// $$ = exp_intop (0);
+// }
+// }
+// }
+// }
+ ;
+
+phdr_qualifiers:
+ /* empty */
+// {
+// memset (&$$, 0, sizeof (struct phdr_info));
+// }
+ | NAME phdr_val phdr_qualifiers
+// {
+// $$ = $3;
+// if (strcmp ($1, "FILEHDR") == 0 && $2 == NULL)
+// $$.filehdr = TRUE;
+// else if (strcmp ($1, "PHDRS") == 0 && $2 == NULL)
+// $$.phdrs = TRUE;
+// else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL)
+// $$.flags = $2;
+// else
+// einfo (_("%X%P:%S: PHDRS syntax error at `%s'\n"),
+// NULL, $1);
+// }
+ | AT '(' exp ')' phdr_qualifiers
+// {
+// $$ = $5;
+// $$.at = $3;
+// }
+ ;
+
+phdr_val:
+ /* empty */
+// {
+// $$ = NULL;
+// }
+ | '(' exp ')'
+// {
+// $$ = $2;
+// }
+ ;
+
+dynamic_list_file:
+// {
+// ldlex_version_file ();
+// PUSH_ERROR (_("dynamic list"));
+// }
+ dynamic_list_nodes
+// {
+// ldlex_popstate ();
+// POP_ERROR ();
+// }
+ ;
+
+dynamic_list_nodes:
+ dynamic_list_node
+ | dynamic_list_nodes dynamic_list_node
+ ;
+
+dynamic_list_node:
+ '{' dynamic_list_tag '}' ';'
+ ;
+
+dynamic_list_tag:
+ vers_defns ';'
+// {
+// lang_append_dynamic_list ($1);
+// }
+ ;
+
+/* This syntax is used within an external version script file. */
+
+version_script_file:
+// {
+// ldlex_version_file ();
+// PUSH_ERROR (_("VERSION script"));
+// }
+ vers_nodes
+// {
+// ldlex_popstate ();
+// POP_ERROR ();
+// }
+ ;
+
+/* This is used within a normal linker script file. */
+
+version:
+// {
+// ldlex_version_script ();
+// }
+ VERSIONK '{' vers_nodes '}'
+// {
+// ldlex_popstate ();
+// }
+ ;
+
+vers_nodes:
+ vers_node
+ | vers_nodes vers_node
+ ;
+
+vers_node:
+ '{' vers_tag '}' ';'
+// {
+// lang_register_vers_node (NULL, $2, NULL);
+// }
+ | VERS_TAG '{' vers_tag '}' ';'
+// {
+// lang_register_vers_node ($1, $3, NULL);
+// }
+ | VERS_TAG '{' vers_tag '}' verdep ';'
+// {
+// lang_register_vers_node ($1, $3, $5);
+// }
+ ;
+
+verdep:
+ VERS_TAG
+// {
+// $$ = lang_add_vers_depend (NULL, $1);
+// }
+ | verdep VERS_TAG
+// {
+// $$ = lang_add_vers_depend ($1, $2);
+// }
+ ;
+
+vers_tag:
+ /* empty */
+// {
+// $$ = lang_new_vers_node (NULL, NULL);
+// }
+ | vers_defns ';'
+// {
+// $$ = lang_new_vers_node ($1, NULL);
+// }
+ | GLOBAL ':' vers_defns ';'
+// {
+// $$ = lang_new_vers_node ($3, NULL);
+// }
+ | LOCAL ':' vers_defns ';'
+// {
+// $$ = lang_new_vers_node (NULL, $3);
+// }
+ | GLOBAL ':' vers_defns ';' LOCAL ':' vers_defns ';'
+// {
+// $$ = lang_new_vers_node ($3, $7);
+// }
+ ;
+
+vers_defns:
+ VERS_IDENTIFIER
+// {
+// $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, FALSE);
+// }
+ | NAME
+// {
+// $$ = lang_new_vers_pattern (NULL, $1, ldgram_vers_current_lang, TRUE);
+// }
+ | vers_defns ';' VERS_IDENTIFIER
+// {
+// $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, FALSE);
+// }
+ | vers_defns ';' NAME
+// {
+// $$ = lang_new_vers_pattern ($1, $3, ldgram_vers_current_lang, TRUE);
+// }
+ | vers_defns ';' EXTERN NAME '{'
+// {
+// $<name>$ = ldgram_vers_current_lang;
+// ldgram_vers_current_lang = $4;
+// }
+ vers_defns opt_semicolon '}'
+// {
+// struct bfd_elf_version_expr *pat;
+// for (pat = $7; pat->next != NULL; pat = pat->next);
+// pat->next = $1;
+// $$ = $7;
+// ldgram_vers_current_lang = $<name>6;
+// }
+ | EXTERN NAME '{'
+// {
+// $<name>$ = ldgram_vers_current_lang;
+// ldgram_vers_current_lang = $2;
+// }
+ vers_defns opt_semicolon '}'
+// {
+// $$ = $5;
+// ldgram_vers_current_lang = $<name>4;
+// }
+ | GLOBAL
+// {
+// $$ = lang_new_vers_pattern (NULL, "global", ldgram_vers_current_lang, FALSE);
+// }
+ | vers_defns ';' GLOBAL
+// {
+// $$ = lang_new_vers_pattern ($1, "global", ldgram_vers_current_lang, FALSE);
+// }
+ | LOCAL
+// {
+// $$ = lang_new_vers_pattern (NULL, "local", ldgram_vers_current_lang, FALSE);
+// }
+ | vers_defns ';' LOCAL
+// {
+// $$ = lang_new_vers_pattern ($1, "local", ldgram_vers_current_lang, FALSE);
+// }
+ | EXTERN
+// {
+// $$ = lang_new_vers_pattern (NULL, "extern", ldgram_vers_current_lang, FALSE);
+// }
+ | vers_defns ';' EXTERN
+// {
+// $$ = lang_new_vers_pattern ($1, "extern", ldgram_vers_current_lang, FALSE);
+// }
+ ;
+
+opt_semicolon:
+ /* empty */
+ | ';'
+ ;
+
+//%token <token>
+LBRACE : '{';
+RBRACE : '}';
+
+// <integer>
+// <token> assign_op atype attributes_opt sect_constraint opt_align_with_input
+// <name> filename
+//%type <versyms> vers_defns
+//%type <versnode> vers_tag
+//%type <deflist> verdep
+
+ABSOLUTE : 'ABSOLUTE';
+ADDR : 'ADDR';
+AFTER : 'AFTER';
+ALIAS : 'ALIAS';
+ALIGN : 'ALIGN';
+ALIGN_K : 'ALIGN';
+ALIGNMOD : 'ALIGNMOD';
+ALIGNOF : 'ALIGNOF';
+ALIGN_WITH_INPUT : 'ALIGN_WITH_INPUT';
+AS_NEEDED : 'AS_NEEDED';
+ASSERT_K : 'ASSERT';
+AT : 'AT';
+BASE : 'BASE';
+BEFORE : 'BEFORE';
+BIND : 'BIND';
+BLOCK : 'BLOCK';
+BYTE : 'BYTE';
+CASE : 'CASE';
+CHIP : 'CHIP';
+CONSTANT : 'CONSTANT';
+CONSTRUCTORS : 'CONSTRUCTORS';
+COPY : 'COPY';
+CREATE_OBJECT_SYMBOLS : 'CREATE_OBJECT_SYMBOLS';
+DATA_SEGMENT_ALIGN : 'DATA_SEGMENT_ALIGN';
+DATA_SEGMENT : 'DATA_SEGMENT';
+DATA_SEGMENT_END : 'DATA_SEGMENT_END';
+DATA_SEGMENT_RELRO_END : 'DATA_SEGMENT_RELRO_END';
+DEFINED : 'DEFINED';
+DEFSYMEND : 'DEFSYMEND';
+DSECT : 'DSECT';
+ENDWORD : 'ENDWORD';
+ENTRY : 'ENTRY';
+EXCLUDE_FILE : 'EXCLUDE_FILE';
+EXTERN : 'EXTERN';
+FILL : 'FILL';
+FLOAT : 'FLOAT';
+FORCE_COMMON_ALLOCATION : 'FORCE_COMMON_ALLOCATION';
+FORMAT : 'FORMAT';
+GLOBAL : 'GLOBAL';
+GROUP : 'GROUP';
+HIDDEN_ : 'HIDDEN';
+HLL : 'HLL';
+INCLUDE : 'INCLUDE';
+INFO : 'INFO';
+INHIBIT_COMMON_ALLOCATION : 'INHIBIT_COMMON_ALLOCATION';
+//INPUT_DEFSYM : 'INPUT_DEFSYM';
+//INPUT_DYNAMIC_LIST : 'INPUT_DYNAMIC_LIST';
+INPUT : 'INPUT';
+//INPUT_MRI_SCRIPT : 'INPUT_MRI_SCRIPT';
+//INPUT_SCRIPT : 'INPUT_SCRIPT';
+//INPUT_SECTION_FLAGS : 'INPUT_SECTION_FLAGS';
+//INPUT_VERSION_SCRIPT : 'INPUT_VERSION_SCRIPT';
+INSERT_K : 'INSERT';
+KEEP : 'KEEP';
+LD_FEATURE : 'LD_FEATURE';
+LENGTH : 'LENGTH';
+LIST : 'LIST';
+LOADADDR : 'LOADADDR';
+LOAD : 'LOAD';
+LOCAL : 'LOCAL';
+LOG2CEIL : 'LOG2CEIL';
+LONG : 'LONG';
+MAP : 'MAP';
+MAX_K : 'MAX';
+MEMORY : 'MEMORY';
+MIN_K : 'MIN';
+NAMEWORD : 'NAMEWORD';
+NEWLINE : 'NEWLINE';
+NEXT : 'NEXT';
+NOCROSSREFS : 'NOCROSSREFS';
+NOCROSSREFS_TO : 'NOCROSSREFS_TO';
+NOFLOAT : 'NOFLOAT';
+NOLOAD : 'NOLOAD';
+ONLY_IF_RO : 'ONLY_IF_RO';
+ONLY_IF_RW : 'ONLY_IF_RW';
+ORDER : 'ORDER';
+ORIGIN : 'ORIGIN'; // TODO: or 'org' or 'o'.
+OUTPUT_ARCH : 'OUTPUT_ARCH';
+OUTPUT_FORMAT : 'OUTPUT_FORMAT';
+OUTPUT : 'OUTPUT';
+OVERLAY : 'OVERLAY';
+PHDRS : 'PHDRS';
+PROVIDE_HIDDEN : 'PROVIDE_HIDDEN';
+PROVIDE : 'PROVIDE';
+PUBLIC : 'PUBLIC';
+QUAD : 'QUAD';
+REGION_ALIAS : 'REGION_ALIAS';
+REL : 'REL';
+SEARCH_DIR : 'SEARCH_DIR';
+SECTIONS : 'SECTIONS';
+SECT : 'SECT';
+SEGMENT_START : 'SEGMENT_START';
+SHORT : 'SHORT';
+SIZEOF_HEADERS : 'SIZEOF_HEADERS';
+SIZEOF : 'SIZEOF';
+SORT_BY_ALIGNMENT : 'SORT_BY_ALIGNMENT';
+SORT_BY_INIT_PRIORITY : 'SORT_BY_INIT_PRIORITY';
+SORT_BY_NAME : 'SORT_BY_NAME';
+SORT_NONE : 'SORT_NONE';
+SPECIAL : 'SPECIAL';
+SQUAD : 'SQUAD';
+START : 'START';
+STARTUP : 'STARTUP';
+SUBALIGN : 'SUBALIGN';
+SYSLIB : 'SYSLIB';
+TARGET_K : 'TARGET';
+TRUNCATE : 'TRUNCATE';
+VERS_IDENTIFIER : 'VERS_IDENTIFIER';
+VERSIONK : 'VERSIONK';
+VERS_TAG : 'VERS_TAG';
+
+/*
+Names are very liberal, they can be full strings and start with a dot.
+*/
+
+NAME : [\._a-zA-Z][_a-zA-Z0-9]*;
+
+// TODO: ld supports some really fancy expressions here, like "0101010b", "ffH", "ffx", "$Aa" etc
+//INT : '0x' [0-9a-fA-F]+
+// | [0-9]+;
+INT : INT_NUMBER INT_SIZE?;
+INT_NUMBER : INT_HEX
+ | INT_DECIMAL;
+INT_HEX : '0x' [0-9a-fA-F]+;
+INT_DECIMAL : [0-9]+;
+INT_SIZE : 'M' | 'm' | 'K' | 'k';
+
+END : 'END';
+
+LNAME : '-l' NAME;
+PLUSEQ : '+=';
+MINUSEQ : '-=';
+MULTEQ : '*=';
+DIVEQ : '/=';
+LSHIFTEQ : '<<=';
+RSHIFTEQ : '>>=';
+ANDEQ : '&=';
+OREQ : '|=';
+LSHIFT : '<<';
+RSHIFT : '>>';
+EQ : '=';
+NE : '!=';
+LE : '<=';
+GE : '>=';
+ANDAND : '&&';
+OROR : '||';
+
+BlockComment
+ : '/*' .*? '*/' -> skip
+ ;
+
+WS : [ \t\r\n]+ -> skip ;