解析 Prolog 中的表达式并返回抽象语法

2023-12-09

我必须编写 parse(Tkns, T) ,它接受标记列表形式的数学表达式并找到 T,并返回表示抽象语法的语句,尊重操作顺序和关联性。

例如,

?- parse( [ num(3), plus, num(2), star, num(1) ], T ).

T = add(integer(3), multiply(integer(2), integer(1))) ;
No

我尝试按如下方式实现 + 和 *

parse([num(X)], integer(X)).
parse(Tkns, T) :-
  (  append(E1, [plus|E2], Tkns),
     parse(E1, T1),
     parse(E2, T2),
     T = add(T1,T2)
  ;  append(E1, [star|E2], Tkns),
     parse(E1, T1),
     parse(E2, T2),
     T = multiply(T1,T2)
  ).

它找到了正确的答案,但也返回不遵循关联性或运算顺序的答案。

ex)

parse( [ num(3), plus, num(2), star, num(1) ], T ). 

也返回

mult(add(integer(3), integer(2)), integer(1))

and

parse([num(1), plus, num(2), plus, num(3)], T)

返回 1+2+3 和 1+(2+3) 的等价物,而它应该只返回前者。

有什么方法可以让它发挥作用吗?

编辑:更多信息:我只需要实现 +、-、*、/、否定(-1、-2 等),并且所有数字都是整数。给出了一个提示,代码的结构将类似于语法

<expression> ::= <expression> + <term>
              |  <expression> - <term>
              |  <term>

      <term> ::= <term> * <factor>
              |  <term> / <factor>
              |  <factor>

    <factor> ::= num
              |  ( <expression> )

仅也实施了否定。

Edit2:我发现了一个用 Prolog 编写的语法解析器(http://www.cs.sunysb.edu/~warren/xsbbook/node10.html)。有没有一种方法可以修改它以打印语法的左手推导(“打印”是指 Prolog 解释器将输出“T=[正确答案]”)


去除左递归将推动您走向基于 DCG 的语法。

但有一个有趣的替代方法:实施自下而上解析。

这在 Prolog 中有多难?好吧,正如佩雷拉和希伯在他们精彩的书中所展示的那样 “Prolog 和自然语言分析”非常简单:来自第 6.5 章

Prolog 默认提供自上而下、从左到右、回溯解析算法 DCG。

众所周知,这种自上而下的解析算法会循环往复 左递归规则(参见程序2.3的例子)。

尽管技术是可用的 能够从上下文无关语法中删除左递归,这些技术不是 很容易推广到 DCG,此外,它们还可以通过以下方式增加语法大小: 大因素。

作为替代方案,我们可以考虑实现自下而上的解析方法 直接在 Prolog 中。在各种可能性中,我们将在这里考虑左角 方法是其对 DCG 的一种修改。

为了编程方便,左角 DCG 解释器的输入语法以 DCG 符号的细微变化表示。的右侧 规则以列表的形式给出,而不是文字的连词。因此规则是单元子句 的形式,例如

s ---> [np, vp].

or

optrel ---> [].

终结符由 word(w,PT) 形式的字典单元子句引入。

考虑在继续之前完成讲座(按标题查找免费书籍条目)信息页).

现在让我们尝试编写一个自下而上的处理器:

:- op(150, xfx, ---> ).

parse(Phrase) -->
    leaf(SubPhrase),
    lc(SubPhrase, Phrase).

leaf(Cat) --> [Word], {word(Word,Cat)}.
leaf(Phrase) --> {Phrase ---> []}.

lc(Phrase, Phrase) --> [].

lc(SubPhrase, SuperPhrase) -->
    {Phrase ---> [SubPhrase|Rest]},
    parse_rest(Rest),
    lc(Phrase, SuperPhrase).

parse_rest([]) --> [].
parse_rest([Phrase|Phrases]) -->
    parse(Phrase),
    parse_rest(Phrases).

% that's all! fairly easy, isn't it ?

% here start the grammar: replace with your one, don't worry about Left Recursion
e(sum(L,R)) ---> [e(L),sum,e(R)].
e(num(N)) ---> [num(N)].

