目前,我只是在ANTLR4中定义了简单的规则:
// Recognizer Rules
program : (class_dcl)+ EOF;
class_dcl: 'class' ID ('extends' ID)? '{' class_body '}';
class_body: (const_dcl|var_dcl|method_dcl)*;
const_dcl: ('static')? 'final' PRIMITIVE_TYPE ID '=' expr ';';
var_dcl: ('static')? id_list ':' type ';';
method_dcl: PRIMITIVE_TYPE ('static')? ID '(' para_list ')' block_stm;
para_list: (para_dcl (';' para_dcl)*)?;
para_dcl: id_list ':' PRIMITIVE_TYPE;
block_stm: '{' '}';
expr: <assoc=right> expr '=' expr | expr1;
expr1: term ('<' | '>' | '<=' | '>=' | '==' | '!=') term | term;
term: ('+'|'-') term | term ('*'|'/') term | term ('+'|'-') term | fact;
fact: INTLIT | FLOATLIT | BOOLLIT | ID | '(' expr ')';
type: PRIMITIVE_TYPE ('[' INTLIT ']')?;
id_list: ID (',' ID)*;
// Lexer Rules
KEYWORD: PRIMITIVE_TYPE | BOOLLIT | 'class' | 'extends' | 'if' | 'then' | 'else'
| 'null' | 'break' | 'continue' | 'while' | 'return' | 'self' | 'final'
| 'static' | 'new' | 'do';
SEPARATOR: '[' | ']' | '{' | '}' | '(' | ')' | ';' | ':' | '.' | ',';
OPERATOR: '^' | 'new' | '=' | UNA_OPERATOR | BIN_OPERATOR;
UNA_OPERATOR: '!';
BIN_OPERATOR: '+' | '-' | '*' | '\' | '/' | '%' | '>' | '>=' | '<' | '<='
| '==' | '<>' | '&&' | '||' | ':=';
PRIMITIVE_TYPE: 'integer' | 'float' | 'bool' | 'string' | 'void';
BOOLLIT: 'true' | 'false';
FLOATLIT: [0-9]+ ((('.'[0-9]* (('E'|'e')('+'|'-')?[0-9]+)? ))|(('E'|'e')('+'|'-')? [0-9]+));
INTLIT: [0-9]+;
STRINGLIT: '"' ('\'[bfrnt\"]|~[rtn\"])* '"';
ILLEGAL_ESC: '"' (('\'[bfrnt\"]|~[n\"]))* ('\'(~[bfrnt\"]))
{if (true) throw new bkool.parser.IllegalEscape(getText());};
UNCLOSED_STRING: '"'('\'[bfrnt\"]|~[rtn\"])*
{if (true) throw new bkool.parser.UncloseString(getText());};
COMMENT: (BLOCK_COMMENT|LINE_COMMENT) -> skip;
BLOCK_COMMENT: '(''*'(('*')?(~')'))*'*'')';
LINE_COMMENT: '#' (~[n])* ('n'|EOF);
ID: [a-zA-z_]+ [a-zA-z_0-9]* ;
WS: [ trn]+ -> skip ;
ERROR_TOKEN: . {if (true) throw new bkool.parser.ErrorToken(getText());};
我打开解析树,试着测试:
class abc
{
final integer x=1;
}
返回错误:
BKOOL::program:3:8: mismatched input 'integer' expecting PRIMITIVE_TYPE
BKOOL::program:3:17: mismatched input '=' expecting {':', ','}
我仍然不知道为什么。你能告诉我为什么它不能像我期望的那样识别规则和符号吗?
Lexer规则是排他的。最长的获胜,而决胜局是语法顺序。
在你的情况下;integer
是KEYWORD
而不是PRIMITIVE_TYPE
。
你应该怎么做:
- 为每个关键字创建一个不同的令牌,而不是捕获所有
KEYWORD
规则。 - 将
PRIMITIVE_TYPE
转换为解析器规则 - 操作
现在,你的例子:
class abc
{
final integer x=1;
}
被转换为诸如:class
ID
{
final
KEYWORD
ID
=
INTLIT
;
}
这要归功于隐式标记类型,因为您在解析器规则中使用了'class'
之类的定义。这些被转换为匿名令牌,如T_001 : 'class';
,获得最高优先级。
如果不是这样的话,你就会得到:KEYWORD
ID
SEPARATOR
KEYWORD
KEYWORD
ID
OPERATOR
INTLIT
;
SEPARATOR
,这是……不太容易解析;-)