• R/O
  • SSH
  • HTTPS

eircompile: Commit


Commit MetaInfo

Revision57 (tree)
Time2021-11-23 18:27:49
Authorquiret

Log Message

- added extension-before-extended attribute to StepExtend so that executed steps can be reordered more flexibly
- added COS control structure unit tests (still have to finalize them by working on type-system semantics)

Change Summary

Incremental Difference

--- testcompiler/src/cos_tests.cpp (revision 56)
+++ testcompiler/src/cos_tests.cpp (revision 57)
@@ -235,7 +235,7 @@
235235
236236 struct IfStatement : public COSNode
237237 {
238- inline IfStatement( Operation *condition = nullptr, COSNode *true_branch = nullptr, COSNode *false_branch = nullptr ) noexcept : condition( condition ), true_branch( true_branch ), false_branch( false_branch )
238+ inline IfStatement( COSNode *condition = nullptr, COSNode *true_branch = nullptr, COSNode *false_branch = nullptr ) noexcept : condition( condition ), true_branch( true_branch ), false_branch( false_branch )
239239 {
240240 return;
241241 }
@@ -251,13 +251,13 @@
251251 right.false_branch = nullptr;
252252 }
253253
254- Operation *condition;
254+ COSNode *condition;
255255 COSNode *true_branch;
256256 COSNode *false_branch;
257257 };
258258 struct WhileLoopStatement : public COSNode
259259 {
260- inline WhileLoopStatement( Operation *condition = nullptr, COSNode *exec = nullptr ) noexcept : condition( condition ), exec( exec )
260+ inline WhileLoopStatement( COSNode *condition = nullptr, COSNode *exec = nullptr ) noexcept : condition( condition ), exec( exec )
261261 {
262262 return;
263263 }
@@ -271,12 +271,12 @@
271271 right.exec = nullptr;
272272 }
273273
274- Operation *condition;
274+ COSNode *condition;
275275 COSNode *exec;
276276 };
277277 struct ForLoopStatement : public COSNode
278278 {
279- inline ForLoopStatement( COSNode *init = nullptr, Operation *condition = nullptr, Operation *iteration = nullptr, COSNode *exec = nullptr ) noexcept : init( init ), condition( condition ), iteration( iteration ), exec( exec )
279+ inline ForLoopStatement( COSNode *init = nullptr, COSNode *condition = nullptr, COSNode *iteration = nullptr, COSNode *exec = nullptr ) noexcept : init( init ), condition( condition ), iteration( iteration ), exec( exec )
280280 {
281281 return;
282282 }
@@ -295,8 +295,8 @@
295295 }
296296
297297 COSNode *init;
298- Operation *condition;
299- Operation *iteration;
298+ COSNode *condition;
299+ COSNode *iteration;
300300 COSNode *exec;
301301 };
302302 struct ContinueStatement : public COSNode
@@ -443,22 +443,20 @@
443443 };
444444 struct TryStatement : public COSNode
445445 {
446- inline TryStatement( COSNode *try_body = nullptr, CatchStatement *error = nullptr ) noexcept : try_body( try_body ), error( error )
446+ inline TryStatement( COSNode *try_body = nullptr, depVector <CatchStatement*> errors = {} ) noexcept : try_body( try_body ), errors( std::move( errors ) )
447447 {
448448 return;
449449 }
450450 inline TryStatement( const TryStatement& ) = default;
451- inline TryStatement( TryStatement&& right ) noexcept
451+ inline TryStatement( TryStatement&& right ) noexcept : errors( std::move( right.errors ) )
452452 {
453453 this->try_body = right.try_body;
454- this->error = right.error;
455454
456455 right.try_body = nullptr;
457- right.error = nullptr;
458456 }
459457
460458 COSNode *try_body;
461- CatchStatement *error;
459+ depVector <CatchStatement*> errors;
462460 };
463461
464462 struct StructStatement : public COSNode
@@ -709,7 +707,7 @@
709707 lexer.GetNamedProduction( "function" ).setSelector <direct_obj_build_selector <char, FunctionDefinition, COSNode, function_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
710708 }
711709 assert( lexer.CompileProduction( compiler, "paramlist", "[<0>declaration, spaces ',' spaces]" ) == true );
712- assert( lexer.CompileProduction( compiler, "funcbody", "^!(block, statement+funcstatement)" ) == true );
710+ assert( lexer.CompileProduction( compiler, "funcbody", "^!(block, <b> statement+funcstatement)" ) == true );
713711 assert( lexer.CompileProduction( compiler, "funcstatement", "\"return\" spaces (op:operation spaces)^0:1 ';'" ) == true );
714712 {
715713 struct return_dispatcher
@@ -1573,7 +1571,7 @@
15731571 {
15741572 if ( attrib == "cond" )
15751573 {
1576- assign_to->condition = dynamic_cast <Operation*> ( node );
1574+ assign_to->condition = node;
15771575 }
15781576 else if ( attrib == "body" )
15791577 {
@@ -1584,7 +1582,7 @@
15841582 };
15851583 lexer.GetNamedProduction( "whileloop" ).setSelector <direct_obj_build_selector <char, WhileLoopStatement, COSNode, while_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
15861584 }
1587- assert( lexer.CompileProduction( compiler, "loopbody", "^(extended statement, loopstatement)" ) == true );
1585+ assert( lexer.CompileProduction( compiler, "loopbody", "^(extended statement, <b> loopstatement)" ) == true );
15881586 assert( lexer.CompileProduction( compiler, "loopstatement", "\"break\" spaces ';'" ) == true );
15891587 {
15901588 lexer.GetNamedProduction( "loopstatement" ).GetLastStep()->setConstructor(
@@ -1611,7 +1609,7 @@
16111609 {
16121610 if ( attrib == "cond" )
16131611 {
1614- assign_to->condition = dynamic_cast <Operation*> ( node );
1612+ assign_to->condition = node;
16151613 return true;
16161614 }
16171615 else if ( attrib == "true_branch" )
@@ -1680,7 +1678,7 @@
16801678 }
16811679 else if ( attrib == "error" )
16821680 {
1683- assign_to->error = dynamic_cast <CatchStatement*> ( node );
1681+ assign_to->errors.AddToBack( dynamic_cast <CatchStatement*> ( node ) );
16841682 return true;
16851683 }
16861684 return false;
@@ -1701,12 +1699,12 @@
17011699 }
17021700 else if ( attrib == "loop_cond" )
17031701 {
1704- assign_to->condition = dynamic_cast <Operation*> ( node );
1702+ assign_to->condition = node;
17051703 return true;
17061704 }
17071705 else if ( attrib == "loop_iteration" )
17081706 {
1709- assign_to->iteration = dynamic_cast <Operation*> ( node );
1707+ assign_to->iteration = node;
17101708 return true;
17111709 }
17121710 else if ( attrib == "body" )
@@ -1720,7 +1718,7 @@
17201718 lexer.GetNamedProduction( "forloop" ).setSelector <direct_obj_build_selector <char, ForLoopStatement, COSNode, for_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
17211719 }
17221720 assert( lexer.CompileProduction( compiler, "loop", "whileloop | forloop" ) == true );
1723- assert( lexer.CompileProduction( compiler, "structdef", "\"struct\" spaces name:spec spaces ^!(body:block, statement+typestatement) spaces ';'" ) == true );
1721+ assert( lexer.CompileProduction( compiler, "structdef", "\"struct\" spaces name:spec spaces ^!(body:block, <b> statement+typestatement) spaces ';'" ) == true );
17241722 {
17251723 struct struct_dispatcher
17261724 {
@@ -3052,7 +3050,1032 @@
30523050
30533051 printf( "testing COS control structures..." );
30543052 {
3055- // TODO.
3053+ // 1)
3054+ {
3055+ COSNode *_root = lexer.StartProduction( "if (1==1){ a=2; }else{ a = 4; }" );
3056+
3057+ IfStatement *root = dynamic_cast <IfStatement*> ( _root );
3058+
3059+ CompareEqualityOperation *cond = dynamic_cast <CompareEqualityOperation*> ( root->condition );
3060+
3061+ assert( cond != nullptr );
3062+
3063+ NumberString *first = dynamic_cast <NumberString*> ( cond->left );
3064+ NumberString *second = dynamic_cast <NumberString*> ( cond->right );
3065+
3066+ assert( first != nullptr );
3067+ assert( first->numeric_string == "1" );
3068+ assert( second != nullptr );
3069+ assert( second->numeric_string == "1" );
3070+
3071+ first->Delete();
3072+ second->Delete();
3073+
3074+ BlockStatement *true_block = dynamic_cast <BlockStatement*> ( root->true_branch );
3075+
3076+ assert( true_block != nullptr );
3077+ assert( true_block->statements.GetCount() == 1 );
3078+
3079+ AssignmentOperation *true_assignment = dynamic_cast <AssignmentOperation*> ( true_block->statements[0] );
3080+
3081+ assert( true_assignment != nullptr );
3082+
3083+ SpecifierString *third = dynamic_cast <SpecifierString*> ( true_assignment->left );
3084+ NumberString *fourth = dynamic_cast <NumberString*> ( true_assignment->right );
3085+
3086+ assert( third != nullptr );
3087+ assert( third->string == "a" );
3088+ assert( fourth != nullptr );
3089+ assert( fourth->numeric_string == "2" );
3090+
3091+ third->Delete();
3092+ fourth->Delete();
3093+
3094+ true_assignment->Delete();
3095+ true_block->Delete();
3096+
3097+ BlockStatement *false_block = dynamic_cast <BlockStatement*> ( root->false_branch );
3098+
3099+ assert( false_block != nullptr );
3100+ assert( false_block->statements.GetCount() == 1 );
3101+
3102+ AssignmentOperation *false_assignment = dynamic_cast <AssignmentOperation*> ( false_block->statements[0] );
3103+
3104+ assert( false_assignment != nullptr );
3105+
3106+ SpecifierString *fifth = dynamic_cast <SpecifierString*> ( false_assignment->left );
3107+ NumberString *sixth = dynamic_cast <NumberString*> ( false_assignment->right );
3108+
3109+ assert( fifth != nullptr );
3110+ assert( fifth->string == "a" );
3111+ assert( sixth != nullptr );
3112+ assert( sixth->numeric_string == "4" );
3113+
3114+ fifth->Delete();
3115+ sixth->Delete();
3116+
3117+ false_assignment->Delete();
3118+ false_block->Delete();
3119+
3120+ root->Delete();
3121+ }
3122+
3123+ // 2)
3124+ {
3125+ COSNode *_root = lexer.StartProduction( "{a=2; {b=3;}} 2=1;" );
3126+
3127+ Program *root = dynamic_cast <Program*> ( _root );
3128+
3129+ assert( root != nullptr );
3130+ assert( root->statements.GetCount() == 2 );
3131+
3132+ BlockStatement *root1 = dynamic_cast <BlockStatement*> ( root->statements[0] );
3133+
3134+ assert( root1 != nullptr );
3135+ assert( root1->statements.GetCount() == 2 );
3136+
3137+ AssignmentOperation *first_root1 = dynamic_cast <AssignmentOperation*> ( root1->statements[0] );
3138+
3139+ assert( first_root1 != nullptr );
3140+
3141+ SpecifierString *first = dynamic_cast <SpecifierString*> ( first_root1->left );
3142+
3143+ assert( first != nullptr );
3144+ assert( first->string == "a" );
3145+
3146+ first->Delete();
3147+
3148+ NumberString *second = dynamic_cast <NumberString*> ( first_root1->right );
3149+
3150+ assert( second != nullptr );
3151+ assert( second->numeric_string == "2" );
3152+
3153+ second->Delete();
3154+
3155+ first_root1->Delete();
3156+
3157+ BlockStatement *second_root1 = dynamic_cast <BlockStatement*> ( root1->statements[1] );
3158+
3159+ assert( second_root1 != nullptr );
3160+ assert( second_root1->statements.GetCount() == 1 );
3161+
3162+ AssignmentOperation *sub_second_root1 = dynamic_cast <AssignmentOperation*> ( second_root1->statements[0] );
3163+
3164+ assert( sub_second_root1 != nullptr );
3165+
3166+ SpecifierString *third = dynamic_cast <SpecifierString*> ( sub_second_root1->left );
3167+ NumberString *fourth = dynamic_cast <NumberString*> ( sub_second_root1->right );
3168+
3169+ assert( third != nullptr );
3170+ assert( third->string == "b" );
3171+ assert( fourth != nullptr );
3172+ assert( fourth->numeric_string == "3" );
3173+
3174+ third->Delete();
3175+ fourth->Delete();
3176+
3177+ sub_second_root1->Delete();
3178+ second_root1->Delete();
3179+ root1->Delete();
3180+
3181+ AssignmentOperation *root2 = dynamic_cast <AssignmentOperation*> ( root->statements[1] );
3182+
3183+ assert( root2 != nullptr );
3184+
3185+ NumberString *fifth = dynamic_cast <NumberString*> ( root2->left );
3186+ NumberString *sixth = dynamic_cast <NumberString*> ( root2->right );
3187+
3188+ assert( fifth != nullptr );
3189+ assert( fifth->numeric_string == "2" );
3190+ assert( sixth != nullptr );
3191+ assert( sixth->numeric_string == "1" );
3192+
3193+ fifth->Delete();
3194+ sixth->Delete();
3195+
3196+ root2->Delete();
3197+ }
3198+
3199+ // 3)
3200+ {
3201+ COSNode *_root = lexer.StartProduction( "while(true)0==0;" );
3202+
3203+ WhileLoopStatement *root = dynamic_cast <WhileLoopStatement*> ( _root );
3204+
3205+ assert( root != nullptr );
3206+
3207+ SpecifierString *cond = dynamic_cast <SpecifierString*> ( root->condition );
3208+
3209+ assert( cond != nullptr );
3210+ assert( cond->string == "true" );
3211+
3212+ cond->Delete();
3213+
3214+ CompareEqualityOperation *exec = dynamic_cast <CompareEqualityOperation*> ( root->exec );
3215+
3216+ assert( exec != nullptr );
3217+
3218+ NumberString *first = dynamic_cast <NumberString*> ( exec->left );
3219+ NumberString *second = dynamic_cast <NumberString*> ( exec->right );
3220+
3221+ assert( first != nullptr );
3222+ assert( first->numeric_string == "0" );
3223+ assert( second != nullptr );
3224+ assert( second->numeric_string == "0" );
3225+
3226+ first->Delete();
3227+ second->Delete();
3228+
3229+ exec->Delete();
3230+
3231+ root->Delete();
3232+ }
3233+
3234+ // 4)
3235+ {
3236+ COSNode *_root = lexer.StartProduction( "while(a<2){a++;if(a==2)break;}" );
3237+
3238+ WhileLoopStatement *root = dynamic_cast <WhileLoopStatement*> ( _root );
3239+
3240+ assert( root != nullptr );
3241+
3242+ CompareLessThanOperation *cond = dynamic_cast <CompareLessThanOperation*> ( root->condition );
3243+
3244+ assert( cond != nullptr );
3245+
3246+ SpecifierString *first = dynamic_cast <SpecifierString*> ( cond->left );
3247+ NumberString *second = dynamic_cast <NumberString*> ( cond->right );
3248+
3249+ assert( first != nullptr );
3250+ assert( first->string == "a" );
3251+ assert( second != nullptr );
3252+ assert( second->numeric_string == "2" );
3253+
3254+ first->Delete();
3255+ second->Delete();
3256+ cond->Delete();
3257+
3258+ BlockStatement *block = dynamic_cast <BlockStatement*> ( root->exec );
3259+
3260+ assert( block != nullptr );
3261+ assert( block->statements.GetCount() == 2 );
3262+
3263+ PostIncrementOperation *block_first = dynamic_cast <PostIncrementOperation*> ( block->statements[0] );
3264+
3265+ assert( block_first != nullptr );
3266+
3267+ SpecifierString *third = dynamic_cast <SpecifierString*> ( block_first->op );
3268+
3269+ assert( third != nullptr );
3270+ assert( third->string == "a" );
3271+
3272+ third->Delete();
3273+
3274+ block_first->Delete();
3275+
3276+ IfStatement *block_second = dynamic_cast <IfStatement*> ( block->statements[1] );
3277+
3278+ assert( block_second != nullptr );
3279+ assert( block_second->false_branch == nullptr );
3280+
3281+ CompareEqualityOperation *block_second_cond = dynamic_cast <CompareEqualityOperation*> ( block_second->condition );
3282+
3283+ assert( block_second_cond != nullptr );
3284+
3285+ SpecifierString *fourth = dynamic_cast <SpecifierString*> ( block_second_cond->left );
3286+
3287+ assert( fourth != nullptr );
3288+ assert( fourth->string == "a" );
3289+
3290+ fourth->Delete();
3291+
3292+ NumberString *fifth = dynamic_cast <NumberString*> ( block_second_cond->right );
3293+
3294+ assert( fifth != nullptr );
3295+ assert( fifth->numeric_string == "2" );
3296+
3297+ fifth->Delete();
3298+
3299+ block_second_cond->Delete();
3300+
3301+ BreakStatement *block_second_trueb = dynamic_cast <BreakStatement*> ( block_second->true_branch );
3302+
3303+ assert( block_second_trueb != nullptr );
3304+
3305+ block_second_trueb->Delete();
3306+
3307+ block_second->Delete();
3308+ block->Delete();
3309+ root->Delete();
3310+ }
3311+
3312+ // 5)
3313+ {
3314+ COSNode *_root = lexer.StartProduction( "if(false)t=0;" );
3315+
3316+ IfStatement *root = dynamic_cast <IfStatement*> ( _root );
3317+
3318+ assert( root != nullptr );
3319+
3320+ SpecifierString *cond = dynamic_cast <SpecifierString*> ( root->condition );
3321+
3322+ assert( cond != nullptr );
3323+ assert( cond->string == "false" );
3324+
3325+ cond->Delete();
3326+
3327+ AssignmentOperation *true_branch = dynamic_cast <AssignmentOperation*> ( root->true_branch );
3328+
3329+ assert( true_branch != nullptr );
3330+
3331+ SpecifierString *first = dynamic_cast <SpecifierString*> ( true_branch->left );
3332+
3333+ assert( first != nullptr );
3334+ assert( first->string == "t" );
3335+
3336+ first->Delete();
3337+
3338+ NumberString *second = dynamic_cast <NumberString*> ( true_branch->right );
3339+
3340+ assert( second != nullptr );
3341+ assert( second->numeric_string == "0" );
3342+
3343+ second->Delete();
3344+
3345+ true_branch->Delete();
3346+ root->Delete();
3347+ }
3348+
3349+ // 6)
3350+ {
3351+ COSNode *_root = lexer.StartProduction( "for(n=0;n<5;n++){output(n);continue;}" );
3352+
3353+ ForLoopStatement *root = dynamic_cast <ForLoopStatement*> ( _root );
3354+
3355+ assert( root != nullptr );
3356+
3357+ AssignmentOperation *init = dynamic_cast <AssignmentOperation*> ( root->init );
3358+
3359+ assert( init != nullptr );
3360+
3361+ SpecifierString *init_left = dynamic_cast <SpecifierString*> ( init->left );
3362+
3363+ assert( init_left != nullptr );
3364+ assert( init_left->string == "n" );
3365+
3366+ init_left->Delete();
3367+
3368+ NumberString *init_right = dynamic_cast <NumberString*> ( init->right );
3369+
3370+ assert( init_right != nullptr );
3371+ assert( init_right->numeric_string == "0" );
3372+
3373+ init_right->Delete();
3374+
3375+ init->Delete();
3376+
3377+ CompareLessThanOperation *cond = dynamic_cast <CompareLessThanOperation*> ( root->condition );
3378+
3379+ assert( cond != nullptr );
3380+
3381+ SpecifierString *cond_left = dynamic_cast <SpecifierString*> ( cond->left );
3382+
3383+ assert( cond_left != nullptr );
3384+ assert( cond_left->string == "n" );
3385+
3386+ cond_left->Delete();
3387+
3388+ NumberString *cond_right = dynamic_cast <NumberString*> ( cond->right );
3389+
3390+ assert( cond_right != nullptr );
3391+ assert( cond_right->numeric_string == "5" );
3392+
3393+ cond_right->Delete();
3394+
3395+ cond->Delete();
3396+
3397+ PostIncrementOperation *iter = dynamic_cast <PostIncrementOperation*> ( root->iteration );
3398+
3399+ assert( iter != nullptr );
3400+
3401+ SpecifierString *iter_sub = dynamic_cast <SpecifierString*> ( iter->op );
3402+
3403+ assert( iter_sub != nullptr );
3404+ assert( iter_sub->string == "n" );
3405+
3406+ iter_sub->Delete();
3407+
3408+ iter->Delete();
3409+
3410+ BlockStatement *true_branch = dynamic_cast <BlockStatement*> ( root->exec );
3411+
3412+ assert( true_branch != nullptr );
3413+ assert( true_branch->statements.GetCount() == 2 );
3414+
3415+ FunctionCallOperation *true_branch_first = dynamic_cast <FunctionCallOperation*> ( true_branch->statements[0] );
3416+
3417+ assert( true_branch_first != nullptr );
3418+ assert( true_branch_first->params.GetCount() == 1 );
3419+
3420+ SpecifierString *tbfirst_what = dynamic_cast <SpecifierString*> ( true_branch_first->what );
3421+
3422+ assert( tbfirst_what != nullptr );
3423+ assert( tbfirst_what->string == "output" );
3424+
3425+ tbfirst_what->Delete();
3426+
3427+ SpecifierString *tbfirst_first = dynamic_cast <SpecifierString*> ( true_branch_first->params[0] );
3428+
3429+ assert( tbfirst_first != nullptr );
3430+ assert( tbfirst_first->string == "n" );
3431+
3432+ tbfirst_first->Delete();
3433+
3434+ true_branch_first->Delete();
3435+
3436+ ContinueStatement *true_branch_second = dynamic_cast <ContinueStatement*> ( true_branch->statements[1] );
3437+
3438+ assert( true_branch_second != nullptr );
3439+
3440+ true_branch_second->Delete();
3441+
3442+ true_branch->Delete();
3443+ root->Delete();
3444+ }
3445+
3446+ // 7)
3447+ {
3448+ COSNode *_root = lexer.StartProduction( "while(true){i++;for(n=0;n<i;n++){print(n);if(doBreak())break;}continue;}" );
3449+
3450+ WhileLoopStatement *root = dynamic_cast <WhileLoopStatement*> ( _root );
3451+
3452+ assert( root != nullptr );
3453+
3454+ SpecifierString *cond = dynamic_cast <SpecifierString*> ( root->condition );
3455+
3456+ assert( cond != nullptr );
3457+ assert( cond->string == "true" );
3458+
3459+ cond->Delete();
3460+
3461+ BlockStatement *exec = dynamic_cast <BlockStatement*> ( root->exec );
3462+
3463+ assert( exec != nullptr );
3464+ assert( exec->statements.GetCount() == 3 );
3465+
3466+ PostIncrementOperation *exec_first = dynamic_cast <PostIncrementOperation*> ( exec->statements[0] );
3467+
3468+ assert( exec_first != nullptr );
3469+
3470+ SpecifierString *exec_first_sub = dynamic_cast <SpecifierString*> ( exec_first->op );
3471+
3472+ assert( exec_first_sub != nullptr );
3473+ assert( exec_first_sub->string == "i" );
3474+
3475+ exec_first_sub->Delete();
3476+
3477+ exec_first->Delete();
3478+
3479+ ForLoopStatement *exec_second = dynamic_cast <ForLoopStatement*> ( exec->statements[1] );
3480+
3481+ assert( exec_second != nullptr );
3482+
3483+ AssignmentOperation *exec_second_init = dynamic_cast <AssignmentOperation*> ( exec_second->init );
3484+
3485+ assert( exec_second_init != nullptr );
3486+
3487+ SpecifierString *exec_second_init_left = dynamic_cast <SpecifierString*> ( exec_second_init->left );
3488+
3489+ assert( exec_second_init_left != nullptr );
3490+ assert( exec_second_init_left->string == "n" );
3491+
3492+ exec_second_init_left->Delete();
3493+
3494+ NumberString *exec_second_init_right = dynamic_cast <NumberString*> ( exec_second_init->right );
3495+
3496+ assert( exec_second_init_right != nullptr );
3497+ assert( exec_second_init_right->numeric_string == "0" );
3498+
3499+ exec_second_init_right->Delete();
3500+
3501+ exec_second_init->Delete();
3502+
3503+ CompareLessThanOperation *exec_second_cond = dynamic_cast <CompareLessThanOperation*> ( exec_second->condition );
3504+
3505+ assert( exec_second_cond != nullptr );
3506+
3507+ SpecifierString *exec_second_cond_left = dynamic_cast <SpecifierString*> ( exec_second_cond->left );
3508+
3509+ assert( exec_second_cond_left != nullptr );
3510+ assert( exec_second_cond_left->string == "n" );
3511+
3512+ exec_second_cond_left->Delete();
3513+
3514+ SpecifierString *exec_second_cond_right = dynamic_cast <SpecifierString*> ( exec_second_cond->right );
3515+
3516+ assert( exec_second_cond_right != nullptr );
3517+ assert( exec_second_cond_right->string == "i" );
3518+
3519+ exec_second_cond_right->Delete();
3520+
3521+ exec_second_cond->Delete();
3522+
3523+ PostIncrementOperation *exec_second_iter = dynamic_cast <PostIncrementOperation*> ( exec_second->iteration );
3524+
3525+ assert( exec_second_iter != nullptr );
3526+
3527+ SpecifierString *exec_second_iter_sub = dynamic_cast <SpecifierString*> ( exec_second_iter->op );
3528+
3529+ assert( exec_second_iter_sub != nullptr );
3530+ assert( exec_second_iter_sub->string == "n" );
3531+
3532+ exec_second_iter_sub->Delete();
3533+
3534+ exec_second_iter->Delete();
3535+
3536+ BlockStatement *exec_second_exec = dynamic_cast <BlockStatement*> ( exec_second->exec );
3537+
3538+ assert( exec_second_exec != nullptr );
3539+ assert( exec_second_exec->statements.GetCount() == 2 );
3540+
3541+ FunctionCallOperation *exec_second_exec_first = dynamic_cast <FunctionCallOperation*> ( exec_second_exec->statements[0] );
3542+
3543+ assert( exec_second_exec_first != nullptr );
3544+ assert( exec_second_exec_first->params.GetCount() == 1 );
3545+
3546+ SpecifierString *exec_second_exec_first_left = dynamic_cast <SpecifierString*> ( exec_second_exec_first->what );
3547+
3548+ assert( exec_second_exec_first_left != nullptr );
3549+ assert( exec_second_exec_first_left->string == "print" );
3550+
3551+ exec_second_exec_first_left->Delete();
3552+
3553+ SpecifierString *exec_second_exec_first_right = dynamic_cast <SpecifierString*> ( exec_second_exec_first->params[0] );
3554+
3555+ assert( exec_second_exec_first_right != nullptr );
3556+ assert( exec_second_exec_first_right->string == "n" );
3557+
3558+ exec_second_exec_first_right->Delete();
3559+
3560+ exec_second_exec_first->Delete();
3561+
3562+ IfStatement *exec_second_exec_second = dynamic_cast <IfStatement*> ( exec_second_exec->statements[1] );
3563+
3564+ assert( exec_second_exec_second != nullptr );
3565+
3566+ FunctionCallOperation *exec_second_exec_second_cond = dynamic_cast <FunctionCallOperation*> ( exec_second_exec_second->condition );
3567+
3568+ assert( exec_second_exec_second_cond != nullptr );
3569+ assert( exec_second_exec_second_cond->params.GetCount() == 0 );
3570+
3571+ SpecifierString *exec_second_exec_second_cond_what = dynamic_cast <SpecifierString*> ( exec_second_exec_second_cond->what );
3572+
3573+ assert( exec_second_exec_second_cond_what != nullptr );
3574+ assert( exec_second_exec_second_cond_what->string == "doBreak" );
3575+
3576+ exec_second_exec_second_cond_what->Delete();
3577+
3578+ exec_second_exec_second_cond->Delete();
3579+
3580+ BreakStatement *exec_second_exec_second_tb = dynamic_cast <BreakStatement*> ( exec_second_exec_second->true_branch );
3581+
3582+ assert( exec_second_exec_second_tb != nullptr );
3583+
3584+ exec_second_exec_second_tb->Delete();
3585+
3586+ exec_second_exec_second->Delete();
3587+
3588+ exec_second_exec->Delete();
3589+
3590+ exec_second->Delete();
3591+
3592+ ContinueStatement *exec_third = dynamic_cast <ContinueStatement*> ( exec->statements[2] );
3593+
3594+ assert( exec_third != nullptr );
3595+
3596+ exec_third->Delete();
3597+
3598+ exec->Delete();
3599+
3600+ root->Delete();
3601+ }
3602+
3603+ // 8)
3604+ {
3605+ COSNode *_root = lexer.StartProduction( "try{if(a=0)throw;}catch(){a=1;}" );
3606+
3607+ TryStatement *root = dynamic_cast <TryStatement*> ( _root );
3608+
3609+ assert( root != nullptr );
3610+ assert( root->errors.GetCount() == 1 );
3611+
3612+ BlockStatement *exec = dynamic_cast <BlockStatement*> ( root->try_body );
3613+
3614+ assert( exec != nullptr );
3615+ assert( exec->statements.GetCount() == 1 );
3616+
3617+ IfStatement *exec_first = dynamic_cast <IfStatement*> ( exec->statements[0] );
3618+
3619+ assert( exec_first != nullptr );
3620+
3621+ AssignmentOperation *exec_first_cond = dynamic_cast <AssignmentOperation*> ( exec_first->condition );
3622+
3623+ assert( exec_first_cond != nullptr );
3624+
3625+ SpecifierString *exec_first_cond_left = dynamic_cast <SpecifierString*> ( exec_first_cond->left );
3626+
3627+ assert( exec_first_cond_left != nullptr );
3628+ assert( exec_first_cond_left->string == "a" );
3629+
3630+ exec_first_cond_left->Delete();
3631+
3632+ NumberString *exec_first_cond_right = dynamic_cast <NumberString*> ( exec_first_cond->right );
3633+
3634+ assert( exec_first_cond_right != nullptr );
3635+ assert( exec_first_cond_right->numeric_string == "0" );
3636+
3637+ exec_first_cond_right->Delete();
3638+
3639+ exec_first_cond->Delete();
3640+
3641+ ThrowStatement *exec_first_tb = dynamic_cast <ThrowStatement*> ( exec_first->true_branch );
3642+
3643+ assert( exec_first_tb != nullptr );
3644+ assert( exec_first_tb->op == nullptr );
3645+
3646+ exec_first_tb->Delete();
3647+
3648+ exec_first->Delete();
3649+
3650+ exec->Delete();
3651+
3652+ CatchStatement *error = dynamic_cast <CatchStatement*> ( root->errors[0] );
3653+
3654+ assert( error != nullptr );
3655+ assert( error->caught_decl == nullptr );
3656+
3657+ BlockStatement *error_body = dynamic_cast <BlockStatement*> ( error->catch_body );
3658+
3659+ assert( error_body != nullptr );
3660+ assert( error_body->statements.GetCount() == 1 );
3661+
3662+ AssignmentOperation *error_body_first = dynamic_cast <AssignmentOperation*> ( error_body->statements[0] );
3663+
3664+ assert( error_body_first != nullptr );
3665+
3666+ SpecifierString *error_body_first_left = dynamic_cast <SpecifierString*> ( error_body_first->left );
3667+
3668+ assert( error_body_first_left != nullptr );
3669+ assert( error_body_first_left->string == "a" );
3670+
3671+ error_body_first_left->Delete();
3672+
3673+ NumberString *error_body_first_right = dynamic_cast <NumberString*> ( error_body_first->right );
3674+
3675+ assert( error_body_first_right != nullptr );
3676+ assert( error_body_first_right->numeric_string == "1" );
3677+
3678+ error_body_first_right->Delete();
3679+
3680+ error_body_first->Delete();
3681+ error_body->Delete();
3682+ error->Delete();
3683+ root->Delete();
3684+ }
3685+
3686+ // 9)
3687+ {
3688+ COSNode *_root = lexer.StartProduction( "try{int arg=3;dangerousFunc(arg,false);}catch(danger d){print(d.reason);}catch(fatal_error e){exit(e.code);}" );
3689+
3690+ TryStatement *root = dynamic_cast <TryStatement*> ( _root );
3691+
3692+ assert( root != nullptr );
3693+ assert( root->errors.GetCount() == 2 );
3694+
3695+ BlockStatement *exec = dynamic_cast <BlockStatement*> ( root->try_body );
3696+
3697+ assert( exec != nullptr );
3698+ assert( exec->statements.GetCount() == 2 );
3699+
3700+ DeclarationStatement *exec_first = dynamic_cast <DeclarationStatement*> ( exec->statements[0] );
3701+
3702+ assert( exec_first != nullptr );
3703+
3704+ SpecifierString *exec_first_type = dynamic_cast <SpecifierString*> ( exec_first->type );
3705+
3706+ assert( exec_first_type != nullptr );
3707+ assert( exec_first_type->string == "int" );
3708+
3709+ exec_first_type->Delete();
3710+
3711+ SpecifierString *exec_first_name = dynamic_cast <SpecifierString*> ( exec_first->name );
3712+
3713+ assert( exec_first_name != nullptr );
3714+ assert( exec_first_name->string == "arg" );
3715+
3716+ exec_first_name->Delete();
3717+
3718+ NumberString *exec_first_init = dynamic_cast <NumberString*> ( exec_first->initializer );
3719+
3720+ assert( exec_first_init != nullptr );
3721+ assert( exec_first_init->numeric_string == "3" );
3722+
3723+ exec_first_init->Delete();
3724+ exec_first->Delete();
3725+
3726+ FunctionCallOperation *exec_second = dynamic_cast <FunctionCallOperation*> ( exec->statements[1] );
3727+
3728+ assert( exec_second != nullptr );
3729+ assert( exec_second->params.GetCount() == 2 );
3730+
3731+ SpecifierString *exec_second_what = dynamic_cast <SpecifierString*> ( exec_second->what );
3732+
3733+ assert( exec_second_what != nullptr );
3734+ assert( exec_second_what->string == "dangerousFunc" );
3735+
3736+ exec_second_what->Delete();
3737+
3738+ SpecifierString *exec_second_first = dynamic_cast <SpecifierString*> ( exec_second->params[0] );
3739+
3740+ assert( exec_second_first != nullptr );
3741+ assert( exec_second_first->string == "arg" );
3742+
3743+ exec_second_first->Delete();
3744+
3745+ SpecifierString *exec_second_second = dynamic_cast <SpecifierString*> ( exec_second->params[1] );
3746+
3747+ assert( exec_second_second != nullptr );
3748+ assert( exec_second_second->string == "false" );
3749+
3750+ exec_second_second->Delete();
3751+
3752+ exec_second->Delete();
3753+
3754+ exec->Delete();
3755+
3756+ CatchStatement *error1 = dynamic_cast <CatchStatement*> ( root->errors[0] );
3757+
3758+ assert( error1 != nullptr );
3759+
3760+ DeclarationStatement *error1_what = dynamic_cast <DeclarationStatement*> ( error1->caught_decl );
3761+
3762+ assert( error1_what != nullptr );
3763+ assert( error1_what->initializer == nullptr );
3764+
3765+ SpecifierString *error1_what_type = dynamic_cast <SpecifierString*> ( error1_what->type );
3766+
3767+ assert( error1_what_type != nullptr );
3768+ assert( error1_what_type->string == "danger" );
3769+
3770+ error1_what_type->Delete();
3771+
3772+ SpecifierString *error1_what_name = dynamic_cast <SpecifierString*> ( error1_what->name );
3773+
3774+ assert( error1_what_name != nullptr );
3775+ assert( error1_what_name->string == "d" );
3776+
3777+ error1_what_name->Delete();
3778+
3779+ error1_what->Delete();
3780+
3781+ BlockStatement *error1_body = dynamic_cast <BlockStatement*> ( error1->catch_body );
3782+
3783+ assert( error1_body != nullptr );
3784+ assert( error1_body->statements.GetCount() == 1 );
3785+
3786+ FunctionCallOperation *error1_body_first = dynamic_cast <FunctionCallOperation*> ( error1_body->statements[0] );
3787+
3788+ assert( error1_body_first != nullptr );
3789+ assert( error1_body_first->params.GetCount() == 1 );
3790+
3791+ SpecifierString *error1_body_first_what = dynamic_cast <SpecifierString*> ( error1_body_first->what );
3792+
3793+ assert( error1_body_first_what != nullptr );
3794+ assert( error1_body_first_what->string == "print" );
3795+
3796+ error1_body_first_what->Delete();
3797+
3798+ DotOperation *error1_body_first_first = dynamic_cast <DotOperation*> ( error1_body_first->params[0] );
3799+
3800+ assert( error1_body_first_first != nullptr );
3801+
3802+ SpecifierString *error1_body_first_first_left = dynamic_cast <SpecifierString*> ( error1_body_first_first->left );
3803+
3804+ assert( error1_body_first_first_left != nullptr );
3805+ assert( error1_body_first_first_left->string == "d" );
3806+
3807+ error1_body_first_first_left->Delete();
3808+
3809+ SpecifierString *error1_body_first_first_right = dynamic_cast <SpecifierString*> ( error1_body_first_first->right );
3810+
3811+ assert( error1_body_first_first_right != nullptr );
3812+ assert( error1_body_first_first_right->string == "reason" );
3813+
3814+ error1_body_first_first_right->Delete();
3815+
3816+ error1_body_first_first->Delete();
3817+ error1_body_first->Delete();
3818+ error1_body->Delete();
3819+ error1->Delete();
3820+
3821+ CatchStatement *error2 = dynamic_cast <CatchStatement*> ( root->errors[1] );
3822+
3823+ assert( error2 != nullptr );
3824+
3825+ DeclarationStatement *error2_decl = dynamic_cast <DeclarationStatement*> ( error2->caught_decl );
3826+
3827+ assert( error2_decl != nullptr );
3828+ assert( error2_decl->initializer == nullptr );
3829+
3830+ SpecifierString *error2_decl_type = dynamic_cast <SpecifierString*> ( error2_decl->type );
3831+
3832+ assert( error2_decl_type != nullptr );
3833+ assert( error2_decl_type->string == "fatal_error" );
3834+
3835+ error2_decl_type->Delete();
3836+
3837+ SpecifierString *error2_decl_name = dynamic_cast <SpecifierString*> ( error2_decl->name );
3838+
3839+ assert( error2_decl_name != nullptr );
3840+ assert( error2_decl_name->string == "e" );
3841+
3842+ error2_decl_name->Delete();
3843+
3844+ BlockStatement *error2_body = dynamic_cast <BlockStatement*> ( error2->catch_body );
3845+
3846+ assert( error2_body != nullptr );
3847+ assert( error2_body->statements.GetCount() == 1 );
3848+
3849+ FunctionCallOperation *error2_body_first = dynamic_cast <FunctionCallOperation*> ( error2_body->statements[0] );
3850+
3851+ assert( error2_body_first != nullptr );
3852+
3853+ SpecifierString *error2_body_first_what = dynamic_cast <SpecifierString*> ( error2_body_first->what );
3854+
3855+ assert( error2_body_first_what != nullptr );
3856+ assert( error2_body_first_what->string == "exit" );
3857+
3858+ error2_body_first_what->Delete();
3859+
3860+ DotOperation *error2_body_first_first = dynamic_cast <DotOperation*> ( error2_body_first->params[0] );
3861+
3862+ assert( error2_body_first_first != nullptr );
3863+
3864+ SpecifierString *error2_body_first_first_left = dynamic_cast <SpecifierString*> ( error2_body_first_first->left );
3865+
3866+ assert( error2_body_first_first_left != nullptr );
3867+ assert( error2_body_first_first_left->string == "e" );
3868+
3869+ error2_body_first_first_left->Delete();
3870+
3871+ SpecifierString *error2_body_first_first_right = dynamic_cast <SpecifierString*> ( error2_body_first_first->right );
3872+
3873+ assert( error2_body_first_first_right != nullptr );
3874+ assert( error2_body_first_first_right->string == "code" );
3875+
3876+ error2_body_first_first_right->Delete();
3877+
3878+ error2_body_first_first->Delete();
3879+ error2_body_first->Delete();
3880+ error2_body->Delete();
3881+ error2->Delete();
3882+ root->Delete();
3883+ }
3884+
3885+ // 10)
3886+ {
3887+ COSNode *_root = lexer.StartProduction( "try{while(true)throw 1;}catch(int){}" );
3888+
3889+ TryStatement *root = dynamic_cast <TryStatement*> ( _root );
3890+
3891+ assert( root != nullptr );
3892+ assert( root->errors.GetCount() == 1 );
3893+
3894+ BlockStatement *body = dynamic_cast <BlockStatement*> ( root->try_body );
3895+
3896+ assert( body != nullptr );
3897+ assert( body->statements.GetCount() == 1 );
3898+
3899+ WhileLoopStatement *body_first = dynamic_cast <WhileLoopStatement*> ( body->statements[0] );
3900+
3901+ assert( body_first != nullptr );
3902+
3903+ SpecifierString *body_first_cond = dynamic_cast <SpecifierString*> ( body_first->condition );
3904+
3905+ assert( body_first_cond != nullptr );
3906+ assert( body_first_cond->string == "true" );
3907+
3908+ body_first_cond->Delete();
3909+
3910+ ThrowStatement *body_first_exec = dynamic_cast <ThrowStatement*> ( body_first->exec );
3911+
3912+ assert( body_first_exec != nullptr );
3913+
3914+ NumberString *body_first_exec_sub = dynamic_cast <NumberString*> ( body_first_exec->op );
3915+
3916+ assert( body_first_exec_sub != nullptr );
3917+ assert( body_first_exec_sub->numeric_string == "1" );
3918+
3919+ body_first_exec_sub->Delete();
3920+
3921+ body_first_exec->Delete();
3922+ body_first->Delete();
3923+ body->Delete();
3924+
3925+ CatchStatement *error = dynamic_cast <CatchStatement*> ( root->errors[0] );
3926+
3927+ assert( error != nullptr );
3928+
3929+ DeclarationStatement *error_decl = dynamic_cast <DeclarationStatement*> ( error->caught_decl );
3930+
3931+ assert( error_decl != nullptr );
3932+ assert( error_decl->name == nullptr );
3933+ assert( error_decl->initializer == nullptr );
3934+
3935+ SpecifierString *error_decl_type = dynamic_cast <SpecifierString*> ( error_decl->type );
3936+
3937+ assert( error_decl_type != nullptr );
3938+ assert( error_decl_type->string == "int" );
3939+
3940+ error_decl_type->Delete();
3941+
3942+ error_decl->Delete();
3943+
3944+ BlockStatement *error_body = dynamic_cast <BlockStatement*> ( error->catch_body );
3945+
3946+ assert( error_body != nullptr );
3947+ assert( error_body->statements.GetCount() == 0 );
3948+
3949+ error_body->Delete();
3950+
3951+ error->Delete();
3952+ root->Delete();
3953+ }
3954+
3955+ // 11)
3956+ {
3957+ COSNode *_root = lexer.StartProduction( "try throw 0;catch(int)throw fatal;" );
3958+
3959+ TryStatement *root = dynamic_cast <TryStatement*> ( _root );
3960+
3961+ assert( root != nullptr );
3962+ assert( root->errors.GetCount() == 1 );
3963+
3964+ ThrowStatement *body = dynamic_cast <ThrowStatement*> ( root->try_body );
3965+
3966+ assert( body != nullptr );
3967+
3968+ NumberString *body_sub = dynamic_cast <NumberString*> ( body->op );
3969+
3970+ assert( body_sub != nullptr );
3971+ assert( body_sub->numeric_string == "0" );
3972+
3973+ body_sub->Delete();
3974+
3975+ body->Delete();
3976+
3977+ CatchStatement *error = dynamic_cast <CatchStatement*> ( root->errors[0] );
3978+
3979+ assert( error != nullptr );
3980+
3981+ DeclarationStatement *error_decl = dynamic_cast <DeclarationStatement*> ( error->caught_decl );
3982+
3983+ assert( error_decl != nullptr );
3984+ assert( error_decl->initializer == nullptr );
3985+ assert( error_decl->name == nullptr );
3986+
3987+ SpecifierString *error_decl_type = dynamic_cast <SpecifierString*> ( error_decl->type );
3988+
3989+ assert( error_decl_type != nullptr );
3990+ assert( error_decl_type->string == "int" );
3991+
3992+ error_decl_type->Delete();
3993+
3994+ ThrowStatement *error_body = dynamic_cast <ThrowStatement*> ( error->catch_body );
3995+
3996+ assert( error_body != nullptr );
3997+
3998+ SpecifierString *error_body_sub = dynamic_cast <SpecifierString*> ( error_body->op );
3999+
4000+ assert( error_body_sub != nullptr );
4001+ assert( error_body_sub->string == "fatal" );
4002+
4003+ error_body_sub->Delete();
4004+
4005+ error_body->Delete();
4006+
4007+ error->Delete();
4008+ root->Delete();
4009+ }
4010+
4011+ // 12)
4012+ {
4013+ COSNode *_root = lexer.StartProduction( "if(bound){unbind();}else if(is_binding){abortBinding();}" );
4014+
4015+ IfStatement *root = dynamic_cast <IfStatement*> ( _root );
4016+
4017+ assert( root != nullptr );
4018+
4019+ SpecifierString *cond = dynamic_cast <SpecifierString*> ( root->condition );
4020+
4021+ assert( cond != nullptr );
4022+ assert( cond->string == "bound" );
4023+
4024+ cond->Delete();
4025+
4026+ BlockStatement *true_branch = dynamic_cast <BlockStatement*> ( root->true_branch );
4027+
4028+ assert( true_branch != nullptr );
4029+ assert( true_branch->statements.GetCount() == 1 );
4030+
4031+ FunctionCallOperation *tb_first = dynamic_cast <FunctionCallOperation*> ( true_branch->statements[0] );
4032+
4033+ assert( tb_first != nullptr );
4034+ assert( tb_first->params.GetCount() == 0 );
4035+
4036+ SpecifierString *tb_first_what = dynamic_cast <SpecifierString*> ( tb_first->what );
4037+
4038+ assert( tb_first_what != nullptr );
4039+ assert( tb_first_what->string == "unbind" );
4040+
4041+ tb_first_what->Delete();
4042+
4043+ tb_first->Delete();
4044+ true_branch->Delete();
4045+
4046+ IfStatement *false_branch = dynamic_cast <IfStatement*> ( root->false_branch );
4047+
4048+ assert( false_branch != nullptr );
4049+ assert( false_branch->false_branch == nullptr );
4050+
4051+ SpecifierString *fb_cond = dynamic_cast <SpecifierString*> ( false_branch->condition );
4052+
4053+ assert( fb_cond != nullptr );
4054+ assert( fb_cond->string == "is_binding" );
4055+
4056+ fb_cond->Delete();
4057+
4058+ BlockStatement *fb_true_branch = dynamic_cast <BlockStatement*> ( false_branch->true_branch );
4059+
4060+ assert( fb_true_branch != nullptr );
4061+ assert( fb_true_branch->statements.GetCount() == 1 );
4062+
4063+ FunctionCallOperation *fb_tb_first = dynamic_cast <FunctionCallOperation*> ( fb_true_branch->statements[0] );
4064+
4065+ assert( fb_tb_first != nullptr );
4066+ assert( fb_tb_first->params.GetCount() == 0 );
4067+
4068+ SpecifierString *fb_tb_first_what = dynamic_cast <SpecifierString*> ( fb_tb_first->what );
4069+
4070+ assert( fb_tb_first_what != nullptr );
4071+ assert( fb_tb_first_what->string == "abortBinding" );
4072+
4073+ fb_tb_first_what->Delete();
4074+ fb_tb_first->Delete();
4075+ fb_true_branch->Delete();
4076+ false_branch->Delete();
4077+ root->Delete();
4078+ }
30564079 }
30574080 printf( "ok.\n" );
30584081
--- testcompiler/src/lexingcomp_tests.cpp (revision 56)
+++ testcompiler/src/lexingcomp_tests.cpp (revision 57)
@@ -496,6 +496,19 @@
496496 }
497497 printf( "ok.\n" );
498498
499+ printf( "testing LexingCompiler compiling extend-step with before-usual attribute..." );
500+ {
501+ LexingEnvironment <char, LexNodeType> env;
502+ LexingCompiler <char, decltype(env)> compiler;
503+
504+ auto *step = compiler.CompileProduction( &env, "^(wire, <b> \"post\")" );
505+
506+ assert( step != nullptr );
507+
508+ step->Delete();
509+ }
510+ printf( "ok.\n" );
511+
499512 printf( "testing LexingCompiler compiling extension-point-step (basic)..." );
500513 {
501514 LexingEnvironment <char, LexNodeType> env;
--- testcompiler/src/lexingenv_tests.cpp (revision 56)
+++ testcompiler/src/lexingenv_tests.cpp (revision 57)
@@ -765,6 +765,76 @@
765765 }
766766 printf( "ok.\n" );
767767
768+ printf( "testing ProductionMachine StepExtend before-or-after ordering..." );
769+ {
770+ struct before_node : public LexNodeType
771+ {
772+ before_node* Clone( void ) override
773+ {
774+ return new before_node();
775+ }
776+ };
777+ struct after_node : public LexNodeType
778+ {
779+ after_node* Clone( void ) override
780+ {
781+ return new after_node();
782+ }
783+ };
784+
785+ TestAllocEnv env( eir::constr_with_alloc::DEFAULT, &globalHeapAlloc );
786+
787+ TestAllocEnv::StepToken tok_bn( &env );
788+ tok_bn.token_str = "tok";
789+ tok_bn.setConstructor(
790+ []
791+ {
792+ return new before_node();
793+ }
794+ );
795+
796+ TestAllocEnv::StepToken tok_an( &env );
797+ tok_an.token_str = "tok";
798+ tok_an.setConstructor(
799+ []
800+ {
801+ return new after_node();
802+ }
803+ );
804+
805+ TestAllocEnv::StepExtend ext( &env );
806+ ext.SetExtendedNode( &tok_bn );
807+ ext.SetExtensionNode( &tok_an );
808+ ext.extension_is_before_usual = true;
809+
810+ TestAllocEnv::ProductionMachine machine( &env );
811+
812+ machine.Execute( "tok", &ext );
813+
814+ assert( machine.successful == true );
815+ {
816+ after_node *an = dynamic_cast <after_node*> ( machine.DetachNode() );
817+
818+ assert( an != nullptr );
819+
820+ an->Delete();
821+ }
822+
823+ ext.extension_is_before_usual = false;
824+
825+ machine.Execute( "tok", &ext );
826+
827+ assert( machine.successful == true );
828+ {
829+ before_node *bn = dynamic_cast <before_node*> ( machine.DetachNode() );
830+
831+ assert( bn != nullptr );
832+
833+ bn->Delete();
834+ }
835+ }
836+ printf( "ok.\n" );
837+
768838 printf( "testing ProductionMachine StepExtensionPoint..." );
769839 {
770840 TestAllocEnv env( eir::constr_with_alloc::DEFAULT, &globalHeapAlloc );
Show on old repository browser