argv --> stdin IN LEX

mcvoy at uwvax.UUCP mcvoy at uwvax.UUCP
Thu Dec 11 12:32:13 AEST 1986


In article <1367 at brl-adm.ARPA> rbbb at rice.EDU (David Chase) writes:
>RTFM! RTFM! RTFM!  I QUOTE:
>	In addition to these routines, Lex also permits access to the
>    I/O routines that it uses.  They are:
>    1)	input() which returns the next input character;
>    2)	output(c) which writes the character c on the
>	output; and
>    3)	unput(c) pushes the character c back onto the
>	input stream to be read later by input().
>
>    By default these routines are provided as macros definitions,
>    but the user can override them and supply private versions.
>    ....

  After RTFM! RTFM! RTFM!-ing again and wading through lex 
output (gag):  Yup.  Works neat.  With lex.  Doesn't work at all 
with yacc.  If y'all go back and read the original posting, you 
will notice that I kinda asked for a solution that works with 
lex and yacc.  
  
  The relevant parts of the code are included below.  My guess 
is that yacc makes some assumptions about buffers, though 
I can't see where.

  I've got a fix that has nothing to do with lex & yacc and I 
like it that way.  The original problem, which might occur in 
situations that don't use lex and yacc, is how do you send 
the chars in argv[] to a process that thinks it's getting
them from stdin?  The answer:  Use a pipe.  If you know that 
you have less than 4k or so, don't even bother to fork.  

Here's the offending code, if you're interested, be warned that 
I don't vouch for this, it's a hack:

---------------------- t.l ---------------------------
%{
# undef		input()
# undef		unput()
# define	input()		myinput()
# define	unput(c)	myunput(c)
# include	<stdio.h>
# include	"y.tab.h"
%}
DIGIT	[0-9]
DSEQ	"-"?{DIGIT}+
RSEQ	"-"?{DSEQ}"."{DSEQ}
EXPONP	("e"|"E")("-"|"+")?{DSEQ}
MULT	[xX*]
RPAR	[)rR]
LPAR	[(lL]
%%
"+"			return(PLUS);
"-"			return(MINUS);
{MULT}			return(MULTIPLY);
"/"			return(DIVIDE);
{LPAR}			return(LPAREN);
{RPAR}			return(RPAREN);
{DSEQ}			return(INT_CONST);
{RSEQ}			return(REAL_CONST);
({DSEQ}|{RSEQ}){EXPONP}	return(REAL_CONST);
\n			return(EOL);
[ \t]			;		/* white space, ignore */
.			{ printf("Scanner error: Illegal Character\n"); }
%%

char*	ptr;
char	buf[4096];

myinput()
{
    fprintf(stderr, "Input called, ptr = '%s'\n", ptr);
    return *ptr++;
}

myunput(c)
    char c;
{
    if (ptr == buf) {
	fprintf(stderr, "ERROR: tried to unput one too many (%c)\n", c);
	exit(1);
    }

    fprintf(stderr, "Unput called, ptr = '%s'\n", ptr);
    *--ptr = c;
}

main(argc, argv)
    char** argv;
{
    int 	i;
    char*	s;

    ptr = buf;
    for (i=1; i<argc; i++)
	for (s=argv[i]; *s; *ptr++ = *s++)
	    ;
    
    ptr = buf;
    printf("Sending %s to lex\n", buf);
    
# ifdef TESTLEX
    /* this works like a charm */
    while (i = yylex())
	printf("Lex returns %d\n", i);
# else
    /* this bombs */
    yyparse();
# endif
}

yyerror(s)
    char* s;
{
    fprintf(stderr, "%s\n");
}

---------------------- t.l ---------------------------

%{
#include <stdio.h>

extern char yytext[];
extern float atof();

static float result;
%}
%token
	PLUS MINUS MULTIPLY DIVIDE INT_CONST REAL_CONST LPAREN RPAREN EOL
%union
{
	float val;
}
%type
	<val>	root expr factor term
%%
root	:	expr EOL	{
				printf("%.4f\n",$1);
				exit(0);
				}
	;
expr	:	expr PLUS term	{ $$ = $1 + $3; }
	|	expr MINUS term { $$ = $1 - $3; }
	|	term
	;
term	:	term MULTIPLY factor	{ $$ = $1 * $3; }
	|	term DIVIDE factor	{ $$ = $1 / $3; }
	|	factor
	;
factor	:	INT_CONST	{ $$ = (float)atoi(yytext); }
	|	REAL_CONST	{ $$ = atof(yytext); }
	|	LPAREN expr RPAREN { $$ = $2; }
	;
-- 
Larry McVoy 	        mcvoy at rsch.wisc.edu, 
      		        {seismo, topaz, harvard, ihnp4, etc}!uwvax!mcvoy

"They're coming soon!  Quad-stated guru-gates!"



More information about the Comp.unix.wizards mailing list