4

次の構文に従って、変数を指定するためにいくつかの XText を定義しようとしています

variables
  MyVar1 : Bool at 0x020 value=true;
  MyVar2, MyVar3 : Int at 0x030 value 200;
end-variables

したがって、各定義は構文的に

VarName ["," VarName]* ":" Type ["at" HEX]? ["value" VALUE]? ";"

すべての変数は参照によってアクセス可能であり、アウトラインの結果は次のようになります。

variables
+-MyVar1 : Bool
+-MyVar2 : Int
+-MyVar3 : Int

編集: ここで要求されたように、私の実際の文法は、上記のいくつかの行の構文定義と同等です。

Variable:
  name=ID
;
Declaration_Var:
  'variables'
  vars+=Declaration_Var_Body+
  'end-variables' ';'
;
Declaration_Var_Body:
  varDecl+=Variable(',' varDecl +=Variable)*
  ':' type=[TR_Any]
  ('at' address=HEX)?
;
TR_Any:
  ...
;
terminal HEX:
  ...
;

これで、次の文字列

variables
  Test1, Test2, Test3 : DWORD at 0x20;
end_var;

アウトラインは次のようになります。

<unnamed>
+-- 0x20
|   +-- Test1
|   +-- Test2
|   +-- Test3

これは私が予想していたものとほぼ反対です。私が期待し、アウトラインで生成したいものは、これに似たものです (データ型とアドレスはそこに表示されてはいけませんが、少なくとも、変数宣言のために生成されたクラスのプロパティとしてアクセスできる必要があります)

Test1
+-- DWORD
+-- 0x20
Test2
+-- DWORD
+-- 0x20
Test3
+-- DWORD
+-- 0x20
4

1 に答える 1

3

ここでケースをカバーするスクリーンキャストを参照してください: http://xtextcasts.org/episodes/18-model-optimization

モデルとメタモデルを変更する必要があります。メタモデルを変更するには、ポストプロセッサを定義する必要があります。次のポストプロセッサは、type属性ディレクトリをVariableクラスに追加します。

詳細については、http: //christiandietrich.wordpress.com/tag/postprocessor/を参照してください。

class MyXtext2EcorePostProcessor implements IXtext2EcorePostProcessor {
  override process(GeneratedMetamodel metamodel) {
    metamodel.EPackage.process
  }

  def process(EPackage p) {
    for (clazz : p.EClassifiers.filter(typeof(EClass))) {
      if (clazz.name == typeof(Variable).simpleName) {
        val typeAttribute = EcoreFactory::eINSTANCE.createEAttribute
        typeAttribute.name = "type"
        typeAttribute.EType = EcorePackage::eINSTANCE.EString
        clazz.EStructuralFeatures += typeAttribute
      }
    }
  }
}

次に、次のように拡張してバインドする必要がありますGenerator

public class ExtendedGenerator extends Generator {
  public ExtendedGenerator() {
    new XtextStandaloneSetup() {
      @Override
      public Injector createInjector() {
        return Guice.createInjector(new XtextRuntimeModule() {
          @Override
          public Class<? extends IXtext2EcorePostProcessor>
                                 bindIXtext2EcorePostProcessor() {
            return MyXtext2EcorePostProcessor.class;
          }
        });
      }
    }.createInjectorAndDoEMFRegistration();
  }
}

最後ExtendedGeneratorに、mwe2-workflow で new を使用します。

... 
Workflow {
  ...
  bean = StandaloneSetup {
    ...
    component = postprocessor.ExtendedGenerator { // Set ExtendedGenerator!
      ...
    }
    ...
  }
  ...
}
...

次に、新しいtype属性にデータを入力する必要があります。インターフェイスを実装して実行できIDerivedStateComputerます。

class MyDerivedStateComputer implements IDerivedStateComputer {

  override discardDerivedState(DerivedStateAwareResource resource) {
    resource.allContents.filter(typeof(VariableDefinition)).forEach [
      type = null
    ]
  }

  override installDerivedState(DerivedStateAwareResource resource,
                               boolean preLinkingPhase) {
    resource.allContents.filter(typeof(VariableDefinition)).forEach [
      type = (eContainer as DefinitionBlock).type
    ]
  }
}

次に、このようにバインドする必要があります (2 番目と 3 番目のバインド方法は、非 Xbase プロジェクトにのみ必要です)。

public class MyDslRuntimeModule extends AbstractMyDslRuntimeModule {
  public Class<? extends IDerivedStateComputer> bindIDerivedStateComputer() {
    return MyDerivedStateComputer.class;
  }

  // Not needed for Xbase-projects
  @Override
  public Class<? extends XtextResource> bindXtextResource() {
    return DerivedStateAwareResource.class;
  }

  // Not needed for Xbase-projects
  public Class<? extends IResourceDescription.Manager>
                         bindIResourceDescriptionManager() {
    return DerivedStateAwareResourceDescriptionManager.class;
  }
}

さらに進んで、ニーズに合わせてその場でモデルを再構築できます。そこまで行った場合に備えて、ソリューションを別の回答としてここに投稿してください。

于 2013-03-15T15:29:27.613 に答える