Hope that helps This response is to your UPDATE section, since that's kind of the heart of the problem.

The TL;DR answer is that the precedence-and-associativity declarations %left '+' and %left '*' apply while parsing BINOP but not while parsing expr, so they're too early (they do nothing at this point) and are gone by the time they are needed.

code :

```
$ cat expr.y
%token TOK_INTCON
%left '+'
%left '*'
%%
expr : expr BINOP expr
| TOK_INTCON
BINOP : '+'
| '*'
%%
$ bison -v expr.y
expr.y: warning: 2 shift/reduce conflicts [-Wconflicts-sr]
```

```
1 op 2 op 3
```

```
op
/ \
1 op
/ \
2 3
```

```
op
/ \
op 3
/ \
1 2
```

```
$ cat expr-repaired.y
%token TOK_INTCON
%left '+'
%left '*'
%%
expr : expr '+' expr
| expr '*' expr
| TOK_INTCON
%%
$ bison -v expr-repaired.y
$
```

```
State 6
1 expr: expr . '+' expr
1 | expr '+' expr .
2 | expr . '*' expr
'*' shift, and go to state 5
$default reduce using rule 1 (expr)
```