Question

I'm trying to write a shell using yacc and lex and I'm running into some problems with my I/O redirectors. Currently, I can use the < and > operators fine and in any order, but my problem is I can redirect twice with no error, such as "ls > log > log2"

My rule code is below, can anyone give me some tips on how to fix this? Thanks!

 io_mod:
    iomodifier_opt io_mod
    |
    ;

 iomodifier_opt:
    GREAT WORD {
        printf("   Yacc: insert output \"%s\"\n", $2);
        Command::_currentCommand._outFile = $2;
    }
    |
    LESS WORD {
       printf("   Yacc: insert input \"%s\"\n", $2);
       Command::_currentCommand._inputFile = $2;
    }
    | /* can be empty */
    ;

EDIT: After talking to my TA, I learned that I did not actually need to have only 1 modifier for my command and that I actually can have multiple copies of the same I/O redirection.

Was it helpful?

Solution

There are two approaches:

(1) Modify the grammar so that you can only have one of each kind of modifier:

io_mod_opt: out_mod in_mod | in_mod out_mod | in_mod | out_mod | ;

(2) Modify the clause handler to count the modifiers and report an error if there's more than one:

GREAT_WORD {
    if (already_have_output_file()) {
        error("too many output files: \"%s\"\n", $2)
    } else {
        /* record output file */
    }
}

Option (2) seems likely to lead to better error messages and a simpler grammar.

OTHER TIPS

There's also a third approach - don't fret. Bash (under Cygwin) does not generate an error for:

ls > x > y

It creates x and then y and ends up writing to y.

I realize this might be just an exercise to learn lexx and yacc, but otherwise the first question is to ask why you want to use lexx and yacc? Any usual shell command language has a pretty simple grammar; what are you gaining from using an LALR generator?

Well, other than complexity, difficulty generating good error messages, and code bulk, I mean.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top