当前位置:  开发笔记 > 编程语言 > 正文

Prolog DCG:编写编程语言词法分析器

如何解决《PrologDCG:编写编程语言词法分析器》经验,为你挑选了1个好方法。

我正在尝试将我的词法分析器和解析器分开,基于Prolog和自然语言分析这本书的模糊建议,这本书并没有详细介绍lexing/tokenizing.所以我给它一个镜头,看到几个小问题向我表明我有一些明显的缺失.

我所有的小标记解析器似乎都正常工作; 目前,这是我的代码片段:

:- use_module(library(dcg/basics)).

operator('(')  --> "(".      operator(')')  --> ")".
operator('[')  --> "[".      operator(']')  --> "]".
% ... etc.

keyword(array)    --> "array".
keyword(break)    --> "break".
% ... etc.

它有点重复,但似乎有效.然后我有一些我不太喜欢的东西,欢迎提出建议,但似乎有效:

id(id(Id)) -->
    [C],
    {
        char_type(C, alpha)
    },
    idRest(Rest),
    {
        atom_chars(Id, [C|Rest])
    }.
idRest([C|Rest]) -->
    [C],
    {
        char_type(C, alpha) ; char_type(C, digit) ; C = '_'
    },
    idRest(Rest).
idRest([]) --> [].

int(int(Int)) --> integer(Int).

string(str(String)) -->
    "\"",
    stringContent(Codes),
    "\"",
    {
        string_chars(String, Codes)
    }.
stringContent([C|Chars]) -->
    stringChar(C), stringContent(Chars).
stringContent([]) --> [].

stringChar(0'\n) --> "\\n".
stringChar(0'\t) --> "\\t".
stringChar(0'\") --> "\\\"".
stringChar(0'\") --> "\\\\".
stringChar(C) --> [C].

我的tokenizer的主要规则是:

token(X) --> whites, (keyword(X) ; operator(X) ; id(X) ; int(X) ; string(X)).

它并不完美; 我会看到因为之前的问题而int被解析.所以我猜这是第一个问题.in,id(t)keyword(X)id(X)

我遇到的更大问题是我没有看到如何将评论正确地整合到这种情况中.我尝试过以下方法:

skipAhead --> [].
skipAhead --> (comment ; whites), skipAhead.

comment --> "/*", anything, "*/".
anything --> [].
anything --> [_], anything.

token(X) --> skipAhead, (keyword(X) ; operator(X) ; id(X) ; int(X) ; string(X)).

这似乎不起作用; 返回的解析(我得到许多解析)似乎没有删除注释.我很担心我的评论规则不必要地效率低下,并且可能引起很多不必要的回溯.我也很紧张,whites//0因为dcg/basics是确定性的; 然而,这个方程的一部分似乎有效,它只是将它与评论跳过相结合似乎没有.

作为最后一点,我没有看到如何使用此处的行/列信息将传播解析错误处理回用户.感觉就像我必须跟踪和穿过某种当前的行/列信息并将其写入令牌,然后如果我想做类似于llvm的操作,可能会尝试重建该行.那是公平还是有"推荐做法"?

整个代码可以在这个仓促中找到.



1> mat..:

它目前看起来仍然有点奇怪(unreadableNamesLikeInJavaAnyone?),但它的核心是非常可靠的,所以我只对代码的某些方面和问题有一些评论:

    将lexing与解析分开是完全合理的.它也是一个完全可以接受的解决方案,用于存储行和列信息以及每个令牌,留下表单的令牌(例如)l_c_t(Line,Column,Token)Token-lc(Line,Column)解析器进行处理.

    评论总是令人讨厌,或者我应该说,通常不是很好吗?DCG中有用的模式通常用于最长匹配,在某些情况下您已经使用过,但尚未使用anything//0.因此,重新排序这两条规则可能会帮助您跳过所有要评论的内容.

    关于确定性:可以提交匹配的第一个解析,但只执行一次,并抵制混淆声明性语法的诱惑.

    在DCG中,使用|而不是优雅;.

    tokenize//1?来吧!那只是tokens//1.它在各个方向都有意义.


我从来没有能够就Prolog中的camelcase是否合适做出决定性的决定......如果他们被广泛认为不受欢迎我会回到下划线.我真的很喜欢Token-loc(Line,Col)的想法,除非必要,否则容易被忽略.
`itIsEasyToSeeThatIdentifiersInCamelCaseCannotBeEasilyRead`,而使用`names_with_underscores_are_perfectly_readable_even_for_longer_names`.
我有太多的Java经验同意它"很容易看到".我们每天都使用我们的培训.
`okIfItIsAsNiceToYouAsTheOtherWayGoUseItButTheBuiltInsWillLookOutOfStyleThen`!
推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有