解析,匹配和关键字

时间:2015-08-14 18:54:43

标签: rascal

我正在使用Java15语法,并且有几个关于Rascal的解析器如何工作以及为什么有些东西不起作用的问题。给出一个具体的语法:

module tests::Concrete

start syntax CompilationUnit =
    compilationUnit: TypeDec* LAYOUTLIST
    ;

syntax TypeDec =
    ClassDec
    ;

syntax ClassDec =
    \class: ClassDecHead ClassBody
    ;

syntax ClassDecHead =
    "class" Id
    ;

syntax ClassBody =
    "{" ClassBodyDec* "}"
    ;

syntax ClassBodyDec =
    ClassMemberDec
    ;

syntax ClassMemberDec =
    MethodDec
    ;

syntax MethodDec =
    \method: MethodDecHead
    ;

syntax MethodDecHead =
    ResultType Id
    ;

syntax ResultType =
    \void: "void"
    ;

syntax Id =
    \id: [A-Z_a-z] !<< ID \ IDKeywords !>> [0-9A-Z_a-z]
    ;

keyword Keyword =
    "void"
    ;

keyword IDKeywords =
    "null"
    | Keyword
    ;

lexical LAYOUT =
    [\t-\n \a0C-\a0D \ ]
    ;

lexical ID =
    [A-Z_a-z] [0-9A-Z_a-z]*
    ;

layout LAYOUTLIST  =
    LAYOUT* !>> [\t-\n \a0C-\a0D \ ] !>> (  [/]  [*]  ) !>> (  [/]  [/]  ) !>> "/*" !>> "//"
    ;

AST定义:

module tests::Abstract

data Declaration =
    \compilationUnit(list[Declaration] body)
   | \package(ID name)
   | \import(ID name)
   | \class(ID name, list[Declaration] body)
   | \method(Type ret, ID name)
             ;

data Type =
    \void()
    ;

data ID =
    \id(str id)
    ;

和加载文件的驱动程序:

module tests::Load

import Prelude;
import tests::Concrete;
import tests::Abstract;

public Declaration load(loc l) = implode(#Declaration, parse(#CompilationUnit, l));

我发现实际工作中有些奇怪,有什么不可以。如果我参加该计划:

class A {

}

按预期解析为compilationUnit([ class(id("A"),[]) ]) 但是,为类内部的方法解析和构造AST节点被证明有点毛茸茸。鉴于该计划:

class A {
    void f
}

这会产生"Cannot find a constructor for Declaration"错误。如果我将语法修改为:

syntax MethodDecHead =
    ResultType
    ;

AST:

| \method(Type ret)

我能够得到我期望的树:compilationUnit([class(id("A"),[method(void())])])

我对这里发生的事情,关键字的处理方式以及造成这种行为的原因感到很困惑。

除此之外如果我不将LAYOUTLIST添加到start syntax作品的末尾,我会在尝试读取文件时随时获得ParseError。< / p>

1 个答案:

答案 0 :(得分:2)

ClassDec的生成规则与AST节点class不兼容。 将其更改为:

syntax ClassDec = \class: "class" Id "{" ClassBodyDec* "}" ; 使用AST节点class(ID name, list[Declaration])

使其更加规则和同构

但是:名称应始终对应,因此我建议在语法中将ID更改为Id。此外,您的AST节点需要Declaration s,但在语法中您有ClassBodyDec s。

implode的一般规则是:

  • 非终端对应于ADT类型
  • 生产标签对应于ADT构造函数
  • 跳过关键字,运算符,布局等。
  • 未标记的词汇制作映射到基元(str,int,real)。
  • 标记的词汇可以根据需要映射到构造函数:lexical Id = id: [a-z]+,可以映射到data Id = id(str x);
  • 如果您没有标记无上下文的作品,implode“查看它们”:如果我有syntax A = B; syntax B = cons: "bla",那么我可以使用ADT:data A = cons()

(这些规则记录在Parsetree.rsc,https://github.com/cwi-swat/rascal/blob/master/src/org/rascalmpl/library/ParseTree.rsc