2009-12-17 16 views
12

Quiero que mi yylex() analice una cadena en lugar de un archivo o una entrada estándar. ¿Cómo puedo hacerlo con Lex y Yacc con Solaris?Cómo hacer que YY_INPUT apunte a una cadena en lugar de stdin en Lex & Yacc (Solaris)

+0

Ver también [Cómo analizar desde una cadena ra más que un archivo] (http://stackoverflow.com/questions/1909166/how-to-parse-from-a-string-rather-than-a-file). –

+0

Vea también http://stackoverflow.com/q/1907847/15168. –

Respuesta

6

Si está utilizando el verdadero lex y no flex creo que simplemente puede definir su propio

int input(void); 

Esto puede devolver caracteres de una cadena o como se quiera.

Como alternativa, creo que podría escribir la cadena en un archivo y abrir el archivo en la secuencia yyin. Sospecho que esto funcionaría con cualquiera de las implementaciones.

Si se utiliza la flexión entonces creo que redefinir la YY_INPUT() macro,

0

Aquí es algo que debería funcionar con cualquier aplicación, aunque arriesgada mediante el uso de 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

Como se dijo antes de que pueda hacerse a través de la redefinición de la input() - Lo he utilizado en AIX, HP-UX y Solaris.

O bien, otro enfoque que yo también uso es hacer una tubería, y use fdopen() -ed FILE* como yyin.

12

Redefina YY_INPUT. Aquí hay un ejemplo de trabajo, compilar y ejecutar con los comandos

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

La entrada se lee de globalInputText. Puede modificar este ejemplo para que el texto de entrada global sea la cadena que desee o desde cualquier fuente de entrada que desee.

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

otro enfoque es utilizar yy_scan_string como ya se ha mencionado en las respuestas vinculadas

Cuestiones relacionadas