How to make YY_INPUT point to a string rather than stdin in Lex & Yacc (Solaris)

11,329

Solution 1

Redefine YY_INPUT. Here's a working example, compile and run with the commands

yacc -d parser.y
lex lexer.l
gcc -o myparser *.c

Input is read from globalInputText. You can modify this example so that global input text is whatever string you want or from any input source you want.

parser.y:

%{
#include <stdio.h>
extern void yyerror(char* s);
extern int yylex();
extern int readInputForLexer(char* buffer,int *numBytesRead,int maxBytesToRead);
%}

%token FUNCTION_PLUS FUNCTION_MINUS NUMBER

%%

expression:
    NUMBER FUNCTION_PLUS NUMBER { printf("got expression!  Yay!\n"); }
    ;

%%

lexer.l:

%{

#include "y.tab.h"
#include <stdio.h>


#undef YY_INPUT
#define YY_INPUT(b,r,s) readInputForLexer(b,&r,s)

%}

DIGIT   [0-9]
%%

\+      { printf("got plus\n"); return FUNCTION_PLUS; }
\-      { printf("got minus\n"); return FUNCTION_MINUS; }
{DIGIT}* { printf("got number\n"); return NUMBER; }
%%


void yyerror(char* s) {
    printf("error\n");
}

int yywrap() {
    return -1;
}

myparser.c:

#include <stdio.h>
#include <string.h>

int yyparse();
int readInputForLexer( char *buffer, int *numBytesRead, int maxBytesToRead );

static int globalReadOffset;
// Text to read:
static const char *globalInputText = "3+4";

int main() {
    globalReadOffset = 0;
    yyparse();
    return 0;
}

int readInputForLexer( char *buffer, int *numBytesRead, int maxBytesToRead ) {
    int numBytesToRead = maxBytesToRead;
    int bytesRemaining = strlen(globalInputText)-globalReadOffset;
    int i;
    if ( numBytesToRead > bytesRemaining ) { numBytesToRead = bytesRemaining; }
    for ( i = 0; i < numBytesToRead; i++ ) {
        buffer[i] = globalInputText[globalReadOffset+i];
    }
    *numBytesRead = numBytesToRead;
    globalReadOffset += numBytesToRead;
    return 0;
}

Solution 2

If you are using the real lex and not flex I believe you can simply define your own

int input(void);

This can return characters from a string or whatever you want.

Alternatively, I believe you could write the string to a file, and open the file on stream yyin. I suspect this would work with either implementation.

If using flex then I think you redefine the YY_INPUT() macro,

Solution 3

another approach is to use yy_scan_string as already mentioned in linked answers

Share:
11,329

Related videos on Youtube

ajai
Author by

ajai

Updated on April 15, 2022

Comments

  • ajai
    ajai about 2 years

    I want my yylex() to parse a string rather than a file or standard input. How can I do it with the Lex and Yacc provided with Solaris?

  • Michael Dorst
    Michael Dorst about 4 years
    numBytesRead and maxBytesToRead should be unsigned long * and unsigned long, respectively.