如何消除带括号的表达式中的子选择的歧义?

2023-12-02

我有以下表达式符号:

expr
    : OpenParen expr (Comma expr)* Comma? CloseParen           # parenExpr
    | OpenParen simpleSelect CloseParen                        # subSelectExpr

不幸的是,一个simpleSelect也可以有括号,因此以下语句变得不明确:

 select ((select 1))

这是我当前的语法,简化为仅显示问题:

grammar Subselect;
options { caseInsensitive=true; }
statement: query_statement EOF;

query_statement
   : query_expr # simple
   | query_statement set_op query_statement # set
   ;

query_expr
    : with_clause?
    ( select | '(' query_statement ')' )
      limit_clause?
    ;

select
    : select_clause
     (from_clause
      where_clause?)?
    ;

with_clause: 'WITH' expr 'AS (' select ')';
select_clause: 'SELECT' expr (',' expr)*;
from_clause: 'FROM' expr;
where_clause: 'WHERE' expr;
limit_clause: 'LIMIT' expr;
set_op: 'UNION'|'INTERSECT'|'EXCEPT';

expr
    : '(' expr ')'                      # parenExpr
    | '(' query_expr ')'                # subSelect
    | Atom                              # identifier
    ;

Atom: [a-z_0-9]+;
WHITESPACE: [ \t\r\n] -> skip;

并在解析上select ((select 1)),这是输出:

enter image description here

有什么可能的方法来消除这种歧义?


我想主要的事情就在这里:

'(' query_statement ')'

由于它递归地调用自身 - 有没有办法进行间接或其他操作,例如query_statement从括号内调用本身永远不能有括号?


另外,也许这是一个普遍现象?在官方 MySQL 语法上运行时,我得到同样不明确的输出here:

enter image description here

我很好奇是否有任何语法可以解决这里的问题:https://github.com/antlr/grammars-v4/tree/master/sql。也许最好的方法是在解析文本之前删除重复的括号? (如果是这样,是否有好的工具可以做到这一点,或者我是否需要编写一个额外的 antlr 解析器来做到这一点?)


您的输入生成此解析树:

enter image description here

这是对您的输入的合理解释,并且它被识别为subSelect expr。它是subSelect嵌套在一个parenExpr(两者都是exprs).

如果我稍微改变一下你的规则:

expr: '(' query_expr ')' # subSelect
    | '(' expr ')'       # parenExpr
    | Atom               # identifier
    ;

现在它是一个subSelect解释嵌套的(select 1)作为查询表达式。

enter image description here

它是不明确的,因为外面的括号表达式could匹配前两个选项中的任何一个都会导致不同的解析树。

在 ANTLR 中,替代方案中的歧义通过“使用”第一个匹配的替代方案来解决。通过这种方式,ANTLR 具有确定性行为,您可以控制使用哪种解释(使用替代顺序)。 ANTLR 语法出现这样的歧义并不罕见。

恕我直言,IntelliJ 插件让很多人绊倒了这个,因为这表明语法有“错误”。在这种情况下 ANTLR 本身不报告错误是有原因的。它具有定义的、确定性的行为。

就“解决”这种歧义而言:语法使用括号来指示两个不同的“事物”这一简单事实表明它本质上是歧义的,所以我不相信您可以在不修改语法的情况下“修复”语法歧义。 (我对此可能是错的,如果有人提供能够消除歧义的重构,我会发现很有趣。)

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

