繁体   English   中英

C词法分析器。 使用开关来分析和计算小数/非小数

[英]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]+

这已经显示了可能的状态转换:

  • 数字可以(可选)以+-开头(如果您支持有符号数字)
  • 它可能有0..n个数字
  • 如果以下字符不是小数点符号,则它应该是分隔符,否则它是无效符号。 如果是分隔符,则终止您的号码。
  • 小数点后应该有1..n位数
  • 当您到达输入结尾或遇到分隔符时,数字将终止

所有这些都可以在少量代码行中完成 - 只需要一个指向当前输入字符的指针,然后逐个前进并检查每个字符并根据字符类决定要做什么。

现在,这种特殊方法不使用科学记数法等处理浮点数,但是一旦完成基本操作,添加额外内容就非常简单。

我认为这补充了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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM