如何在解析过程中获取光标位置?

How to get the cursor location during parsing?

我为 Packcc 解析器生成器做了一个最小的例子。 在这里,解析器必须识别浮点数或整数。 我尝试打印检测到的数字的位置。为简单起见,没有 line/column 计数,只是来自“ftell”的数字。

%auxil "FILE*" # The type sent to "pcc_create" for access in "ftell".

test <- line+
        /
        _ EOL+

line <- num _ EOL

num <-  [0-9]+'.'[0-9]+     {printf("Float at %li\n", ftell(auxil));}
        /
        [0-9]+              {printf("Integer at %li\n", ftell(auxil));}

_ <- [ \t]*

EOL <- '\n' / '\r\n' / '\r'

%%

int main()
{
    FILE* file = fopen("test.txt", "r");
    stdin = file;
    if(file == NULL) {
    // try to open.
        puts("File not found");
    }
    else {
    //  parse.
        pcc_context_t *ctx = pcc_create(file);
        while(pcc_parse(ctx, NULL));
        pcc_destroy(ctx);
    }
    return 0;
}

要解析的文件可以是

2.0
42

命令可以

packcc test.peg && cc test.c && ./a.out

问题是游标值总是在文件末尾,无论数字是多少 位置。

如果不仔细查看生成的代码,解析器似乎会坚持在执行任何操作之前将整个文本读入内存。这对于这个语法来说似乎是不必要的,而且它肯定不是典型的生成词法扫描器的工作方式。这特别奇怪,因为生成的扫描器似乎使用 getchar 一次读取一个字节,如果您打算读取整个文件,这不是很有效。

公平地说,您也无法在 flex-generated 扫描仪中使用 ftell,除非您强制扫描仪进入交互模式。 (原始的 AT&T lex 也一次读取一个字符,将从 ftell 中为您提供合理的值。但您不太可能再找到用它构建的扫描仪。)

Flex 会给你错误的答案,因为它故意以其缓冲区大小(通常为 8k)的块读取输入。这比 character-at-a-time 阅读效率高得多。但它不适用于交互式环境——例如,您直接从用户输入解析的地方——因为您不想阅读超出用户键入行尾的内容。

您必须询问维护 packcc 的人他们维护源位置的预期方法是什么。他们可能内置了一些东西。

可以通过特殊变量检索位置。 在上面的示例中,“ftell”必须替换为“$0s”或“$0e”。 $0s 是匹配模式的开始,$0e 是匹配模式的结束。

https://github.com/arithy/packcc/blob/master/README.md