[英]C lexical analyzer. Using switch to analyze and count a decimal/not decimal
我的词法分析器识别数字(5,555,543667),小数(44.65,4.1)和句点(。)。
我可以计算数字,小数和句点,但是当我遇到一个数字和一个彼此相邻的句点时,它将它计为小数。
考虑一个包含以下内容的文本文件:555 2.3 55.23 44 5。
我的输出是
1型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;
尝试了多件事但我正式陷入困境。
你真的应该使用字符分类函数来代替long switch语句。 您的代码将更加简单,您根本不必使用goto
。
例如,可以使用以下正则表达式来描述数字(添加空格以分解各个块):
[-+]? [0-9]* \.? [0-9]+
这已经显示了可能的状态转换:
+
或-
开头(如果您支持有符号数字) 所有这些都可以在少量代码行中完成 - 只需要一个指向当前输入字符的指针,然后逐个前进并检查每个字符并根据字符类决定要做什么。
现在,这种特殊方法不使用科学记数法等处理浮点数,但是一旦完成基本操作,添加额外内容就非常简单。
我认为这补充了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。 解析除简单数字之外的令牌。
使用像digit_follow_peroid
这样的变量来保持状态。 每次遇到peroid时,将变量设置为false,然后在十进制开关块中遇到一个数字时,将其设置为true。 检查变量的值以确定strncpy
的t.length。 也许你还需要其他变量来与它一起工作。 最好的方法是定义一个状态转换矩阵,它比gotos好得多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.