1

我目前正在尝试 Rascal 创建一个小型 DSL。我试图修改 Pico 示例,但是我目前被卡住了。以下代码像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 TYPE@location;
anno loc PROGRAM@location;
anno loc DECL@location;
anno loc EXP@location;
anno loc STATEMENT@location;
anno loc OPTION@location;

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
}

非常感谢,克里斯

4

1 回答 1

1

不幸的是,当前的内爆工具依赖于一个隐藏的语义假设,即语法定义中的非终结符与数据定义中的类型具有相同的名称。所以如果非终端叫“Program”,在数据定义中不应该叫“PROGRAM”,而应该叫“Program”。

我们正在寻找一种更流畅的方式来集成具体和抽象的语法树,但现在请不要大写您的数据名称。

于 2013-08-20T12:25:33.947 回答