Java的抽象语法树 (AST)
抽象语法树是一种用编程语言编写的源代码抽象句法结构的树表示。树的每个节点表示源代码中出现的一个构造。
AST 在编译器中的应用具有许多重要性,因为抽象语法树是编译器中广泛用于表示程序代码结构的数据结构。 AST 通常是编译器语法分析阶段的结果。它通常通过编译器需要的几个阶段作为程序的中间表示,对编译器的最终输出有很大的影响。
在进一步讨论实现部分之前,让我们先讨论一下 AST 的使用。 AST 主要用于编译器来检查代码的准确性。如果生成的树有错误,编译器会打印错误消息。使用抽象语法树 (AST) 是因为某些构造无法用上下文无关文法表示,例如隐式类型。它们高度特定于编程语言,但对通用语法树的研究正在进行中。
Flow Chart:
id + id * id would have the following syntax tree which is as follows:
Abstract syntax tree will be as follows:
执行:
在这里,我们将编写对应的自定义Java源代码,我们将为与实现中相同的Java源代码提供 AST。
示例 1(A) Java源代码
Java
// Java Custom Source Code
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Print statement
System.out.println("Hello World!");
}
}
Java
CLASS_DEF -> CLASS_DEF [1:0]
|--MODIFIERS -> MODIFIERS [1:0]
| `--LITERAL_PUBLIC -> public [1:0]
|--LITERAL_CLASS -> class [1:7]
|--IDENT -> GFG [1:13]
`--OBJBLOCK -> OBJBLOCK [1:17]
|--LCURLY -> { [1:17]
|--METHOD_DEF -> METHOD_DEF [2:4]
| |--MODIFIERS -> MODIFIERS [2:4]
| | |--LITERAL_PUBLIC -> public [2:4]
| | `--LITERAL_STATIC -> static [2:11]
| |--TYPE -> TYPE [2:18]
| | `--LITERAL_VOID -> void [2:18]
| |--IDENT -> main [2:23]
| |--LPAREN -> ( [2:27]
| |--PARAMETERS -> PARAMETERS [2:34]
| | `--PARAMETER_DEF -> PARAMETER_DEF [2:34]
| | |--MODIFIERS -> MODIFIERS [2:34]
| | |--TYPE -> TYPE [2:34]
| | | `--ARRAY_DECLARATOR -> [ [2:34]
| | | |--IDENT -> String [2:28]
| | | `--RBRACK -> ] [2:35]
| | `--IDENT -> args [2:37]
| |--RPAREN -> ) [2:41]
| `--SLIST -> { [2:43]
| |--EXPR -> EXPR [3:26]
| | `--METHOD_CALL -> ( [3:26]
| | |--DOT -> . [3:18]
| | | |--DOT -> . [3:14]
| | | | |--IDENT -> System [3:8]
| | | | `--IDENT -> out [3:15]
| | | `--IDENT -> println [3:19]
| | |--ELIST -> ELIST [3:27]
| | | `--EXPR -> EXPR [3:27]
| | | `--STRING_LITERAL -> "Hello World!" [3:27]
| | `--RPAREN -> ) [3:41]
| |--SEMI -> ; [3:42]
| `--RCURLY -> } [4:4]
`--RCURLY -> } [5:0]
Java
CLASS_DEF -> CLASS_DEF
|--MODIFIERS -> MODIFIERS
| `--LITERAL_PUBLIC -> public
|--LITERAL_CLASS -> class
|--IDENT -> GFG
`--OBJBLOCK -> OBJBLOCK
|--LCURLY -> {
|--METHOD_DEF -> METHOD_DEF
| |--MODIFIERS -> MODIFIERS
| | |--LITERAL_PUBLIC -> public
| | `--LITERAL_STATIC -> static
| |--TYPE -> TYPE
| | `--LITERAL_VOID -> void
| |--IDENT -> main
| |--LPAREN -> (
| |--PARAMETERS -> PARAMETERS
| | `--PARAMETER_DEF -> PARAMETER_DEF
| | |--MODIFIERS -> MODIFIERS
| | |--TYPE -> TYPE
| | | `--ARRAY_DECLARATOR -> [
| | | |--IDENT -> String
| | | `--RBRACK -> ]
| | `--IDENT -> args
| |--RPAREN -> )
| `--SLIST -> {
| |--EXPR -> EXPR
| | `--METHOD_CALL -> (
| | |--DOT -> .
| | | |--DOT -> .
| | | | |--IDENT -> System
| | | | `--IDENT -> out
| | | `--IDENT -> println
| | |--ELIST -> ELIST
| | | `--EXPR -> EXPR
| | | `--STRING_LITERAL -> "Hello World!"
| | `--RPAREN -> )
| |--SEMI -> ;
| `--RCURLY -> }
`--RCURLY -> }
Java
+ BinaryExpression
- type: +
- left_value:
LiteralExpr:
value: 1
- right_vaue:
LiteralExpr:
value: 2
示例 1(B)上述源代码的 AST
Java
CLASS_DEF -> CLASS_DEF [1:0]
|--MODIFIERS -> MODIFIERS [1:0]
| `--LITERAL_PUBLIC -> public [1:0]
|--LITERAL_CLASS -> class [1:7]
|--IDENT -> GFG [1:13]
`--OBJBLOCK -> OBJBLOCK [1:17]
|--LCURLY -> { [1:17]
|--METHOD_DEF -> METHOD_DEF [2:4]
| |--MODIFIERS -> MODIFIERS [2:4]
| | |--LITERAL_PUBLIC -> public [2:4]
| | `--LITERAL_STATIC -> static [2:11]
| |--TYPE -> TYPE [2:18]
| | `--LITERAL_VOID -> void [2:18]
| |--IDENT -> main [2:23]
| |--LPAREN -> ( [2:27]
| |--PARAMETERS -> PARAMETERS [2:34]
| | `--PARAMETER_DEF -> PARAMETER_DEF [2:34]
| | |--MODIFIERS -> MODIFIERS [2:34]
| | |--TYPE -> TYPE [2:34]
| | | `--ARRAY_DECLARATOR -> [ [2:34]
| | | |--IDENT -> String [2:28]
| | | `--RBRACK -> ] [2:35]
| | `--IDENT -> args [2:37]
| |--RPAREN -> ) [2:41]
| `--SLIST -> { [2:43]
| |--EXPR -> EXPR [3:26]
| | `--METHOD_CALL -> ( [3:26]
| | |--DOT -> . [3:18]
| | | |--DOT -> . [3:14]
| | | | |--IDENT -> System [3:8]
| | | | `--IDENT -> out [3:15]
| | | `--IDENT -> println [3:19]
| | |--ELIST -> ELIST [3:27]
| | | `--EXPR -> EXPR [3:27]
| | | `--STRING_LITERAL -> "Hello World!" [3:27]
| | `--RPAREN -> ) [3:41]
| |--SEMI -> ; [3:42]
| `--RCURLY -> } [4:4]
`--RCURLY -> } [5:0]
现在您一定想知道如何制作 AST 或如何按照按顺序列出的简单步骤为该极客生成上述代码。
- 在本地环境中运行源代码。
- 下载 Checkstyle 命令行
checkstyle-8.43-all.jar
- 借助终端中的 Checkstyle 审核程序:
java -jar checkstyle-8.43-all.jar -c /google_checks.xml YourFile.java
- 审核后,在终端中运行此命令以获取首选代码的 AST: Java -jar checkstyle-8.43-all.jar -t YourFile。Java
- AST 现在准备好了。但是等待极客,
Note: This is not an Updated AST
请记住:要更新 AST,我们必须执行以下两个步骤
第 1 步:我们应该更换
">" with ">" and "<" with "<"
第 2 步:删除代码行
Example 1(C)更新后的 AST 上面代码的例子如下:
Java
CLASS_DEF -> CLASS_DEF
|--MODIFIERS -> MODIFIERS
| `--LITERAL_PUBLIC -> public
|--LITERAL_CLASS -> class
|--IDENT -> GFG
`--OBJBLOCK -> OBJBLOCK
|--LCURLY -> {
|--METHOD_DEF -> METHOD_DEF
| |--MODIFIERS -> MODIFIERS
| | |--LITERAL_PUBLIC -> public
| | `--LITERAL_STATIC -> static
| |--TYPE -> TYPE
| | `--LITERAL_VOID -> void
| |--IDENT -> main
| |--LPAREN -> (
| |--PARAMETERS -> PARAMETERS
| | `--PARAMETER_DEF -> PARAMETER_DEF
| | |--MODIFIERS -> MODIFIERS
| | |--TYPE -> TYPE
| | | `--ARRAY_DECLARATOR -> [
| | | |--IDENT -> String
| | | `--RBRACK -> ]
| | `--IDENT -> args
| |--RPAREN -> )
| `--SLIST -> {
| |--EXPR -> EXPR
| | `--METHOD_CALL -> (
| | |--DOT -> .
| | | |--DOT -> .
| | | | |--IDENT -> System
| | | | `--IDENT -> out
| | | `--IDENT -> println
| | |--ELIST -> ELIST
| | | `--EXPR -> EXPR
| | | `--STRING_LITERAL -> "Hello World!"
| | `--RPAREN -> )
| |--SEMI -> ;
| `--RCURLY -> }
`--RCURLY -> }
例2:表示1+2可以用AST表示
Java
+ BinaryExpression
- type: +
- left_value:
LiteralExpr:
value: 1
- right_vaue:
LiteralExpr:
value: 2