2015-08-14 72 views
2

我正在使用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 { 

} 

这解析预期为:​​ 但是解析和构​​建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

+0

还不如贴在这里的整个示例文件。看起来足够小 – jurgenv

回答

2

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

syntax ClassDec = \class: "class" Id "{" ClassBodyDec* "}" ; 使得它更经常和同构与AST节点class(ID name, list[Declaration])

但是:它们的名称应该总是对应的,所以我会建议在语法变化IDId。此外,您的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

+0

完美,谢谢@Tijs。我有一些工作,我认为我现在有工具来推动,并希望找出其他:) – josh

1

我不是implode的专家,所以我现在就离开,但LAYOUTLIST的事情是由于调用parse的方式。

通过start Something =定义的每个start非末端产生两种类型,即: *非终端本身Something和 *包装非末端命名start[Something]

的包装自动/隐含这样定义的:

syntax start[Something] = LAYOUTLIST before Something top LAYOUTLIST after; 

所以,如果你想之前有空格和注释,以及你的程序在调用解析像这样:

parse(#start[Something], yourLocation) 

而且如果您对以后的评论或空白不感兴趣,那么您可以像这样投影顶部树:

Something mySomething = parse(#start[Something], myLocation).top; 
+0

太好了,谢谢!我在哪里可以看到/我应该联系谁以获取更多关于'implode'的信息。我怀疑这是由布局,ID和关键字如何与语法交互引起的。 – josh