rbbb@rice.EDU (David Chase) (12/09/86)
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.
....
Read the rest of "Lex- A Lexical Analyzer Generator" by M. E. Lesk and E.
Schmidt for other details, including the lookahead issues, use of yywrap,
etc.
>>"Look at the code generated by these tools! It's easy to change it!"
David
mcvoy@uwvax.UUCP (12/11/86)
In article <1367@brl-adm.ARPA> rbbb@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@rsch.wisc.edu, {seismo, topaz, harvard, ihnp4, etc}!uwvax!mcvoy "They're coming soon! Quad-stated guru-gates!"
ejp@ausmelb.OZ (Esmond Pitt) (12/12/86)
In article <3060@rsch.WISC.EDU> mcvoy@rsch.WISC.EDU (Lawrence W. McVoy) writes: >In article <1367@brl-adm.ARPA> rbbb@rice.EDU (David Chase) writes: >>RTFM! RTFM! RTFM! I QUOTE: > > 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. Bad guess. Your code kinda has at least two bugs: 1. Your yyerror() function is wrong, so you didn't see the parser trying to print 'syntax error'. (Why not use yyerror() from -ly?) 2. The syntax error occurs because the grammar expects a newline, but you didn't append one to the argument buffer. >main(argc, argv) ... > for (i=1; i<argc; i++) > for (s=argv[i]; *s; *ptr++ = *s++) > ; > ! *ptr++ = '\n'; /* Terminate argument list with newline */ > ptr = buf; ... >yyerror(s) > char* s; >{ /* fprintf(stderr, "%s\n"); */ /* WRONG */ ! fprintf(stderr, "%s\n",s); /* RIGHT */ >} Fix & it works fine. -- Esmond Pitt, ACSnet: ejp@ausmelb.oz Austec International Ltd, UUCP: ...!seismo!munnari!ausmelb.oz!ejp 344 St Kilda Rd, ARPA: ejp%ausmelb.oz@SEISMO.CSS.GOV Melbourne, 3004, AUSTRALIA. Phone: +61 3 699 4511; Telex: AA38559 D