如何提高词法分析效率?

2024-03-24

在解析一个 3 GB 的大文件时DCG https://www.metalevel.at/prolog/dcg,效率很重要。

我的词法分析器的当前版本主要使用 or 谓词;/2 http://www.swi-prolog.org/pldoc/doc_for?object=(%3B)/2但我读到索引可以提供帮助。

Indexing http://www.swi-prolog.org/pldoc/man?section=glossary是一种用于快速选择候选子句的技术 特定目标的谓词。在大多数 Prolog 系统中,索引是 (仅)在头部的第一个参数上完成。如果这个论点是 实例化为原子、整数、浮点或带有函子的复合项, 散列用于快速选择第一个参数所在的所有子句 可以与目标的第一个参数相结合。 SWI-Prolog 支持 即时和多参数索引。参见部分2.18 http://www.swi-prolog.org/pldoc/man?section=jitindex.

有人可以举一个使用索引进行词法分析的示例,并可能解释它如何提高效率吗?


Details

注意:在将源代码处理到这个问题之前,我更改了一些名称。如果您发现错误,请随时在此处编辑或给我留言,我很乐意修复它。

目前我的词法分析器/分词器(基于 mzapotoczny/序言解释器 https://github.com/mzapotoczny/prolog-interpreter 解析器.pl https://github.com/mzapotoczny/prolog-interpreter/blob/master/parser.pl) 这是

% N.B.
% Since the lexer uses "" for values, the double_quotes flag has to be set to `chars`.
% If double_quotes flag is set to `code`, the the values with "" will not be matched.

:- use_module(library(pio)). 
:- use_module(library(dcg/basics)).
:- set_prolog_flag(double_quotes,chars).

lexer(Tokens) -->
   white_space,
   (
       (  ":",       !, { Token = tokColon }
      ;  "(",       !, { Token = tokLParen }
      ;  ")",       !, { Token = tokRParen }
      ;  "{",       !, { Token = tokLMusta}
      ;  "}",       !, { Token = tokRMusta}
      ;  "\\",      !, { Token = tokSlash}
      ;  "->",      !, { Token = tokImpl}
      ;  "+",       !, { Token = tokPlus }
      ;  "-",       !, { Token = tokMinus }
      ;  "*",       !, { Token = tokTimes }
      ;  "=",       !, { Token = tokEqual }
      ;  "<",       !, { Token = tokLt }
      ;  ">",       !, { Token = tokGt }
      ;  "_",       !, { Token = tokUnderscore }
      ;  ".",       !, { Token = tokPeriod }
      ;  "/",       !, { Token = tokForwardSlash }
      ;  ",",       !, { Token = tokComma }
      ;  ";",       !, { Token = tokSemicolon }
      ;  digit(D),  !,
            number(D, N),
            { Token = tokNumber(N) }
      ;  letter(L), !, identifier(L, Id),
            {  member((Id, Token), [ (div, tokDiv),
                                     (mod, tokMod),
                                     (where, tokWhere)]),
               !
            ;  Token = tokVar(Id)
            }
      ;  [_],
            { Token = tokUnknown }
      ),
      !,
      { Tokens = [Token | TokList] },
      lexer(TokList)
   ;  [],
         { Tokens = [] }
   ).

white_space -->
   [Char], { code_type(Char, space) }, !, white_space.
white_space -->
    "--", whole_line, !, white_space.
white_space -->
   [].

whole_line --> "\n", !.
whole_line --> [_], whole_line.

digit(D) -->
   [D],
      { code_type(D, digit) }.

digits([D|T]) -->
   digit(D),
   !,
   digits(T).
digits([]) -->
   [].

number(D, N) -->
   digits(Ds),
      { number_chars(N, [D|Ds]) }.

letter(L) -->
   [L], { code_type(L, alpha) }.

alphanum([A|T]) -->
   [A], { code_type(A, alnum) }, !, alphanum(T).
alphanum([]) -->
   [].

alphanum([]).
alphanum([H|T]) :- code_type(H, alpha), alphanum(T).

identifier(L, Id) -->
   alphanum(As),
      { atom_codes(Id, [L|As]) }.

以下是一些用于开发和测试的辅助谓词。

read_file_for_lexing_and_user_review(Path) :-
    open(Path,read,Input),
    read_input_for_user_review(Input), !,
    close(Input).

read_file_for_lexing_and_performance(Path,Limit) :-
    open(Path,read,Input),
    read_input_for_performance(Input,0,Limit), !,
    close(Input).

read_input(Input) :-
    at_end_of_stream(Input).

read_input(Input) :-
    \+ at_end_of_stream(Input),
    read_string(Input, "\n", "\r\t ", _, Line),
    lex_line(Line),
    read_input(Input).

read_input_for_user_review(Input) :-
    at_end_of_stream(Input).

read_input_for_user_review(Input) :-
    \+ at_end_of_stream(Input),
    read_string(Input, "\n", "\r\t ", _, Line),
    lex_line_for_user_review(Line),
    nl,
    print('Press spacebar to continue or any other key to exit: '),
    get_single_char(Key),
    process_user_continue_or_exit_key(Key,Input).

read_input_for_performance(Input,Count,Limit) :-
    Count >= Limit.

read_input_for_performance(Input,_,_) :-
    at_end_of_stream(Input).

read_input_for_performance(Input,Count0,Limit) :-
    % print(Count0),
    \+ at_end_of_stream(Input),
    read_string(Input, "\n", "\r\t ", _, Line),
    lex_line(Line),
    Count is Count0 + 1,
    read_input_for_performance(Input,Count,Limit).

process_user_continue_or_exit_key(32,Input) :-  % space bar
    nl, nl,
    read_input_for_user_review(Input).

process_user_continue_or_exit_key(Key) :-
    Key \= 32.

lex_line_for_user_review(Line) :-
    lex_line(Line,TokList),
    print(Line),
    nl,
    print(TokList),
    nl.

lex_line(Line,TokList) :-
    string_chars(Line,Code_line),
    phrase(lexer(TokList),Code_line).

lex_line(Line) :-
    string_chars(Line,Code_line),
    phrase(lexer(TokList),Code_line).

read_user_input_for_lexing_and_user_review :-
    print('Enter a line to parse or just Enter to exit: '),
    nl,
    read_string(user, "\n", "\r", _, String),
    nl,
    lex_line_for_user_review(String),
    nl,
    continue_user_input_for_lexing_and_user_review(String).

continue_user_input_for_lexing_and_user_review(String) :-
    string_length(String,N),
    N > 0,
    read_user_input_for_lexing_and_user_review.

continue_user_input_for_lexing_and_user_review(String) :-
    string_length(String,0).

read_user_input_for_lexing_and_user_review/0允许用户在终端输入字符串进行词法分析并查看标记。

read_file_for_lexing_and_user_review/1读取文件进行词法分析并一次一行地检查每一行的标记。

read_file_for_lexing_and_performance/2读取文件进行词法分析,并限制词法行数。这用于收集基本性能统计数据以衡量效率。旨在与time/1 http://www.swi-prolog.org/pldoc/man?section=statistics.


它意味着一件事是这是愚蠢的代码:

token(T) -->
    ( "1", !, { T = one }
    ; "2", !, { T = two }
    ; "3", !, { T = three }
    )

这是不太愚蠢的代码:

token(T) --> one_two_three(T).

one_two_three(one) --> "1".
one_two_three(two) --> "2".
one_two_three(three) --> "3".

但还是不太好。可能更好:

token(T) --> [X], { one_two_three(X, T) }.

one_two_three(0'1, one).
one_two_three(0'2, two).
one_two_three(0'3, three).

最后一个示例也开始看起来很愚蠢,但请记住,现在您已经对第一个参数建立了索引。读一遍,没有选择点,没有回头路。

但如果你想真正知道如何高效写作,你需要衡量时间和空间的去向。你测量过吗?

但如果你真的想知道如何解决,你可以阅读“Craft of Prolog”,我不明白这本书的全部内容,但我记得它有很大一部分是关于 DCG 的。

但如果你真的想解析这种格式的大文件,可能会找到其他语言的现有库,它可能比最快的 Prolog 快得多。

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

如何提高词法分析效率? 的相关文章

  • 使用 hisorian.py 时显示“找不到结束时间”

    我正在尝试收集我的应用程序的电池统计信息 运行指定的所有命令后http developer android com tools performance batterystats battery historian index html ht
  • 在Python中计算矩阵乘以其转置(AA^T)的最快方法

    在Python中将矩阵与其转置 AA T 相乘的最快方法是什么 我认为 NumPy SciPy 没有考虑使用例如时涉及的对称性 np dot or np matmul 得到的矩阵总是对称的 所以我可以想象有一个更快的解决方案 None
  • CUDA 矩阵加法时序,按行与按行比较按栏目

    我目前正在学习 CUDA 并正在做一些练习 其中之一是实现以 3 种不同方式添加矩阵的内核 每个元素 1 个线程 每行 1 个线程和每列 1 个线程 矩阵是方阵 并被实现为一维向量 我只需用以下命令对其进行索引 A N row col 直觉
  • 在 Transact SQL 中何时使用 EXCEPT 而不是 NOT EXISTS?

    我最近刚刚通过阅读同事编写的代码了解到 SQL Server 中存在新的 EXCEPT 子句 有点晚了 我知道 真的让我很惊讶 但是我对它的使用有一些疑问 建议什么时候使用它 使用它与使用 AND NOT EXISTS 的相关查询在性能方面
  • 为什么 Dart 中的原生包装函数与非常轻量级的“DEFINE NATIVE ENTRY”函数相比如此重量级?

    我不明白 为什么要这样保证 这是自定义本机函数的包装器dart runtime vm native entry cc 它适用于想要编写的 Dart 程序员native extensions void NativeEntry NativeCa
  • SQL 与 LINQ 性能 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 主键删除需要多长时间?

    画一个简单的表结构 Table1 Table2 ID lt ID Name gt Table1ID Name Table1有几百万行 例如 350 万行 我通过主键发出删除 DELETE FROM Table1 WHERE ID 100 中
  • 使用 html 属性的 DOM 惩罚

    我正在考虑使用 HTML5 数据属性来更轻松地编写我的应用程序的第三方脚本 因此 考虑两种情况 页面上有 10 000 个 HTML 元素 例如 div Sticker div 还有其他 10 000 个 HTML 元素 例如 div St
  • 如何使用 VBA 将符号/图标格式化为单元格而不使用条件格式

    我使用 VBA 代码放置条件格式以覆盖大型表格中的值 每个单元格使用 2 个公式来确定使用 3 个符号中的哪一个 我需要根据列使用不同的单元格检查每个单元格的值 因此据我了解 我必须将条件格式规则单独放置在每个单元格上 以确保每个单元格中的
  • 什么是样板代码、热点代码和热点?

    我知道这些术语是在性能实现 优化的背景下使用的 最近一直在研究这个问题 并尝试过搜索 但没有得到任何例子 清楚地阐述 描述这些概念以及在现实世界开发场景中实现这些问题 概念 有人可以彻底解释这些术语 示例场景以及可能使用这些概念和术语的地方
  • 实现用户定义的算术函数

    如何添加函数 例如汉明权重 并在右侧出现的表达式中使用它是一些 is 2 goal 像 goal expansion 或 term expansion 这样的东西可以帮助这里吗 我承认这不是一个大功能 但它可以提高我的一些 Prolog 程
  • 导入 csv 文件数据以填充 Prolog 知识库

    我有一个 csv 文件example csv其中包含两列 标题为 var1 和 var2 我想填充一个最初为空的 Prolog 知识库文件import pl具有重复的事实 而每一行example csv处理方式相同 fact A1 A2 f
  • 在 R 中替换数据帧中最低列表值的最有效方法

    我有一个数据框 df 其中包含为每个受试者记录的数字列表 向量 用于测试项目的两次重复 subj item rep vec s1 1 1 2 1 4 5 8 4 7 s1 1 2 1 1 3 4 7 5 3 s1 2 1 6 5 4 1 2
  • 我想优化这个短循环

    我想优化这个简单的循环 unsigned int i while j 0 j is an unsigned int with a start value of about N 36 000 000 float sub 0 i 1 unsig
  • 为什么 Chrome 审核建议我最小化 Cookie 大小?

    如何最小化请求的 cookie 大小 Chrome 似乎 警告我 我的 cookie 大小为 41B 这根本不是很多 但是它警告我有什么原因吗 这是一个 PHPSESSID cookie 我真的不知道如何最小化它 有任何想法吗 我的请求响应
  • 如何提高QNX6下Eclipse IDE的性能

    我们在 VMWare 环境中通过 QNX6 运行 Eclipse 速度非常慢 Eclipse 是这样启动的 usr qnx630 host qnx6 x86 usr qde eclipse eclipse data root workspa
  • SWI Prolog 使用的检查优化会发生什么情况?

    去引用SICStus Prolog 手册 https sicstus sics se sicstus docs 3 12 9 html sicstus Occur html 逻辑编程背后的通常数学理论禁止 创建循环项 规定发生检查应该是 每
  • glBlitFramebuffer 渲染缓冲区和渲染全屏纹理哪个更快?

    哪个更快更高效 使用 OpenGL 纹理作为 CUDA 表面并在四边形上渲染 新样式 使用渲染缓冲区作为 CUDA 表面并使用 glBlitFramebuffer 进行渲染 None
  • 实现词法分析器时,DFA 与正则表达式?

    我刚刚学习如何编写编译器 所以如果我有任何错误的说法 请纠正我 当人们可以简单地使用正则表达式时 为什么还要在代码中实现 DFA goto 语句 表驱动实现 据我了解 词法分析器接收一串字符并生成一个标记列表 这些标记在语言的语法定义中是终
  • PrintStream是有缓冲的,但是flush不会降低性能,而BufferedOutputStream会加速性能

    我预计由于 PrintStream 是缓冲的 通过在每次 print 之后添加刷新操作 速度性能应该会显着降低 但事实并非如此 如下面的代码片段所示 此外 将 PrintStream 包裹在 BufferedOutputStream 周围可

随机推荐

  • React-router 4.0.0 的路由器历史记录

    In react router 4 0 0历史提供似乎已经改变 如下index js import React from react import ReactDOM from react dom import Router Route ha
  • Cordova 运行的 Java 版本错误。如何让 Cordova 运行特定的 Java 版本?

    javac warning options source value 1 5 is obsolete and will be removed in a future release and error strings in switch a
  • Ionic“似乎是一种非常古老的项目文件格式 - 请在更新版本的 Xcode 中打开您的项目文件”

    fastlane 完成了与automatic code signing 相关的错误 我不确定这意味着什么以及如何修复它 但这是我以前从未遇到过的错误 我使用的是 Ionic v3 这与 iOS 平台未更新有关 iOS 版本 包括 cordo
  • Gson.toJson 返回 null [ProGuard 问题]

    用户错误报告显示Gson toJson obj 偶尔回来 但对于大多数用户来说它工作正常 我拜访了一位用户 他遇到了该错误并在他的手机上调试了应用程序 我做了Toast显示发送到服务器的内容 我看到 Toast 显示 并且Records a
  • 如何在我的 ubuntu 容器中安装 Docker?

    我在运行的容器内安装了 dockerubuntu 18 04要运行我的nodejs应用程序 我需要在这个容器内安装docker 因为我需要dockerize另一个小应用程序 她是我的 Dockerfile FROM ubuntu 18 04
  • 如何使用 Zend Framework 和 netbeans 编写 JavaScript?

    我正在这样编写 JavaScript function some javascript magic 但问题是它没有突出显示并且没有自动完成功能 我尝试过这样写
  • 从网站获取图像列表并显示它

    我正在创建一个 iOS 应用程序 该应用程序应该获取网站上存在的图像列表并将它们显示为屏幕上的图块 类似于显示照片库中的图像 我可以在 UIImageView 中显示 URL 中的单个图像 但是当涉及到显示网站中的完整图像列表时 我一无所知
  • 在 Java 中嵌入 Gecko/WebKit

    我希望将 Gecko WebKit 或其他 Web 浏览器嵌入到 Java 中作为 Swing AWT 控件 我正在寻找不同于 JRex 或JWebPane 你可以使用浏览器 https www teamdev com jxbrowser
  • 如何使用 emscripten 通过 node.js 进行文件输入?

    我有一个 C 项目 我已使用 emscripten 将其转换为 javascript 我需要帮助通过节点实现文件输入到程序中 据我了解 emscripten 中的默认文件系统使用只能在网页或网络工作人员上完成的预加载数据 我需要我的在命令行
  • 在 C++ 声明中使用 ^ 字符意味着什么? [复制]

    这个问题在这里已经有答案了 可能的重复 C CLI 中插入符号 是什么意思 https stackoverflow com questions 202463 what does the caret mean in c cli 在 C CLR
  • 为什么我会遇到映射异常?

    我正进入 状态 org hibernate MappingException Foreign key FKBB979BF4266AA123 address a id must have same number of columns as t
  • 如何在android中设置定时器

    在 android 中设置计时器以启动任务 我创建的不会更改 UI 的函数 的正确方法是什么 以 Java 方式使用它 http docs oracle com javase 1 5 0 docs api java util Timer h
  • 应用程序无法使用 libcurl C++ Windows 7 VS 2010 启动(0xc0150002)[重复]

    这个问题在这里已经有答案了 可能的重复 应用程序无法正确初始化 0xc0150002 https stackoverflow com questions 3537429 the application failed to initializ
  • 从 NSMenu 打开 NSWindowController

    我在代理应用程序中使用 NSMenu 坞站中没有图标 当点击此菜单中的按钮时 我想显示一个通用的 NSWindowController 我的菜单按钮操作 IBAction menuButtonTapped id sender MyWindo
  • 如何列出GC终结列表中的所有对象?

    我的程序崩溃了 它是VS的可视化工具 所以 调试它非常困难 我尝试过转储并使用WinDbg来研究它 但没有成功 所以 现在我尝试以编程方式把手放在该列表上 但我不知道如何 谢谢 如果您想查看某个对象是否在终结队列或 f reachable
  • 对 Stripe 的 API 请求失败(错误:不是有效的 URL)

    我想在 Node 应用程序中使用 Stripe 预构建结帐页面构建一个简单的结帐页面 我遵循 Stripe 文档中的所有必要步骤 但 API 请求似乎不起作用 服务器 js const express require express con
  • 针对网站特定部分的移动检测

    我是网络开发的初学者 我很难解决这个问题 我拍摄了一段视频并将其编码为 mp4 文件和 ism 文件 我有两个不同的视频标签 一个将播放每个文件 对于我正在开发的网站 如果在移动设备上查看该网站 我希望它使用其中一个视频标签 如果不是 则使
  • 如何检测系统日期回滚?

    如何检测用户何时回滚系统日期 使用情况是为了防止规避许可 程序需要检测在未运行时发生的回滚 好吧 您可以在程序中使用嵌入式数据库 其中每隔一段时间就会插 入一个加密的系统日期 如果您发现 较新 的日期早于之前的某个日期 则可以看出有人更改了
  • 加快 IIS/.NET/LINQ 从网络缓冲区检索数据的速度

    当对我的 Web 服务器和数据库服务器之间的流量进行 TCP 分析时 我发现网络缓冲区 TCP 窗口 经常被填满 然后 Web 服务器向数据库服务器发送 TCP 消息 告知其缓冲区已满 并且在更新之前不要发送更多数据 例如 这是随着时间的推
  • 如何提高词法分析效率?

    在解析一个 3 GB 的大文件时DCG https www metalevel at prolog dcg 效率很重要 我的词法分析器的当前版本主要使用 or 谓词 2 http www swi prolog org pldoc doc f