word(N, num(N)) :- integer(N).
word(+, sum).

例如,产生

phrase(parse(P), [1,+,3,+,1]).
P = e(sum(sum(num(1), num(3)), num(1))) 

注意使用的左递归语法是e ::= e + e | num

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

解析 Prolog 中的表达式并返回抽象语法 的相关文章

  • 如何使用 SimpleDateFormat 解析多种格式的日期

    我正在尝试解析文档中的一些日期 用户似乎以类似但不完全相同的格式输入了这些日期 以下是格式 9 09 9 2009 09 2009 9 1 2009 9 1 2009 尝试解析所有这些内容的最佳方法是什么 这些似乎是最常见的 但我想让我困扰
  • 用 C/C++ 编写的通用代码补全框架

    有没有用 C C C 11 编写的框架用于编写代码补全工具 或者也许有一些库允许 Java 或 C 的代码完成 也是用 C 编写的 我正在用 C 编写我的自定义 IDE 用于 Java 而不仅仅是 Java 开发 我想以最好的方式为其添加代
  • 使用 isdigit 表示浮点数?

    a raw input How much is 1 share in that company while not a isdigit print You need to write a number n a raw input How m
  • Prolog中如何选择bagof、setof和findall

    如何在 bagof setof 和 findall 之间做出选择 有什么重要的区别吗 哪个最常用 哪个最安全 感谢您的评论 回答 我检查了SWI Prolog 手册页findall 3 http www swi prolog org pld
  • 从终端查询不会打印任何内容

    当在命令行中运行时 这 swipl g write 42 t halt 打印 42 到STDOUT正如预期的那样 然而 这 swipl g X 42 t halt 不打印任何内容 它只是返回 我如何让它打印在 REPL 中打印的内容 即X
  • 查找相邻成员

    我必须找出列表中的两个成员是否相邻 限制是使用append 3谓词 到目前为止 我已经完成了下面的操作 如果它是真的 它就有效 否则我得不到答案 就像它永远运行一样 adjacent X Y L append L1 X Y T1 appen
  • 将字符串解析为结构变量

    我试图将字符串解析为其中包含不同变量的结构向量 这是我到目前为止所拥有的 但似乎不起作用 struct client string PhoneNumber string FirstName string LastName string Ag
  • Python将文本文件解析为嵌套字典

    考虑以下数据结构 HEADER1 key value key value HEADER2 key value key value HEADER3 key value HEADER4 key value key value 原始数据中没有缩进
  • 使用 prolog 添加另外两次出现

    我有一个清单 a b a a a c c 我需要为每个元素添加两次以上的出现 最终结果应该是这样的 a a a b b b a a a a a c c c c 如果列表中有一个与下一个项目相同的项目 那么它会继续下去 直到出现一个新项目 当
  • 如何从 JavaScript 中的 URL 中提取主机?

    捕获域直到结束字符 我需要一个捕获的正则表达式example com在所有这些中 example com 3000 example com pass gas example com example com 如果您确实有有效的 URL 那么这
  • 使用 XSLT 转换 XML 并保留 CDATA(在 Ruby 中)

    我正在尝试将包含如下内容的文档转换为另一个文档 使 CDATA 与第一个文档中的完全相同 但我还没有弄清楚如何使用 XSLT 保留 CDATA 初始 XML
  • 如何从 Perl 中的文本文件中提取/解析表格数据?

    我正在寻找类似的东西HTML 表格提取 http search cpan org dist HTML TableExtract 只是不适用于 HTML 输入 而是适用于包含采用缩进和间距格式化的 表格 的纯文本输入 数据可能如下所示 Her
  • 是否有任何库可以解析Java中的“数字表达式”,例如1,2-9,33-

    我不认为这很难 只是写起来很乏味 一些小的免费 如啤酒 库 我可以在其中放入像 1 2 9 33 这样的字符串 它可以告诉我给定的数字是否与该数字匹配表达 就像大多数程序的打印范围对话框一样 仅匹配奇数或偶数 或匹配每个 2 mod 5 或
  • 解析未完全加载 VBA 的网站

    尝试进行简单的网络解析 我的问题是页面在向下滚动之前无法完全加载 谷歌搜索已经提出可能使用硒 但由于我不知道如何使用它 我想我会在这里问 我使用的代码 Sub gfquote Dim oHttp As MSXML2 XMLHTTP Dim
  • Prolog中计算数字是否为素数

    我正在尝试计算输入是否是素数 但出了问题 这是我的代码 primeNumber X prime prime A 1 prime prime A B R is A mod B R 1 R A prime prime X B B lt A Ne
  • 使用 JSONKit 解析 JSON 文件

    我正在构建一个音叉应用程序 货叉应允许最多 12 个预设节距 此外 我希望允许用户选择一个主题 每个主题都会加载一组预设 不必使用所有预设 我的配置文件看起来像这样 theme A3 comment An octave below conc
  • javax.xml.transform.TransformerException: java.io.FileNotFoundException: (访问被拒绝)

    我在最后一行代码中遇到异常 Transformer transformer TransformerFactory newInstance newTransformer DOMSource xmlSource new DOMSource do
  • Python itertools groupby 中令人不安的奇怪行为/错误?

    我在用itertools groupby解析一个短的制表符分隔的文本文件 文本文件有几列 我想做的就是对具有特定值的所有条目进行分组x在特定的列中 下面的代码对名为的列执行此操作name2 寻找变量中的值x 我尝试使用以下方法来做到这一点c
  • 无法使用 NSDateFormatter 解析日期

    我正在获取 RSS 其中我收到以下日期戳 2010 05 10T06 11 14 000Z 现在我正在使用 NSDateFormatter 来解析这个日期时间戳 parseFormatter setDateFormat yyyy MM dT
  • 如何使用 string#split 用分隔符 + - * / ( ) 和空格分割字符串并将它们保留为额外标记?

    我需要拆分包含基本数学表达式的字符串 例如 a b c or a c d 分隔符是 和空格 我需要它们作为独立的标记 基本上结果应该是这样的 a b c 对于第二个例子 a 我读了很多关于具有不太复杂的分隔符的类似问题的问题 常见的答案是使

