我的词法分析器识别数字(5,555,543667),小数(44.65,4.1)和句点(。)。
我可以计算数字,小数和句号,但是当我遇到一个数字和一个相邻的句点时,它会将其计为小数。
考虑一个包含以下内容的文本文件:555 2.3 55.23 44 5.
我的输出是
1 type 1:555
2型3:2.3
3型3:55.23
4型1:44
5 3:5。
其中类型3是我的小数点标识符。
我希望将第5和第6个令牌计为数字,然后计算一段时间。
以下是我处理switch语句的方法。
switch(*b) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
digits:
t.length++;
switch(*(b + t.length)) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
goto digits;
case '.':
goto decimal;
break;
default:
break;
}
t.type = TOKEN_DIGITS;
t.string = (char *)calloc(t.length + 1, sizeof(char));
strncpy(t.string, b, t.length);
break;
decimal:
t.length++;
switch(*(b + t.length)) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
goto decimal;
break;
}
t.type = TOKEN_DECIMAL;
t.string = (char *)calloc(t.length+1,sizeof(char));
strncpy(t.string,b,t.length);
break;
尝试了多件事,但我被正式卡住了。
答案 0 :(得分:1)
你真的应该使用character classification functions这种练习而不是长切换语句。您的代码将更加简单,您根本不必使用goto
。
例如,可以使用以下正则表达式来描述数字(添加空格以分解各个块):
[-+]? [0-9]* \.? [0-9]+
这已经显示了可能的状态转换:
+
或-
开头(如果您支持已签名的号码)这一切都可以在少量代码行中完成 - 只需要一个指向当前输入字符的指针,然后逐个前进并检查每个字符并根据字符类决定做什么
现在,这种特殊方法不会使用科学记数法等来处理浮点数,但是一旦完成基本操作,添加额外内容就非常简单。
答案 1 :(得分:1)
我认为这补充了xxbbcc的答案。
* 非常粗略* 这样的事情。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
yylex() {
int c;
char *p, buf[1000];
for(c = get(); isspace(c); c = get());
if(isdigit(c)) {
p = buf;
while(isdigit(c)) {
*p++ = c;
c = get();
}
*p = 0;
if(c != '.') {
unget(c);
int i = atoi(buf);
return INT;
}
assert(c == '.');
*p++ = c;
c = get();
while(isdigit(c)) {
*p++ = c;
c = get();
}
*p = 0;
float f = atof(buf);
unget(c);
return DECIMAL;
}
}
有很多细节没有说明。看着EOF。缓冲区溢出。将yylval设置为int或float。解析除简单数字之外的令牌。
答案 2 :(得分:0)
使用digit_follow_peroid
之类的变量来保持状态。每次遇到peroid时,将变量设置为false,然后在十进制开关块中遇到一个数字时,将其设置为true。检查变量的值以确定strncpy
之前的t.lengthbe。也许你还需要其他变量来与它一起工作。最好的方法是定义一个状态转换矩阵,它比gotos好得多。