我一直在为我的程序编写扫描程序,大多数在线教程包括解析器和扫描程序。如果不同时编写解析器,似乎不可能编写词法分析器。我只是想生成令牌,而不是解释它们。我想识别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;}
;
答案 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
的令牌:您需要区分BEGIN
和END
令牌,对吧?但如果你真的想要这个,那就干嘛:
KEYWORD
: 'BEGIN'
| 'END'
;
并删除BEGIN
和END
规则。只需确保在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,其他)扫描工具中试用。
考虑那些可能存在一些令牌重叠的特殊情况。
祝你好运。