我正在编写一个小解析器,我想知道加载要解析的数据的不同方法的优缺点。我想到的两种方式是:
fgetc
)前者允许我有两个功能:一个用于parse_from_file
和parse_from_string
,但我相信这种模式会占用更多内存。后者不会有使用更多内存的缺点。
有人对此事有任何建议吗?
答案 0 :(得分:2)
读取整个文件或内存映射它会更快,但如果您希望您的语言能够#include
其他文件,可能会导致问题,因为这些文件将被内存映射或读入内存。 / p>
stdio函数可以很好地工作,因为它们通常会尝试为您缓冲数据,但它们也是通用的,因此它们也会尝试查找与从头到尾读取文件不同的使用模式,但这不应该开销太大了。
一个很好的平衡是有一个大的循环缓冲区(x * 2 * 4096是一个很好的大小),你加载文件数据,然后读取你的标记器。每当块的数据传递到您的tokenizer(并且您知道它不会被推回)时,您可以使用文件中的新数据重新填充该块并更新一些缓冲区位置信息。
另一件需要考虑的事情是,是否有可能需要将tokenizer用于从管道或直接在某些文本中输入的人员进行读取。在这些情况下,如果没有它在文件的末尾,您的读取可能返回的数据少于您要求的数据,并且上面提到的缓冲方法变得更加复杂。 stdio缓冲很有用,因为它可以很容易地切换到线路或块缓冲(或不缓冲)。
使用gnu fast lex(flex,但不是Adobe Flash的东西)或类似的东西可以大大减轻所有这一切的麻烦。您应该考虑使用它来为您的tokenizer生成C代码(词法分析)。
无论你做什么,你都应该尝试做到这一点,这样你的代码就可以很容易地改变,使用不同形式的下一个角色偷看并消耗功能,这样如果你改变主意,就不必重新开始。
答案 1 :(得分:0)
考虑使用lex(如果语法的语言与其功能相匹配,也可以使用yacc)。 Lex将为您处理词法分析的所有细节,并生成有效的代码。您可以将其内存占用量减少几个字节,但是您想要花费多少精力呢?
答案 2 :(得分:0)
POSIX系统上效率最高的可能都不是两者(如果你愿意,可能是第一个的变体):只用mmap
将文件只读映射,然后解析它。现代系统非常有效,因为它们在检测到流式访问等时预取数据。解析同一文件的程序的多个实例将获得相同的内存物理页面等。并且接口相对易于处理,我想。