是否可以设置规则的优先级以避免“最长最早”的匹配模式?

2024-01-02

另一个简单的问题:有没有办法告诉 flex 更喜欢匹配短事物的规则而不是匹配长事物的规则?我找不到任何关于这方面的好的文档。

这就是我需要它的原因:我解析一个伪语言文件,其中包含一些与控制指令相对应的关键字。我希望它们成为绝对优先级,这样它们就不会被解析为表达式的一部分。我实际上需要这个优先事项,因为我不必为我的项目编写完整的语法(在我的情况下这完全是矫枉过正,因为我对解析的程序进行结构分析,我不需要知道细节.. .),所以我无法使用精细的语法调整来确保这些块不会被解析为表达式。

任何帮助将不胜感激。

这是解析文件的示例:

If a > 0 Then read(b); Endif
c := "If I were...";
While d > 5 Do d := d + 1 Endwhile

我只是想收集有关 If、Then、Endif 等的信息...其余的对我来说并不重要。这就是为什么我希望对 If、Then 等相关规则进行优先级排序,而不必编写语法。


来自龙书第二版,第3.5.3节“Lex 中的冲突解决”:

We have alluded to the two rules that Lex uses to decide on the proper lexeme
to select, when several prefixes of the input match one or more patterns:
    1. Always prefer a longer prefix to a shorter prefix.
    2. If the longest possible prefix matches two or more patterns, prefer the
       pattern listed first in the Lex program.

上述规则也适用于 Flex。这是什么Flex手册说(第7章:输入如何匹配。)

When the generated scanner is run, it analyzes its input looking for strings 
which match any of its patterns. If it finds more than one match, it takes the 
one matching the most text (for trailing context rules, this includes the length 
of the trailing part, even though it will then be returned to the input). If it 
finds two or more matches of the same length, the rule listed first in the flex 
input file is chosen.

如果我理解正确的话,你的词法分析器会将关键字视为Endif作为标识符,因此之后它将被视为表达式的一部分。如果这是你的问题,只需将关键字规则放在您的规范之上,比如下面这样:(假设每个大写的单词是一个预定义的枚举,对应一个token)

"If"                      { return IF;         }
"Then"                    { return THEN;       }
"Endif"                   { return ENDIF;      }
"While"                   { return WHILE;      }
"Do"                      { return DO;         }
"EndWhile"                { return ENDWHILE;   }
\"(\\.|[^\\"])*\"         { return STRING;     }
[a-zA-Z_][a-zA-Z0-9_]*    { return IDENTIFIER; }

那么关键字将始终匹配在标识符之前由于规则 2。

EDIT:

谢谢你的评论,kol。我忘记添加字符串规则。但我不认为我的解决方案是错误的。例如,如果一个标识符称为If_this_is_an_identifier, rule 1将应用,因此标识符规则将生效(因为它匹配最长的字符串)。我编写了一个简单的测试用例,发现我的解决方案没有问题。这是我的 lex.l 文件:

%{
  #include <iostream>
  using namespace std;
%}

ID       [a-zA-Z_][a-zA-Z0-9_]*

%option noyywrap
%%

"If"                      { cout << "IF: " << yytext << endl;         }
"Then"                    { cout << "THEN: " << yytext << endl;       }
"Endif"                   { cout << "ENDIF: " << yytext << endl;      }
"While"                   { cout << "WHILE: " << yytext << endl;      }
"Do"                      { cout << "DO: " << yytext << endl;         }
"EndWhile"                { cout << "ENDWHILE: " << yytext << endl;   }
\"(\\.|[^\\"])*\"         { cout << "STRING: " << yytext << endl;     }
{ID}                      { cout << "IDENTIFIER: " << yytext << endl; }
.                         { cout << "Ignore token: " << yytext << endl; }

%%

int main(int argc, char* argv[]) {
  ++argv, --argc;  /* skip over program name */
  if ( argc > 0 )
    yyin = fopen( argv[0], "r" );
  else
    yyin = stdin;

  yylex();
}

我使用以下测试用例测试了我的解决方案:

If If_this_is_an_identifier > 0 Then read(b); Endif
    c := "If I were...";
While While_this_is_also_an_identifier > 5 Do d := d + 1 Endwhile

它给了我以下输出(与您提到的问题无关的其他输出将被忽略。)

IF: If
IDENTIFIER: If_this_is_an_identifier
......
STRING: "If I were..."
......
WHILE: While
IDENTIFIER: While_this_is_also_an_identifier

lex.l 程序是根据示例进行修改的灵活手册 http://westes.github.io/flex/manual/Simple-Examples.html:(使用相同的方法来匹配标识符中的关键字)

还可以看看ANSI C 语法、Lex 规范 http://www.lysator.liu.se/c/ANSI-C-grammar-l.html.

我在我的个人项目中也使用了这种方法,到目前为止我没有发现任何问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以设置规则的优先级以避免“最长最早”的匹配模式? 的相关文章

