Reputation: 13
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
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