如何消除带括号的表达式中的子选择的歧义? 的相关文章

  • 使用 python 将 bibtex 文件转换为 html (也许是 pybtex?)

    您好 我想解析 bibtex 出版物文件并对特定字段 例如年份 进行排序并过滤某些内容 然后将其放在网站上 我遇到了 pybtex 它可以读取和解析 bibtex 文件 但它基本上没有记录 我不知道如何对条目进行排序 pybtex 是可行的
  • 单个查询删除并显示重复记录

    采访中提出的问题之一是 一张表有100条记录 其中 50 个 是重复的 是否可以用单个 查询删除重复记录 从表中以及选择和 显示剩余 50 条记录 这可以在单个 SQL 查询中实现吗 Thanks SNA 对于 SQL Server 你会使
  • pyspark.sql.functions.window 函数的“startTime”参数和 window.start 有何作用?

    示例如下 df spark createDataFrame 1 2017 05 15 23 12 26 2 5 1 2017 05 09 15 26 58 3 5 1 2017 05 18 15 26 58 3 6 2 2017 05 15
  • 使用显式创建表语句与 select into 创建表

    使用显式创建表语句和加载数据与选择数据之间是否存在性能差异 此示例仅显示 2 列 但问题是针对使用非常大的表 下面的示例也使用临时表 尽管我也想知道使用常规表的效果 我认为无论表格类型如何 它们都是相同的 临时表场景 Explicitly
  • 使用 FileTable 通过 SQL INSERT 创建子目录

    之前 我请求如何在一个目录中创建一个目录FileTable不使用文件 I O API https stackoverflow com q 10483906 175679 我现在想为刚刚创建的父目录创建一个子目录 在插入期间如何分配我的父母
  • 火鸟删除速度很慢

    我正在做这个简单的交易 DELETE FROM ominve01 WHERE CVE OBS IN SELECT CVE OBS FROM minve01 M WHERE M FECHA DOCU lt 31 12 2010 OR FECH
  • 迁移问题:MS SQL > MySQL:插入缓冲区内存

    我在使用 MySQL Workbench 上的内置迁移工具时遇到问题 我正在将一个非常大的数据库从 MS SQL 2014 迁移到 MySQL MS SQL 服务器本地部署在我的 Windows 8 1 桌面上 MySQL 服务器在我的网络
  • SQL Server - SQL 替换整个数据库中所有表中的所有列

    这是一个很遥远的事情 我猜这个问题没有简单的答案 但是 我继承了一个数据库 其中填充了一些可怕的数据 许多包含描述的行都有回车符 这意味着当我们 BCP 输出数据时 它会带有回车符 我的问题 有没有办法在 MS SQL Server 中对整
  • 我们可以使用sql列出MS Access数据库中的所有表吗?

    我们可以使用 sql 找到 ms access 中的所有表吗 就像我们在 sql server 中所做的那样 select from sys tables 在sqlite中 SELECT FROM sqlite master where t
  • SQLite 使用循环重新编号 ID

    您好 我有一个包含许多插入行的表 我需要按 id 对所有行重新编号并排序 我找到了这段代码 但它对我不起作用 SET i 100 UPDATE main Categories SET ID i i 1 WHERE Name White AL
  • 从一张表更新并插入另一张表

    我有两张桌子 table1 ID 代码 姓名 table2 ID 代码 姓名 具有相同的列 我想将数据从 table1 插入到 table2 或更新列 如果 table2 中存在 table1 ID table2 ID 执行此操作的简单方法
  • LEFT JOIN 比 INNER JOIN 快得多

    我有一张桌子 MainTable 有超过 600 000 条记录 它通过第二个表连接到自身 JoinTable 在父 子类型关系中 SELECT Child ID Parent ID FROM MainTable AS Child JOIN
  • 获取 SQL 表上的某些百分位值

    假设我有一个表 其中存储用户 他们拥有的红球数量 球总数 蓝色 黄色 其他颜色等 以及红球与球总数的比率 架构如下所示 user id ratio red balls total balls 1 2 2 10 2 3 6 20 我想根据排序
  • 是否存在用于解析 ASN.1 或基于它生成 PHP 代码的 PHP 库?

    我已经审视过自己了 但今天我的 Google fu 似乎并不强 我正在努力开发一种标准化协议 用于通过 TCP IP 连接在 Apache PHP 服务器和微控制器上的嵌入式 C 代码之间交换数据结构 我们使用 ASN 1 表示法 我真正想
  • 停止在 Visual Studio 2010 中显示 SQL 错误

    如何阻止 VS2010 在附加到项目的 sql 文件中显示错误 我根本不想检查它们 只想检查 C 代码 这些文件用作资源 构建操作 设置为 内容 我想保留 sql 扩展名以用于语法着色目的 Regards 看起来你的问题在这里得到了回答 h
  • Postgres LEFT JOIN 与 WHERE 条件

    我需要使用 where 条件左连接两个表 Table time table id rid start date end date 1 2 2017 07 01 00 00 00 2018 11 01 00 00 00 2 5 2017 01
  • 查询以查找平均加权价格

    我在 Oracle 中有一个表 每个给定部分包含多行 每行都有一个与其关联的数量和价格 还有一个给定零件的行集相加的总数量 以下是数据示例 我需要的是获得该零件的平均加权价格 例如 如果数量为 100 的零件的价格为 1 数量为 50 的零
  • 在sql server中生成下一个序列号

    我需要生成一个序列号用作主键 在遗留系统中 我想知道以下解决方案在竞争条件下是否会遇到并发问题 CREATE TABLE SequenceGenerator Sequence INT INSERT INTO SequenceGenerato
  • SQLAlchemy:检查给定值是否在列表中

    问题 在 PostgreSQL 中 检查某个字段是否在给定列表中是使用IN操作员 SELECT FROM stars WHERE star type IN Nova Planet SQLAlchemy 的等价物是什么INSQL查询 我尝试过
  • 用户表到用户和用户首选项。这是正常化了吗?

    我有一张桌子叫Users其偏好列表不断增加 这些首选项可以包括 ReligionId 它将连接到另一个包含宗教列表的表 偏好列表正在不断增加 我想把它分开Users表分成2个表 我认为行之有效的策略是制作一个单独的表 名为UserPrefe

随机推荐