2015-08-14 130 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