Tôi muốn số yylex()
để phân tích cú pháp chuỗi thay vì tệp hoặc đầu vào chuẩn. Làm thế nào tôi có thể làm điều đó với Lex và Yacc cung cấp với Solaris?Cách tạo điểm YY_INPUT thành chuỗi thay vì stdin trong Lex & Yacc (Solaris)
Trả lời
Nếu bạn đang sử dụng thực sự lex
và không flex
Tôi tin rằng bạn chỉ có thể xác định riêng bạn
int input(void);
này có thể trở lại ký tự từ một chuỗi hoặc bất cứ điều gì bạn muốn.
Hoặc, tôi tin rằng bạn có thể viết chuỗi đó vào một tệp và mở tệp trên luồng yyin
. Tôi nghi ngờ điều này sẽ làm việc với một trong hai thực hiện.
Nếu sử dụng flex sau đó tôi nghĩ rằng bạn xác định lại YY_INPUT()
vĩ mô,
Đây là cái gì đó sẽ làm việc với bất kỳ thực hiện, mặc dù rủi ro bằng cách sử dụng 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]
Như đã nói trước khi nó có thể được thực hiện thông qua việc xác định lại input()
- tôi đã sử dụng nó trên aix, HPUX và solaris.
Hoặc cách tiếp cận khác mà tôi sử dụng là tạo đường ống và sử dụng fdopen()
-ed FILE*
là yyin
.
Xác định lại YY_INPUT. Dưới đây là ví dụ hoạt động, biên dịch và chạy với các lệnh
yacc -d parser.y
lex lexer.l
gcc -o myparser *.c
Đầu vào được đọc từ globalInputText. Bạn có thể sửa đổi ví dụ này để văn bản nhập toàn cục là bất kỳ chuỗi ký tự nào bạn muốn hoặc từ bất kỳ nguồn đầu vào nào bạn muốn.
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;
}
phương pháp khác là sử dụng yy_scan_string như đã đề cập trong câu trả lời liên quan
Xem thêm [Cách phân tích cú pháp từ chuỗi hơn một tệp] (http://stackoverflow.com/questions/1909166/how-to-parse-from-a-string-rather-than-a-file). –
Xem thêm http://stackoverflow.com/q/1907847/15168. –