- 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)
@@ -235,7 +235,7 @@ | ||
235 | 235 | |
236 | 236 | struct IfStatement : public COSNode |
237 | 237 | { |
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 ) | |
239 | 239 | { |
240 | 240 | return; |
241 | 241 | } |
@@ -251,13 +251,13 @@ | ||
251 | 251 | right.false_branch = nullptr; |
252 | 252 | } |
253 | 253 | |
254 | - Operation *condition; | |
254 | + COSNode *condition; | |
255 | 255 | COSNode *true_branch; |
256 | 256 | COSNode *false_branch; |
257 | 257 | }; |
258 | 258 | struct WhileLoopStatement : public COSNode |
259 | 259 | { |
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 ) | |
261 | 261 | { |
262 | 262 | return; |
263 | 263 | } |
@@ -271,12 +271,12 @@ | ||
271 | 271 | right.exec = nullptr; |
272 | 272 | } |
273 | 273 | |
274 | - Operation *condition; | |
274 | + COSNode *condition; | |
275 | 275 | COSNode *exec; |
276 | 276 | }; |
277 | 277 | struct ForLoopStatement : public COSNode |
278 | 278 | { |
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 ) | |
280 | 280 | { |
281 | 281 | return; |
282 | 282 | } |
@@ -295,8 +295,8 @@ | ||
295 | 295 | } |
296 | 296 | |
297 | 297 | COSNode *init; |
298 | - Operation *condition; | |
299 | - Operation *iteration; | |
298 | + COSNode *condition; | |
299 | + COSNode *iteration; | |
300 | 300 | COSNode *exec; |
301 | 301 | }; |
302 | 302 | struct ContinueStatement : public COSNode |
@@ -443,22 +443,20 @@ | ||
443 | 443 | }; |
444 | 444 | struct TryStatement : public COSNode |
445 | 445 | { |
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 ) ) | |
447 | 447 | { |
448 | 448 | return; |
449 | 449 | } |
450 | 450 | inline TryStatement( const TryStatement& ) = default; |
451 | - inline TryStatement( TryStatement&& right ) noexcept | |
451 | + inline TryStatement( TryStatement&& right ) noexcept : errors( std::move( right.errors ) ) | |
452 | 452 | { |
453 | 453 | this->try_body = right.try_body; |
454 | - this->error = right.error; | |
455 | 454 | |
456 | 455 | right.try_body = nullptr; |
457 | - right.error = nullptr; | |
458 | 456 | } |
459 | 457 | |
460 | 458 | COSNode *try_body; |
461 | - CatchStatement *error; | |
459 | + depVector <CatchStatement*> errors; | |
462 | 460 | }; |
463 | 461 | |
464 | 462 | struct StructStatement : public COSNode |
@@ -709,7 +707,7 @@ | ||
709 | 707 | lexer.GetNamedProduction( "function" ).setSelector <direct_obj_build_selector <char, FunctionDefinition, COSNode, function_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); |
710 | 708 | } |
711 | 709 | 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 ); | |
713 | 711 | assert( lexer.CompileProduction( compiler, "funcstatement", "\"return\" spaces (op:operation spaces)^0:1 ';'" ) == true ); |
714 | 712 | { |
715 | 713 | struct return_dispatcher |
@@ -1573,7 +1571,7 @@ | ||
1573 | 1571 | { |
1574 | 1572 | if ( attrib == "cond" ) |
1575 | 1573 | { |
1576 | - assign_to->condition = dynamic_cast <Operation*> ( node ); | |
1574 | + assign_to->condition = node; | |
1577 | 1575 | } |
1578 | 1576 | else if ( attrib == "body" ) |
1579 | 1577 | { |
@@ -1584,7 +1582,7 @@ | ||
1584 | 1582 | }; |
1585 | 1583 | lexer.GetNamedProduction( "whileloop" ).setSelector <direct_obj_build_selector <char, WhileLoopStatement, COSNode, while_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); |
1586 | 1584 | } |
1587 | - assert( lexer.CompileProduction( compiler, "loopbody", "^(extended statement, loopstatement)" ) == true ); | |
1585 | + assert( lexer.CompileProduction( compiler, "loopbody", "^(extended statement, <b> loopstatement)" ) == true ); | |
1588 | 1586 | assert( lexer.CompileProduction( compiler, "loopstatement", "\"break\" spaces ';'" ) == true ); |
1589 | 1587 | { |
1590 | 1588 | lexer.GetNamedProduction( "loopstatement" ).GetLastStep()->setConstructor( |
@@ -1611,7 +1609,7 @@ | ||
1611 | 1609 | { |
1612 | 1610 | if ( attrib == "cond" ) |
1613 | 1611 | { |
1614 | - assign_to->condition = dynamic_cast <Operation*> ( node ); | |
1612 | + assign_to->condition = node; | |
1615 | 1613 | return true; |
1616 | 1614 | } |
1617 | 1615 | else if ( attrib == "true_branch" ) |
@@ -1680,7 +1678,7 @@ | ||
1680 | 1678 | } |
1681 | 1679 | else if ( attrib == "error" ) |
1682 | 1680 | { |
1683 | - assign_to->error = dynamic_cast <CatchStatement*> ( node ); | |
1681 | + assign_to->errors.AddToBack( dynamic_cast <CatchStatement*> ( node ) ); | |
1684 | 1682 | return true; |
1685 | 1683 | } |
1686 | 1684 | return false; |
@@ -1701,12 +1699,12 @@ | ||
1701 | 1699 | } |
1702 | 1700 | else if ( attrib == "loop_cond" ) |
1703 | 1701 | { |
1704 | - assign_to->condition = dynamic_cast <Operation*> ( node ); | |
1702 | + assign_to->condition = node; | |
1705 | 1703 | return true; |
1706 | 1704 | } |
1707 | 1705 | else if ( attrib == "loop_iteration" ) |
1708 | 1706 | { |
1709 | - assign_to->iteration = dynamic_cast <Operation*> ( node ); | |
1707 | + assign_to->iteration = node; | |
1710 | 1708 | return true; |
1711 | 1709 | } |
1712 | 1710 | else if ( attrib == "body" ) |
@@ -1720,7 +1718,7 @@ | ||
1720 | 1718 | lexer.GetNamedProduction( "forloop" ).setSelector <direct_obj_build_selector <char, ForLoopStatement, COSNode, for_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() ); |
1721 | 1719 | } |
1722 | 1720 | 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 ); | |
1724 | 1722 | { |
1725 | 1723 | struct struct_dispatcher |
1726 | 1724 | { |
@@ -3052,7 +3050,1032 @@ | ||
3052 | 3050 | |
3053 | 3051 | printf( "testing COS control structures..." ); |
3054 | 3052 | { |
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 | + } | |
3056 | 4079 | } |
3057 | 4080 | printf( "ok.\n" ); |
3058 | 4081 |
@@ -496,6 +496,19 @@ | ||
496 | 496 | } |
497 | 497 | printf( "ok.\n" ); |
498 | 498 | |
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 | + | |
499 | 512 | printf( "testing LexingCompiler compiling extension-point-step (basic)..." ); |
500 | 513 | { |
501 | 514 | LexingEnvironment <char, LexNodeType> env; |
@@ -765,6 +765,76 @@ | ||
765 | 765 | } |
766 | 766 | printf( "ok.\n" ); |
767 | 767 | |
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 | + | |
768 | 838 | printf( "testing ProductionMachine StepExtensionPoint..." ); |
769 | 839 | { |
770 | 840 | TestAllocEnv env( eir::constr_with_alloc::DEFAULT, &globalHeapAlloc ); |