我有一个语法,需要处理输入流中任何一点以"{*"开头、以"*"结尾的注释。此外,它还需要处理以"{"开头、后跟"$"或和标识符、以"}"结尾的模板标记,并将其他所有内容作为文本传递。
实现这一点的唯一方法似乎是将任何不是注释或令牌的东西作为单个字符传递回解析器,并让解析器构建字符串。这是非常低效的,因为解析器必须为它接收到的每个字符构建一个节点,然后我必须遍历节点并从中构建一个字符串。如果lexer可以将文本作为一个大字符串返回,我会简单得多,速度也会更快。
在一个I7上,该程序作为一个32位#C程序在一个90K的文本文件上运行,没有标记或注释,只有文本,大约需要15分钟才能因内存异常和内存不足而崩溃。
语法基本上是
Parser:
text: ANY_CHAR+;
Lexer:
COMMENT: '{*' .*? '*}' -> skip;
... Token Definitions .....
ANY_CHAR: [ -~];
如果我试图在lexer中累积文本,它会吞下所有内容,并且不会识别注释或标记,因为像ANY_CHAR+这样的东西匹配所有内容,并在字符串中返回注释和模板标记。
有人知道解决这个问题的方法吗?现在看来我必须手写一个lexer。
是的,这是低效的,但也不是这样做的方法。解决方案完全在lexer中。
我知道你想要检测评论、模板标记和文本。为此,您应该使用lexer模式。每次你点击"{"进入某个lexer模式,比如说MODE1,在那里你只能检测到"*"或"$",或者(因为我不明白你所说的'{' followed by a '$' or and identifier
是什么意思)其他东西,然后根据你点击的内容进入MODE2或MODE3。之后(MODE2或MODE3)等待"}"并切换回默认模式。当然,有可能在两者之间制作更多的模式,这取决于你想做什么,但对于我刚刚写的:
- MODE1将在其中确定您的区域现在是否检测到注释或模板标记。此模式下只有两个令牌''和其他所有令牌。如果是"",则转到MODE2,如果有其他情况,则转到MODE 3
- MODE2这里只需要一个令牌,即COMMENT,但您还需要检测"*}"或"}"(取决于您想要如何处理它)
- MODE3类似于MODE2-检测您需要什么,并有一个将切换回默认模式的令牌