2009-12-17 10 views
12

Desidero che il mio yylex() analizzi una stringa anziché un file o uno standard input. Come posso farlo con Lex e Yacc forniti con Solaris?Come rendere YY_INPUT puntare a una stringa anziché a stdin in Lex & Yacc (Solaris)

+0

Vedere anche [Come analizzare da una stringa ra ther than a file] (http://stackoverflow.com/questions/1909166/how-to-parse-from-a-string-rather-than-a-file). –

+0

Vedere anche http://stackoverflow.com/q/1907847/15168. –

risposta

6

Se si utilizza il vero lex e non flex io credo che si può semplicemente definire il proprio

int input(void); 

Questo può tornare caratteri da una stringa o quello che volete.

In alternativa, credo che si possa scrivere la stringa in un file e aprire il file nello stream yyin. Sospetto che ciò funzionerebbe con entrambe le implementazioni.

Se si utilizza Flex, allora penso che si ridefinisce il YY_INPUT() macro,

0

Qui è qualcosa che dovrebbe funzionare con qualsiasi applicazione, anche se rischiosa usando popen.

$ cat a.l 
%% 
"abc" {printf("got ABC\n");} 
"def" {printf("got DEF\n");} 
. {printf("got [%s]\n", yytext);} 
%% 
int main(int argc, char **argv) 
{ 
    return(lex("abcdefxyz")); 
} 
lex(char *s) 
{ 
    FILE *fp; 
    char *cmd; 
    cmd=malloc(strlen(s)+16); 
    sprintf(cmd, "/bin/echo %s", s); // major vulnerability here ... 
    fp=popen(cmd, "r"); 
    dup2(fileno(fp), 0); 
    return(yylex()); 
} 
yywrap() 
{ 
    exit(0); 
} 
$ ./a 
got ABC 
got DEF 
got [x] 
got [y] 
got [z] 
0

Come è stato detto prima che possa essere fatto attraverso la ridefinizione del input() - ho usato su AIX, HP-UX e Solaris.

O un altro approccio che uso anch'io è creare una pipe e utilizzare fdopen() -ed FILE* come yyin.

12

Ridefinire YY_INPUT. Ecco un esempio di lavoro, compilazione ed esecuzione con i comandi

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

L'input viene letto da globalInputText. È possibile modificare questo esempio in modo che il testo di input globale sia quello che si desidera o da qualsiasi sorgente di input desiderata.

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; 
} 
3

un altro approccio è quello di utilizzare yy_scan_string come già accennato nelle risposte legate

Problemi correlati