%{ ?> | | Zeev Suraski | | native PHP version: Greg Beaver | | native PHP version: Alan Knowles | +----------------------------------------------------------------------+ */ // // This does nothing on it's own - refer to PHP_Parser // It's purely the code for the Parser, generated by phpJay // class PintCompiler_Parser { /** * Options, used to control how the parser collects * and distributes the data it finds. * * Currently, options are grouped into two categories: * - containers for data * - publishing of data * * Default action is to return arrays of parsed data * for use by other applications. The first set of * options, container options, provide a means to * tell the parser to encapsulate data in objects * instead of in arrays. The option tells the parser which * class to instantiate for each documentable element. The * default value of false will prompt the usage of arrays * instead. * * The second set of options provide for intermediary * publishing of data while parsing, to allow other * classes to hook into functionality if they desire * @var array */ var $_options = array(); /** * global variable name of parser arrays * should match the build options * * @var string * @access public */ var $yyGlobalName = '_PINTCOMPILER_PARSER'; var $tree = array( 'statements' => array(), 'functions' => array(), 'classes' => array(), ); /** * parse a string. * and build the tokens etc.. * * @var string * @access public */ function parseString($string) { require_once 'PintCompiler/Tokenizer.php'; $tokenizer = new PintCompiler_Tokenizer($string); $c = __CLASS__; $p = new $c; $GLOBALS['PintCompiler_Tokenizer']['singleton'] = &$tokenizer; return $p->yyparse($tokenizer); } %} %token T_INCLUDE 257 %token T_INCLUDE_ONCE 258 %token T_EVAL 259 %token T_REQUIRE 260 %token T_REQUIRE_ONCE 261 %token T_LOGICAL_OR 262 %token T_LOGICAL_XOR 263 %token T_LOGICAL_AND 264 %token T_PRINT 265 %token T_PLUS_EQUAL 266 %token T_MINUS_EQUAL 267 %token T_MUL_EQUAL 268 %token T_DIV_EQUAL 269 %token T_CONCAT_EQUAL 270 %token T_MOD_EQUAL 271 %token T_AND_EQUAL 272 %token T_OR_EQUAL 273 %token T_XOR_EQUAL 274 %token T_SL_EQUAL 275 %token T_SR_EQUAL 276 %token T_BOOLEAN_OR 277 %token T_BOOLEAN_AND 278 %token T_IS_EQUAL 279 %token T_IS_NOT_EQUAL 280 %token T_IS_IDENTICAL 281 %token T_IS_NOT_IDENTICAL 282 %token T_IS_SMALLER_OR_EQUAL 283 %token T_IS_GREATER_OR_EQUAL 284 %token T_SL 285 %token T_SR 286 %token T_INC 287 %token T_DEC 288 %token T_INT_CAST 289 %token T_DOUBLE_CAST 290 %token T_STRING_CAST 291 %token T_ARRAY_CAST 292 %token T_OBJECT_CAST 293 %token T_BOOL_CAST 294 %token T_UNSET_CAST 295 %token T_NEW 296 %token T_INSTANCEOF 297 %token T_EXIT 298 %token T_IF 299 %token T_ELSEIF 300 %token T_ELSE 301 %token T_ENDIF 302 %token T_LNUMBER 303 %token T_DNUMBER 304 %token T_STRING 305 %token T_STRING_VARNAME 306 %token T_VARIABLE 307 %token T_NUM_STRING 308 %token T_INLINE_HTML 309 %token T_CHARACTER 310 %token T_BAD_CHARACTER 311 %token T_ENCAPSED_AND_WHITESPACE 312 %token T_CONSTANT_ENCAPSED_STRING 313 %token T_ECHO 314 %token T_DO 315 %token T_WHILE 316 %token T_ENDWHILE 317 %token T_FOR 318 %token T_ENDFOR 319 %token T_FOREACH 320 %token T_ENDFOREACH 321 %token T_DECLARE 322 %token T_ENDDECLARE 323 %token T_AS 324 %token T_SWITCH 325 %token T_ENDSWITCH 326 %token T_CASE 327 %token T_DEFAULT 328 %token T_BREAK 329 %token T_CONTINUE 330 %token T_FUNCTION 331 %token T_CONST 332 %token T_RETURN 333 %token T_TRY 334 %token T_CATCH 335 %token T_THROW 336 %token T_USE 337 %token T_GLOBAL 338 %token T_STATIC 339 %token T_ABSTRACT 340 %token T_FINAL 341 %token T_PRIVATE 342 %token T_PROTECTED 343 %token T_PUBLIC 344 %token T_VAR 345 %token T_UNSET 346 %token T_ISSET 347 %token T_EMPTY 348 %token T_CLASS 349 %token T_INTERFACE 350 %token T_EXTENDS 351 %token T_IMPLEMENTS 352 %token T_OBJECT_OPERATOR 353 %token T_DOUBLE_ARROW 354 %token T_LIST 355 %token T_ARRAY 356 %token T_CLASS_C 357 %token T_FUNC_C 358 %token T_LINE 359 %token T_FILE 360 %token T_COMMENT 361 %token T_DOC_COMMENT 362 %token T_OPEN_TAG 363 %token T_OPEN_TAG_WITH_ECHO 364 %token T_CLOSE_TAG 365 %token T_WHITESPACE 366 %token T_START_HEREDOC 367 %token T_END_HEREDOC 368 %token T_DOLLAR_OPEN_CURLY_BRACES 369 %token T_CURLY_OPEN 370 %token T_PAAMAYIM_NEKUDOTAYIM 371 %right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC %left T_ELSEIF %left T_ELSE %left T_ENDIF %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE %left ',' %left T_LOGICAL_OR %left T_LOGICAL_XOR %left T_LOGICAL_AND %right T_PRINT %left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL %left '?' ':' %left T_BOOLEAN_OR %left T_BOOLEAN_AND %left '|' %left '^' %left '&' %nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL %nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL %left T_SL T_SR %left '+' '-' '.' %left '*' '/' '%' %right '!' '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@' %right '[' %nonassoc T_NEW T_INSTANCEOF %start top_statement_list %% /* Rules */ top_statement_list: top_statement_list top_statement | /* empty */ ; top_statement: statement { $func = &PintCompiler_Generator::getFunction(); $func->statements[] = $1; } | function_declaration_statement | class_declaration_statement ; inner_statement_list: inner_statement_list inner_statement { $$ = $1; $$[] = $2; } | inner_statement { $$ = array($1); } | /* empty */ { $$ = array(); } ; inner_statement: statement { $$ = $1; } | function_declaration_statement { $$ = $1; } | class_declaration_statement { $$ = $1; } ; statement: unticked_statement { $$ = $1; } ; unticked_statement: '{' inner_statement_list '}' { $$ = $2; } | T_IF '(' expr ')' statement elseif_list else_single { $$ = PintCompiler_Generator::nodeFactory('If',array( 'condition' =>$3, 'true' => is_array($5) ? $5 : array($5), 'false' => $7, 'elseif' => $6 )); } | T_IF '(' expr ')' ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' { $$ =PintCompiler_Generator::nodeFactory('If',array( 'condition' => $3, 'true ' => $6, 'false' => $8, 'elseif' => $7 )); } | T_WHILE '(' expr ')' while_statement { $$ = PintCompiler_Generator::nodeFactory('while',array( 'condition' => $3, 'statements' => $5 )); } | T_DO statement T_WHILE '(' expr ')' ';' { $$ = PintCompiler_Generator::nodeFactory('DoWhile',array( 'condition' => $5, 'statements' => array($2) )); } | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement { $$ = PintCompiler_Generator::nodeFactory('For',array( 'initializer' => $3, // * probalby needs more work! 'condition' => $5, // * probalby needs more work! 'iterator' => $7, 'statements' => $9, )); //echo "RETURNING FOR STATMENT?"; } | T_SWITCH '(' expr ')' switch_case_list { $$ = PintCompiler_Generator::nodeFactory('Switch',array( 'value' => $3, 'cases' => $5, )); } | T_BREAK ';' { $$ = PintCompiler_Generator::nodeFactory('Break'); } | T_BREAK expr ';' { $$ = PintCompiler_Generator::nodeFactory('Break',array( 'value' => $2 )); } | T_CONTINUE ';' { $$ = PintCompiler_Generator::nodeFactory('Continue'); } | T_CONTINUE expr ';' { $$ = PintCompiler_Generator::nodeFactory('Continue',array( 'value' => $2 )); } | T_RETURN ';' { $$ = PintCompiler_Generator::nodeFactory('Return',array( 'value' => PintCompiler_Generator::nodeFactory('LiteralBoolean', array( 'value' => false )) )); } | T_RETURN expr_without_variable ';' { $$ = PintCompiler_Generator::nodeFactory('Return',array( 'value' => $2 )); } | T_RETURN variable ';' { $$ = PintCompiler_Generator::nodeFactory('Return',array( 'value' => $2 )); } | T_GLOBAL global_var_list ';' { $$ = PintCompiler_Generator::nodeFactory('Global',array( 'value' => $2 )); } | T_STATIC static_var_list ';' { $$ = PintCompiler_Generator::nodeFactory('Static',array( 'value' => $2 )); } | T_ECHO echo_expr_list ';' { $$ = PintCompiler_Generator::nodeFactory('Echo',array( 'args' => $2 )); } | T_INLINE_HTML { $$ = PintCompiler_Generator::nodeFactory('Echo',array( 'args' => $1 )); } | expr ';' { $$ = $1; } | T_USE use_filename ';' { $$ = PintCompiler_Generator::nodeFactory('Use',array( 'args' => $2 )); } | T_UNSET '(' unset_variables ')' ';' { $$ = PintCompiler_Generator::nodeFactory('Unset',array( 'args' => $3 )); } | T_FOREACH '(' variable T_AS variable foreach_optional_arg ')' foreach_statement { $args = array(); $args['array'] = $3; if ($6 === null) { $args['key'] = false; $args['value'] = $5; } else { $args['key'] = $5; $args['value'] = $6; } $args['statements'] = $8; $$ = PintCompiler_Generator::nodeFactory('Foreach',$args); } | T_FOREACH '(' expr_without_variable T_AS variable foreach_optional_arg ')' foreach_statement { $args = array(); $args['array'] = $3; if ($6 === null) { $args['key'] = false; $args['value'] = $5; } else { $args['key'] = $5; $args['value'] = $6; } $args['statements'] = $8; $$ = PintCompiler_Generator::nodeFactory('Foreach',$args); } | T_DECLARE '(' declare_list ')' declare_statement { $$ = PintCompiler_Generator::nodeFactory('Declare',array( 'directive'=>$3, 'statements' => $5 )); } | ';' /* empty statement */ { $$ = PintCompiler_Generator::nodeFactory('Noop'); } | T_TRY '{' inner_statement_list '}' T_CATCH '(' fully_qualified_class_name T_VARIABLE ')' '{' inner_statement_list '}' additional_catches { $catches = array_unshift($13, PintCompiler_Generator::nodeFactory('Catch',array( 'type' => $7, 'var' => $8, 'statements' => $11 ))); $$ = PintCompiler_Generator::nodeFactory('Try',array( 'try' => $3, 'catches' => $13 )); } | T_THROW expr ';' { $$ = PintCompiler_Generator::nodeFactory('Throw',array( 'expr' => $2, )); } ; additional_catches: non_empty_additional_catches { $$ = $1; } | /* empty */ { $$ = array(); } ; non_empty_additional_catches: non_empty_additional_catches T_CATCH '(' fully_qualified_class_name T_VARIABLE ')' '{' inner_statement_list '}' { $$ = $1; $$[] = PintCompiler_Generator::nodeFactory('Catch',array( 'type' => $4, 'var' => $5, 'statements' => $8 )); } | T_CATCH '(' fully_qualified_class_name T_VARIABLE ')' '{' inner_statement_list '}' { $$ = array( PintCompiler_Generator::nodeFactory('Catch',array( 'type' => $3, 'var' => $4, 'statements' => $7 )) ); } ; unset_variables: unset_variable { $$ = array($1); } | unset_variables ',' unset_variable { $$ = $1; $$[] = $3; } ; unset_variable: variable { $$ = $1; } ; use_filename: T_CONSTANT_ENCAPSED_STRING { $$ = $1; } | '(' T_CONSTANT_ENCAPSED_STRING ')' { $$ = $2; } ; function_declaration_statement: unticked_function_declaration_statement ; class_declaration_statement: unticked_class_declaration_statement ; is_reference: /* empty */ { $$ = false; } | '&' { $$ = true; } ; unticked_function_declaration_statement: T_FUNCTION optional_class_type is_reference T_STRING '(' parameter_list ')' '{' inner_statement_list '}' { $f = PintCompiler_Generator::nodeFactory('Function',array( 'name' => $4, 'type' => $2, 'returnByReference' => $3, 'args' => $6, 'statements' => $9, )); PintCompiler_Generator::addFunction($f); } ; unticked_class_declaration_statement: class_entry_type T_STRING extends_from implements_list '{' { $c = PintCompiler_Generator::nodeFactory('Class',array( 'modifiers' => $1, 'name' => $2, 'extends' => $3, 'implements' => $4, 'members' => array() )); PintCompiler_Generator::addClass($c); } class_statement_list '}' { // needs more thought? $c = &PintCompiler_Generator::getActiveClass(); $c->members = $7; } ; class_entry_type: T_CLASS { $$ = null; } | T_ABSTRACT T_CLASS { $$ = 'abstract'; } | T_FINAL T_CLASS { $$ = 'final'; } | T_INTERFACE { $$ = 'interface'; } ; extends_from: /* empty */ { $$ = null; } | T_EXTENDS fully_qualified_class_name { $$ = $2; } ; implements_list: /* empty */ { $$ = null; } | T_IMPLEMENTS interface_list { $$ = $1; } ; interface_list: fully_qualified_class_name { $$ = array($1); } | interface_list ',' fully_qualified_class_name { $$ = $1; $$[] = $2; } ; foreach_optional_arg: /* empty */ { $$ = null; } | T_DOUBLE_ARROW variable { $$ = $2; } ; for_statement: statement { $$ = is_array($1) ? $1 : array($1); } | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } ; foreach_statement: statement { $$ = array($1); } | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } ; declare_statement: statement {$$ = array($1); } | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } ; declare_list: T_STRING '=' static_scalar /* dont support this = ticks.. */ | declare_list ',' T_STRING '=' static_scalar ; switch_case_list: '{' case_list '}' { $$ = $1; } | '{' ';' case_list '}' /* arg what!! */ | ':' case_list T_ENDSWITCH ';' { $$ = $1; } | ':' ';' case_list T_ENDSWITCH ';' /* arg what!! */ ; case_list: /* empty */ { $$ = array(); } | case_list T_CASE expr case_separator inner_statement_list { $$ = $1 ? $1 : array(); $$[] = PintCompiler_Generator::nodeFactory('Case',array( 'condition' => $3, 'statements' => $5, )); } | case_list T_DEFAULT case_separator inner_statement_list { $$ = $1 ? $1 : array(); $$[] = PintCompiler_Generator::nodeFactory('CaseDefault',array( 'statements' => $4, )); } ; case_separator: ':' | ';' ; while_statement: statement { $$ = $1; } | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } ; elseif_list: /* empty */ { $$ = array(); } | elseif_list T_ELSEIF '(' expr ')' statement { $$ = $1 ? $1 : array(); $$[] = PintCompiler_Generator::nodeFactory('ElseIf',array( 'condition' => $4, 'true' => array($6) )); } ; new_elseif_list: /* empty */ { $$ = array(); } | new_elseif_list T_ELSEIF '(' expr ')' ':' inner_statement_list { $$ = $1 ? $1 : array(); $$[] = PintCompiler_Generator::nodeFactory('ElseIf',array( 'condition' => $4, 'true' => $7 )); } ; else_single: /* empty */ { $$ = array(); } | T_ELSE statement { $$ = array($1); } ; new_else_single: /* empty */{ $$ = array(); } | T_ELSE ':' inner_statement_list { $$ = PintCompiler_Generator::nodeFactory('Else',array( 'statements' => $3 )); } ; parameter_list: non_empty_parameter_list { $$ = $1; } | /* empty */ { $$ = array(); } ; non_empty_parameter_list: non_empty_parameter_list ',' non_empty_parameter_list_item { $$=$1; $$[] = $3; } | non_empty_parameter_list_item { $$ = array($1); } ; non_empty_parameter_list_item: optional_class_type T_VARIABLE { //echo "\n\n:::got pararmenter ". $1."::".$2."\n"; $$ = PintCompiler_Generator::nodeFactory('VariableAccess',array( 'name' => $2, 'type' => $1, )); } | optional_class_type '&' T_VARIABLE { $$ = PintCompiler_Generator::nodeFactory('VariableAccess',array( 'name' => $3, 'type' => $1, 'byRef' => true, )); } | optional_class_type '&' T_VARIABLE '=' static_scalar { $$ = PintCompiler_Generator::nodeFactory('VariableAccess',array( 'name' => $3, 'type' => $1, 'byRef' => true, 'default' => $5 )); } | T_CONST optional_class_type T_VARIABLE { $$ = PintCompiler_Generator::nodeFactory('VariableAccess',array( 'name' => $3, 'type' => $2, 'const' => true )); } | optional_class_type T_VARIABLE '=' static_scalar { $$ = PintCompiler_Generator::nodeFactory('VariableAccess',array( 'name' => $2, 'type' => $1, 'default' => $4 )); } ; optional_class_type: /* empty */ { $$ = null; } | fully_qualified_class_name { $$ = $1; } ; function_call_parameter_list: non_empty_function_call_parameter_list { $$ = $1; } | /* empty */ { $$ = array(); } ; non_empty_function_call_parameter_list: non_empty_function_call_parameter_list ',' non_empty_function_call_parameter_list_item { $$ = $1; $$[] = $3; } | non_empty_function_call_parameter_list_item { $$ = array($1); } ; non_empty_function_call_parameter_list_item: expr_without_variable { $$ = $1; } | variable { $$ = $1; } | '&' variable { $$ = $1; $$->byRef = true; /* is this illegal? */ } ; global_var_list: global_var_list ',' global_var | global_var ; global_var: T_VARIABLE | '$' variable | '$' '{' expr '}' ; static_var_list: static_var_list ',' T_VARIABLE | static_var_list ',' T_VARIABLE '=' static_scalar | T_VARIABLE | T_VARIABLE '=' static_scalar ; class_statement_list: class_statement_list class_statement { $$ = $1; $$[] = $2; } | class_statement { $$ = array($1); } | /* empty */ { $$ = null; } ; class_statement: variable_modifiers class_variable_declaration ';' { $c = &PintCompiler_Generator::getActiveClass(); $2->modifiers = $1; $c->members[] = $2; } | class_constant_declaration ';' { $c = &PintCompiler_Generator::getActiveClass(); $c->members[] = $1; } | method_modifiers T_FUNCTION is_reference T_STRING '(' parameter_list ')' method_body { $c = PintCompiler_Generator::getActiveClass(); $f = PintCompiler_Generator::nodeFactory('Function',array( 'name' => $4, 'returnByReference' => $3, 'args' => $6, 'statements' => $8, )); PintCompiler_Generator::addFunction($f); } ; method_body: ';' /* abstract method */ { $$ = null; } | '{' inner_statement_list '}' { $$ = $2; } ; variable_modifiers: non_empty_member_modifiers { $$ = $1; } | T_VAR { $$ = array('public'); } ; method_modifiers: /* empty */ { $$ = array('public'); } | non_empty_member_modifiers { $$ = $1; } ; non_empty_member_modifiers: member_modifier { $$ = array($1);} | non_empty_member_modifiers member_modifier { $$ = $1; $$[] = $2; } ; member_modifier: T_PUBLIC { $$ = 'public'; } | T_PROTECTED { $$ = 'protected'; } | T_PRIVATE { $$ = 'private'; } | T_STATIC { $$ = 'static'; } | T_ABSTRACT { $$ = 'abstract'; } | T_FINAL { $$ = 'final'; } ; class_variable_declaration: class_variable_declaration ',' T_VARIABLE { $v = PintCompiler_Generator::nodeFactory('Member',array( 'name' => $3 )); $$ = $1; $$[] = $v; } | class_variable_declaration ',' T_VARIABLE '=' static_scalar { $v = PintCompiler_Generator::nodeFactory('Member',array( 'name' => $3, 'default' => $5, )); $$ = $1; $$[] = $v; } | T_VARIABLE { $v = PintCompiler_Generator::nodeFactory('Member',array( 'name' => $1, )); $$ = array($v);; } | T_VARIABLE '=' static_scalar { $v = PintCompiler_Generator::nodeFactory('Member',array( 'name' => $1, 'default' => $3, )); $$ = array($v); } ; class_constant_declaration: class_constant_declaration ',' T_STRING '=' const_scalar_expr | T_CONST T_STRING '=' const_scalar_expr ; echo_expr_list: echo_expr_list ',' expr { $$ = $1; $$[] = $3; } | expr { $$ = array($1); } ; for_expr: non_empty_for_expr { $$ = $1; } | /* empty */ { $$ = array(); } ; non_empty_for_expr: non_empty_for_expr ',' expr { $$ = $1; $$[] = $3; } | expr { $$ = array($1); } ; var_expr_operator: T_MINUS_EQUAL { $$ = PintCompiler_Generator::nodeFactory('BinaryAssign',array('operator'=>$1)); } | T_MUL_EQUAL { $$ = PintCompiler_Generator::nodeFactory('BinaryAssign',array('operator'=>$1)); } | T_DIV_EQUAL { $$ = PintCompiler_Generator::nodeFactory('BinaryAssign',array('operator'=>$1)); } | T_CONCAT_EQUAL { $$ = PintCompiler_Generator::nodeFactory('BinaryAssignString'); } | T_MOD_EQUAL { $$ = PintCompiler_Generator::nodeFactory('BinaryAssign',array('operator'=>$1)); } | T_AND_EQUAL { $$ = PintCompiler_Generator::nodeFactory('BinaryAssign',array('operator'=>$1)); } | T_OR_EQUAL { $$ = PintCompiler_Generator::nodeFactory('BinaryAssign',array('operator'=>$1)); } | T_XOR_EQUAL { $$ = PintCompiler_Generator::nodeFactory('BinaryAssign',array('operator'=>$1)); } | T_SL_EQUAL { $$ = PintCompiler_Generator::nodeFactory('BinaryAssign',array('operator'=>$1)); } | T_SR_EQUAL { $$ = PintCompiler_Generator::nodeFactory('BinaryAssign',array('operator'=>$1)); } ; expr_operator: | T_BOOLEAN_OR { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | T_BOOLEAN_AND { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | T_LOGICAL_OR { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | T_LOGICAL_AND { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | T_LOGICAL_XOR { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | '|' { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | '&' { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | '^' { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | '.' { $$ = PintCompiler_Generator::nodeFactory('BinaryString'); } | '+' { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | '-' { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | '*' { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | '/' { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | '%' { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | T_SL { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | T_SR { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | T_IS_IDENTICAL { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | T_IS_NOT_IDENTICAL { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | T_IS_EQUAL { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | T_IS_NOT_EQUAL { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | '<' { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | T_IS_SMALLER_OR_EQUAL { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | '>' { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } | T_IS_GREATER_OR_EQUAL { $$ = PintCompiler_Generator::nodeFactory('Binary',array('operator'=>$1)); } ; expr_without_variable: T_LIST '(' assignment_list ')' '=' expr { $$ = PintCompiler_Generator::nodeFactory('ListAssign',array( 'left'=>$3, 'right' => $6 )); } | variable '=' expr { $$ = PintCompiler_Generator::nodeFactory('Assign',array( 'left'=>$1, 'right' => $3 )); } | variable '=' '&' variable { $$ = PintCompiler_Generator::nodeFactory('Assign',array( 'left' => $1, 'right' => $3, 'byRef' => true, )); } | variable '=' '&' T_NEW class_name_reference ctor_arguments { $$ = PintCompiler_Generator::nodeFactory('CallConstructor',array( 'name' => $2, 'args' => $3, 'byRef' => true, )); } | T_NEW class_name_reference ctor_arguments { $$ = PintCompiler_Generator::nodeFactory('CallConstructor',array( 'name' => $2, 'args' => $3, 'byRef' => false, )); } | variable var_expr_operator expr { $$ = $2; $$->left = $1; $$->right = $3; } | expr expr_operator expr { $$ = $2; $$->left = $1; $$->right = $3; } | variable T_INC { $$ = PintCompiler_Generator::nodeFactory('UnaryMutator',array( 'operator' => $2, 'left' => $1 )); } | T_INC variable { $$ = PintCompiler_Generator::nodeFactory('UnaryMutator',array( 'operator' => $1, 'right' => $2 )); } | variable T_DEC { $$ = PintCompiler_Generator::nodeFactory('UnaryMutator',array( 'operator' => $2, 'left' => $1 )); } | T_DEC variable { $$ = PintCompiler_Generator::nodeFactory('UnaryMutator',array( 'operator' => $1, 'right' => $2 )); } | '+' expr { $$ = PintCompiler_Generator::nodeFactory('Unary',array( 'operator' => $1, 'right' => $2 )); } | '-' expr { $$ = PintCompiler_Generator::nodeFactory('Unary',array( 'operator' => $1, 'right' => $2 )); } | '!' expr { $$ = PintCompiler_Generator::nodeFactory('Unary',array( 'operator' => $1, 'right' => $2 )); } | '~' expr { $$ = PintCompiler_Generator::nodeFactory('Unary',array( 'operator' => $1, 'right' => $2 )); } | T_INSTANCEOF class_name_reference { $$ = PintCompiler_Generator::nodeFactory('InstanceOf',array( 'name' => $2 )); } | '(' expr ')' { $$ = PintCompiler_Generator::nodeFactory('ExpressionGroup',array( 'expression' => $2 )); } | expr '?' expr ':' expr { $$ = PintCompiler_Generator::nodeFactory('ShortIf',array( 'condition' => $1, 'true' => $3, 'false' => $5 )); } | internal_functions_in_yacc { $$ = $1; } | T_INT_CAST expr { $$ = PintCompiler_Generator::nodeFactory('Cast',array( 'expression' => $2, 'type' => 'int', )); } | T_DOUBLE_CAST expr { $$ = PintCompiler_Generator::nodeFactory('Cast',array( 'expression' => $2, 'type' => 'double', )); } | T_STRING_CAST expr { $$ = PintCompiler_Generator::nodeFactory('Cast',array( 'expression' => $2, 'type' => 'string', )); } | T_ARRAY_CAST expr { $$ = PintCompiler_Generator::nodeFactory('Cast',array( 'expression' => $2, 'type' => 'array', )); } | T_OBJECT_CAST expr { $$ = PintCompiler_Generator::nodeFactory('Cast',array( 'expression' => $2, 'type' => 'object', )); } | T_BOOL_CAST expr { $$ = PintCompiler_Generator::nodeFactory('Cast',array( 'expression' => $2, 'type' => 'bool', )); } | T_UNSET_CAST expr { $$ = PintCompiler_Generator::nodeFactory('Cast',array( 'expression' => $2, 'type' => 'unset', )); } | T_EXIT exit_expr { $$ = PintCompiler_Generator::nodeFactory('Die',array( 'expression' => $2, )); } | '@' expr { $$ = PintCompiler_Generator::nodeFactory('Silence',array( 'expression' => $2, )); } | scalar { $$ = $1; } | T_ARRAY '(' array_pair_list ')' { $$ = PintCompiler_Generator::nodeFactory('ArrayCreation',array( 'elements' => $3 )); } | '`' encaps_list '`' { $$ = PintCompiler_Generator::nodeFactory('Exec',array( 'args' => $2 )); } | T_PRINT expr { $$ = PintCompiler_Generator::nodeFactory('Echo',array( 'args' => $2 )); } ; function_call: T_STRING '(' function_call_parameter_list ')' { $$ = PintCompiler_Generator::nodeFactory('CallFunction',array( 'name' => $1, 'args' => $3, )); } | class_constant '(' function_call_parameter_list ')' { $$ = PintCompiler_Generator::nodeFactory('CallFunction',array( 'name' => $1, 'args' => $3, )); } | variable_without_objects '(' function_call_parameter_list ')' { $$ = PintCompiler_Generator::nodeFactory('CallFunction',array( 'name' => $1, 'args' => $3, )); } ; fully_qualified_class_name: T_STRING ; class_name_reference: T_STRING { $$ = $1; } | dynamic_class_name_reference { $$ = $1; } ; dynamic_class_name_reference: base_variable T_OBJECT_OPERATOR object_property dynamic_class_name_variable_properties { $$ = PintCompiler_Generator::nodeFactory('ObjectRef',array( 'object' => $1, 'property' => $3, 'callAfter' => $4 )); } | base_variable { $$ = $1; } ; dynamic_class_name_variable_properties: dynamic_class_name_variable_properties dynamic_class_name_variable_property { $$ = $1; $$[] = $2; } | /* empty */ { $$ = array(); } ; dynamic_class_name_variable_property: T_OBJECT_OPERATOR object_property { $$ = $1; //echo "ACCESS object property?"; print_R($1); } ; exit_expr: /* empty */ { $$ = null; } | '(' ')' { $$ = null; } | '(' expr ')' { $$ = $2; } ; ctor_arguments: /* empty */ { $$ = null; } | '(' function_call_parameter_list ')' { $$ = $2; } ; common_scalar: T_LNUMBER { $$ = PintCompiler_Generator::nodeFactory('LiteralLong',array('value'=>$1)); } | T_DNUMBER { $$ = PintCompiler_Generator::nodeFactory('LiteralFloat',array('value'=>$1)); } | T_CONSTANT_ENCAPSED_STRING { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>$1)); } | T_LINE { $$ = PintCompiler_Generator::nodeFactory('LiteralLong',array('value'=>0)); /* FIXME */ } | T_FILE { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>'filename')); /* FIXME */ } | T_CLASS_C { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>'classname')); /* FIXME */ } | T_FUNC_C { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>'funcname')); /* FIXME */ } ; const_scalar_expr: /* compile-time evaluated scalar expressions */ const_scalar | const_scalar_expr_list ; const_scalar_expr_list: const_scalar_expr T_SL const_scalar_expr { $$ = PintCompiler_Generator::nodeScalarFactory($2,$1,$3); } | const_scalar_expr T_SR const_scalar_expr { $$ = PintCompiler_Generator::nodeScalarFactory($2,$1,$2); } | const_scalar_expr T_LOGICAL_XOR const_scalar_expr { $$ = PintCompiler_Generator::nodeScalarFactory($1 xor $3); } | const_scalar_expr '|' const_scalar_expr { $$ = PintCompiler_Generator::nodeScalarFactory($2,$1,$3); } | const_scalar_expr '&' const_scalar_expr { $$ = PintCompiler_Generator::nodeScalarFactory($2,$1,$3); } | const_scalar_expr '^' const_scalar_expr { $$ = PintCompiler_Generator::nodeScalarFactory($2,$1,$3); } | const_scalar_expr '.' const_scalar_expr { $$ = PintCompiler_Generator::nodeScalarFactory($2,$1,$3); } | const_scalar_expr '+' const_scalar_expr { $$ = PintCompiler_Generator::nodeScalarFactory($2,$1,$3); } | const_scalar_expr '-' const_scalar_expr { $$ = PintCompiler_Generator::nodeScalarFactory($2,$1,$3); } | const_scalar_expr '*' const_scalar_expr { $$ = PintCompiler_Generator::nodeScalarFactory($2,$1,$3); } | const_scalar_expr '/' const_scalar_expr { $$ = PintCompiler_Generator::nodeScalarFactory($2,$1,$3); } | const_scalar_expr '%' const_scalar_expr { $$ = PintCompiler_Generator::nodeScalarFactory($2,$1,$3); } | '~' const_scalar_expr { $$ = PintCompiler_Generator::nodeScalarFactory($1,$2); } | '(' const_scalar_expr ')' { $$ = $1; } ; const_scalar: common_scalar { $$ = $1; } | T_STRING { $$ = $1; } | '+' const_scalar { $$ = PintCompiler_Generator::nodeScalarFactory($1,$2); } | '-' const_scalar { $$ = PintCompiler_Generator::nodeScalarFactory($1,$2); } | T_ARRAY '(' static_array_pair_list ')' { echo "UNSUPPORTED const_scalar T_ARRAY";exit; } | static_class_constant { $$ = $1; } ; static_scalar: /* compile-time evaluated scalars */ common_scalar { $$ = $1; } | T_STRING { $$ = $1; } | '+' static_scalar { $$ = PintCompiler_Generator::nodeScalarFactory($1,$2); } | '-' static_scalar { $$ = PintCompiler_Generator::nodeScalarFactory($1,$2); } | T_ARRAY '(' static_array_pair_list ')' { echo "UNSUPPORTED const_scalar T_ARRAY";exit; } | static_class_constant { $$ = $1; } ; static_class_constant: T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING { $$ = $1 . '::' . $3; } ; scalar: T_STRING { $$ = $1; } | T_STRING_VARNAME { $$ = $1; } | class_constant { $$ = $1; } | common_scalar { $$ = $1; } | '"' encaps_list '"' { $args = array(); foreach($2 as $arg) { $arg->quote = '"'; $args[] = $arg; } $$ = PintCompiler_Generator::nodeFactory('BinaryString',array('args' => $args)); } | '\'' encaps_list '\'' { $args = array(); foreach($2 as $arg) { $arg->quote = "'"; $args[] = $arg; } $$ = PintCompiler_Generator::nodeFactory('BinaryString',array('args' => $args)); } | T_START_HEREDOC encaps_list T_END_HEREDOC { $args = array(); foreach($2 as $arg) { $arg->quote = $1; $args[] = $arg; } $$ = PintCompiler_Generator::nodeFactory('BinaryString',array('args' => $args)); } ; static_array_pair_list: /* empty */ { $$ = null; } | non_empty_static_array_pair_list possible_comma { $$ = $1; } ; possible_comma: /* empty */ { $$ = null; } | ',' ; non_empty_static_array_pair_list: non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW static_scalar { echo "NOT SUPPORTED YET: non_empty_static_array_pair_list";exit; } | non_empty_static_array_pair_list ',' static_scalar { echo "NOT SUPPORTED YET: non_empty_static_array_pair_list";exit; } | static_scalar T_DOUBLE_ARROW static_scalar { echo "NOT SUPPORTED YET: non_empty_static_array_pair_list";exit; } | static_scalar { echo "NOT SUPPORTED YET: non_empty_static_array_pair_list";exit; } ; expr: variable { $$ = $1; } | expr_without_variable { $$ = $1; } ; variable: base_variable_with_function_calls T_OBJECT_OPERATOR object_property method_or_not variable_properties { // $something->something()->something.... if ($4 === false) { $$ = PintCompiler_Generator::nodeFactory('MemberAccess', array( 'name' => $3, 'object'=>$1, 'extra' =>$5 )); return; } $$ = PintCompiler_Generator::nodeFactory('MemberAccess', array( 'args' => $4, 'name' => $3, 'object'=>$1, 'extra' =>$5 )); } | base_variable_with_function_calls { $$ = $1; //echo "BV _WITH FUNC CALLS";print_r($$); } ; variable_properties: variable_properties variable_property { $$ = $1; $$[] = $2; } | variable_property { $$ = array($1); } | /* empty */ { $$ = false; } ; variable_property: T_OBJECT_OPERATOR object_property method_or_not { if ($3 === false) { $$ = PintCompiler_Generator::nodeFactory('MemberAccess', array( 'name' => $2, )); return; } $$ = PintCompiler_Generator::nodeFactory('MemberAccess', array( 'args' => $3, 'name' => $2, )); } ; method_or_not: '(' function_call_parameter_list ')' { $$ = $2; } | /* empty */ { $$ = false; } ; variable_without_objects: reference_variable { $$ = $1; } | simple_indirect_reference reference_variable { echo "NOT SUPPORTED YET: variable_without_objects";exit; } ; static_member: fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { echo "NOT SUPPORTED YET:static_member";exit; } ; base_variable_with_function_calls: base_variable { $$ = $1; } | function_call { $$ = $1; } ; base_variable: reference_variable { $$ = $1; } | simple_indirect_reference reference_variable { echo "NOT SUPPORTED YET: base_variable";exit; } | static_member { $$ = $1;} ; reference_variable: reference_variable '[' dim_offset ']' { $$ = PintCompiler_Generator::nodeFactory('ElementAccess', array( 'parent' => $1, 'element' => $3, )); } | reference_variable '{' expr '}' { echo "NOT SUPPORTED YET: reference_variable";exit; } | compound_variable { $$ = $1; } ; compound_variable: T_VARIABLE { $$ = PintCompiler_Generator::nodeFactory('VariableAccess', array( 'name' => $1, )); } | '$' '{' expr '}' $$ = PintCompiler_Generator::nodeFactory('VariableAccessIndirect', array( 'expression' => $3, )); ; dim_offset: /* empty */ { $$ = null; } | expr { $$ = $1; } ; object_property: object_dim_list | variable_without_objects ; object_dim_list: object_dim_list '[' dim_offset ']' { echo "NOT SUPPORTED YET: object_dim_list";exit; } | object_dim_list '{' expr '}' { echo "NOT SUPPORTED YET: object_dim_list";exit; } | variable_name { $$ = $1; } ; variable_name: T_STRING { $$ = $1; } | '{' expr '}' { $$ = $2; } ; simple_indirect_reference: '$' | simple_indirect_reference '$' ; assignment_list: assignment_list ',' assignment_list_element | assignment_list_element ; assignment_list_element: variable | T_LIST '(' assignment_list ')' | /* empty */ ; array_pair_list: /* empty */ { $$ = array(); } | non_empty_array_pair_list possible_comma { $$ = $1; } ; non_empty_array_pair_list: non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr { $$ = $1; $$[$3] = $5; } | non_empty_array_pair_list ',' expr { $$ = $1; $$[] = $3; } | expr T_DOUBLE_ARROW expr { $$ = array($1 => $3); } | expr { $$ = array($1); } | non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' variable { $$ = $1 ; $6->byRef = true; $$[$3] = $6; } | non_empty_array_pair_list ',' '&' variable { $$ = $1 ; $4->byRef = true; $$[] = $4; } | expr T_DOUBLE_ARROW '&' variable { $4->byRef = true; $$ = array($1=> $4); } | '&' variable { $1->byRef = true; $$ = array($1); } ; encaps_list: encaps_list encaps_list_item { $$ = $1; $$[] = $2; } | encaps_list_item { $$ = array($1); } | /* empty */ { $$ = array(); } encaps_list_item: encaps_var { $$ = $1; } | T_STRING { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>$1));} | T_NUM_STRING { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>$1)); } | T_ENCAPSED_AND_WHITESPACE { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>$1));} | T_CHARACTER { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>$1));} | T_BAD_CHARACTER { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>$1));} | '[' { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>$1)); } | ']' { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>$1)); } | '{' { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>$1)); } | '}' { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>$1)); } | T_OBJECT_OPERATOR { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>$1)); } ; encaps_var: T_VARIABLE { $$ = PintCompiler_Generator::nodeFactory('VariableAccess',array('name'=>$1)); } | T_VARIABLE '[' encaps_var_offset ']' { $$ = PintCompiler_Generator::nodeFactory('ElementAccess', array( 'parent'=>$1, 'element' => $3 )); } | T_VARIABLE T_OBJECT_OPERATOR T_STRING { $$ = PintCompiler_Generator::nodeFactory('MemberAccess', array( 'property'=>$1, 'variable' => $3 )); } | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = $2; } | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' { echo "NOT SUPPORTED YET: encaps_var";exit; } | T_CURLY_OPEN variable '}' { $$ = $2; } ; encaps_var_offset: T_STRING { $$ = new PHPSharp_Node_LiteralString($1); } | T_NUM_STRING { $$ = PintCompiler_Generator::nodeFactory('LiteralString',array('value'=>$1)); } | T_VARIABLE { $$ = PintCompiler_Generator::nodeFactory('VariableAccess',array('name'=>$1));} ; internal_functions_in_yacc: T_ISSET '(' isset_variables ')' { echo "NOT SUPPORTED YET: interal functions";exit; } | T_EMPTY '(' variable ')' { echo "NOT SUPPORTED YET: interal functions";exit; } | T_INCLUDE expr { echo "NOT SUPPORTED YET: interal functions";exit; } | T_INCLUDE_ONCE expr { echo "NOT SUPPORTED YET: interal functions";exit; } | T_EVAL '(' expr ')' { echo "NOT SUPPORTED YET: interal functions";exit; } | T_REQUIRE expr { echo "NOT SUPPORTED YET: interal functions";exit; } | T_REQUIRE_ONCE expr { echo "NOT SUPPORTED YET: interal functions";exit; } ; isset_variables: variable | isset_variables ',' variable ; class_constant: fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING ; %% }