如何使YY_INPUT指向Lex&Yacc(Solaris)中的字符串而不是stdin

我希望我的yylex()解析字符串而不是文件或标准输入。 如何使用Solaris提供的Lex和Yacc?

重新定义YY_INPUT。 这是一个工作示例,使用命令编译和运行

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

输入从globalInputText读取。 您可以修改此示例,以便全局输入文本是您想要的任何字符串,或者来自您想要的任何输入源。

parser.y:

 %{ #include  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  #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  #include  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; } 

如果你使用真正的lex而不是flex我相信你可以简单地定义你自己的

 int input(void); 

这可以从字符串或任何您想要的内容返回字符。

或者,我相信你可以将字符串写入文件,并在流yyin上打开文件。 我怀疑这适用于任何一种实现。

如果使用flex,我认为你重新定义了YY_INPUT()宏,

另一种方法是使用链接答案中已提到的yy_scan_string

这是适用于任何实现的东西,尽管使用popen有风险。

 $ cat al %% "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] 

如前所述,它可以通过重新定义input()来完成 – 我已经在aix,hpux和solaris上使用它。

或者我使用的另一种方法是制作管道,并使用fdopen() FILE*作为yyin