14

yylex()ファイルや標準入力ではなく文字列を解析したい。Solaris で提供されている Lex と Yacc を使用してこれを行うにはどうすればよいですか?

4

5 に答える 5

15

YY_INPUTを再定義します。これが実際の例です。コンパイルしてコマンドで実行します

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

入力は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;
}
于 2011-07-19T17:16:48.330 に答える
6

あなたが本物を使っていて、そうではlexないなら、あなたはflex自分自身を定義することができると信じています

int input(void);

これは、文字列または必要なものから文字を返すことができます。

または、文字列をファイルに書き込み、ストリームでファイルを開くことができると思いますyyin。これはどちらの実装でも機能すると思います。

YY_INPUT()フレックスを使用している場合は、マクロを再定義すると思いますが、

于 2009-12-20T18:47:14.723 に答える
3

別のアプローチは、リンクされた回答ですでに述べたようにyy_scan_stringを使用することです

于 2012-11-16T11:01:42.203 に答える
0

これは、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]
于 2009-12-20T20:19:14.237 に答える
0

前に言ったように、再定義することで実行できますinput()-私はそれをaix、hpux、およびsolarisで使用しました。

または、私も使用する別のアプローチは、パイプを作成し、fdopen()-ed FILE*asを使用することyyinです。

于 2011-02-06T14:51:14.397 に答える