我正在使用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>
答案 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
的一般规则是:
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)
中