Bison Flex将在特定规则中永久备份

Bison Flex将在特定规则中永久备份,bison,flex-lexer,Bison,Flex Lexer,我的解析器是针对汇编程序的,这里是和文件以防万一 在本例中,所有操作都像一个符咒: nop nop nop 这里是调试输出 --accepting rule at line 154 ("nop") --accepting rule at line 248 (" ") --accepting rule at line 154 ("nop") --accepting rule at line 248 (" ") --accepting rule at line 154 ("nop") --acce

我的解析器是针对汇编程序的,这里是和文件以防万一

在本例中,所有操作都像一个符咒:

nop
nop
nop
这里是调试输出

--accepting rule at line 154 ("nop")
--accepting rule at line 248 ("
")
--accepting rule at line 154 ("nop")
--accepting rule at line 248 ("
")
--accepting rule at line 154 ("nop")
--accepting rule at line 248 ("
")
--(end of buffer or a NUL)
--accepting rule at line 248 ("
")
--(end of buffer or a NUL)
--EOF (start condition 0)
当我试图解析这段代码时出现了这个问题(规则在lex文件的第255行)

它会永远备份,看起来无法到达newline(我有一个规则)。 我是从flex生成的,但不知道如何使用它来找到根本原因

--accepting rule at line 255 ("DEFB")
--accepting rule at line 280 (" ")
--accepting rule at line 280 (" ")
--accepting rule at line 280 (" ")
--accepting rule at line 280 (" ")
--(end of buffer or a NUL)
--scanner backing up
--accepting rule at line 105 ("'?'")
--accepting rule at line 233 ("+")
--accepting rule at line 56 ("$80")

备份问题在于
char
的模式:

ascii             [\x00-\x7F]+
char              '{ascii}{1}'
ascii
可以是任意数量的“ascii”字符;该集合包括换行符和撇号。由于flex模式总是贪婪的,
char
将从第一个“到最后一个”匹配,因此匹配的令牌将是:

        '?'+$80
DEFM    "RN"
DEFB    'D'
然后它匹配剩余的代币+和$80

这种模式也存在类似的问题

\"{ascii}*\"        { SAVE_CTX; return STRING;}
我想知道您使用
{ascii}{1}
是否是因为您认为
{1}
在扩展
{ascii}
时会以某种方式覆盖
+
。(不会的)否则,我发现在flex模式的不同位置使用冗余的
{1}
操作符是一个谜。对我来说,它们只是视觉上的杂音,这使得理解模式更加困难,因为
{1}
只是一个身份操作符

无论您希望
char
匹配一个或任意数量的“ascii”字符,您都肯定希望它在您点击“a”时停止匹配,对于字符串模式也是如此。您可能还希望能够使用转义序列,特别是(例如)
\''
“两行带引号的字符串”

(另外,是否确实要允许在字符串中包含NUL的任意控制字符?如果是,为什么要任意排除代码值大于127的字符?)

识别所有可能的转义序列是一项工作,我不知道您想要处理哪些序列,但基本上您需要类似以下的模式:

["]([\x00-\x7F]{-}["\\\n]|\\(.|\n))*["]
以及(对你的意图进行大胆猜测):

尽管如我上面所说,我不愿意认可
[\x00-\x7F]
,并且我仅将其用于说明目的,特别是用于说明特定于flex的
{-}
操作符


一些与问题无关的最后注释:

  • 通常最好从源文件中包含最少的可编译摘录。由于SO是一个永久性的问题和答案存储库,可能在未来几年会使其他有类似问题的程序员受益,因此指向可能过期的pastebin资源的链接没有多大帮助

  • 随意使用
    SAVE_CTX
    意味着您将不必要地调用大量字符串(例如操作码),然后需要
    free()
    。我没有查看bison文件,因为它与问题无关,但一般来说,我尽量避免将复制的字符串传递给bison,以获得具有已知(或规范)表示形式的令牌,部分原因是所有字符串副本的开销,部分原因是必须释放所有字符串会给每个bison操作增加不必要的复杂性。YMMV

  • 定义标准标记以外的文件结束标记通常是不必要的,并且可能会导致不明确的错误。通常最好让扫描器实现其默认的
    规则,bison生成的解析器会将其识别为文件结束信号,从而使解析器知道它不应该尝试读取更多的令牌

  • 尽管
    flex
    允许您使用特殊动作标记|将多个模式组合成单个动作,但这些模式保持独立。通常应首选使用正则表达式替换运算符(也写为|),因为它生成具有较小表的扫描程序。因此,不是:

    "xxx"          |
    ".xxx"         { /* some action */ }
    
    你应该更喜欢

    "xxx"|".xxx"   { /* some action */ }
    
    甚至

    [.]?"xxx"      { /* some action */ }
    
    当模式是单个字符且操作是返回字符时,情况尤其如此;我始终建议使用单一默认规则:

    .              { return yytext[0]; }
    
    在语法的末尾。这意味着“无效”字符将作为未知的令牌代码传递给解析器,解析器随后将错误地拒绝该令牌代码;这允许错误处理集中在解析器中,而不是分散在解析器和扫描器之间。它还有一个额外的优点,即在解析器中添加新的操作符时,保持扫描程序和解析器的同步;
    flex
    文件不需要修改


  • 我一句话也说不出你是如何帮助我的!非常感谢你的帮助!EOF规则是由于一些错误而实现的,正如我现在所理解的,这些错误是由错误的ascii解析引起的
    [.]?"xxx"      { /* some action */ }
    
    .              { return yytext[0]; }