2009-12-17 7 views
12

Ich möchte meine yylex() eine Zeichenfolge anstelle einer Datei oder Standardeingabe analysieren. Wie kann ich das mit Lex und Yacc machen, die mit Solaris geliefert werden?Wie YY_INPUT in Lex & Yacc (Solaris) auf eine Zeichenkette statt auf stdin zeigen kann

+0

Siehe auch [Wie man von einem String ra analysiert als eine Datei] (http://stackoverflow.com/questions/1909166/how-to-parse-from-a-string-rather-than-a-file). –

+0

Siehe auch http://StackOverflow.com/q/1907847/15168. –

Antwort

6

Wenn Sie die reale lex verwenden und nicht flex Ich glaube, Sie einfach Ihre eigene definieren

int input(void); 

Diese Zeichen aus einer Zeichenfolge zurückgeben kann oder was auch immer Sie wollen.

Alternativ könnte ich glaube, Sie könnten die Zeichenfolge in eine Datei schreiben und öffnen Sie die Datei im Stream yyin. Ich vermute, das würde bei beiden Implementierungen funktionieren.

Bei der Verwendung von Flex neu definiert Ich denke, man dann die YY_INPUT() Makro,

0

Dies ist etwas, das mit jeder Implementierung funktionieren sollte, obwohl riskant von popen verwenden.

$ 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

Wie gesagt wurde, bevor es durch die Neudefinition der input() getan werden kann - ich habe es auf AIX-, HP-UX und Solaris verwendet.

Oder ein anderer Ansatz, den ich auch verwende, ist ein Rohr zu machen, und fdopen() -ed FILE* als yyin zu verwenden.

12

Neudefinieren von YY_INPUT. Hier ist ein funktionierendes Beispiel, kompilieren und mit den Befehlen

Eingabe wird von GlobalInputText gelesen. Sie können dieses Beispiel so ändern, dass der globale Eingabetext unabhängig von der von Ihnen gewünschten Zeichenfolge oder von einer beliebigen Eingabequelle ist.

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

ein weiterer Ansatz ist yy_scan_string zu verwenden, wie bereits in verknüpften Antworten erwähnt

Verwandte Themen