随机推荐

  • 获取导致 SQLiteConstraintException 的约束名称

    如何获取导致 SQLiteConstraintException 的约束的名称 在异常上调用 toString 只会给我 错误代码 19 约束失败 并且异常中没有方法可以获取原因 这使得调试我的sql变得相当困难 从版本开始3 7 17 S
  • 使用 Vega Lite 显示已经聚合的数据

    我正在尝试显示随时间变化的总和的堆积条形图 数据看起来像这样 date 12345 sumA 100 sumB 150 我将 x 轴编码为 日期 字段 我需要将日期 12345 的条形图堆叠起来 其中一部分高 100 另一部分高 以另一种颜
  • 在 C# 中从 DataGridView 更新 SQL 数据库

    有一些关于此的教程 但我假设我一定实现了错误 因为我从组合教程中遵循的代码无法正常工作 这些是教程 https youtu be i4mYXSaD4w https youtu be sB0A6FIhUM 我正在尝试创建一个显示一些基本数据的
  • 在Prolog中逐行读取文件

    我想读取一个纯文本文件并对每一行应用一个谓词 谓词包含write其输出 我该怎么做呢 您可以使用read读取流 记得调用at end of stream以确保没有语法错误 例子 读文件 pl main open myFile txt rea
  • NSAutoresizingMaskLayoutConstraint 的 UITableViewCell 舍入错误,但在 Storyboard 和 heightForRowAtIndexPath 中正确设置大小:

    我正在尝试使用 AutoLayout 在表视图单元格中配置子视图 在理想情况下 希望表视图单元格的高度足以包含所有子视图 然而 这似乎不可能 因为单元的高度是在实际创建单元之前确定的 因此 现在 我只是查看了设置的约束并计算了包含所有内容所
  • 每个项目的 Terraform 都有不同的后端

    我是 Terraform 的新手 仍在研究文档 尚未找到一种方法来适应我需要实现的特定解决方案的设置 并希望某种灵魂能够能够推动我朝正确的方向前进 我正在尝试管理一组参数化模板 这些模板部署支持我们在 GCP 中开发的新应用程序所需的一切
  • Neo4j 中带空格的全文搜索

    当 neo4j lucene 自动索引处于精确模式 默认 时 查询类型为 start n node node auto index name asfd a return n 正常工作 假设您有一个名为asdf adsf例如 但是 当将索引切
  • 使用 Docker Swarm 和覆盖网络进行组播

    我正在测试使用多播进行发现的应用程序 我创建了一个 Swarm 集群和一个network create d overlay swarm net因此容器在多个 Swarm 代理主机之间共享相同的 LAN 发现好像不行 所以我安装了tshark
  • 新版本应用部署后需要重启apache + APC吗?

    当我们部署应用程序时 我们只需创建一个新文件夹并指向它的符号链接 这样 apache 就会始终找到最新版本 然而 当我们部署并继续测试而不首先重新启动 apache 服务器时 我们会遇到奇怪的错误 我们还运行了 APC 感觉缓存与此有关 当
  • 将数据从设备复制到主机时出现无效参数错误

    我在将数据从设备复制回主机时遇到问题 我的数据排列在一个结构中 typedef struct Array2D double arr int rows int cols Array2D arr是一个 平面 数组 rows and cols描述
  • 如何将 CORS 与 grails Rest API 一起使用?

    我正在使用 grails 开发 Rest Api 它正在 localhost 8080 上运行 当我与 POSTMAN 通话时 它以 json 响应 我想使用这些数据 并在其他域上运行的网页上执行 CRUD 操作 当我尝试调用用 grail
  • 解密使用 AES-128 加密的 M3U8 播放列表,无需 IV

    我目前正在构建一个用于下载 M3U8 播放列表的应用程序 但我遇到了一个问题 如果播放列表使用 AES 128 加密 例如有这样一行 EXT X KEY METHOD AES 128 URI https website com link k
  • R-标签中的剪切函数,无需科学记数法,可在 ggplot2 中使用

    我使用 cut 和 classIntervals 对 R 中的数据进行分组 然后使用 ggplot2 进行绘制 因此 按 n 3 的分位数进行切割的基本操作如下所示 library classInt a lt c 1 10 100 1000
  • Lua关闭/程序执行结束回调

    我正在为 Lua 编写一个模块 关闭 lua 解释器时 即使用户忘记隐式调用关闭例程 它也必须运行清理例程 该模块主要是用 C 编写的 我应该使用 Lua C Api 中的哪个回调来检测程序执行结束 我唯一的想法是在代表我的模块的表上使用
  • Angular 7 滤波器阵列

    我有以下角度组件 private json JsonResponseDTO constructor private dtoService PoolDTOServiceService ngOnInit this dtoService setJ
  • 如何使用 apt 安装指定版本的 Ruby

    我尝试安装指定版本 2 5 1 的 Ruby 该版本只是示例 并尝试执行以下脚本 但出现如下错误 是否可以使用 apt 安装来安装 Ruby 版本 以便我可以处理 Ruby 版本依赖性问题 sudo apt update sudo apt
  • rxjava:我可以使用 retry() 但有延迟吗?

    我在 Android 应用程序中使用 rxjava 来异步处理网络请求 现在我想仅在经过一定时间后重试失败的网络请求 有没有办法在 Observable 上使用 retry 但仅在一定延迟后重试 有没有办法让 Observable 知道当前
  • 为什么我收到“没有为复数定义排序关系”错误?

    See 这个问题一些背景 我在该问题上的主要问题已解决 建议我向另一个问题询问我遇到的第二个问题 print cubic 1 2 3 4 Correct solution about 1 65 if x gt 0 TypeError no
  • 如何在 django 模板中迭代查询集列表

    有没有办法在模板中迭代这个查询集列表
  • 解析 Prolog 中的表达式并返回抽象语法

    我必须编写 parse Tkns T 它接受标记列表形式的数学表达式并找到 T 并返回表示抽象语法的语句 尊重操作顺序和关联性 例如 parse num 3 plus num 2 star num 1 T T add integer 3 m