4

I'm developing a programming language, and I'm having trouble dealing with condition statements. Here's the code in my language:

x = 4 ->
? 2 > 5 <?
    x = 7 -> 
?> ->
[o] <- x ->

Here's the specific part of the grammar that defines condition statements:

post_condition_evaluation_block : post_condition_evaluation_block_opening_operator compound_statement post_condition_evaluation_block_closing_operator
condition_statement : condition_specification_operator expression post_condition_evaluation_block
                    | condition_specification_operator expression post_condition_evaluation_block condition_extension

There's nothing actually wrong with the grammar, the code runs normally. The problem is that the expression 2 > 5 gets evaluated after the following statement x = 7, so what gets printed is 7 instead of 4 (Which is wrong, since the expression evaluates to false). I'm dealing with this problem counting the condition blocks:

condition_blocks = {0: True}
current_condition_block = 0

And then when it comes to the condition statement:

def p_condition_statement(p):
    """condition_statement : condition_specification_operator expression post_condition_evaluation_block
                           | condition_specification_operator expression post_condition_evaluation_block condition_extension"""
    global current_condition_block
    current_condition_block += 1
    condition_blocks[current_condition_block] = p[2]
    print(condition_blocks)

It adds the value of False (p2) of the expression to the corresponding block index in the dictionary. The problem is that when I get to do the assignment:

def p_assignment(p):
    """assignment : identifier assignment_operator expression"""
    if len(p) == 4 and condition_blocks[current_condition_block]:
        if p[2] == '=':
            identifiers[p[1]] = parse_object(p[3])
        elif p[2] == "+=":
            identifiers[p[1]] += parse_object(p[3])
        elif p[2] == "-=":
            identifiers[p[1]] -= parse_object(p[3])
        elif p[2] == "*=":
            identifiers[p[1]] *= parse_object(p[3])
        elif p[2] == "/=":
            identifiers[p[1]] /= parse_object(p[3])
        p[0] = (p[1], p[2], p[3])

The block that gets evaluated is the default "out-of-block-scope" one. The assignment rule gets parsed / processed before the expression, which makes no sense in my head, since the whole code should be processed from the beginning to the end.

I'm obviously no expert in parsing / YACC, it's my first attempt and I find absolutely no hint of what to do in the docs. I don't know how to stop the parser, to skip the parser, to change the parsing order... Perhaps the problem is in my grammar, but I can't see how to change the parsing order.

Ericson Willians
  • 7,606
  • 11
  • 63
  • 114

1 Answers1

1

When a production is reduced -- that is, its semantic action is executed -- all of the non-terminals referenced have already been reduced. In other words, children are always reduced before their parents, which is why yacc is called a bottom-up parser.

The only practical way to achieve more flexibility is to build an AST during the parse, and then evaluate (or whatever) the complete expression afterwards by doing a treewalk over the AST. You are then free to walk the complete tree in whatever order(s) seem appropriate.

rici
  • 234,347
  • 28
  • 237
  • 341