내가 당신을 위해 무엇을 요구 정말 모르겠어요. 그것에 대해 생각한 후에 나는 가능한 질문을 다음과 같이 유도합니다.
1.) 스크립트를 두 개의 파일로 분할하려고합니다. 파일 a에는 선언 만 포함되고 파일 b에는 명령문 만 포함됩니다. 그러나 어떤 'what'속성은 File의 선언에 대한 참조를 보유합니다.
문법과 함께 사용하면 즉시 사용할 수 있습니다.
2.) 예를 들어 '선언 인터페이스'를 정의하는 클래스를 제공하는 자바 소스 코드가 있으며 'what'속성이이 인터페이스 또는이 인터페이스를 구현하는 클래스를 참조하도록합니다.
// Grammar now inherits from the Xbase grammar
// instead of the common terminals grammar
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.xbase.Xbase
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
declarator=Declarator?
statements+=Statement*;
Declarator:
'Declare' name=ID;
Statement:
'Execute' what=JvmTypeReference;
제 1, 당신은 모든 Java 유형 (자바 API, 링크 된 API, 사용자 정의 유형)로 참조 할 수 있습니다 : 당신이 당신의 문법 내에서해야하는 수정은 내가이 보일 수 있다고 생각, 어려운되지 않습니다 그들의 자격있는 이름으로 그들을 격려. Referring to JVM types look like this in an Xtext language. (Screenshot)
참조 된 JVM 유형이 유효한지 여부도 유효성을 검사 할 수 있습니다. 모델에서 단 하나의 선택적 선언 자로 정의 할 인터페이스를 구현합니다. Referenced JVM type is checked whether it is a valid type. (Screenshot)
Xbase를 사용하면이 모델 요소에 대한 Java 인터페이스를 쉽게 추론 할 수 있습니다. 생성 그루터기 mydsl.MyDslJvmModelInferrer ... '를 사용
class MyDslJvmModelInferrer extends AbstractModelInferrer {
@Inject extension JvmTypesBuilder
@Inject extension TypeReferences
def dispatch void infer(Model element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
acceptor.accept(
element.declaration.toInterface('declarator.' + element.declaration.name) [
members += it.toMethod("execute", TypesFactory.eINSTANCE.createJvmVoid.createTypeRef)[]
])
}
}
그것은 오직 하나의 방법으로 각각 명명 된 하나의 인터페이스를 유도한다 "실행().
그런 다음,이 같은 정적 검사를 구현, 당신은 생성 된 스텁 '... mydsl를 사용해야합니다.validation.MyDslValidator은 '내 예에서 매우 신속하고 더러운,하지만 당신은 그것의 아이디어를 얻을해야합니다 class MyDslValidator extends AbstractMyDslValidator {
@Check
def checkReferredType(Statement s) {
val declarator = (s.eContainer as Model).declaration.name
for (st : (s.what.type as JvmDeclaredType).superTypes) {
if (st.qualifiedName.equals('declarator.' + declarator)) {
return
}
}
(s.what.simpleName + " doesn't implement the declarator interface " + declarator).
warning(MyDslPackage.eINSTANCE.statement_What)
}
}
(I 정적 검사를 구현하기 위해 선호 Xtend 프로그래밍 언어를 사용!) 정적 검사 여부를 결정한다 지정된 JvmTypeReference (프로젝트의 Java 클래스)는 선언 된 인터페이스를 구현합니다. 그렇지 않으면 dsl 문서에 경고가 표시됩니다.
잘하면이 질문에 대한 답변을드립니다.
다음 업데이트 : 아이디어가 잘 작동하지 않습니다! Xbase를 사용하지 않고 Xtend를 사용하여 템플릿을 작성할 수는 있지만 좋은 방법으로 사용하는 방법을 상상할 수는 없습니다. 문제는 구멍 클래스 '이동'과 구멍 실행 프로세스를 생성하지 않는다고 가정하는 것입니다. 내가 쓸모있는 코드를 생성하려고 조금 놀았하고 해킹 것으로 보인다! Neverthess, 내 해결책은 다음과 같습니다.
Xtext는 'void doGenerate'메서드를 사용하여 스텁 '... mydsl.generator.MyDslGenerator'를 생성했습니다. 이 방법을 채워야합니다. 내 생각은 다음과 같습니다. 첫째, 두 개의 일반 매개 변수 T와 U로 추상 및 일반 Executor 클래스를 생성합니다. 내 executor 클래스는 반환 값 T를 사용하여 추상 메서드 'executeMoves()'를 사용합니다. 비 프리미티브 'Void'클래스. 이 클래스는 List를 보유하지만 Move 클래스의 하위 클래스로 정의 된 일반 유형 u를 보유합니다.
Move 클래스도 생성되지만 String을 저장할 필드 만 포함됩니다. 그런 다음 파생되어야합니다. 내 'MyDslGenerator은'그 다음과 같습니다
class MyDslGenerator implements IGenerator {
static var cnt = 0
override void doGenerate(Resource resource, IFileSystemAccess fsa) {
cnt = 0
resource.allContents.filter(typeof(Model)).forEach [ m |
fsa.generateFile('mydsl/execution/Move.java', generateMove)
fsa.generateFile('mydsl/execution/Executor' + cnt++ + '.java', m.generateExecutor)
]
}
def generateMove() '''
package mydsl.execution;
public class Move {
protected String s;
public Move(String s) {
this.s = s;
}
}
'''
def generateExecutor(Model m) '''
package mydsl.execution;
import java.util.List;
import java.util.Arrays;
/**
* The class Executor is abstract because the execution has to implemented somewhere else.
* The class Executor is generic because one does not know if the execution has a return
* value. If it has no return value, use the not primitive type 'Void':
* public class MyExecutor extends Executor_i<Void> {...}
*/
public abstract class Executor«cnt - 1»<T, U extends Move> {
@SuppressWarnings("unchecked")
private List<U> declarations = Arrays.<U>asList(
«FOR Statement s : m.statements»
(U) new Move("«s.what.name»")«IF !m.statements.get(m.statements.size - 1).equals(s)»,«ENDIF»
«ENDFOR»
);
/**
* This method return list of moves.
*/
public List<U> getMoves() {
return declarations;
}
/**
* The executor class has to be extended and the extending class has to implement this
* method.
*/
public abstract T executeMoves();
}'''
}
주셔서 감사합니다 상세한 답변을 많은; 그러나 당신이 언급했듯이, 제 질문은 불분명했습니다. 방금 질문을 업데이트했습니다. 내 언어는 Java/JVM과 아무 관계가 없습니다. 그럼 Xbase를 사용하는 것이 합리적입니까? –
실행 문에서 간단한 목록 만 생성하려면 Xbase가 필요하지 않습니다. Xbase는 일반적으로 JVMTypes를 참조하거나 사용자의 언어로 표현식이 필요한 경우에 사용됩니다. 원하는대로 Java 코드를 작성하는 방법에 대한 대답을 살펴보고이를 업데이트했습니다. – Joko