【发布时间】:2018-03-27 08:14:48
【问题描述】:
我是 lex 和 yacc 的新手,我正在关注 "lex & yacc 1992" book。
我正在编写第 3 章的示例,编译过程中出现错误,但找不到解决方案; 这是代码:
lex 文件.l :
%{
#include "y.tab.h"
#include "symboletable.h"
#include <math.h>
extern int yylavl;
%}
%%
([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) {
yylval.dval = atof(yytext);
return NUMBER;
}
[ \t] ; /* ignore whitespace */
[A-Za-z][A-Za-z0-9]* { /* return symbol pointer */
yylval.symp = symlook(yytext);
return NAME;
}
"$" { return 0; }
\n |
. return yytext[0];
%%
这里是 yacc file.y
%{
#include "symboletable.h"
#include <string.h>
#include <stdio.h> /* C declarations used in actions */
int yylex();
void yyerror(const char *s);
%}
%union {
double dval;
struct symtab *symp;
}
%token <symp> NAME
%token <dval> NUMBER
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%type <dval> expression
%%
statement_list : statement '\n'
| statement_list statement '\n'
;
statement : expression { printf("= %g\n", $1); }
| NAME '=' expression {$1->value = $3; }
;
expression : NAME {$$ = $1->value; }
| expression '+' expression {$$ = $1 + $3; }
| expression '-' expression {$$ = $1 - $3; }
| expression '*' expression {$$ = $1 * $3; }
| expression '/' expression
{ if ($3 ==0.0)
yyerror("divide by zero");
else
$$ = $1 / $3;
}
| '-' expression %prec UMINUS {$$ = -$2; }
| '(' expression ')' {$$ = $2; }
| NUMBER
;
%%
根据书中的例子,我需要写一个符号表例程,来获取字符串并为字符串分配动态空间,这里是file.h
符号表.h
#define NSYMS 20 /* maximum number of symbols */
struct symtab {
char *name;
double value;
} symtab[NSYMS];
struct symtab *symlook();
和 symboletable.pgm:
/* look up a symbol table entry, add if not present */
struct symtab *
symlook(s)
char *s;
{
char *p;
struct symtab *sp;
for (sp = symtab; sp < &symtab[NSYMS]; sp++){
/* is it already here ? */
if (sp->name && !strcmp(sp->name, s))
return sp;
/* is it free */
if (!sp->name){
sp->name = strdup(s);
return sp;
}
/* otherwise continue to next */
}
yyerror("Too many symbols");
exit(1); /* cannot continue */
} /* symlook */
现在当我运行以下命令时:
yacc -d file.y
lex file.l
cc -c lex.yy.c -o newfile -ll
cc -o new y.tab.c lex.yy.c -ly -ll
但我得到的错误是:
/tmp/ccGnPAO2.o:在函数
yylex': lex.yy.c:(.text+0x2ac): undefined reference tosymlook'collect2:错误:ld返回1退出 状态
那么,为什么我得到了那个错误,我完全按照这个例子?
【问题讨论】:
-
你为什么要写这么古老的代码?我完全迷失了你对
symlook()的定义。更新你的书。或者只有你的代码,参数声明的风格对你来说太旧了,你是新一代。 -
struct symtab *symlook(s) char *s { }is K&R C - ancient 是一个合适的描述。从 ANSI C 开始,这可以写为struct symtab* symlook(char *s) { }。关于原型struct symtab *symlook();:它可能有效,但更好的是具有正确签名的原型:struct symtab* symlook(char*);。 -
虽然 K&R C 很古老,但很多 C 编译器似乎仍然支持它。 (可能是对发明者的致敬......)我相信,语法不是你的问题。是什么让我怀疑:如果您的文件实现了
symlook()真的被命名为symboletable.pgm(就像您的问题中所述),那么您忘记在编译和链接行中提及它。因此,链接错误而不是语法错误。顺便提一句。.pgm不被禁止,但对于 c 源文件来说是不寻常的。为什么不用后缀.c? -
您知道可以在
.lex文件的第二个%%之后添加常规C 代码吗?如果您将symlook()的实现移到该位置,您的问题也应该得到解决。 -
我对使用 lex 和 yacc 有点陌生,所以我不想让更改变得更糟,实际上我正在考虑在 lex 的第三部分将代码添加为普通的 c 样式文件,我只是想作为初学者按照书上的说明进行操作,好的,我将检查这些选项。
标签: c compiler-construction flex-lexer yacc lex