C 使用Ragel解析器捕获字段

C 使用Ragel解析器捕获字段,c,parsing,lexical-analysis,ragel,C,Parsing,Lexical Analysis,Ragel,我正在考虑使用Ragel为嵌入式系统中的NMEA GPS数据生成一个lexer。我会有一个任意大小的缓冲区,从UART读取数据块,每次读取时,我都会将数据传递到lexer 我希望能够提取特定字段,但问题是我不能保证整个字段都存在于数据块中。任何字段都可能被拆分为两次读取,因此设置指向字段开始和结束的指针可能会将开始指针保留在上一个(现在已覆盖)缓冲区的末尾,并将结束指针保留在其前面 突然想到的一个解决方案是在每个字段上使用“$”操作,将字符逐个推入另一个内存位(可能是一个结构字段)。这是最好的方

我正在考虑使用Ragel为嵌入式系统中的NMEA GPS数据生成一个lexer。我会有一个任意大小的缓冲区,从UART读取数据块,每次读取时,我都会将数据传递到lexer

我希望能够提取特定字段,但问题是我不能保证整个字段都存在于数据块中。任何字段都可能被拆分为两次读取,因此设置指向字段开始和结束的指针可能会将开始指针保留在上一个(现在已覆盖)缓冲区的末尾,并将结束指针保留在其前面


突然想到的一个解决方案是在每个字段上使用“$”操作,将字符逐个推入另一个内存位(可能是一个结构字段)。这是最好的方法吗?

您可能希望在代码中添加溢出保护,以避免在恶意或错误输入上出现未定义的行为:

char buf[1024], *wptr = buf, *wmax = buf + sizeof(buf) - 2;

action append { if (wptr < wmax) *wptr++ = fc; }
charbuf[1024],*wptr=buf,*wmax=buf+sizeof(buf)-2;
动作追加{if(wptr
不管它值多少钱,我最终得出以下结论:

%%{
    machine nmea;

    action store { *wptr = fc; }
    action append { *wptr++ = fc; }
    action term { *wptr++ = 0; }

    integer = digit+;
    float = digit+ '.' digit+;

    rmc = '$GPRMC,'
        float ','
        [AV] >{ wptr = &loc.valid; } $store ','
        float? >{ wptr = loc.lat; } $append %term ','
        [NS]? >{ wptr = &loc.ns; } $store ','
        float? >{ wptr = loc.lng; } $append %term ','
        [EW]? >{ wptr = &loc.ew; } $store
        print*
        '\n' >{ printf("%c, %s, %c, %s, %c\n", loc.valid, loc.lat, loc.ns, loc.lng, loc.ew); }
    ;

    main := any* rmc;
}%%

假设您希望使用可扩展的字符串包装器,这样您就不会溢出内容(例如,当您尝试存储时会发生什么情况’,“当您已经处于
wptr
分配的限制时)。当长度达到分配时,应该像realloc一样简单capacity@amdixon我尽量避免使用malloc(到目前为止我根本没有使用它)。不过,没有一块田地会溢出——它们都足够大了。(我不在任何地方储存“,”顺便说一句)总体来说你是对的,但在这种情况下,它是一个严格控制的系统,没有恶意或意外输入的机会。谢谢你的例子,顺便说一句。(好吧,最好把它作为一个答案发布,这样人们就会知道问题的答案)。好的,我把它移到了一个答案。