编译原理c语言的抽象语法树
在本文中,我们将看到如何处理和转换从解析器获得的信息。 ANTLR解析器识别源代码中存在的元素,并构建一个解析树 。 从语法分析树中,我们将获得抽象语法树 ,该语法树将用于执行验证并生成已编译的代码。
请注意,术语可能会有所不同:许多人会将从ANTLR获得的树称为抽象语法树。 我更喜欢标记这两个步骤的区别。 对我而言, 解析树是对解析器有意义的信息, 抽象语法树是经过重组以更好地支持后续步骤的信息。
建立自己的语言的系列
以前的帖子:
代码在GitHub上的标签为05_ ast
丰富我们的语言
在本系列文章中,我们一直在研究一种非常简单的表达语言。 现在是时候让我们的语言稍微复杂一些了:
- 例如, 强制转换为: 10作为十进制或(1 * 2.45)作为Int
- 打印声明 例如: print(3 + 11)
为此,我们需要修改我们的词法分析器和解析器语法。 我们在之前的文章中构建的语法高亮和自动完成功能将继续起作用。
新的词法分析器语法:
lexer grammar SandyLexer;
// Whitespace
NEWLINE : '\r\n' | 'r' | '\n' ;
WS : [\t ]+ -> skip ;
// Keywords
VAR : 'var' ;
PRINT : 'print';
AS : 'as';
INT : 'Int';
DECIMAL : 'Decimal';
// Literals
INTLIT : '0'|[1-9][0-9]* ;
DECLIT : '0'|[1-9][0-9]* '.' [0-9]+ ;
// Operators
PLUS : '+' ;
MINUS : '-' ;
ASTERISK : '*' ;
DIVISION : '/' ;
ASSIGN : '=' ;
LPAREN : '(' ;
RPAREN : ')' ;
// Identifiers
ID : [_]*[a-z][A-Za-z0-9_]* ;
以及新的解析器语法:
parser grammar SandyParser;
options { tokenVocab=SandyLexer; }
sandyFile : lines=line+ ;
line : statement (NEWLINE | EOF) ;
statement : varDeclaration # varDeclarationStatement
| assignment # assignmentStatement
| print # printStatement ;
print : PRINT LPAREN expression RPAREN ;
varDeclaration : VAR assignment ;
assignment : ID ASSIGN expression ;
expression : left=expression operator=(DIVISION|ASTERISK) right=expression # binaryOperation
| left=expression operator=(PLUS|MINUS) right=expression # binaryOperation
| value=expression AS targetType=type # typeConversion
| LPAREN expression RPAREN