上一篇的字符变量都是一个字母的,这不够用,需要支持单词的变量
首先定义一个结构体,用来存储符号和符号的值(可以实现一个哈希表,会比较快)
ch3hdr.h
#define NSYMS 20
struct symtable{
char *name;
double value;
}symtable[NSYMS];
extern struct symtable *symlook(char *s);
ch3hdr.c
#include "ch3hdr.h"
#include <string.h>
struct symtable *symlook(char *s)
{
struct symtable *iterator = symtable;
for(; iterator < &symtable[NSYMS]; iterator++){
if (iterator->name && !strcmp(iterator->name, s)){
return iterator;
}
if (!iterator->name){
iterator->name = strdup(s);
return iterator;
}
}
yyerror("too many symbols");
exit(1);
}
cal.y
%{
#include <stdio.h>
#include "ch3hdr.h"
%}
%union{
double dval;
struct symtable *symble;
}
%token PRINT
%token <symble> NAME
%token <dval> NUMBER
%type <dval> expression
%left '+' '-'
%left '*' '/'
%%
paragraph:
paragraph statement '\n'
|statement '\n'
;
statement:
PRINT expression {
printf("\ntest yacc PRINT expression\n");
printf("result is %lf", $2);
}
|NAME '=' expression {
printf("\ntest yacc = expression\n");
$1->value = $3;
}
;
expression:
expression '*' expression {
printf("\ntest yacc expression + expression\n");
$$ = $1 * $3;
}
|expression '/' expression {
printf("\ntest yacc expression + expression\n");
$$ = $1 / $3;
}
|expression '+' expression {
printf("\ntest yacc expression + expression\n");
$$ = $1 + $3;
}
|expression '-' expression {
printf("\ntest yacc expression + expression\n");
$$ = $1 - $3;
}
|NUMBER {
printf("\ntest yacc NUMBER\n");
$$ = $1;
}
|NAME {
$$ = $1->value;
}
;
%%
cal.l
%{
#include "y.tab.h"
#include "ch3hdr.h"
#include <math.h>
%}
%%
print {printf("\ntest lex print\n"); return PRINT;}
[0-9]+ |
[0-9]*\.[0-9]+ {printf("\ntest lex NUMBER\n");yylval.dval = atof(yytext); return NUMBER;}
[ \t] ;
[a-zA-Z][a-zA-Z0-9]* {
printf("\ntest lex %s", yytext);
yylval.symble = symlook(yytext);
return NAME;
}
"$" {return 0;}
\n |
. {printf("\ntest lex %s", yytext); return yytext[0];}
%%
nosourcesmatoMacBook-Pro:~ nosources$ yacc -d cal.y && lex cal.l && cc -o cal y.tab.c lex.yy.c ch3hdr.c -ly -ll
variablename = 1+2*3-4*4
test lex variablename
test lex =
test lex NUMBER
test yacc NUMBER
test lex +
test lex NUMBER
test yacc NUMBER
test lex *
test lex NUMBER
test yacc NUMBER
test yacc expression + expression
test lex -
test yacc expression + expression
test lex NUMBER
test yacc NUMBER
test lex *
test lex NUMBER
test yacc NUMBER
test yacc expression + expression
test lex
test yacc expression + expression
test yacc = expression
print variablename
test lex print
test lex variablename
test lex
test yacc PRINT expression
result is -9.000000