【发布时间】:2011-03-06 07:57:45
【问题描述】:
我想用类似 FSM 的解析器在 C++ 中解析一个自行设计的文件格式(这是一个 teach-myself-c++-the-hard-way-by-doing-something-big-and-difficult 类型的项目 :))。我有一个带有换行符的标记化字符串,表示 euh... 行的结尾。见here for an input example。所有的 cmets 都会和垃圾被过滤掉,所以我有一个像这样的 std::string:
global \n { \n SOURCE_DIRS src \n HEADER_DIRS include \n SOURCES bitwise.c framing.c \n HEADERS ogg/os_types.h ogg/ogg.h \n } \n ...
语法解释:
- { } 是范围,大写的单词表示后面有一个选项/文件列表。
- \n 仅在选项/文件列表中很重要,表示列表的结尾。
所以我认为 FSM 足够简单/可扩展,足以满足我的需求/知识。据我所知(并希望我的文件设计如此),我不需要并发状态或类似的东西。一些设计/实施问题:
- 我应该为我的状态使用
enum或抽象class+ 派生词吗?第一个可能更适合小语法,但以后可能会变得丑陋,而第二个恰恰相反。我倾向于第一个,因为它很简单。enumexample 和 class example。编辑:this suggestion 对于goto怎么样,我认为它们在 C++ 中是邪恶的? - 阅读列表时,我不需要忽略
\n。我通过stringstream使用string的首选方式默认会忽略\n。所以我需要一种简单的方式告诉(同样的!)stringstream在启用某个状态时不要忽略换行符。 - 简单的
enum状态是否足以进行多级解析({...{...}...}范围内的范围)还是需要 hacky 实现? - 这是我想到的草案状态:
-
upper:读取全局、exe、lib+ 目标名称... -
normal:在作用域内,可以读取 SOURCES...,创建用户变量... -
list:将项目添加到列表中,直到遇到换行符。
-
每个作用域都有一种条件(例如 win32:global { gcc:CFLAGS = ... }),并且需要在任何地方以完全相同的方式处理(即使在list 状态下,每个项目) .
感谢您的任何意见。
【问题讨论】:
-
会飞的意大利面怪物?
-
goto是不是邪恶的。 滥用goto是邪恶的。正确使用goto可以使代码更易于阅读和遵循,而我所知道的正确用例之一就是编码 FSM。为什么这么多人坚持goto是邪恶的?宗教。 -
问题是滥用造成无法辨认的怪物。