随机推荐

  • 带过滤器 Android 的自定义列表视图适配器

    请尝试在我的列表视图上实现过滤器 但每当文本发生变化时 列表就会消失 请帮忙 这是我的代码 适配器类 package com talagbe schymn import java util ArrayList import android
  • 从 Oracle 的 RAW(16) 转换为 .NET 的 GUID

    我在手动调试 NET 应用程序时遇到困难 其中 Guid 值与 NET 和 Oracle 不同 Where C reads 17D89D326C2142D69B989F5201288DBF Oracle reads 329DD817216C
  • 将 Windows SID 存储在数据库中以供查找

    我有一个 ASP NET MVC 应用程序 我需要允许客户根据其环境配置 MembershipProviders 但仍然能够将该 MembershipUser 映射到我们数据库中的具体用户模型 Membership GetUser 将使我能
  • 将 Java 套接字配置为在断开连接时快速失败?

    我的服务器上有一个监听端口 我使用 Java 类连接到该端口Socket接口 即 Socket mySocket new Socket host port 然后我抓起一个OutputStream 用一个装饰PrintWriter在自动刷新模
  • 具有滚动背景的 Recyclerview

    我正在尝试创建一个具有滚动背景的 RecyclerView 如下所示 这个想法是 当我向上 向下滚动视图保持器时 背景 浅绿色 图像也应该同步向上 向下移动 关于如何实现这一目标有任何线索吗 这是我的基本 RecyclerView 配置
  • 使用特定 SA 通过 Cloud Build 部署 Dataflow 管道

    我竭尽全力尝试使用特定 SA 而不是默认的 Cloud Build SA 从 Cloud Build 部署数据流管道 但到目前为止尚未成功 我遵循了这个过程 https cloud google com build docs secure
  • 将值从一种方法返回到另一种方法

    Assume as precondition that the list of players is not empty Returns the winning score that is the lowest total score re
  • 将非 ASCII/UTF-8 字符转换为 LaTeX 代码

    我们必须将非 ASCII UTF 8 或命名实体字符转换为 LaTeX 代码 现在我们使用非 ASCII 到 Unicode 然后使用 Perl 脚本将 Unicode 转换为 LaTeX 实体 例如 oacute gt o x000F3
  • python-requests post 带有 unicode 文件名

    我已经在这里阅读了几个相关的问题 但没有找到可行的解决方案 我有一个 Flask 服务器 其中包含以下简化代码 app Flask name api Api app class SendMailAPI Resource def post s
  • 使用 Excel VBA 更改连接字符串时创建的新数据连接

    我有一个工作簿 其中包含由宏更新的数据透视表 不过 在刷新数据之前 连接字符串会发生更改 With ThisWorkbook Connections Data ODBCConnection Connection Redacted Comma
  • 如何通过谷歌表格上的查询比较日期或日期与今天?

    我正在努力将sheet1的副本复制到另一个sheet2 同一文档 上 并且query 工作得很好 直到我想要过滤的列是公式单元格 每个都有查询 匹配等的长单元格 我想要做的是过滤sheet1中的行 其中M列中的事件日期即将到来 有更多过滤条
  • JPA 创建 - Hibernate 未显示在平台中

    我正在尝试创建一个使用 Hibernate 作为持久性提供者的 JPA 项目 但是当我单击平台时 它没有显示 Hibernate 它在平台下拉框中显示 Generic 和 EclipseLink 我应该怎么做才能在下拉框下获得 Hibern
  • Python os.system 命令不起作用?

    早些时候 我曾经很好地使用 python 进行编码 但是在我格式化计算机并重新安装相同的 python 设置之后 我的os system命令停止工作 以及subprocess Popen 看来是路径问题 我重现该 1 错误的唯一方法是将路径
  • 我如何告诉 PyCUDA 使用哪个 GPU?

    我的机器中有两张 NVidia 卡 并且都支持 CUDA 当我运行示例脚本以开始使用此处所示的 PyCUDA 时 http documen tician de pycuda http documen tician de pycuda 我得到
  • 使用 ECS Fargate 执行 Step Function“任务”

    在 Re Invent 2018 中 AWS 似乎推出了与 Step Functions 的新集成 其中包括 ECS Fargate 支持 https docs aws amazon com step functions latest dg
  • c_include_path 与 ld_library_path

    在 Ubunutu 12 04 或 Springdale 6 4 上 使用 gcc 和 g 有什么区别C INCLUDE PATH or CPLUS INCLUDE PATH and LD LIBRARY PATH 是个LD一个仅在运行时使
  • 异常消息是英文的吗?

    我们通过将 Exception Message 写入文件来记录系统中发生的任何异常 然而 它们是根据客户的文化编写的 土耳其的错误对我来说意义不大 那么我们如何才能在不改变用户文化的情况下用英语记录错误消息呢 这个问题可以部分解决 框架异常
  • 什么是接口断言?

    我刚刚遇到了这段代码 type Logger interface Debug msg string keyvals interface error Info msg string keyvals interface error Error
  • Python 使用 tenacity 模块重试

    我很难获得坚韧图书馆 https github com jd tenacity按预期工作 下面测试中的重试根本不会触发 我希望每 5 秒重试一次 并让日志文件反映重试尝试 import paramiko import tenacity fr
  • 是否可以设置规则的优先级以避免“最长最早”的匹配模式?

    另一个简单的问题 有没有办法告诉 flex 更喜欢匹配短事物的规则而不是匹配长事物的规则 我找不到任何关于这方面的好的文档 这就是我需要它的原因 我解析一个伪语言文件 其中包含一些与控制指令相对应的关键字 我希望它们成为绝对优先级 这样它们