help-bison
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Finding out when a token is consumed


From: Frank Heckenbach
Subject: Finding out when a token is consumed
Date: Wed, 30 Apr 2003 13:33:19 +0200

I have a bison parser, and I'd like to do something whenever a token
is consumed (used in a rule). More precisely, before an action is
run, something should be done for each terminal used in the rule.

Obviously, when I handle the tokens when they're lexed, that's too
early in case of parser lookahead. OTOH, if I handle the previous
token at the start of the lexer before the next one is lexed, that's
too late if there was no lookahead. So a pure lexer-based solution
doesn't seem to work.

Putting the extra code into every action would be clumsy. So I think
I need the possibility to run some code before any action (something
like YY_USER_ACTION in flex).

I see that YYLLOC_DEFAULT does this -- and the following example
using it seems to do what I want (and perhaps explains better what I
mean if my description isn't clear). But it seems like abuse of the
location tracking feature. Is there any other/better way?

%{
#include <stdio.h>
#include <stdlib.h>

static void yyerror (const char *s)
{
  printf ("%s\n", s);
}

static int yylex (void);

static void output_last (const char *);

#define YYLLOC_DEFAULT(A, B, C) \
  if (yychar == YYEMPTY) output_last ("parser => no lookahead");
%}

%token NUM

%locations

%%

expression:
    term
  | expression '+' term
      { $$ = $1 + $3; printf ("%i + %i = %i\n", $1, $3, $$); }
  ;

term:
    factor
  | term '*' factor
      { $$ = $1 * $3; printf ("%i * %i = %i\n", $1, $3, $$); }
  ;

factor:
    NUM
  | '(' expression ')'
      { $$ = $2; }
  ;

%%

static int last = -1;

static void output_last (const char *n)
{
  if (last >= 0)
    {
      if (last == NUM)
        printf ("consumed NUM %i", yylval);
      else
        printf ("consumed %c", last ? last : '$');
      printf (" (called from %s)\n", n);
    }
  last = -1;
}

static int yylex ()
{
  int c;
  output_last ("lexer => lookahead");
  c = getchar ();
  if (c == EOF || c == '\n')
    c = 0;
  if (c >= '0' && c <= '9')
    {
      yylval = c - '0';
      c = NUM;
    }
  if (c == NUM)
    printf ("lexed NUM %i\n", yylval);
  else
    printf ("lexed %c\n", c ? c : '$');
  last = c;
  return c;
}

int main ()
{
  return yyparse ();
}

Sample session:

# echo '1+2*3+4' | ./token-consume-test
lexed NUM 1
consumed NUM 1 (called from parser => no lookahead)
lexed +
consumed + (called from lexer => lookahead)
lexed NUM 2
consumed NUM 2 (called from parser => no lookahead)
lexed *
consumed * (called from lexer => lookahead)
lexed NUM 3
consumed NUM 3 (called from parser => no lookahead)
2 * 3 = 6
lexed +
1 + 6 = 7
consumed + (called from lexer => lookahead)
lexed NUM 4
consumed NUM 4 (called from parser => no lookahead)
lexed $
7 + 4 = 11

(E.g., the second `+' is lexed before the first addition is done,
but consumed afterwards, as is typical with lookahead tokens.)

Frank

-- 
Frank Heckenbach, address@hidden
http://fjf.gnu.de/
GnuPG and PGP keys: http://fjf.gnu.de/plan (7977168E)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]