# # ruby_parser.rb.y # vienna # # Created by Adam Beynon. # Copyright 2009 Adam Beynon. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # class Vienna::RubyParser # prechigh # nonassoc tLOWEST # nonassoc tLBRACE_ARG # # left tLSHFT tRSHFT # nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD # left kOR kAND # right kNOT # nonassoc kDEFined # right '=' tOP_ASGN # left kRESCUE_MOD # right '?' ':' # nonassoc tDOT2 tDOT3 # left tOROP # left tANDOP # nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH # left '>' tGEQ '<' tLEQ # left '|' '^' # left '&' # left '+' '-' # left '*' '/' '%' # right tUMINUS_NUM tUMINUS # right tPOW # right '!' '~' tUPLUS # preclow prechigh right '!' tTILDE tUPLUS right tPOW right tUMINUS_NUM tUMINUS left tSTAR2 tDIVIDE tPERCENT left tPLUS tMINUS left tLSHFT tRSHFT left tAMPER2 left tPIPE tCARET left '>' tGEQ '<' tLEQ nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH left tANDOP left tOROP nonassoc tDOT2 tDOT3 right '?' ':' left kRESCUE_MOD right '=' tOP_ASGN # left tANDOP # left tOROP nonassoc kDEFINED right kNOT left kOR kAND nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD nonassoc tLBRACE_ARG nonassoc tLOWEST preclow token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS token kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT token kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kDO_LAMBDA kRETURN kYIELD token kSUPER kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD token kWHILE_MOD kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND token k__LINE__ k__FILE__ k__ENCODING__ token kDEFined kBLOCK_GIVEN token tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL tINTEGER tFLOAT token tSTRING_CONTENT tCHAR tNTH_REF tBACK_REF tREGEXP_END tUPLUS tUMINUS token tPOW tCMP tEQ tEQQ tNEQ tGEQ tLEQ tANDOP tOROP tMATCH tNMATCH tDOT2 token tDOT3 tAREF tASET tLSHFT tRSHFT tCOLON2 tCOLON3 tOP_ASGN tASSOC token tLPAREN tLPAREN_ARG tRPAREN tLBRACK tLBRACE tLBRACE_ARG tSTAR tAMPER token tLAMBDA tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG token tQWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END tLAMBEG tUMINUS_NUM token tSTRING tXSTRING_END rule target: program { # puts 'well, we got here..' # puts val[0] @parser_result = val[0] result = val[0] } program: { self.lex_state = :EXPR_BEG } top_compstmt { # puts 'program' # puts val[1] result = val[1] } top_compstmt: top_stmts opt_terms { # puts 'top_compstmt' # puts val[0] # puts val[1] result = val[0] } top_stmts: none { result = [] } | top_stmt { result = [val[0]] } | top_stmts terms top_stmt { result = val[0] + [val[2]] } | error top_stmt { result = val[1] } top_stmt: stmt { result = val[0] } | kBEGIN bodystmt: compstmt opt_rescue opt_else opt_ensure { # puts "erm wtf?!" # puts val[1] result = self.node_bodystmt(val[0], val[1], val[2], val[3]) # if val[1] # pp result # end } compstmt: stmts opt_terms { result = val[0] } stmts: none { result = [] } | stmt { result = [val[0]] } | stmts terms stmt { result = val[0] + [val[2]] } | error stmt stmt: kALIAS fitem { self.lex_state = :EXPR_FNAME } fitem { result = node :alias, :lhs => val[1], :rhs => val[3] } | kALIAS tGVAR tGVAR | kALIAS tGVAR tBACK_REF | kALIAS tGVAR tNTH_REF | kUNDEF undef_list | stmt kIF_MOD expr_value { result = node :if, :expr => val[2], :stmt => [val[0]], :tail => [] } | stmt kUNLESS_MOD expr_value { result = node :unless, :expr => val[2], :stmt => [val[0]], :tail => [] } | stmt kWHILE_MOD expr_value { result = node :while, :expr => val[2], :stmt => [val[0]] } | stmt kUNTIL_MOD expr_value { result = node :until, :expr => val[2], :stmt => [val[0]] } | stmt kRESCUE_MOD stmt | klEND '{' compstmt '}' | lhs '=' command_call { result = node :assign, :lhs => val[0], :rhs => val[2] } | mlhs '=' command_call | var_lhs tOP_ASGN command_call { result = node :op_asgn, :lhs => val[0], :op => val[1], :rhs => val[2] } | primary_value '[' opt_call_args rbracket tOP_ASGN command_call { puts "in here for #{val[0]}" } | primary_value '.' tIDENTIFIER tOP_ASGN command_call | primary_value '.' tCONSTANT tOP_ASGN command_call | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call | backref tOP_ASGN command_call | lhs '=' mrhs | mlhs '=' arg_value | mlhs '=' mrhs | expr expr: command_call | expr kAND expr { result = node :andop, :lhs => val[0], :rhs => val[2] } | expr kOR expr { result = node :orop, :lhs => val[0], :rhs => val[2] } | kNOT opt_nl expr { result = node :not, :expr => val[2] } | '!' command_call | arg expr_value: expr command_call: command | block_command | kRETURN call_args { result = node :return, :call_args => val[1] } | kBREAK call_args { result = node :break, :call_args => val[1] } | kNEXT call_args { result = node :next, :call_args => val[1] } block_command: block_call | block_call '.' operation2 command_args | block_call tCOLON2 operation2 command_args cmd_brace_block: tLBRACE_ARG opt_block_param compstmt '}' command: operation command_args =tLOWEST { # command call - no brackets/recv result = node :call, :recv => nil, :meth => val[0], :call_args => val[1] } | operation command_args cmd_brace_block | primary_value '.' operation2 command_args =tLOWEST { result = node :call, :recv => val[0], :meth => val[2], :call_args => val[3] } | primary_value '.' operation2 command_args cmd_brace_block | primary_value tCOLON2 operation2 command_args =tLOWEST | primary_value tCOLON2 operation2 command_args cmd_brace_block | kSUPER command_args { result = node :super, :call_args => val[1] } | kYIELD command_args { result = node :yield, :call_args => val[1] } mlhs: mlhs_basic | tLPAREN mlhs_inner rparen mlhs_inner: mlhs_basic | tLPAREN mlhs_inner rparen mlhs_basic: mlhs_head | mlhs_head mlhs_item | mlhs_head tSTAR mlhs_node | mlhs_head tSTAR mlhs_node ',' mlhs_post | mlhs_head tSTAR | mlhs_head tSTAR ',' mlhs_post | tSTAR mlhs_node | tSTAR mlhs_node ',' mlhs_post | tSTAR | tSTAR ',' mlhs_post mlhs_item: mlhs_node | tLPAREN mlhs_inner rparen mlhs_head: mlhs_item ',' | mlhs_head mlhs_item ',' mlhs_post: mlhs_item | mlhs_post ',' mlhs_item mlhs_node: variable | primary_value '[' opt_call_args rbracket | primary_value '.' tIDENTIFIER | primary_value tCOLON2 tIDENTIFIER | primary_value '.' tCONSTANT | primary_value tCOLON2 tCONSTANT | tCOLON3 tCONSTANT | backref lhs: variable | primary_value '[' opt_call_args rbracket { result = node :call, :recv => val[0], :meth => '[]', :args => val[2] } | primary_value '.' tIDENTIFIER { result = node :call, :recv => val[0], :meth => val[2], :call_args => {} } | primary_value tCOLON2 tIDENTIFIER | primary_value '.' tCONSTANT | primary_value tCOLON2 tCONSTANT | tCOLON3 tCONSTANT { result = node :colon3, :name => val[1] } | backref cname: tIDENTIFIER { puts 'ERROR: cant use identifier for class/mod name' } | tCONSTANT { result = val[0] } cpath: tCOLON3 cname { } | cname { result = node :path, :cname => val[0] } | primary_value tCOLON2 cname fname: tIDENTIFIER | tCONSTANT | tFID | op { self.lex_state = :EXPR_END result = val[0] } | reswords { self.lex_state = :EXPR_END result = val[0] } fsym: fname | symbol fitem: fsym | dsym undef_list: fitem | undef_list ',' fitem op: '|' | '^' | '&' | tCMP | tEQ | tEQQ | tMATCH | tNMATCH | '>' | tGEQ | '<' | tLEQ | tNEQ | tLSHFT | tRSHFT | '+' | '-' | '*' | tSTAR | '/' | '%' | tPOW | '!' | '~' | tUPLUS | tUMINUS | tAREF | tASET | '`' reswords: k__LINE__ | k__FILE__ | k__ENCODING__ | kBEGIN | kEND | kALIAS | kAND | kBEGIN | kBREAK | kCASE | kCLASS | kDEF | kDEFined | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE | kFOR | kIN | kMODULE | kNEXT | kNIL | kNOT | kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF | kSUPER | kTHEN | kTRUE | kUNDEF | kWHEN | kYIELD | kIF | kUNLESS | kWHILE | kUNTIL | kBLOCK_GIVEN arg: lhs '=' arg { result = node :assign, :lhs => val[0], :rhs => val[2] } | lhs '=' arg kRESCUE_MOD arg | var_lhs tOP_ASGN arg { result = node :op_asgn, :lhs => val[0], :op => val[1], :rhs => val[2] } | var_lhs tOP_ASGN arg kRESCUE_MOD arg | primary_value '[' opt_call_args rbracket tOP_ASGN arg { result = node :aset_op_asgn, :recv => val[0], :call_args => val[2], :op => val[4], :arg => val[5] } | primary_value '.' tIDENTIFIER tOP_ASGN arg { result = node :op_asgn, :lhs => node(:call, :recv => val[0], :meth => val[2], :call_args => {}), :op => val[3], :rhs => val[4] # result = node :dot_identifier_op_asgn, :lhs => node(:call, :recv => val[0], :meth => val[2]), :op => val[3], :rhs => val[4] } | primary_value '.' tCONSTANT tOP_ASGN arg | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg | primary_value tCOLON2 tCONSTANT tOP_ASGN arg | tCOLON3 tCONSTANT tOP_ASGN arg | backref tOP_ASGN arg | arg tDOT2 arg { result = node :dot2, :start => val[0], :ending => val[2] } | arg tDOT3 arg { result = node :dot3, :start => val[0], :ending => val[2] } | arg '+' arg { result = node :opt_plus, :recv => val[0], :meth => '+', :call_args => { :args => [val[2]]} } | arg '-' arg { result = node :opt_minus, :recv => val[0], :meth => '-', :call_args => { :args => [val[2]]} } | arg '*' arg { result = node :opt_mult, :recv => val[0], :meth => '*', :call_args => { :args => [val[2]]} } | arg '/' arg { result = node :opt_div, :recv => val[0], :meth => '/', :call_args => { :args => [val[2]]} } | arg '%' arg { result = node :call, :recv => val[0], :meth => '%', :call_args => { :args => [val[2]]} } | arg tPOW arg { result = node :call, :recv => val[0], :meth => '**', :call_args => { :args => [val[2]]} } | tUMINUS_NUM tINTEGER tPOW arg | tUMINUS_NUM tFLOAT tPOW arg | tUPLUS arg { result = node :call, :recv => val[1], :meth => '+@', :call_args => { :args => []} } | tUMINUS arg { result = node :call, :recv => val[1], :meth => '-@', :call_args => { :args => []} } | arg '|' arg { result = node :call, :recv => val[0], :meth => '|', :call_args => { :args => [val[2]]} } | arg '^' arg { result = node :call, :recv => val[0], :meth => '^', :call_args => { :args => [val[2]]} } | arg '&' arg { result = node :call, :recv => val[0], :meth => '&', :call_args => { :args => [val[2]]} } | arg tCMP arg { result = node :call, :recv => val[0], :meth => '<=>', :call_args => { :args => [val[2]]} } | arg '>' arg { result = node :call, :recv => val[0], :meth => '>', :call_args => { :args => [val[2]]} } | arg tGEQ arg { result = node :call, :recv => val[0], :meth => '>=', :call_args => { :args => [val[2]]} } | arg '<' arg { result = node :call, :recv => val[0], :meth => '<', :call_args => { :args => [val[2]]} } | arg tLEQ arg { result = node :call, :recv => val[0], :meth => '<=', :call_args => { :args => [val[2]]} } | arg tEQ arg { result = node :call, :recv => val[0], :meth => '==', :call_args => { :args => [val[2]]} } | arg tEQQ arg { result = node :call, :recv => val[0], :meth => '===', :call_args => { :args => [val[2]]} } | arg tNEQ arg { result = node :call, :recv => val[0], :meth => '!=', :call_args => { :args => [val[2]]} } | arg tMATCH arg { result = node :call, :recv => val[0], :meth => '=~', :call_args => { :args => [val[2]]} } | arg tNMATCH arg { result = node :call, :recv => val[0], :meth => '!~', :call_args => { :args => [val[2]]} } | '!' arg { result = node :not, :expr => val[1] } | '~' arg { result = node :call, :recv => val[1], :meth => '~', :call_args => { :args => []} } | arg tLSHFT arg { result = node :call, :recv => val[0], :meth => '<<', :call_args => { :args => [val[2]]} } | arg tRSHFT arg { result = node :call, :recv => val[0], :meth => '>>', :call_args => { :args => [val[2]]} } | arg tANDOP arg { result = node :andop, :lhs => val[0], :rhs => val[2] } | arg tOROP arg { result = node :orop, :lhs => val[0], :rhs => val[2] } | kDEFined opt_nl arg | arg '?' arg opt_nl ':' arg { result = node :tertiary, :expr => val[0], :true => val[2], :false => val[5] } | primary arg_value: arg aref_args: none | args trailer | args ',' assocs trailer | assocs trailer paren_args: '(' opt_call_args rparen { result = val[1] } opt_paren_args: none { result = node :call_args, :args => nil } | paren_args opt_call_args: none { result = node :call_args, :args => nil } | call_args call_args: command { result = node :call_args, :args => [val[0]] } | args opt_block_arg { result = node :call_args, :args => val[0], :block_arg => val[1] } | assocs opt_block_arg { result = node :call_args, :assocs => val[0], :block_arg => val[1] } | args ',' assocs opt_block_arg { result = node :call_args, :args => val[0], :assocs => val[2], :block_arg => val[3] } | block_arg { result = node :call_args, :block_arg => val[0] } command_args: call_args block_arg: tAMPER arg_value { # puts "here for #{val[1]}" # puts val[1] result = self.node :block_arg, :arg => val[1] } | '&' arg_value { # puts val[1] result = self.node :block_arg, :arg => val[1] } opt_block_arg: ',' block_arg { result = val[1] } | ',' | none args: arg_value { result = [val[0]] } | tSTAR arg_value { result = [node(:splat, :val => val[1])] } | args ',' arg_value { result = val[0] + [val[2]] } | args ',' tSTAR arg_value { result = val[0] + [node(:splat, :val => val[3])] } mrhs: args ',' arg_value | args ',' tSTAR arg_value | tSTAR arg_value primary: literal | strings | xstring | regexp | words | qwords | tIDENTIFIER do_block { # if val[0].node == :self # result = val[0] # else # HACK: this rule shouldnt even exist. But for now it must for "identifier do .. end" result = node :call, :recv => nil, :meth => val[0], :brace_block => val[1] # end } | var_ref | backref | tFID | k_begin bodystmt k_end { result = node :begin, :stmt => val[1] } | tLPAREN_ARG expr rparen | tLPAREN compstmt ')' { result = node :lparen, :stmt => val[1] } | primary_value tCOLON2 tCONSTANT { result = node :colon2, :lhs => val[0], :rhs => val[2] } | tCOLON3 tCONSTANT { result = node :colon3, :name => val[1] } | tLBRACK aref_args ']' { result = node :array, :args => val[1] } | tLBRACE assoc_list '}' { result = node :assoc_list, :list => val[1] } | kRETURN { result = node :return } | kYIELD '(' call_args rparen { result = node :yield, :call_args => val[2] } | kYIELD '(' rparen { result = node :yield } | kYIELD { result = node :yield } | kDEFined opt_nl '(' expr rparen | kNOT '(' expr rparen | kNOT '(' rparen | operation brace_block { result = node :call, :recv => nil, :meth => val[0], :brace_block => val[1] } | method_call { # puts 2 } | method_call brace_block { val[0][:brace_block] = val[1] result = val[0] } | tLAMBDA lambda { result = node :lambda, :args => val[1][:args], :body => val[1][:body] } | k_if expr_value then compstmt if_tail k_end { result = self.node :if, :expr => val[1], :stmt => val[3], :tail => val[4] } | k_unless expr_value then compstmt opt_else k_end { result = self.node :unless, :expr => val[1], :stmt => val[3], :tail => val[4] } | k_while expr_value do compstmt k_end { # puts "in node while" result = node :while, :expr => val[1], :stmt => val[3] } | k_until expr_value do compstmt k_end { result = node :until, :expr => val[1], :stmt => val[3] } | k_case expr_value opt_terms case_body k_end { result = node :case, :expr => val[1], :body => val[3] } | k_case opt_terms case_body k_end { result = node :case, :expr => nil, :body => val[2] } | k_for for_var kIN expr_value do compstmt k_end | k_class cpath superclass bodystmt k_end { result = self.node_class(:cpath => val[1], :superclass => val[2], :bodystmt => val[3]) } | k_class tLSHFT expr term bodystmt k_end { result = node :class_shift, :expr => val[2], :bodystmt => val[4] } | k_module cpath bodystmt k_end { result = self.node_module(:cpath => val[1], :body => val[2]) } | k_def fname f_arglist bodystmt k_end { result = self.node :def, :fname => val[1], :arglist => val[2], :bodystmt => val[3], :line_number => @current_def_linenumber } | k_def singleton dot_or_colon fname f_arglist bodystmt k_end { result = self.node :def, :singleton => val[1], :fname => val[3], :arglist => val[4], :bodystmt => val[5], :line_number => @current_def_linenumber } | kBREAK { result = node :break, :call_args => nil } | kNEXT { result = node :next, :call_args => nil } | kREDO { result = node :redo } | kRETRY primary_value: primary k_begin: kBEGIN k_if: kIF k_unless: kUNLESS k_while: kWHILE k_until: kUNTIL k_case: kCASE k_for: kFOR k_class: kCLASS k_module: kMODULE k_def: kDEF k_end: kEND then: term | kTHEN | term kTHEN do: term | kDO_COND | kDO if_tail: opt_else { result = val[0] } | kELSIF expr_value then compstmt if_tail { result = [self.node(:elsif, :expr => val[1], :stmt => val[3])] + val[4] } opt_else: none { result = [] } | kELSE compstmt { result = [self.node(:else, :stmt => val[1])] } for_var: lhs | mlhs f_marg: f_norm_arg | tLPAREN f_margs rparen f_marg_list: f_marg | f_marg_list ',' f_marg f_margs: f_marg_list | f_marg_list ',' tSTAR f_norm_arg | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list | f_marg_list ',' tSTAR | f_marg_list ',' tSTAR ',' f_marg_list | tSTAR f_norm_arg | tSTAR f_norm_arg ',' f_marg_list | tSTAR | tSTAR ',' f_marg_list block_param: f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg | f_arg ',' f_block_optarg opt_f_block_arg | f_arg ',' f_block_optarg ',' f_arg opt_f_block_arg | f_arg ',' f_rest_arg opt_f_block_arg | f_arg ',' | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg | f_arg opt_f_block_arg | f_block_optarg ',' f_rest_arg opt_f_block_arg | f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg | f_block_optarg opt_f_block_arg | f_block_optarg ',' f_arg opt_f_block_arg | f_rest_arg opt_f_block_arg | f_rest_arg ',' f_arg opt_f_block_arg | f_block_arg opt_block_param: none { result = nil } | block_param_def block_param_def: '|' opt_bv_decl '|' | tOROP | '|' block_param opt_bv_decl '|' { result = val[1] } opt_bv_decl: none | ';' bv_decls bv_decls: bvar | bv_decls ',' bvar bvar: tIDENTIFIER | f_bad_arg lambda: f_larglist lambda_body { result = {:args => val[0], :body => val[1]} } f_larglist: '(' f_args opt_bv_decl rparen | f_args lambda_body: tLBRACE compstmt '}' { result = val[1] } | kDO_LAMBDA compstmt kEND { result = val[1] } do_block: kDO_BLOCK opt_block_param compstmt kEND | kDO opt_block_param compstmt kEND { result = node :brace_block, :params => val[1], :stmt => val[2] } block_call: command do_block { val[0][:brace_block] = val[1] result = val[0] } | block_call '.' operation2 opt_paren_args | block_call tCOLON2 operation2 opt_paren_args method_call: operation paren_args { result = node :call, :recv => nil, :meth => val[0], :call_args => val[1] } | primary_value '.' operation2 opt_paren_args { result = node :call, :recv => val[0], :meth => val[2], :call_args => val[3] } | primary_value tCOLON2 operation2 paren_args { result = node :tCOLON2call, :recv => val[0], :meth => val[2], :args => val[3] puts "tCOLON2call" } | primary_value tCOLON2 operation3 { result = node :tCOLON2call, :recv => val[0], :meth => val[2] puts "tCOLON2call.noargs." } | primary_value '.' paren_args | primary_value tCOLON2 paren_args | kSUPER paren_args { result = node :super, :call_args => val[1], :paren => true } | kSUPER { result = node :super, :call_args => nil, :inherit => true } | primary_value '[' opt_call_args rbracket { result = node :call, :recv => val[0], :meth => '[]', :call_args => val[2] } brace_block: '{' opt_block_param compstmt '}' { result = node :brace_block, :params => val[1], :stmt => val[2] } | kDO opt_block_param compstmt kEND { result = node :brace_block, :params => val[1], :stmt => val[2] } case_body: kWHEN args then compstmt cases { result = [node(:when, :args => val[1], :stmt => val[3])] + val[4] } cases: opt_else { result = val[0] } | case_body opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue { result = node :rescue, :list => val[1], :var => val[2], :stmt => val[4], :opt_rescue => val[5] # puts result } | none { result = nil } exc_list: arg_value { result = val[0] } | mrhs { result = val[0] } | none { result = nil } exc_var: tASSOC lhs { result = val[1] } | none { result = nil } opt_ensure: kENSURE compstmt { result = val[1] } | none { result = nil } literal: numeric | symbol | dsym strings: string string: tCHAR | string1 | string string1 string1: tSTRING_BEG string_contents tSTRING_END { result = node :string, :value => val[1], :beg => val[0] } xstring: tXSTRING_BEG xstring_contents tXSTRING_END { result = node :xstring, :value => val[1] } regexp: tREGEXP_BEG xstring_contents tREGEXP_END { result = node :regexp, :value => val[1] } words: tWORDS_BEG ' ' tSTRING_END | tWORDS_BEG word_list tSTRING_END { result = node :words, :list => val[1] } word_list: /* none */ { result = [] } | word_list word { result = val[0] + [val[1]] } word: string_content { result = [val[0]] } | word string_content { result = val[0] + [val[1]] } qwords: tQWORDS_BEG ' ' tSTRING_END | tQWORDS_BEG qword_list tSTRING_END qword_list: { # none.. result = [] } | qword_list tSTRING_CONTENT ' ' string_contents: { # none.. result = [] } | string_contents string_content { result = val[0] + [val[1]] } xstring_contents: { # none.. result = [] } | xstring_contents string_content { result = val[0] + [val[1]] } string_content: tSTRING_CONTENT { result = node :string_content, :value => val[0] } | tSTRING_DVAR string_dvar { result = node :string_dvar, :value => val[1] } | tSTRING_DBEG compstmt '}' { result = node :string_dbeg, :value => val[1] } string_dvar: tGVAR | tIVAR | tCVAR | backref symbol: tSYMBEG sym { result = node :symbol, :name => val[1] } sym: fname | tIVAR | tGVAR | tCVAR dsym: tSYMBEG xstring_contents tSTRING_END { result = node :dsym, :contents => val[1] } numeric: tINTEGER { result = node :numeric, :value => val[0], :float => false } | tFLOAT { result = node :numeric, :value => val[0], :float => true } | tUMINUS_NUM tINTEGER | tUMINUS_NUM tFLOAT variable: tIDENTIFIER { result = node :identifier, :name => val[0] } | tIVAR { result = node :ivar, :name => val[0] } | tGVAR { result = node :gvar, :name => val[0] } | tCONSTANT { result = node :constant, :name => val[0] } | tCVAR { result = node :cvar, :name => val[0] } | kNIL { result = node :nil, :name => val[0] } | kSELF { result = node :self, :name => val[0] } | kTRUE { result = node :true, :name => val[0] } | kFALSE { result = node :false, :name => val[0] } | k__FILE__ { result = node :__FILE__, :name => val[0] } | k__LINE__ { result = node :__LINE__, :name => val[0] } | k__ENCODING__ { result = node :__ENCODING__, :name => val[0] } | kBLOCK_GIVEN { # added for block_given? support.. :D result = node :block_given, :name => val[0] } var_ref: variable var_lhs: variable backref: tNTH_REF | tBACK_REF superclass: term { result = nil } | '<' expr_value term { result = node :superclass, :expr => val[1] } | error term { puts 'OMFG' } f_arglist: '(' f_args rparen { result = val[1] self.lex_state = :EXPR_BEG } | f_args term { result = val[0] self.lex_state = :EXPR_BEG } f_args: f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg { result = node_args(val[0], val[2], val[4], nil, val[5]) } | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg { result = node_args(val[0], val[2], val[4], val[6], val[7]) } | f_arg ',' f_optarg opt_f_block_arg { result = node_args(val[0], val[2], nil, nil, val[3]) } | f_arg ',' f_optarg ',' f_arg opt_f_block_arg { result = node_args(val[0], val[2], nil, val[4], val[5]) } | f_arg ',' f_rest_arg opt_f_block_arg { result = node_args(val[0], nil, val[2], nil, val[3]) } | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg { result = node_args(val[0], nil, val[2], val[4], val[5]) } | f_arg opt_f_block_arg { result = node_args(val[0], nil, nil, nil, val[1]) } | f_optarg ',' f_rest_arg opt_f_block_arg { result = node_args(nil, val[0], val[2], nil, val[3]) } | f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg { result = node_args(nil, val[0], val[2], val[4], val[5]) } | f_optarg opt_f_block_arg { result = node_args(nil, val[0], nil, nil, val[1]) } | f_optarg ',' f_arg opt_f_block_arg { result = node_args(nil, val[0], nil, val[2], val[3]) } | f_rest_arg opt_f_block_arg { result = node_args(nil, nil, val[0], nil, val[1]) } | f_rest_arg ',' f_arg opt_f_block_arg { result = node_args(nil, nil, val[0], val[2], val[3]) } | f_block_arg { result = node_args(nil, nil, nil, nil, val[0]) } | # none .. { result = node_args(nil, nil, nil, nil, nil) } f_bad_arg: tCONSTANT | tIVAR | tGVAR | tCVAR f_norm_arg: f_bad_arg | tIDENTIFIER { # result = val[0] result = node :norm_arg, :value => val[0] } | tIDENTIFIER tASSOC tIDENTIFIER { } | tLABEL tIDENTIFIER { result = node :label_arg, :name => val[0], :value => val[1] } f_arg_item: f_norm_arg { result = val[0] } | tLPAREN f_margs rparen f_arg: f_arg_item { result = [val[0]] } | f_arg ',' f_arg_item { # val[0] + val[2] result = val[0] + [val[2]] } f_opt: tIDENTIFIER '=' arg_value { result = [val[0], val[2]] } f_block_opt: tIDENTIFIER '=' primary_value f_block_optarg: f_block_opt | f_block_optarg ',' f_block_opt f_optarg: f_opt { result = [val[0]] } | f_optarg ',' f_opt { result = val[0] + [val[2]] } restarg_mark: '*' | tSTAR f_rest_arg: restarg_mark tIDENTIFIER { result = val[1] } | restarg_mark blkarg_mark: '&' | tAMPER f_block_arg: blkarg_mark tIDENTIFIER { result = val[1] } | tLABEL blkarg_mark tIDENTIFIER { result = node :label_arg, :name => val[0], :value => val[1] } opt_f_block_arg: ',' f_block_arg { result = val[1] } | none singleton: var_ref | '(' expr rparen assoc_list: none { result = [] } | assocs trailer { result = val[0] } assocs: assoc { result = [val[0]] } | assocs ',' assoc { result = val[0] + [val[2]] } assoc: arg_value tASSOC arg_value { result = node :assoc, :key => val[0], :value => val[2] } | tLABEL arg_value { result = node :label_assoc, :key => val[0], :value => val[1] } operation: tIDENTIFIER | tCONSTANT | tFID operation2: tIDENTIFIER { } | tCONSTANT | tFID | op operation3: tIDENTIFIER { puts 4 } | tFID | op dot_or_colon: '.' | tCOLON2 opt_terms: | terms opt_nl: /* none */ | '\n' rparen: opt_nl ')' rbracket: opt_nl ']' trailer: /* none */ | '\n' | ',' term: ';' | '\n' terms: term | terms ';' none: end ---- header ---- # require 'ctokenizer' require 'strscan' ---- inner ---- ---- footer ----