Search code examples
parsinglemon

Why does lemon not execute terminals immediately?


I am moving a small threaded interpreter using flex and yacc to re2c and lemon. Everything is working but literals.

Why does the action associated with literals fail to run as it does with yacc? I expect "1.0 end" but get "0.0 end"

dspgrammar.y

%include {#include <assert.h>}
%name dsp
%token_type {float}
program   ::= expr.    {printf("end\n");}
expr(val) ::= LITERAL. {printf("%f ", val);}

main.c

#include <stdio.h>
#include <stdlib.h>
#include "dspgrammar.h"

void *dspAlloc(void *(*)(size_t));
void dsp(void *, int, float);
void dspFree(void *, void (*)(void *));
void dspTrace(FILE *, char *);

int main(int argc, char *argv[])
{
        void *parser = dspAlloc(malloc);
        dspTrace(stderr, "TRACE: ");
        dsp(parser, LITERAL, 1.0f);
        dsp(parser,       0, 0.0f);
        dspFree(parser, free);
        return EXIT_SUCCESS;
}

Makefile

CC      = gcc
CFLAGS  = -O0 -g -Wall -Wextra -pedantic -std=gnu99
LD      = gcc
LDFLAGS = -lm

dsp: main.o dspgrammar.o
        $(LD) $(CFLAGS) -o $@ $^ $(LDFLAGS)

main.o: main.c
        $(CC) $(CFLAGS) -c main.c

dspgrammar.o: dspgrammar.c
        $(CC) -c $(CFLAGS) -c dspgrammar.c

dspgrammar.c: dspgrammar.y
        lemon dspgrammar.y

Solution

  • In

    expr(val) ::= LITERAL. { /* something with val */ }
    

    val is the name of the reduction value. In other words, it corresponds to $$ in yacc. The semantic value of the terminal LITERAL is $1, since you haven't provided a symbolic name for that value.

    Perhaps you meant:

    expr ::= LITERAL(val). { /* something with val */ }
    

    Or

    expr(e) ::= LITERAL(v). { e = v; /* some other action */ }