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

发布于 2024-08-15 07:58:30 字数 72 浏览 7 评论 0原文

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

I want my yylex() to parse a string rather than a file or standard input. How can I do it with the Lex and Yacc provided with Solaris?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

瑾夏年华 2024-08-22 07:58:30

重新定义YY_INPUT。这是一个工作示例,使用命令“

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

Input is read from globalInputText”进行编译和运行。您可以修改此示例,以便全局输入文本是您想要的任何字符串或来自您想要的任何输入源。

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;
}

Redefine YY_INPUT. Here's a working example, compile and run with the commands

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

Input is read from globalInputText. You can modify this example so that global input text is whatever string you want or from any input source you want.

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;
}
孤君无依 2024-08-22 07:58:30

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

int input(void);

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

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

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

If you are using the real lex and not flex I believe you can simply define your own

int input(void);

This can return characters from a string or whatever you want.

Alternatively, I believe you could write the string to a file, and open the file on stream yyin. I suspect this would work with either implementation.

If using flex then I think you redefine the YY_INPUT() macro,

一场春暖 2024-08-22 07:58:30

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

another approach is to use yy_scan_string as already mentioned in linked answers

述情 2024-08-22 07:58:30

尽管使用 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]

Here is something that should work with any implementation, although risky by using 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]
离笑几人歌 2024-08-22 07:58:30

正如之前所说,可以通过重新定义 input() 来完成 - 我已经在 aix、hpux 和Solaris 上使用过它。

或者我也使用的另一种方法是创建一个管道,并使用 fdopen()-ed FILE* 作为 yyin

As was said before it can be done through redefining the input() - i've used it on aix, hpux and solaris.

Or another approach i use too is to make a pipe, and use fdopen()-ed FILE* as yyin.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文