表示语法中的语句终止换行符?

2024-02-15

许多编程语言都有以行结束符终止的语句。不过,通常情况下,如果解析器无法理解该行,则在语句中间允许使用行结束符。例如,

a = 3 +
4

...将在 Ruby 和 Python* 中解析为语句a = 3+4, since a = 3+没有任何意义。换句话说,换行符被忽略,因为它会导致解析错误。

我的问题是:如何使用分词器和解析器简单/优雅地完成相同的行为?我使用 Lemon 作为解析器生成器,如果它有什么区别的话(尽管我也将这个问题标记为 yacc 因为我确信该解决方案同样适用于这两个程序)。

我现在是这样做的:在任何不会出现语法歧义的情况下,允许有选择地出现语句终止符。换句话说,就像

expression ::= identifier PLUS identifier statement_terminator.
expression ::= identifier PLUS statement_terminator identifier statement_terminator.

...换句话说,可以在加号后面使用换行符,因为这不会对语法的歧义产生任何影响。我担心这会扩大语法的大小,并且我有很多机会错过案例或在语法中引入微妙的错误。有没有更简单的方法来做到这一点?

编辑*:实际上,该代码示例不适用于 Python。事实上,如果你传入这样的内容,Python 确实会忽略换行符:

print (1, 2,
3)

您可能可以使解析器生成器得到正确的结果,但这可能需要修改解析器生成器的骨架。

我知道三种可行的算法;没有一个是完美的。

  1. 如果出现以下情况,请在行尾插入显式语句终止符:

    A。前一个标记不是语句终止符,并且

    b.可以移动语句终止符。

  2. 在以下情况下,在不可移动标记(Ecmascript 中的“违规标记”)之前插入显式语句终止符:

    A。有问题的标记位于行的开头,或者是}或者是输入结束标记,并且

    b.移动语句终止符不会导致空语句生成量的减少。 [1]

  3. 列出所有代币对的清单。对于每个标记对,确定是否适合用语句终止符替换行结束符。您也许可以使用上述算法之一来计算此表。

算法3是最容易实现的,但也是最难计算的。而且每次修改语法时可能都需要调整表格,这会大大增加修改语法的难度。如果您可以计算标记对表,则词法分析器可以处理插入语句终止符。 (如果您的语法是运算符优先语法,那么您可以在任何没有优先关系的标记之间插入语句终止符。但是,即使这样,您也可能希望针对受限上下文进行一些调整。)

如果您可以在不破坏上下文的情况下向解析器查询标记的可移动性,则可以在解析器中实现算法 1 和 2。最近版本的 bison 允许您指定他们所谓的“LAC”(LookAhead Correction),这涉及到这样做。从概念上讲,解析器堆栈被复制并且解析器尝试处理令牌;如果令牌最终被转移(可能在一定次数的减少之后),而没有触发错误产生,则令牌是有效前瞻的一部分。我还没有查看实现,但很明显实际上没有必要复制堆栈来计算可转移性。无论如何,如果你想使用它,你必须对该设施进行逆向工程到 Lemon 中,这将是一个有趣的练习,可能不会太困难。 (您还需要修改 bison 骨架才能执行此操作,但从 LAC 实现开始可能会更容易。bison 目前仅使用 LAC 来生成更好的错误消息,但它确实涉及测试每个令牌的可转移性。)

在上述所有算法中,需要注意的一件事是可能以括号表达式开头的语句。 Ecmascript 尤其会犯这个错误(恕我直言)。 Ecmascript 示例,直接来自报告:

a = b + c
(d + e).print()

