2009-12-17 13 views
12

yylex() numaramın bir dosya veya standart girdi yerine bir dizeyi ayrıştırmasını istiyorum. Solaris ile sağlanan Lex ve Yacc ile nasıl yapabilirim? Gerçek lex değil flex kullanıyorsanızYY_INPUT, Lex & Yacc (Solaris) içinde stdin yerine bir dizeye nasıl işaretlenir

+0

Ayrıca bkz. [Bir dizgeden ayrıştırma ra bir dosyadan daha fazlası] (http://stackoverflow.com/questions/1909166/how-to-parse-from-a-string-rather-than-a-file). –

+0

Ayrıca bkz. Http://stackoverflow.com/q/1907847/15168. –

cevap

6

Ben sadece bu istediğini bir dize veya karakterleri dönebilirsiniz

int input(void); 

Kendi tanımlayabilirsiniz inanıyoruz.

Alternatif olarak, dizeyi bir dosyaya yazabileceğinizi ve dosyayı yyin akışında açabileceğinizi düşünüyorum. Bunun uygulama ile çalışacağından şüpheleniyorum.

esnek kullanılıyorsa o zaman burada makro YY_INPUT(),

0

yeniden tanımlamak düşünüyorum popen kullanarak riskli olmasına rağmen, herhangi bir uygulama ile çalışması gerekir şeydir. i aix, HPUX ve Solaris üzerinde kullandım - bu input() yeniden tanımlanması yoluyla yapılabilir önce

$ 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

şöyle söyleniyordu. Ya da ben de bir boru yapmak ve fdopen() -ed FILE* kullanmak yyin olarak kullanmak başka bir yaklaşım.

12

Yeniden tanımlama YY_INPUT. İşte çalışan bir örnektir, derlemek ve

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

Girdi globalInputText okunur komutlarla çalıştırın. Bu örneği, genel giriş metnini istediğiniz herhangi bir dize veya istediğiniz herhangi bir giriş kaynağından alacak şekilde değiştirebilirsiniz.

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:

başka yaklaşım olarak zaten bağlanmış cevapları belirtilen yy_scan_string kullanmaktır
#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

İlgili konular