扫描仪(带有ANTLR的Lexing关键字)

时间:2011-09-02 12:35:43

标签: compiler-construction antlr antlr3 lexer

我一直在为我的程序编写扫描程序,大多数在线教程包括解析器和扫描程序。如果不同时编写解析器,似乎不可能编写词法分析器。我只是想生成令牌,而不是解释它们。我想识别INT令牌,浮动令牌以及“开始”和“结束”等一些令牌

我对如何匹配关键字感到困惑。我没有成功尝试以下内容:

KEYWORD : KEY1 | KEY2;

KEY1 : {input.LT(1).getText().equals("BEGIN")}? LETTER+ ;
KEY2 : {input.LT(1).getText().equals("END")}? LETTER+ ;

FLOATLITERAL_INTLITERAL
  : DIGIT+ 
  ( 
    { input.LA(2) != '.' }? => '.' DIGIT* { $type = FLOATLITERAL; }
    | { $type = INTLITERAL; }
  )
  | '.'  DIGIT+ {$type = FLOATLITERAL}
;

fragment LETTER : ('a'..'z' | 'A'..'Z');
fragment DIGIT  : ('0'..'9');

IDENTIFIER 
 : LETTER 
   | LETTER DIGIT (LETTER|DIGIT)+ 
   | LETTER LETTER (LETTER|DIGIT)*
 ;

WS  //Whitespace
  : (' ' | '\t' | '\n' | '\r' | '\f')+  {$channel = HIDDEN;}
;  

2 个答案:

答案 0 :(得分:2)

如果您只想要词法分析器,请使用以下语言开始您的语法:

lexer grammar FooLexer; // creates: FooLexer.java

LT(int): Token只能在解析器规则中使用(在TokenStream上)。在词法分析器规则中,您只能使用LA(int): int来获取IntStream中的下一个int(字符)。但是没有必要将所有手册展望未来。做这样的事情:

lexer grammar FooLexer;

BEGIN
  :  'BEGIN'
  ;

END
  :  'END'
  ;

FLOAT
  :  DIGIT+ '.' DIGIT+
  ;

INT
  :  DIGIT+
  ;

IDENTIFIER 
  :  LETTER (LETTER | DIGIT)*
  ;

WS
  :  (' ' | '\t' | '\n' | '\r' | '\f')+  {$channel = HIDDEN;}
  ; 

fragment LETTER : ('a'..'z' | 'A'..'Z');
fragment DIGIT  : ('0'..'9');

我认为无需创建与所有关键字匹配的名为KEYWORD的令牌:您需要区分BEGINEND令牌,对吧?但如果你真的想要这个,那就干嘛:

KEYWORD
  :  'BEGIN'
  |  'END'
  ;

并删除BEGINEND规则。只需确保在KEYWORD之前定义IDENTIFIER

修改

使用以下类测试词法分析器:

import org.antlr.runtime.*;

public class Main {
  public static void main(String[] args) throws Exception {
    String src = "BEGIN END 3.14159 42 FOO";
    FooLexer lexer = new FooLexer(new ANTLRStringStream(src));
    while(true) {
      Token token = lexer.nextToken();
      if(token.getType() == FooLexer.EOF) {
        break;
      }
      System.out.println(token.getType() + " :: " + token.getText());
    }
  }
}

如果你生成一个词法分析器,编译.java源文件并像这样运行Main类:

java -cp antlr-3.3.jar org.antlr.Tool FooLexer.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar Main

以下输出将打印到控制台:

4 :: BEGIN
11 ::  
5 :: END
11 ::  
7 :: 3.14159
11 ::  
8 :: 42
11 ::  
10 :: FOO

答案 1 :(得分:1)

[来自制作自定义词法工具的人,并且仍在尝试学习ANTLR]

无聊的回答:

你是对的。许多书籍和课程混合了两种工具。有时候“生成/检测令牌”和“解释令牌”可能会混合在一起。

有时,开发人员正在尝试使用扫描仪,并且仍在混合扫描和扫描。解析它的思想; - )

通常,在检测令牌时,您还必须执行操作(“解释”),就像将消息或找到的令牌打印到字符串一样简单。 示例:“{cout<<”嘿,我找到了一个整数常量“<<”\ n“}”

还有一些案例可能会使该主题的初学者难以进行扫描。

有一种情况是,可能会有多个文本用于不同的令牌。

示例:

“ - ”作为减法二元运算符,“ - ”作为负前缀运算符。 或者,将5都视为整数和浮点数。在扫描仪中,“ - ”可以看作是相同的标记,而在解析器中,您可以将其视为不同的标记。

为了解决这个问题,我最喜欢的方法是在扫描/词法分析器过程中使用“通用标记”,然后在解析/语法过程中将它们转换为“自定义标记”。

快速回答:

正如之前的答案中所提到的,从制作语法开始,事实上,我建议在白板或笔记本中试用,然后在你最喜欢的(ANTLRL,其他)扫描工具中试用。

考虑那些可能存在一些令牌重叠的特殊情况。

祝你好运。