antlr4略解

1. antlr4是用来干什么的?

是用来生成某语言lexer和parser的。
通俗点说,就是输入一个语言的规则描述文件,输出这个语言的lexer和parser。

2. 什么是lexer和parser?

编译可以分成词法分析,语法分析,语义分析等若干步骤,
以如下c++代码为例

int b;
int a=b+1;

词法分析是把源代码分成一个token序列,lexer就是负责词法分析的程序,lexer中文叫分词器或词法分析器,上述代码可能会被lexer分成如下token序列

int 'int' 
identifier 'b'
semi ';'
int 'int'
identifier 'a'
equal '='
identifier 'b' 
plus '+' 
numeric_constant '1'
semi ';'
eof ''

语法分析是把经词法分析得到的token序列,转换成一颗抽象语法树,parser就是负责语法分析的程序,parser的中文叫语法分析器或解析器,上述代码可能会被解析成如下抽象语法树

|-VarDecl 0x1cf11c82838  used b 'int'
`-VarDecl 0x1cf11c82918 a 'int' cinit
  `-BinaryOperator 0x1cf11c829e0  'int' '+'
    |-ImplicitCastExpr 0x1cf11c829c8  'int' <LValueToRValue>
    | `-DeclRefExpr 0x1cf11c82980  'int' lvalue Var 0x1cf11c82838 'b' 'int'
    `-IntegerLiteral 0x1cf11c829a0  'int' 1

3. 使用antlr4生成某语言的lexer和parser的具体过程

在下文中为了避免混淆,先澄清一些名词的含义。例如,我们使用ANTLR4工具生成了用于解析XML语言lexer和parser,而生成的lexer和parser的源代码是Python的。在这个例子中,XML语言是要解析的语言,而Python是最终生成的代码的目标语言。

下文使用术语“被解析语言”来指代需要解析的语言,它既可以是编程语言,也可以是其他类型的语言。而“目标语言”则严格指代生成的代码所采用的编程语言。ANTLR4工具支持通过编写语言规则文件来支持各种自定义的“被解析语言”。目前,ANTLR4支持十几种常见的目标语言,如C++、Java、Python等。

具体生成lexer/parser的过程如下:

  1. 安装antlr4,参考https://github.com/antlr/antlr4/blob/master/doc/getting-started.md
  2. 编写被解析语言的规则文件,规则文件的具体写法可参考https://github.com/antlr/antlr4/blob/master/doc/grammars.md,antlr4项目本身已经包含了大量写好的常见语言的规则文件,在仓库https://github.com/antlr/grammars-v4里,这样大部分常见语言都不用自己写规则文件了。
  3. 根据规则文件生成对应的lexer/parser和对应lexer/paser依赖的运行时库,参考https://github.com/antlr/antlr4/blob/master/doc/getting-started.md,其中需要注意的是选择是否生成ast对应的visitor或listener,visitor和listener都是用来遍历抽象语法树的。

4. 其他

