joenatech7
joenatech7

Reputation: 13

How to stop parsing and reset yacc?

I am writing a job control shell. I use Yacc and Lex for parsing. The top rule in my grammar is pipeline_list, which is a list of pipelines separated by a comma. Thus, examples of pipelinelists are as follows:

cmd1 | cmd2; cmd3; cmd4 | cmd5 <newline>
cmd1 <newline>
<nothing> <newline>

I represent a pipeline with the pipeline rule (showed below). within that rule, I do the following:

1. call execute_pipeline() to execute the pipeline. execute_pipeline() returns -1 if anything went wrong in the execution of the pipeline.

2. Check the return value of execute_pipeline() and if it is -1, then STOP parsing the rest of the input, AND make sure YACC starts fresh when called again in the main function (shown below). The rationale for doing this is this: Take, for example, the following pipelinelist: cd ..; ls -al. My intent here would be to move one directory up, and then list its content. However, if execution of the first pipeline (i.e., "cd ..") in the pipelinelist fails, then carrying on to execute the second pipeline (i.e. " ls -al") would list of the contents of the current directory (not the parent), which is wrong! For this reason, when parsing a pipelinelist of length n, if executing of some pipeline k > n fails, then I want to discard the rest of the pipelinelist (i.e., pipelines k+1..n), AND make sure the next invocation of yyparse() starts brand new (i.e. recieve new input from readline() -- see code below). if tried the following, but it does not work:

pipeline: 
simple_command_list redirection_list background pipeline_terminator // ignore these
{
if (execute_pipeline() == -1)
{
    // do some stuff
    // then call YYABORT, YYACCEPT, or YYERROR, but none of them works
}
}


int main()
{
    while(1)
    {
        char *buffer = readline("> ");
        if (buffer)
        {
            struct yy_buffer_state *bp;
            bp = yy_scan_string(buffer);
            yy_switch_to_buffer(bp);

            yyparse()

            yy_delete_buffer(bp);

            free(buffer);
        } // end if

    } // end while
    return 0;
} // end main()

Upvotes: 0

Views: 2965

Answers (1)

Chris Dodd
Chris Dodd

Reputation: 126488

You can use YYABORT; in an action to abort the current parse and immediately return from yyparse with a failure. You can use YYACCEPT; to immediately return success from yyparse.

Both of these macros can only be used directly in an action in the grammar -- they can't be used in some other function called by the action.

Upvotes: 1

Related Questions