2013-08-20 6 views
1

현재 작은 DSL을 생성하기 위해 Rascal을 사용하고 있습니다. 피코 예제를 수정하려고했지만 현재 막혔습니다. 다음 코드는 a = 3, b = 7 begin declare x : natural, field real @ cells blubb; x := 5.7 end과 같은 예제를 완벽하게 파싱하지만 implode 함수는 "PROGRAM의 생성자를 찾을 수 없습니다"라는 오류 메시지와 함께 실패합니다. 나는 다양한 생성자 선언을 시도했지만 아무도 적합하지 않게 보였다. 예상 생성자가 어떻게 보이는지 볼 수있는 방법이 있습니까?오류 "생성자를 찾을 수 없습니다"

구문 :

module BlaTest::Syntax 

import Prelude; 

lexical Identifier = [a-z][a-z0-9]* !>> [a-z0-9]; 
lexical NaturalConstant = [0-9]+; 
lexical IntegerConstant = [\-+]? NaturalConstant; 
lexical RealConstant = IntegerConstant "." NaturalConstant; 
lexical StringConstant = "\"" ![\"]* "\""; 

layout Layout = WhitespaceAndComment* !>> [\ \t\n\r%]; 

lexical WhitespaceAndComment 
    = [\ \t\n\r] 
    | @category="Comment" "%" ![%]+ "%" 
    | @category="Comment" "%%" ![\n]* $ 
    ; 

start syntax Program 
    = program: {ExaOption ","}* exadomain "begin" Declarations decls {Statement ";"}* body "end" 
    ; 

syntax Domain = "domain" "{" ExaOption ", " exaoptions "}" 
    ; 

syntax ExaOption = Identifier id "=" Expression val 
    ; 

syntax Declarations 
    = "declare" {Declaration ","}* decls ";" ; 

syntax Declaration 
    = variable_declaration: Identifier id ":" Type tp 
    | field_declaration: "field" Type tp "@" FieldLocation fieldLocation Identifier id 
    ; 

syntax FieldLocation 
    = exacell: "cells" 
    | exanode: "nodes" 
    ; 

syntax Type 
    = natural:"natural" 
    | exareal: "real" 
    | string :"string" 
    ; 


syntax Statement 
    = asgStat: Identifier var ":=" Expression val 
    | ifElseStat: "if" Expression cond "then" {Statement ";"}* thenPart "else" {Statement ";"}* elsePart "fi" 
    | whileStat: "while" Expression cond "do" {Statement ";"}* body "od" 
    ; 

syntax Expression 
    = id: Identifier name 
    | stringConstant: StringConstant stringconstant 
    | naturalConstant: NaturalConstant naturalconstant 
    | realConstant: RealConstant realconstant 
    | bracket "(" Expression e ")" 
    > left conc: Expression lhs "||" Expression rhs 
    > left (add: Expression lhs "+" Expression rhs 
      | sub: Expression lhs "-" Expression rhs 
     ) 
    ; 

public start[Program] program(str s) { 
    return parse(#start[Program], s); 
} 

public start[Program] program(str s, loc l) { 
    return parse(#start[Program], s, l); 
} 

추상 :

module BlaTest::Abstract 

public data TYPE = natural() | string() | exareal(); 
public data FIELDLOCATION = exacell() | exanode(); 

public alias ExaIdentifier = str; 

public data PROGRAM = program(list[OPTION] exadomain, list[DECL] decls, list[STATEMENT] stats); 


public data DOMAIN 
    = domain_declaration(list[OPTION] options) 
    ; 


public data OPTION 
    = exaoption(ExaIdentifier name, EXP exp) 
    ; 

public data DECL 
    = variable_declaration(ExaIdentifier name, TYPE tp) 
    | field_declaration(TYPE tp, FIELDLOCATION fieldlocation, ExaIdentifier name) 
    ; 



public data EXP 
    = id(ExaIdentifier name) 
    | naturalConstant(int iVal) 
    | stringConstant(str sVal) 
    | realConstant(real rVal) 
    | add(EXP left, EXP right) 
    | sub(EXP left, EXP right) 
    | conc(EXP left, EXP right) 
    ; 

public data STATEMENT 
    = asgStat(ExaIdentifier name, EXP exp) 
    | ifElseStat(EXP exp, list[STATEMENT] thenpart, list[STATEMENT] elsepart) 
    | whileStat(EXP exp, list[STATEMENT] body) 
    ; 

anno loc [email protected]; 
anno loc [email protected]; 
anno loc [email protected]; 
anno loc [email protected]; 
anno loc [email protected]; 
anno loc [email protected]; 

public alias Occurrence = tuple[loc location, ExaIdentifier name, STATEMENT stat]; 

로드 :

module BlaTest::Load 

import IO; 
import Exception; 
import Prelude; 

import BlaTest::Syntax; 
import BlaTest::Abstract; 

import BlaTest::ControlFlow; 
import BlaTest::Visualize; 

public PROGRAM exaload(str txt) { 
    PROGRAM p; 
    try { 
     p = implode(#PROGRAM, parse(#Program, txt)); 
    } catch ParseError(loc l): { 
     println("Parse error at line <l.begin.line>, column <l.begin.column>"); 
    } 
    return p; // return will fail in case of error 
} 

public Program exaparse(str txt) { 
    Program p; 
    try { 
     p = parse(#Program, txt); 
    } catch ParseError(loc l): { 
     println("Parse error at line <l.begin.line>, column <l.begin.column>"); 
    } 
    return p; // return will fail in case of error 
} 

고마워, 크리스

답변

1

불행하게도 현재의 내파 f를 acility는 숨겨진 의미 론적 가정, 즉 구문 정의의 비 터미널이 데이터 정의의 유형과 동일한 이름을 가짐에 따라 달라집니다. 따라서 비 터미널이 "프로그램"이라면, 데이터 정의에서 "PROGRAM"이라기보다는 "Program"이라고 불러야합니다.

콘크리트와 추상 구문 트리를 통합하는 더 매끄러운 방법을 찾고 있습니다. 그러나 지금은 데이터 이름의 자본을 소중히하십시오.

+0

문제가 여전히 최신 stable (0.7.2.201501130937)에서 발생합니다. 덧붙여 말하자면, 나는 OP와 같은 명명 규칙을 사용하고 _realy_는 동일한 파일에 구문과 AST 정의를 유지하려고합니다 ... –

+0

업데이트 : 실제로 implode는 다르게 명명 된 제작물과 AST를 잘 지원합니다. 그들이 어휘가 아닌 한. Implode는 복잡한 어휘를 정말로 싫어합니다. –

관련 문제