当前位置:   article > 正文

ANTLR和Jetbrains MPS:解析文件并以树符号显示AST

如何使用 mps写antlr

Itemis再次这样做:他们刚刚为Jetbrains MPS发布了一个非常酷的新插件。 这允许定义新的树编辑器。

他们看起来像这样:

AST

在这篇文章中,我们将看到:

  • 如何在MPS中使用ANTLR解析器
  • 如何使用树符号表示已解析的AST

特别是,我们将使用解析ANTLR语法的ANTLR语法。 那是元吗? 当然,每个ANTLR语法都可以使用相同的方法。

GitHub上始终提供代码

依存关系

首先,您需要安装Jetbrains MPS。 在这里获取免费副本。

要使用树符号,您应该安装mbeddr平台。 只需转到此处 ,下载zip并将其解压缩到MPS安装的插件中​​即可。

全部设置好了,该做些编程了。

包装ANTLR以在MPS内部使用

在上一篇文章中,我们讨论了如何使用Gradle在Java项目中使用现有的ANTLR语法。 我们还将在此处应用该技术。

我们首先从此处下载语法: https : //github.com/antlr/grammars-v4/tree/master/antlr4

通过将LexBasic直接包含到ANTLRv4Lexer中,我们进行了一些小的更改。 注意,我们还需要LexerAdaptor

为了简化用法,我们创建了一个Facade:

  1. package me.tomasetti.mpsantlr.parser;
  2. import me.tomassetti.antlr4.parser.ANTLRv4Lexer;
  3. import me.tomassetti.antlr4.parser.ANTLRv4Parser;
  4. import org.antlr.v4.runtime.CommonTokenStream;
  5. import org.antlr.v4.runtime.TokenStream;
  6. import java.io.*;
  7. import java.nio.charset.StandardCharsets;
  8. public class Antlr4ParserFacade {
  9. public ANTLRv4Parser.GrammarSpecContext parseString(String code) {
  10. InputStream inputStream = new ByteArrayInputStream(code.getBytes(StandardCharsets.UTF_8));
  11. return parseStream(inputStream);
  12. }
  13. public ANTLRv4Parser.GrammarSpecContext parseFile(File file) throws FileNotFoundException {
  14. return parseStream(new FileInputStream(file));
  15. }
  16. public ANTLRv4Parser.GrammarSpecContext parseStream(InputStream inputStream) {
  17. try {
  18. ANTLRv4Lexer lexer = new ANTLRv4Lexer(new org.antlr.v4.runtime.ANTLRInputStream(inputStream));
  19. TokenStream tokens = new CommonTokenStream(lexer);
  20. ANTLRv4Parser parser = new ANTLRv4Parser(tokens);
  21. return parser.grammarSpec();
  22. } catch (IOException e) {
  23. throw new RuntimeException("That is unexpected", e);
  24. }
  25. }
  26. }

现在我们需要一个构建文件:

  1. buildscript {
  2. repositories {
  3. maven {
  4. name 'JFrog OSS snapshot repo'
  5. url 'https://oss.jfrog.org/oss-snapshot-local/'
  6. }
  7. jcenter()
  8. }
  9. }
  10. repositories {
  11. mavenCentral()
  12. jcenter()
  13. }
  14. apply plugin: 'java'
  15. apply plugin: 'antlr'
  16. apply plugin: 'idea'
  17. dependencies {
  18. antlr "org.antlr:antlr4:4.5.1"
  19. compile "org.antlr:antlr4-runtime:4.5.1"
  20. testCompile 'junit:junit:4.12'
  21. }
  22. generateGrammarSource {
  23. maxHeapSize = "64m"
  24. arguments += ['-package', 'me.tomassetti.antlr4.parser']
  25. outputDirectory = new File("${project.buildDir}/generated-src/antlr/main/me/tomassetti/antlr4/parser".toString())
  26. }
  27. task fatJar(type: Jar) {
  28. manifest {
  29. attributes 'Implementation-Title': 'Antlr4-Parser',
  30. 'Implementation-Version': '0.0.1'
  31. }
  32. baseName = project.name + '-all'
  33. from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
  34. with jar
  35. }

