I’m trying to implement the && and || operators of the bash shell for an assignment – in C. For an input like:
a && b && c
my parser makes a linked list with “symbol” and “connector” i.e.:
a - &&
b - &&
c - END
so I can evaluate the symbol to determine whether to check the next condition or not. I know the basic idea, but is there a general algorithm for how to implement the conditionals? Mainly, if somebody passes in something like a && (b | c) || d && e || f, then I just don’t know what’s a good way to attack that. I tried evaluating the first symbol and storing status to check what to read next, but it’s not a good approach.
Any suggestions?
The general method for implementing this results in a syntax tree, not a list. You need to parse the list of tokens (which is what you’ve created) into an AST (Abstract Syntax Tree) describing the expression.
There is no way to get the precedence right with the way you’re doing it now. And this is crucial for the short-circuit evaluation property the
&&and||operators have.Here is some sample code in Python that will build your tree structure. It’s kinda ugly, and I would write a prettier parser if I were really doing this. This is just to give you the general idea:
The tree structure this code builds is very lispish. Each node of your tree consists of a ‘tuple’ (sort of like a lisp list) in Python that looks like
(operator, arg1, arg2). It’s up to you to figure out how to use it. As a hint, you would have to write an evaluator that processed the tree in a particular order.Also, this parser drops the parenthesis because it treats the parenthesis as merely a grouping construct. But for
bashthis isn’t wise because parenthesis have meaning beyond mere grouping. So the thing should be modified (which is relatively trivial) to put the ‘parenthesis operator’ back into the resulting tree.Here’s an example of how to use the parser and what it’s output looks like: