分别使用ANTLR解析器和词法分析器

本文关键字:词法分析器 ANTLR | 更新日期: 2023-09-27 18:09:30

我使用ANTLR版本4创建编译器。第一阶段是Lexer部分。我创建了"CompilerLexer"。G4"文件,并在其中放入词法分析器规则。

CompilerLexer.g4:


lexer grammar CompilerLexer;
INT         :   'int'   ;   //1
FLOAT       :   'float' ;   //2
BEGIN       :   'begin' ;   //3
END         :   'end'   ;   //4
To          :   'to'    ;   //5
NEXT        :   'next'  ;   //6
REAL        :   'real'  ;   //7
BOOLEAN     :   'bool'  ;   //8
.
.
.
NOTEQUAL    :   '!='    ;   //46
AND         :   '&&'    ;   //47
OR          :   '||'    ;   //48
POW         :   '^'     ;   //49
ID          : [a-zA-Z]+ ;   //50


WS
:   ' ' -> channel(HIDDEN)  //50
;

现在是第二阶段的时候了,也就是解析器。我创建了"CompilerParser"。G4"文件,并在其中放置了语法,但有几十个警告和错误。

CompilerParser.g4:


parser grammar CompilerParser;
options {   tokenVocab = CompilerLexer; }
STATEMENT   :   EXPRESSION SEMIC
        |   IFSTMT
        |   WHILESTMT
        |   FORSTMT
        |   READSTMT SEMIC
        |   WRITESTMT SEMIC
        |   VARDEF SEMIC
        |   BLOCK
        ;
BLOCK       : BEGIN STATEMENTS END
        ;
STATEMENTS  : STATEMENT STATEMENTS*
        ;
EXPRESSION  : ID ASSIGN EXPRESSION
        | BOOLEXP
        ;
RELEXP      : MODEXP (GT | LT | EQUAL | NOTEQUAL | LE | GE | AND | OR) RELEXP
        | MODEXP
        ;
.
.
.
VARDEF      : (ID COMA)* ID COLON VARTYPE
        ;
VARTYPE     : INT
        | FLOAT
        | CHAR
        | STRING
        ;
compileUnit
:   EOF
;

警告和错误:

  • 解析器中令牌'BLOCK'的隐式定义
  • 解析器中令牌'BOOLEXP'的隐式定义
  • 解析器中标记'EXP'的隐式定义
  • 解析器中标记'EXPLIST'的隐式定义
  • 解析器不允许词法分析器规则'BLOCK'
  • 词法分析器规则'EXP'在解析器中不允许
  • 解析器不允许词法分析器规则'EXPLIST'
  • 词法分析器规则'EXPRESSION'在解析器中不允许

有很多这样的警告和错误。原因是什么?

一般问题:使用组合语法和单独使用词法分析器和解析器有什么区别?应该如何连接单独的语法和词法分析器文件?

分别使用ANTLR解析器和词法分析器

Lexer规则以大写字母开头,而解析器规则以小写字母开头。在解析器语法中,不能定义令牌。由于ANTLR认为所有的大写规则都是词法分析器规则,所以它产生了这些错误/警告。

<标题>编辑

user2998131写道:

一般问题:使用组合语法和单独使用词法分析器和解析器有什么区别?

分隔词法分析器和解析器规则将使事情更有条理。此外,在创建单独的词法分析器和解析器语法时,您不能(意外地)将文字标记放在解析器语法中,而需要在词法分析器语法中定义所有标记。这将使哪个词法分析器规则在其他规则之前得到匹配,并且您不能在重复出现的文字标记中进行任何打字错误:

grammar P;
r1 : 'foo' r2;
r2 : r3 'foo '; // added an accidental space after 'foo'

但是当你有了语法分析器,你就不会犯这个错误了。您必须使用匹配'foo'的词法分析器规则:

parser grammar P
options { tokenVocab=L; }
r1 : FOO r2;
r2 : r3 FOO;

lexer grammar L;
FOO : 'foo';

user2998131写道:

如何连接单独的语法和词法分析器文件?

就像你在解析器语法中做的那样:你在options { ... }块中指向适当的tokenVocab

请注意,您还可以导入语法,这是不同的:https://github.com/antlr/antlr4/blob/master/doc/grammars.md#grammar-imports