您可能要运行:

  • gradle这个主意 ,以创建一个Jetbrains的IDEA项目
  • gradle fatJar创建一个Jar,其中将包含我们的编译代码和所有依赖项

好。 现在要将这个解析器用于MPS,我们首先创建一个项目。 在向导中,我们还选择运行时和沙箱选项。 完成后,我们应该将胖子复制到运行时解决方案的models目录下。 在我的情况下,我从Java项目的目录运行以下命令:

cp build/libs/parser-all.jar ../languages/me.tomassetti.mpsantlr/runtime/models/

窗口1
然后我们也将其添加到库中:

window2

现在,JAR的内容应出现在运行时解决方案的存根中。

存根

从AST节点创建MPS节点

现在,我们将建立一个名为AntlrImporter的新概念。 我们将使用它来选择并将ANTLR语法导入MPS:

进口商

概念结构将非常简单:

蚂蚁进口

我们还需要要导入的AST节点的概念。 首先,我们将定义抽象概念AstNode 。 然后,我们将为终端和非终端AST节点定义两个子概念。

terminal_node non_terminal_node

现在,让我们看一下AntlrImporter的编辑器。

antlrimporter_editor

第一个swing组件是一个按钮,用于打开文件选择器。 这样,我们可以轻松地选择一个文件并设置属性path 。 或者,如果愿意,我们可以手动编辑它。

file_chooser

选择文件后,我们可以通过单击第二个按钮将其导入

纽扣

导入逻辑在importModel中 ,这是AntlrImporter行为的一种方法。

import_logic

好。 这就对了。 这样我们就可以解析任何ANTLR语法并将其放入MPS。 现在我们只需要使用一个很好的表示。 我们要使用树符号。

使用树符号

树符号令人惊讶地易于使用。

首先,将com.mbeddr.mpsutil.treenotation.styles.editor添加到我们语言的编辑器方面的依赖项中。

editor_deps

我们还需要com.mbeddr.mpsutil.treenotation成为使用的语言。

editor_langs

Non TerminalNode的编辑器由单个树单元组成。 树单元的顶部代表此节点。 我们将使用ruleName表示它。 相反,我们应该在底部选择包含要在树中显示的子项的关系

non_terminal_editor

我们可以将光标放在顶部和底部之间的树形图上(“ / | \”符号),然后打开检查器。 在那里,我们可以使用样式属性来自定义树的外观

non_terminal_inspector

我们只是决定从左到右而不是从上到下显示树。 然后,当孩子过多时,我们决定在父母与孩子之间添加更多空间。 这样,线条就不会重叠太多。

这是没有财产的样子

挤

属性集的外观如下

不拥挤

例如,还有其他属性可用于控制线条的颜色和粗细。 或者,您可以在线条的末端添加形状。 现在我们不需要这些功能,但是很高兴知道它们在那里。

TerminalNode的编辑器非常简单

terminal_editor

结论

多年来,MPS变得更加稳定且易于使用。 它已达到您可以非常有效地使用它的地步。 投影编辑是一个已经存在了一段时间的想法,并且还有其他可用的实现方式,例如整个平台 。 但是,MPS的成熟度很高。

我认为我们仍然想念的是:

  • 流程和最佳实践:我们应该如何管理与其他MPS项目的依赖关系? 我们应该如何与Java库集成?
  • 示例:令人惊讶的是,几乎没有公开的应用程序。 毕竟,许多用户针对其特定用途开发DSL,并且不打算共享它们。 但是,这意味着我们几乎没有机会互相学习
  • 扩展:Mbeddr团队作为Mbeddr平台的一部分,提供了很多好东西,做得很棒。 但是,它们似乎是唯一生产可复用组件并共享它们的组件

我认为现在是时候共同了解使用投影编辑可以实现的目标了。 我认为这将是非常有趣的时期。

如果我要表达的一个愿望是,我想听到更多有关其他人如何使用MPS的信息。 如果您在那里,请敲门。 并发表评论

翻译自: https://www.javacodegeeks.com/2016/05/antlr-jetbrains-mps-parsing-files-display-ast-usign-tree-notation.html

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号