flex / bison:如何在同一输入文件上切换两个词法分析器

2023-12-01

我如何移交打开的文件,例如由另一个扫描仪读取到下一个扫描仪 - 并将其交给解析器?


Flex 缓冲区无法轻松地从一台扫描仪传输到另一台扫描仪。许多细节对于扫描仪来说是私有的,需要进行逆向工程,从而导致可维护性的丧失。

然而,只要语义类型兼容,将两个(或多个)扫描器定义组合成单个扫描器并不困难。只需给它们不同的启动条件即可。由于甚至可以在扫描仪操作之外设置启动条件,因此从一个扫描仪定义切换到另一种扫描仪定义很简单。

由于 Flex 扫描仪是基于桌面的,因此将两台扫描仪结合起来并不存在真正的低效率;事实上,不重复代码可能有一定的价值。组合表可能比各个表的总和稍大,因为可能有更多的字符等价类,但另一方面,较大的表可能允许更好的表压缩。这些影响可能都不明显。


这是一个简单但可能有用的示例。该解析器读取文件并替换${arithmetic expressions}与评估的表达式。 (由于它只是一个示例,因此只允许非常基本的表达式,但它应该很容易扩展。)

由于词法扫描器需要在启动条件下启动SC_ECHO,需要初始化。就我个人而言,我更愿意从INITIAL为了避免在这个简单的情况下进行初始化,但有时扫描仪需要能够处理各种启动条件,所以我保留了代码。错误处理可以改进,但它是功能性的。

解析器使用一个非常简单的error重新同步并跟踪替换错误的规则。非终结符的语义值subst, file and start是文件的错误计数;的语义值expr是表达式的值。在这个简单的例子中,它们都是整数,所以默认类型yylval works.

未终止的替换处理不优雅;特别是,如果在词法扫描期间读取 EOF 进行替换,则不会将任何指示插入到输出中。我把解决这个问题作为练习。 :)

这是词法分析器:

%{
#include "xsub.tab.h"
%}
%option noinput nounput noyywrap nodefault
%option yylineno
%x SC_ECHO
%%
   /* In a reentrant lexer, this would go into the state object */
   static int braces;

   /* This start condition just echos until it finds ${... */
<SC_ECHO>{
  "${"        braces = 0; BEGIN(INITIAL);
  [^$\n]+     ECHO;
  "$"         ECHO;
  \n          ECHO;
}
 /* We need to figure out where the substitution ends, which is why we can't
  * just use a standard calculator. Here we deal with terminations.
  */
"{"           ++braces; return '{';
"}"           { if (braces) { --braces; return '}'; }
                else        { BEGIN(SC_ECHO); return FIN; }
              }

 /* The rest is just a normal calculator */
[0-9]+        yylval = strtol(yytext, NULL, 10); return NUMBER;
[[:blank:]]+  /* Ignore white space */
\n            /* Ignore newlines, too (but could also be an error) */
.             return yytext[0];

%%
void initialize_scanner(void) {
  BEGIN(SC_ECHO);
}

解析器导出一个接口:

int parseFile(FILE *in, *out);

如果一切顺利,则返回 0,否则返回错误替换的数量(以上述未终止替换的问题为模)。这是文件:

%{
#include <stdio.h>
int yylex(void);
void yyerror(const char* msg);
void initialize_scanner(void);

extern int yylineno;
extern FILE *yyin, *yyout;
%}
%token NUMBER FIN UNOP
%left '+' '-'
%left '*' '/' '%'
%nonassoc UNOP

%define parse.lac full
%define parse.error verbose
%%
start: file          { if ($1) YYABORT; else YYACCEPT; }
file :               { $$ = 0; }
     | file subst    { $$ = $1 + $2; }
subst: expr FIN      { fprintf(yyout, "%d", $1); $$ = 0; }
     | error FIN     { fputs("${ BAD SUBSTITUTION }", yyout); $$ = 1; }
expr : NUMBER
     | '-' expr %prec UNOP { $$ = -$2; }
     | '(' expr ')'  { $$ = $2; }
     | expr '+' expr { $$ = $1 + $3; }
     | expr '-' expr { $$ = $1 - $3; }
     | expr '*' expr { $$ = $1 * $3; }
     | expr '/' expr { $$ = $1 / $3; }
     | expr '%' expr { $$ = $1 % $3; }
