我是Rascal的新手,嘗試其轉換/術語重寫功能。使用RASCAL分割聲明和初始化
我想寫一個分裂的聲明類似的腳本:
INT X = 5;
進入聲明/初始化如:
int x; x = 5;
我該怎麼辦?假設我正在嘗試轉換的語言是Java。
感謝您的任何幫助。
我是Rascal的新手,嘗試其轉換/術語重寫功能。使用RASCAL分割聲明和初始化
我想寫一個分裂的聲明類似的腳本:
INT X = 5;
進入聲明/初始化如:
int x; x = 5;
我該怎麼辦?假設我正在嘗試轉換的語言是Java。
感謝您的任何幫助。
好問題。有幾種方法可以做到這一點,我將展示最簡單的方法。請注意,您的示例不是最簡單的示例,因爲它需要從單個語句轉換爲語句列表(即,它不是類型保留)。
這裏沒有進一步的完整例子,下面的解釋如下。
module Decl
import IO;
import ParseTree;
// Decl, a trivial language, to demo simple program trafo
lexical Id = [a-z][a-z0-9]* !>> [a-z0-9] \ Reserved;
lexical Natural = [0-9]+ ;
lexical String = "\"" ![\"]* "\"";
layout Layout = WhitespaceAndComment* !>> [\ \t\n];
lexical WhitespaceAndComment
= [\ \t\n\r]
;
keyword Reserved = "int" | "str" | "if" | "then" | "else" | "fi" | "while" | "do" | "od";
start syntax Program
= {Statement ";"}* body
;
syntax Type
= "int"
| "str"
;
syntax Statement
= Type tp Id var
| Type tp Id var ":=" Expression exp
| Id var ":=" Expression val
| "if" Expression cond "then" {Statement ";"}* thenPart "else" {Statement ";"}* elsePart "fi"
| "while" Expression cond "do" {Statement ";"}* body "od"
;
syntax Expression
= Id name
| String string
| Natural natcon
| bracket "(" Expression e ")"
> left (Expression lhs "+" Expression rhs
| Expression lhs "-" Expression rhs
)
;
str trafo1() {
p = parse(#start[Program], "int x := 1").top;
newBody = "";
for(stat <- p.body){
if((Statement) `<Type tp> <Id var> := <Expression exp>` := stat){
newBody += "<tp> <var>; <var> := <exp>";
} else {
newBody += "<stat>";
}
}
return newBody;
}
主要部分是一個簡單語言的完整語法。實際轉換由trafo1
完成:
newBody
(用於構建結果)。該解決方案的大號樣式取決於你的目標。這裏我們只是建立一個字符串。如果需要,您可以返回解析的字符串作爲結果。
替代方案:
希望這可以幫助你開始。
我這裏有一些更多的代碼示例使用了具體語法匹配和替換,以你想要的東西到達:
module JavaMatch
import lang::java::\syntax::Java15;
// this just replaces exactly these specific kinds of declarations, as the only statement in a block:
CompilationUnit splitInitializersSimple(CompilationUnit u) = visit(u) {
case (Block) `{ int i = 0; }` => (Block) `{int i; i = 0;}`
};
// the next generalizes over any type, variable name or expression, but still one statement in a block:
CompilationUnit splitInitializersSingle(CompilationUnit u) = visit(u) {
case (Block) `{ <Type t> <Id i> = <Expr e>; }`
=> (Block) `{<Type t> <Id i>; <Id i> = <Expr e>;}`
};
// Now we allow more statements around the declaration, and we simply leave them where they are
CompilationUnit splitInitializersInContext(CompilationUnit u) = visit(u) {
case (Block) `{ <BlockStm* pre>
' <Type t> <Id i> = <Expr e>;
' <BlockStm* post>
'}`
=> (Block) `{ <BlockStm* pre>
' <Type t> <Id i>;
' <Id i> = <Expr e>;
' <BlockStm* post>
'}`
};
// But there could be more initializers in the same decl as well, as in int i, j = 0, k; :
CompilationUnit splitInitializersInContext2(CompilationUnit u) = visit(u) {
case (Block) `{ <BlockStm* pre>
' <Type t> <{VarDec ","}+ a>, <Id i>= <Expr e>, <{VarDec ","}+ b>;
' <BlockStm* post>
'}`
=> (Block) `{ <BlockStm* pre>
' <Type t> <{VarDec ","}+ a>, <Id i>, <{VarDec ","}+ b>;
' <Id i> = <Expr e>;
' <BlockStm* post>
'}`
};
// and now we add `innermost` such that not only the first but all occurrences are replaced:
CompilationUnit splitInitializersInContext2(CompilationUnit u) = innermost visit(u) {
case (Block) `{ <BlockStm* pre>
' <Type t> <{VarDec ","}+ a>, <Id i>= <Expr e>, <{VarDec ","}+ b>;
' <BlockStm* post>
'}`
=> (Block) `{ <BlockStm* pre>
' <Type t> <{VarDec ","}+ a>, <Id i>, <{VarDec ","}+ b>;
' <Id i> = <Expr e>;
' <BlockStm* post>
'}`
};
void doIt(loc file) {
start[CompilationUnit] unit = parse(#start[CompilationUnit], file);
unit.top = splitInitializersInContext(unit.top);
writeFile(file, "<unit>");
}
結束語,因爲這仍然不是完全通用:
再次感謝,這正是我一直在尋找的。我想我需要更多的代表來表決,但這是值得的。第一個版本中有 –