Как заставить YY_INPUT указывать на строку, а не на stdin в Lex & Yacc (Solaris)

Я хочу, чтобы мой yylex() разбирал строку, а не файл или стандартный ввод. Как я могу это сделать с Lex и Yacc, предоставляемыми Solaris?

    Переопределите 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); 

    Это может возвращать символы из строки или того, что вы хотите.

    В качестве альтернативы, я считаю, что вы можете записать строку в файл и открыть файл в streamе 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() -ed FILE* как yyin .

    Давайте будем гением компьютера.