Ecmascript 会将其解析为单个语句,因为c(d + e)是语法上有效的函数调用。最后,(不是一个有问题的令牌,因为它可以被转移。不过,程序员不太可能有意这样做,并且在执行代码(如果执行的话)之前不会产生错误。

请注意,算法 1 会在第一行末尾插入一个语句终止符,但同样不会标记歧义。这更有可能是程序员的意图,但未标记的歧义仍然令人烦恼。

Lua 5.1 会将上面的示例视为错误,因为它不允许在函数对象和(在调用表达式中。然而,Lua 5.2 的行为类似于 Ecmascript。

另一个经典的歧义是return(以及可能的其他陈述)其中有一个optional表达。在 ECMAScript 中,return <expr>属于限制生产;关键字和表达式之间不允许有换行符,因此return在行尾自动插入分号。在 Lua 中,它并不含糊,因为return语句后面不能跟另一个语句。


Notes:

  1. Ecmascript 还要求将语句终止符标记解析为语句终止符,尽管它并没有完全这么说;它不允许在 a 的迭代器子句中使用分号for自动插入语句。其算法还包括在两个上下文中强制插入分号:在return/throw/continue/break出现在行尾和之前的标记++/--出现在行开头的标记。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

表示语法中的语句终止换行符? 的相关文章

  • 解析 XML 标签不匹配时出错

  • 如何将 HTML 表格转换为 csv 格式?

    是否有 HTML 解析器或某些库可以自动将 HTML 表格转换为 CSV 数据行 Here is http www unix com shell programming scripting 45274 html table csv html
  • 有没有好的方法来解析用户代理字符串?

    我有一个Java接收模块User Agent来自最终用户浏览器的字符串的行为需要略有不同 具体取决于浏览器类型 浏览器版本甚至操作系统 例如 FireFox 7 0 Win7 Safari 3 2 iOS9 我明白了User Agent由于
  • JavaScript 中的小数点分隔符是什么?

    当我正在编写一段处理一些浮点值的 JavaScript 代码时 我突然想到了一个想法 JavaScript 中的小数点符号是什么 是不是总是 或者它是特定于文化的 那么呢 toFixed and parseFloat 如果我正在处理用户输入
  • 获取单个方程的脚本

    在文本文件中输入 a 2 8 b 3 9 c 4 8 d 5 9 e a b f c d g 0 6 h 1 7 i e g j f h output i j 期望的输出 输出 2 8 3 9 0 6 4 8 5 9 1 7 如果输入文件名
  • 如何读取本地 JSON 文件进行测试

    我正在尝试编写用于 json 验证的单元测试 因为该应用程序严重依赖于来自 REST API 的 json 我有一个包含简单 json 的本地文件 goodFeaturedJson txt 内容 test TEST 测试用例 void te
  • HTML 解析 - 从 div 内的表格获取数据?

    我对 HTML 解析 抓取的整个想法还比较陌生 我希望我能来这里获得我需要的帮助 基本上我想要做的 我认为 是指定我希望从中获取数据的页面的 url 在这种情况下 http www epgpweb com guild us Caelestr
  • 解析整数集的字符串并列出间隔

    I have 2 5 7 9 12 string 我想从中获取 2 5 7 8 9 12 列表 python中有没有内置的函数 Thanks UPD 我想 直接的答案是No 不管怎样 谢谢你的 片段 使用一个 建议者斯文 马尔纳克 s 2
  • D3 删除千位的逗号分隔符

    我有一个包含 3 列的 json 其中一列是 年份 该列仅包含年份 没有日期 当我在 x 轴上绘制它时 年份会以逗号分隔符表示数千 所以在 json 中 日期的格式是 Year 1990 在 x 轴上 结果是 1 990 我一直在试图弄清楚
  • ANTLR 中的布尔和算术表达式语法

    我正在尝试编写算术和布尔表达式的语法 我不明白我做错了什么 对于我的语法 ANTLR 说 致命 规则logic atom 由于可从 alts 1 2 到达的递归规则调用而具有非 LL 决策 通过左分解或使用语法谓词或使用 backtrack
  • 从 HTML 文件中获取 jpg 图像

    我正在尝试使用 grep 获取 HTML 文件中 jpg 图像的完整 url 地址 一个问题是其中没有很多换行符 所以当我使用 grep 时 它会获取路径 但也会获取很多我不感兴趣的其他内容 我怎样才能获取 jpg 图像的 url 一张单人
  • PHP - 解析具有固定列宽的文本文件

    我是 PHP 和 Laravel 的新手 我需要打开文件并解析内容以将它们传递到数据库 文本文件具有固定的列宽 它没有分隔符或标题 我认为使用子字符串并将每个子字符串分配给变量将是正确的方法 但我仍在学习该语言的过程中 我不知道如何实现这一
  • 解析器解析 SQL 查询并返回 Java 中的列名和相应的表名 [重复]

    这个问题在这里已经有答案了 可能的重复 Java 的 SQL 解析器库 https stackoverflow com questions 660609 sql parser library for java 我需要一个解析器 它应该以以下
  • AWK 中多行的匹配正则表达式。 && 操作员?

    我不确定 运算符在正则表达式中是否有效 我想做的是匹配一行 使其以数字开头并具有字母 a 下一行以数字开头并具有字母 b 并且下一行 字母 c 该 abc 序列将用作开始读取文件的唯一标识符 这就是我在 awk 中想要的东西 0 9 a n
  • 如何在 Java 中解析这样的 URI

    我正在尝试解析以下 URI http translate google com zh CN en 你 http translate google com zh CN 7Cen 7C E4 BD A0 但收到此错误消息 java net UR
  • 寻找引文解析器

    我需要一个解析器来扫描学术文本 提取引文 并将这些引文解析为其组成部分 作者 标题 出版日期等 我尝试过 Paracite 但它速度非常慢 而且不能产生高质量的结果 任何语言都可以 但首选 Java 看一眼ParsCit http aye
  • String.Format 小数,带有千位分隔符和强制小数位

    我想String Format小数 使其同时具有千位分隔符和强制小数位 3 例如 Input 123456 12 78545 8 Output 123 456 120 78 545 800 我努力了 String Format 0 0 0
  • 解析 (yyyy-MM-dd) 格式的字符串日期

    我有一个 2013 09 18 形式的字符串 我想将其转换为 java util Date 我正在做这个 SimpleDateFormat sdf new SimpleDateFormat yyyy MM dd Date converted
  • SimpleDateFormat.parse() 忽略模式中的字符数

    我正在尝试解析一个可以具有不同格式的日期字符串 尽管字符串不应与第二个模式匹配 但它却以某种方式匹配 因此返回错误的日期 这是我的代码 import java text ParseException import java text Sim
  • 在 Delphi 中使用 XML(将特定数据返回到变量)

    过去几天我一直在尝试使用 Delphi 2010 和 MSXML 我是一个极端的新手 需要一点指导 var MemoryStream TMemoryStream XMLPath String sName String XMLDoc vari

随机推荐