antlr4一般是用来生成自定义语言或者比较小众的语言的语法分析器的,如果是需要解析比较常用的语言,可能用现成的lexer/parser,比使用antlr4生成的lexer/parser更合适。例如解析c++有clang,解析python有ast标准库,都比antlr4方便且强大。

  • 20
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ANTLR4 可以用来解析 C 代码,但是需要先编写好 C 语言的词法和语法规则。你可以使用 ANTLR4 提供的 C 语言语法规范作为参考,该语法规范定义了 C 语言的词法结构和语法结构。 具体来说,你需要使用 ANTLR4 编写 C 语言的词法规则和语法规则。词法规则用来将 C 代码分解成一个个词法单元(Token),语法规则用来将 Token 组合成一个抽象语法树(AST)。 下面是一个简单的示例,演示如何使用 ANTLR4 解析 C 代码: 1. 编写 C 语言的词法规则和语法规则(以 C99 标准为例): ``` grammar C99; compilationUnit : externalDeclaration+ ; externalDeclaration : functionDefinition | declaration ; functionDefinition : declarationSpecifiers declarator declarationList? compoundStatement ; declaration : declarationSpecifiers (initDeclaratorList)? ';' ; declarationSpecifiers : (storageClassSpecifier | typeSpecifier | typeQualifier)* ; initDeclaratorList : initDeclarator (',' initDeclarator)* ; initDeclarator : declarator ('=' initializer)? ; declarator : pointer? directDeclarator ; pointer : '*' typeQualifier* pointer? ; directDeclarator : identifier | '(' declarator ')' | directDeclarator '[' constantExpression? ']' ; typeQualifier : 'const' | 'volatile' ; typeSpecifier : 'void' | 'char' | 'short' | 'int' | 'long' | 'float' | 'double' | 'signed' | 'unsigned' | structOrUnionSpecifier | enumSpecifier | typedefName ; structOrUnionSpecifier : ('struct' | 'union') identifier? '{' structDeclaration* '}' ; structDeclaration : specifierQualifierList structDeclaratorList? ';' ; specifierQualifierList : (typeSpecifier | typeQualifier)+ ; structDeclaratorList : structDeclarator (',' structDeclarator)* ; structDeclarator : declarator? (':' constantExpression)? ; enumSpecifier : 'enum' identifier? '{' enumeratorList? '}' ; enumeratorList : enumerator (',' enumerator)* ; enumerator : identifier ('=' constantExpression)? ; typedefName : identifier ; initializer : assignmentExpression | '{' initializerList '}' | '{' initializerList ',' '}' ; initializerList : initializer (',' initializer)* ; statement : labeledStatement | compoundStatement | expressionStatement | selectionStatement | iterationStatement | jumpStatement ; labeledStatement : identifier ':' statement | 'case' constantExpression ':' statement | 'default' ':' statement ; compoundStatement : '{' (declaration | statement)* '}' ; expressionStatement : expression? ';' ; selectionStatement : 'if' '(' expression ')' statement ('else' statement)? | 'switch' '(' expression ')' statement ; iterationStatement : 'while' '(' expression ')' statement | 'do' statement 'while' '(' expression ')' | 'for' '(' expressionStatement expressionStatement? ')' statement ; jumpStatement : 'goto' identifier ';' | 'continue' ';' | 'break' ';' | 'return' expression? ';' ; expression : assignmentExpression (',' assignmentExpression)* ; assignmentExpression : conditionalExpression | unaryExpression assignmentOperator assignmentExpression ; conditionalExpression : logicalOrExpression ('?' expression ':' conditionalExpression)? ; logicalOrExpression : logicalAndExpression ('||' logicalAndExpression)* ; logicalAndExpression : inclusiveOrExpression ('&&' inclusiveOrExpression)* ; inclusiveOrExpression : exclusiveOrExpression ('|' exclusiveOrExpression)* ; exclusiveOrExpression : andExpression ('^' andExpression)* ; andExpression : equalityExpression ('&' equalityExpression)* ; equalityExpression : relationalExpression (('==' | '!=') relationalExpression)* ; relationalExpression : shiftExpression (('<' | '>' | '<=' | '>=') shiftExpression)* ; shiftExpression : additiveExpression (('<<' | '>>') additiveExpression)* ; additiveExpression : multiplicativeExpression (('+' | '-') multiplicativeExpression)* ; multiplicativeExpression : castExpression (('*' | '/' | '%') castExpression)* ; castExpression : '(' typeName ')' castExpression | unaryExpression ; unaryExpression : postfixExpression | ('++' | '--') unaryExpression | unaryOperator castExpression | sizeof unaryExpression | sizeof '(' typeName ')' ; postfixExpression : primaryExpression ( '[' expression ']' | '(' argumentExpressionList? ')' | '.' identifier | '->' identifier | '++' | '--' )* ; argumentExpressionList : assignmentExpression (',' assignmentExpression)* ; primaryExpression : identifier | constant | stringLiteral | '(' expression ')' ; constant : integerConstant | floatingConstant | enumerationConstant ; integerConstant : decimalConstant | octalConstant | hexadecimalConstant ; decimalConstant : ('0' | nonZeroDigit digit* ) ; octalConstant : '0' octalDigit* ; hexadecimalConstant : '0x' hexDigit+ ; floatingConstant : decimalFloatingConstant | hexadecimalFloatingConstant ; decimalFloatingConstant : fraction | exponent | fraction exponent ; fraction : digit+ '.' digit* ; exponent : ('e' | 'E') ('+' | '-')? digit+ ; hexadecimalFloatingConstant : hexadecimalPrefix hexFraction binaryExponent | hexadecimalPrefix hexadecimalDigit+ binaryExponent ; hexPrefix : ('0x' | '0X') ; hexFraction : hexadecimalDigit* '.' hexadecimalDigit+ | hexadecimalDigit+ '.' ; binaryExponent : ('p' | 'P') ('+' | '-')? digit+ ; enumerationConstant : identifier ; identifier : [a-zA-Z_] [a-zA-Z_0-9]* ; stringLiteral : '"' [^"\n]* '"' ; constantExpression : conditionalExpression ; typeName : specifierQualifierList abstractDeclarator? ; abstractDeclarator : pointer? directAbstractDeclarator ; directAbstractDeclarator : '(' abstractDeclarator ')' | '[' '*'? ']' | '[' directAbstractDeclarator ']' '[' assignmentExpression? ']' | '(' parameterTypeList? ')' ; parameterTypeList : parameterList (',' '...')? ; parameterList : parameterDeclaration (',' parameterDeclaration)* ; parameterDeclaration : declarationSpecifiers declarator | declarationSpecifiers abstractDeclarator? ; ``` 2. 使用 ANTLR4 生成 C 解析器的代码: ``` antlr4 C99.g4 javac C99*.java ``` 3. 编写一个 Java 类来读取 C 代码文件并解析: ``` import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.tree.*; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class CParser { public static void main(String[] args) throws IOException { String inputFile = null; if (args.length > 0) inputFile = args[0]; InputStream is = System.in; if (inputFile != null) is = new FileInputStream(inputFile); CharStream input = CharStreams.fromStream(is); CLexer lexer = new CLexer(input); CommonTokenStream tokens = new CommonTokenStream(lexer); C99Parser parser = new C99Parser(tokens); ParseTree tree = parser.compilationUnit(); // 解析 C 代码文件 System.out.println(tree.toStringTree(parser)); } } ``` 4. 运行 Java 程序来解析 C 代码文件: ``` java CParser test.c ``` 其中,`test.c` 是需要解析的 C 代码文件。 这样,就可以使用 ANTLR4 解析 C 代码了。需要注意的是,ANTLR4 生成的解析器只能解析语法正确的 C 代码,如果 C 代码存在语法错误,解析器将会抛出异常。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值