我正在建立一个语法,我需要解析lambda x : x + x end
,提取args = "x"
和body = "x + x"
。我的语法正确返回了body
,但是arg
是x : x + x end
。 arg应该停在冒号上,但不要停。
这是我的语法:
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *oper(char op, char *l, char *r) {
char *res = malloc(strlen(l)+strlen(r)+6);
sprintf(res, "(%c %s %s)", op, l, r);
return res;
}
char *dup(char *orig) {
char *res = malloc(strlen(orig)+1);
strcpy(res,orig);
return res;
}
char* lambda(char *arg, char *body){
printf("arg: %s\nbody: %s\n\n", arg, body);
char *res = malloc(strlen(arg) + strlen(body) + 10);
sprintf(res,"(func %s (%s))", arg, body);
return res;
}
int yylex();
void yyerror(char *);
%}
%union {
char *val;
}
%token <val> NUM
%token <val> SYMBOL
%token LAMBDA
%token COLON
%token END
%type <val> exp
%left ADD
/* Gramatic */
%%
input:
| exp { puts($1); }
| error { fprintf(stderr, "Invalid input\n"); }
;
exp:
NUM { $$ = dup($1); }
| SYMBOL { $$ = dup($1); }
| LAMBDA SYMBOL COLON exp END { $$ = lambda($2, $4); }
| exp ADD exp { $$ = oper('+', $1, $3); }
;
%%
void yyerror(char *s) {
fprintf(stderr,"%s\n",s);
}
lex文件非常简单:
alpha [A-Za-z]
dig [0-9]
name {alpha}({alpha}|{dig})*
number [-+]?{dig}+\.?([eE][-+]?{dig}+)?
%{
#include <math.h>
#include "parser.tab.h"
%}
%%
{number} { yylval.val = yytext; return NUM; }
[ \t\n]+ /* whitespace */
[+] { return ADD; }
(end) { return END; }
(:) { return COLON; }
(lambda) { return LAMBDA; }
{name} { yylval.val = yytext; return SYMBOL; }
. { fprintf(stderr, "Entrada ignorada\n-->%s\n", yytext); }
%%
/* Local Variables: */
/* mode: c */
/* End: */
然后我用Makefile进行编译:
parser: parser.tab.o lex.yy.o main.o
gcc -o $@ $^ -lfl
parser.tab.o: parser.y
bison -d parser.y
gcc -c parser.tab.c
lex.yy.o: parser.l
flex parser.l
gcc -c lex.yy.c
然后,运行一个简单的测试,我得到了错误的结果:
$ echo "lambda x : x + x end" | ./parser
arg: x : x + x end
body: (+ x x)
(func x : x + x end ((+ x x)))
任何指导表示赞赏:)