%%
void yyerror(const char* msg) {
  fprintf(stderr, "%d: %s\n", yylineno, msg);
}

int parseFile(FILE* in, FILE* out) {
  initialize_scanner();
  yyin = in;
  yyout = out;
  return yyparse();
}

还有一个简单的驱动程序:

#include <stdio.h>
int parseFile(FILE* in, FILE* out);
int main() {
  return parseFile(stdin, stdout);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

flex / bison:如何在同一输入文件上切换两个词法分析器 的相关文章

  • Python 中的词法分析、标记化和解析资源

    人们可以向我指出有关使用 Python 进行词法分析 解析和标记化的资源吗 我正在对一个开源项目进行一些黑客攻击 hotwire http www hotwire shell org 并想对代码进行一些更改lexes http code g
  • 具有启动条件的 Flex 可重入

    我正在尝试制作一个依赖于启动条件的可重入扫描仪 我正在遵循与这个人的问题类似的问题 使用 Flex 编写可重入词法分析器 https stackoverflow com questions 2634998 writing re entran
  • 野牛规格和优先顺序

    给定 Bison 规范 right TOK ADD TOK MUL 我想知道 TOK ADD 和 TOK MUL 的优先顺序是什么 另外如果我有野牛规格 left TOKMUL TOKADD left TOKDIV left TOKSUB
  • GNU Flex 库 libfl 提供什么?

    我可以从 flex 和 bison 生成的文件编译一个程序 cc lex yy c program tab c o output 也由 cc lex yy c program tab c lfl o output 它们都运行顺利 没有任何问
  • 使用 Flex 生成的文件时出现问题

    我正在尝试设置一个使用 flex 的项目 fast lex 而不是 adobe 我在 Ubuntu 上运行 并通过 apt get 方法安装了 flex 我用谷歌搜索了编译错误 我要么找到了围绕它创建自己的补丁的人 要么找到了很多论坛 人们
  • yylineno 在 yacc 文件中始终具有相同的值[重复]

    这个问题在这里已经有答案了 对于编译器中的一个项目 我在语法分析器中遇到一个问题 当我在符号表中添加符号时 我在 yylineno 中始终采用相同的值 我一开始就是这样做的 int yylex void int yyerror char y
  • Flex/Bison IDE? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个良好的开发环境 可以在 Flex 或 Bison 或两者上工作 是否有任何 IDE 具有
  • 对 yyparse 的未定义引用(flex 和 bison)

    我正在尝试学习一些 Flex Bison 并且正在阅读 John Levine O Reilly 的 Flex Bison 有一个我需要运行的示例 但是我无法运行它 因为出现以下错误 tmp ccKZcRYB o In function y
  • 如何将 lex 文件中的 yytext 传递给 yacc?

    请我面临一个简单的问题 这就是问题 在我的 lex 文件中 我有类似的内容 char ptr String name BEGIN sName
  • 用于多行注释的 Unix Flex 正则表达式

    我正在 Unix 上使用 Flex 制作词法分析器 如果您之前使用过它 您就会知道您主要只是为您为其编写词法分析器的任何语言的标记定义正则表达式 我被困在最后一部分 我需要正确的正则表达式来进行多行注释 以允许类似的事情 This is a
  • flex 中 yywrap() 的含义

    该指令在 flex lex 中意味着什么 define yywrap 1 和这个 t 我在下面的代码中找到它 t putchar t 输入 你好世界 输出 你好世界 根据Lex 和 Yacc 页面 http dinosaur compile
  • 为什么 yacc 无法解析语法规则的第二行,即使它正确解析了第一行?

    我想将行解析为 20191201 170003296 1 102290 1 102470 0 为此 我编写了以下基本 yacc lex 语法 词法分析器 语法上 include
  • lex :如何覆盖 YY_BUF_SIZE

    根据manual http westes github io flex manual The Default Memory Management html YY BUF SIZE is 16K我们需要重写它 但是 手册没有指定如何覆盖它 我
  • 解析器 - 调用 yytext 时出现分段错误

    我的解析器正在识别语法并使用 yylineno 指示正确的错误行 我想打印导致错误的符号 int yyerror string s extern int yylineno defined and maintained in lex yy c
  • 如何使 YY_INPUT 指向字符串而不是 Lex & Yacc (Solaris) 中的标准输入

    我想要我的yylex 解析字符串而不是文件或标准输入 如何使用 Solaris 提供的 Lex 和 Yacc 来做到这一点 重新定义YY INPUT 这是一个工作示例 使用命令编译并运行 yacc d parser y lex lexer
  • Flex,连续扫描流(来自套接字)。我是否错过了使用 yywrap() 的某些内容?

    使用 Flex 进行模式识别 在基于套接字的扫描仪 连续流 上工作 Flex 找不到与 数组边界 重叠的匹配项 所以我实现了 yywrap 来设置新的数组内容 一旦 yylex 检测到 它将调用 yywrap 到目前为止还没有成功 基本上
  • 无法弄清楚为什么 Bison 抛出“由于冲突,规则在解析器中无用”

    我正在为一种非常简单的编程语言编写 BNF 语法 并使用 Flex 和 Bison 进行编译 我只有 3 种变量和常量类型 实数 整数 字符串 我的 l 文件具有 ID 的标记定义 如下所示 DIGIT 0 9 LETTER a zA Z
  • 野牛语义类型检查分析

    我一直试图到处寻找例子 但徒劳无功 我正在尝试编写一个基本的 Ruby 解释器 为此 我编写了一个 Flex 词汇文件 其中包含标记识别句子和一个语法文件 我希望我的语法包含语义类型检查 我的语法文件包含 例如 arg arg arg 这应
  • Bison:奇怪的转变-减少冲突

    我尝试在自定义语法中实现函数调用 加上类似的数组访问运算符 expression OTHER EXPRESSION RULES expression PARENTHESIS OPEN expressions PARENTHESIS CLOS
  • Bison/Flex 中哪里可以释放内存?

    我使用 Bison 和 Flex 的时间或多或少有 1 个月 所以如果我没有看到明显的东西 但我不认为是 我很抱歉 我在使用 Flex Bison 释放内存时遇到问题 我的代码如下所示 parser l DATE yylval str st

随机推荐

  • 为什么多个 on_message 事件不起作用?

    为什么我不能有多个on message events import discord client discord Client client event async def on ready print in on ready client
  • Power BI 上个月 DAX 滚动总计

    我正在 POWER BI 中工作 并尝试计算上个月滚动总计的 DAX 表达式 我有一个过滤器 我选择某个月份 我想计算上个月的滚动总数 下面的计算非常适合计算所选日期范围的滚动总计 如何计算前几个月的滚动总额 Rolling Total C
  • 在 Android 中使用 Html.fromHtml() 突出显示文本颜色?

    我正在开发一个应用程序 其中会有一个搜索屏幕 用户可以在其中搜索特定关键字 并且该关键字应该是 突出显示 我找到了 Html fromHtml 方法 但我想知道这是否是正确的做法或 不是 请让我知道您对此的看法 或者比处理简单得多Spann
  • 仅从特定文件夹进行 Git 合并

    我已经为客户 X 创建了一个 Rails 网站 我现在有一个客户 Y 他想要一个与客户 X 执行完全相同的操作但具有不同外观的网站 我从 clientXcode 创建了一个 git 分支 并将其命名为 clientYcode 然后我对视图进
  • 有没有办法根据 R 中另一个数据框中的共享值构建成对数据框?

    例如 DF1 是 Id1 Id2 1 10 2 10 3 7 4 7 5 10 并想要 DF2 Id1 Id2 1 2 1 5 2 5 3 4 数据框 DF2 是 DF1 中 Id1 列中的一组值 它们共享 DF1 中 Id2 中的公共值
  • 将多维数组元素转换为不同类型

    假设我有这个多维数组 float vertices new float 0f 1 28f 1 28f 2 56f 3 84f 2 56f 5 12f 1 28f 3 84f 0f 1 28f 0f 0f 1 28f new float 0f
  • 使用数组方法的素数列表

    我有一个获取素数列表的代码 def primes numbers num primes 2 3 step Math sqrt num 1 2 do i is prime true primes each do p here if p gt
  • 单元测试 ASP.Net MVC 授权属性以验证重定向到登录页面

    这可能只是需要另一双眼睛的情况 我一定错过了一些东西 但我不明白为什么这种东西不能被测试 我基本上试图通过使用 Authorize 属性标记控制器来确保未经身份验证的用户无法访问视图 并且我尝试使用以下代码对此进行测试 Fact publi
  • 重新打开窗口抛出 Gtk-CRITICAL **:gtk_widget_get_window:断言“GTK_IS_WIDGET(小部件)”失败

    我有简单的 python3 gtk3 代码 它连接到 dbus 并监听所有事件 当用户单击托盘中的图标时 他必须看到包含所有显示的早期事件的窗口 代码 我不知道问题出在哪里并且代码大小 gt 100行 https github com ra
  • string.h 中的 strupr() 和 strlwr() 是 ANSI 标准的一部分吗?

    我在互联网上寻找这个 并且在每个具有 string h 功能的地方都没有提到这两个 是因为什么 它们并不存在于每个编译器中 它们是来自 Microsoft C 库的非标准函数 此后 MS 已弃用它们 转而采用重命名的函数 strlwr an
  • C++ 中的 OpenID 库?

    我需要在 C 网站中使用 openid 但找不到可以使用的工作库 我正在尝试使用这个 http kin klever net libopkele requirements 但它会停止配置并显示以下消息 检查 OPENSSL 配置 错误 未找
  • Django 在调试模式下损坏管道

    我在 Nginx 后面的远程服务器上有 django 1 3 如果我使用 apache mod wsgi 运行 django 我可以查看 apache 日志文件中的错误 没关系 但我想在控制台中使用 如果我运行 django 自己的开发服务
  • TFS 构建代理用户功能的值可以在构建步骤中获得吗?

    我正在尝试在 TFS 中编写一个构建步骤 该步骤依赖于了解构建代理存储 nuget exe 的位置 标准 nuget install 步骤以破坏构建执行的方式破坏了参数的顺序 所以我想使用batch shell ps 步骤之一自己运行exe
  • 检查连续元素之间的差异是否相同

    我是在 Prolog 中使用算术的新手 我做过一些小程序 但主要涉及逻辑 我正在尝试实现一个将返回的函数true or false每个连续元素对之间的差异是否相同 我的输入如下所示 sameSeqDiffs 3 5 7 9 2 我觉得我需要
  • Gradle 替代 mvn install

    我在 mvn 上构建了 2 个不同的项目 我正在尝试更换为 Gradle 项目 1 是一个 SDK 项目 2 使用该 sdk 示例 在 maven 的时候 它使用 mvn install 创建工件 将整个项目添加到本地存储库中 我喜欢这样在
  • 如何将 linq 结果转换为 HashSet 或 HashedSet

    我有一个 ISet 类的属性 我正在尝试将 linq 查询的结果获取到该属性中 但不知道如何执行此操作 基本上 寻找最后一部分 ISet
  • 执行程序时,代码块打开 2 个控制台窗口

    我最近安装了 Code Blocks 并使用它进行 C 编程 我编写了一个基本的 Hello World 程序 当我运行该程序时 会打开 2 个控制台窗口而不是 1 个 如果只有输出 则第一个控制台在显示输出后关闭 然后第二个窗口保持打开状
  • 如果数据库发生变化,自动刷新内容

    当 mysql 数据库表更改时 如何自动将数据库行 PHP 的值添加到页面 而不刷新页面本身 所以 它有点像这样 自动刷新浏览器以响应文件系统更改 but当数据库发生变化时 不要刷新浏览器来更改文件系统 而是更新内容 而不刷新任何内容 谢谢
  • 使用Session存储Datatable

    目前 我们使用会话在页面中存储数据表 这样我们就不必一次又一次地访问数据库来获取相同的数据表 但我担心它会占用服务器内存 如果有一天大量用户登录 服务器的响应会变慢 我们的应用程序也可能崩溃 请告诉我将数据表存储到会话中是个好主意还是我们应
  • flex / bison:如何在同一输入文件上切换两个词法分析器

    我如何移交打开的文件 例如由另一个扫描仪读取到下一个扫描仪 并将其交给解析器 Flex 缓冲区无法轻松地从一台扫描仪传输到另一台扫描仪 许多细节对于扫描仪来说是私有的 需要进行逆向工程 从而导致可维护性的丧失 然而 只要语义类型兼容 将两个