Changeset c86b08d for src/Parser


Ignore:
Timestamp:
May 1, 2023, 4:06:07 PM (14 months ago)
Author:
caparsons <caparson@…>
Branches:
ADT, ast-experimental, master
Children:
a33a5e2
Parents:
73bf7ddc
Message:

added support for the waituntil statement in the compiler

Location:
src/Parser
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/Parser/ParseNode.h

    r73bf7ddc rc86b08d  
    441441ast::WaitForStmt * build_waitfor_else( const CodeLocation &, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt );
    442442ast::WaitForStmt * build_waitfor_timeout( const CodeLocation &, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt );
     443ast::WaitUntilStmt::ClauseNode * build_waituntil_clause( const CodeLocation &, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt );
     444ast::WaitUntilStmt::ClauseNode * build_waituntil_else( const CodeLocation &, ExpressionNode * when, StatementNode * stmt );
     445ast::WaitUntilStmt::ClauseNode * build_waituntil_timeout( const CodeLocation &, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt );
     446ast::WaitUntilStmt * build_waituntil_stmt( const CodeLocation &, ast::WaitUntilStmt::ClauseNode * root );
    443447ast::Stmt * build_with( const CodeLocation &, ExpressionNode * exprs, StatementNode * stmt );
    444448ast::Stmt * build_mutex( const CodeLocation &, ExpressionNode * exprs, StatementNode * stmt );
  • src/Parser/StatementNode.cc

    r73bf7ddc rc86b08d  
    377377ast::WaitForStmt * build_waitfor( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
    378378        auto clause = new ast::WaitForClause( location );
    379         clause->target_func = maybeBuild( targetExpr );
     379        clause->target = maybeBuild( targetExpr );
    380380        clause->stmt = maybeMoveBuild( stmt );
    381         clause->cond = notZeroExpr( maybeMoveBuild( when ) );
     381        clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
    382382
    383383        ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
     
    408408        return existing;
    409409} // build_waitfor_timeout
     410
     411ast::WaitUntilStmt::ClauseNode * build_waituntil_clause( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
     412    ast::WhenClause * clause = new ast::WhenClause( loc );
     413    clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
     414    clause->stmt = maybeMoveBuild( stmt );
     415    clause->target = maybeMoveBuild( targetExpr );
     416    return new ast::WaitUntilStmt::ClauseNode( clause );
     417}
     418ast::WaitUntilStmt::ClauseNode * build_waituntil_else( const CodeLocation & loc, ExpressionNode * when, StatementNode * stmt ) {
     419    ast::WhenClause * clause = new ast::WhenClause( loc );
     420    clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
     421    clause->stmt = maybeMoveBuild( stmt );
     422    return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::ELSE, clause );
     423}
     424ast::WaitUntilStmt::ClauseNode * build_waituntil_timeout( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
     425    ast::WhenClause * clause = new ast::WhenClause( loc );
     426    clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
     427    clause->stmt = maybeMoveBuild( stmt );
     428    clause->target = maybeMoveBuild( timeout );
     429    return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::TIMEOUT, clause );
     430}
     431
     432ast::WaitUntilStmt * build_waituntil_stmt( const CodeLocation & loc, ast::WaitUntilStmt::ClauseNode * root ) {
     433    ast::WaitUntilStmt * retStmt = new ast::WaitUntilStmt( loc );
     434    retStmt->predicateTree = root;
     435   
     436    // iterative tree traversal
     437    std::vector<ast::WaitUntilStmt::ClauseNode *> nodeStack; // stack needed for iterative traversal
     438    ast::WaitUntilStmt::ClauseNode * currNode = nullptr;
     439    ast::WaitUntilStmt::ClauseNode * lastInternalNode = nullptr;
     440    ast::WaitUntilStmt::ClauseNode * cleanup = nullptr; // used to cleanup removed else/timeout
     441    nodeStack.push_back(root);
     442
     443    do {
     444        currNode = nodeStack.back();
     445        nodeStack.pop_back(); // remove node since it will be processed
     446
     447        switch (currNode->op) {
     448            case ast::WaitUntilStmt::ClauseNode::LEAF:
     449                retStmt->clauses.push_back(currNode->leaf);
     450                break;
     451            case ast::WaitUntilStmt::ClauseNode::ELSE:
     452                retStmt->else_stmt = currNode->leaf->stmt
     453                    ? ast::deepCopy( currNode->leaf->stmt )
     454                    : nullptr;
     455               
     456                retStmt->else_cond = currNode->leaf->when_cond
     457                    ? ast::deepCopy( currNode->leaf->when_cond )
     458                    : nullptr;
     459
     460                delete currNode->leaf;
     461                break;
     462            case ast::WaitUntilStmt::ClauseNode::TIMEOUT:
     463                retStmt->timeout_time = currNode->leaf->target
     464                    ? ast::deepCopy( currNode->leaf->target )
     465                    : nullptr;
     466                retStmt->timeout_stmt = currNode->leaf->stmt
     467                    ? ast::deepCopy( currNode->leaf->stmt )
     468                    : nullptr;
     469                retStmt->timeout_cond = currNode->leaf->when_cond
     470                    ? ast::deepCopy( currNode->leaf->when_cond )
     471                    : nullptr;
     472
     473                delete currNode->leaf;
     474                break;
     475            default:
     476                nodeStack.push_back( currNode->right ); // process right after left
     477                nodeStack.push_back( currNode->left );
     478
     479                // Cut else/timeout out of the tree
     480                if ( currNode->op == ast::WaitUntilStmt::ClauseNode::LEFT_OR ) {
     481                    if ( lastInternalNode )
     482                        lastInternalNode->right = currNode->left;
     483                    else    // if not set then root is LEFT_OR
     484                        retStmt->predicateTree = currNode->left;
     485   
     486                    currNode->left = nullptr;
     487                    cleanup = currNode;
     488                }
     489               
     490                lastInternalNode = currNode;
     491                break;
     492        }
     493    } while ( !nodeStack.empty() );
     494
     495    if ( cleanup ) delete cleanup;
     496
     497    return retStmt;
     498}
    410499
    411500ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
  • src/Parser/parser.yy

    r73bf7ddc rc86b08d  
    304304        StatementNode * sn;
    305305        ast::WaitForStmt * wfs;
     306    ast::WaitUntilStmt::ClauseNode * wuscn;
    306307        ast::Expr * constant;
    307308        CondCtl * ifctl;
     
    425426%type<en> when_clause                                   when_clause_opt                         waitfor         waituntil               timeout
    426427%type<sn> waitfor_statement                             waituntil_statement
    427 %type<wfs> wor_waitfor_clause                   waituntil_clause                        wand_waituntil_clause   wor_waituntil_clause
     428%type<wfs> wor_waitfor_clause
     429%type<wuscn> waituntil_clause                   wand_waituntil_clause       wor_waituntil_clause
    428430
    429431// declarations
     
    16831685waituntil_clause:
    16841686        when_clause_opt waituntil statement
    1685                 { printf( "waituntil_clause 1\n" ); $$ = nullptr; }
     1687                { $$ = build_waituntil_clause( yylloc, $1, $2, maybe_build_compound( yylloc, $3 ) ); }
    16861688        | '(' wor_waituntil_clause ')'
    1687                 { printf( "waituntil_clause 2\n" ); $$ = nullptr; }
     1689                { $$ = $2; }
    16881690        ;
    16891691
    16901692wand_waituntil_clause:
    16911693        waituntil_clause                                                                        %prec THEN
    1692                 { printf( "wand_waituntil_clause 1\n" ); $$ = nullptr; }
     1694                { $$ = $1; }
    16931695        | waituntil_clause wand wand_waituntil_clause
    1694                 { printf( "wand_waituntil_clause 2\n" ); $$ = nullptr; }
     1696                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::AND, $1, $3 ); }
    16951697        ;
    16961698
    16971699wor_waituntil_clause:
    16981700        wand_waituntil_clause
    1699                 { printf( "wor_waituntil_clause 1\n" ); $$ = nullptr; }
     1701                { $$ = $1; }
    17001702        | wor_waituntil_clause wor wand_waituntil_clause
    1701                 { printf( "wor_waituntil_clause 2\n" ); $$ = nullptr; }
     1703                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::OR, $1, $3 ); }
    17021704        | wor_waituntil_clause wor when_clause_opt ELSE statement
    1703                 { printf( "wor_waituntil_clause 3\n" ); $$ = nullptr; }
     1705                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_else( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
    17041706        | wor_waituntil_clause wor when_clause_opt timeout statement    %prec THEN
    1705                 { printf( "wor_waituntil_clause 4\n" ); $$ = nullptr; }
     1707                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ) ); }
    17061708        // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
    17071709        | wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
    17081710                { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
    17091711        | wor_waituntil_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
    1710                 { printf( "wor_waituntil_clause 6\n" ); $$ = nullptr; }
     1712                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1,
     1713                new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::OR,
     1714                    build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ),
     1715                    build_waituntil_else( yylloc, $7, maybe_build_compound( yylloc, $9 ) ) ) ); }
    17111716        ;
    17121717
     
    17141719        wor_waituntil_clause                                                            %prec THEN
    17151720                // SKULLDUGGERY: create an empty compound statement to test parsing of waituntil statement.
    1716                 { $$ = new StatementNode( build_compound( yylloc, nullptr ) ); }
     1721                {
     1722            $$ = new StatementNode( build_waituntil_stmt( yylloc, $1 ) );
     1723            // $$ = new StatementNode( build_compound( yylloc, nullptr ) );
     1724        }
    17171725        ;
    17181726
Note: See TracChangeset for help on using the changeset viewer.