我想解析一个UTF8编码的文本文件,其中可能包含以下内容:
int 1
text " some text with \" and \\ "
int list[-45,54, 435 ,-65]
float list [ 4.0, 5.2,-5.2342e+4]
列表中的数字用逗号分隔。允许使用空格,但不要求任何数字和任何符号(如逗号和括号)之间。类似于单词和符号,例如list[
我通过强制扫描器给我单个字符(将其分隔符设置为空模式)完成了引用的字符串读取,因为我仍然认为它对读取整数和浮点数很有用,但我不确定了。
扫描程序始终采用完整的令牌,然后尝试匹配它。我需要的是尝试尽可能多地(或尽可能少)匹配,无视分隔符。
基本上是为了这个输入
int list[-45,54, 435 ,-65]
我希望能够致电并获得此
s.nextWord() // int
s.nextWord() // list
s.nextSymbol() // [
s.nextInt() // -45
s.nextSymbol() // ,
s.nextInt() // 54
s.nextSymbol() // ,
s.nextInt() // 435
s.nextSymbol() // ,
s.nextInt() // -65
s.nextSymbol() // ]
等等。
或者,如果它无法解析双精度数和其他类型本身,至少采用正则表达式的方法,返回与其匹配的最大字符串(或错误),并将流位置设置为匹配后的位置。
扫描仪能以某种方式用于此吗?或者还有另一种方法吗?我觉得这一定很常见,但我似乎找不到合适的工具。
答案 0 :(得分:1)
我不是ANTLR专家,但这个ANTLR语法能够解析你的代码:
grammar Expressions;
expressions
: expression+ EOF
;
expression
: intExpression
| intListExpression
| floatExpression
| floatListExpression
| textExpression
| textListExpression
;
intExpression : intType INT;
intListExpression : intType listType '[' ( INT (',' INT)* )? ']';
floatExpression : floatType FLOAT;
floatListExpression : floatType listType '[' ( (INT|FLOAT) (',' (INT|FLOAT))* )? ']';
textExpression : textType STRING;
textListExpression : textType listType '[' ( STRING (',' STRING)* )? ']';
intType : 'int';
floatType : 'float';
textType : 'text';
listType : 'list';
INT : '0'..'9'+
;
FLOAT
: ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
| '.' ('0'..'9')+ EXPONENT?
| ('0'..'9')+ EXPONENT
;
STRING
: '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
;
fragment
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;
fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
fragment
ESC_SEQ
: '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
| UNICODE_ESC
| OCTAL_ESC
;
fragment
OCTAL_ESC
: '\\' ('0'..'3') ('0'..'7') ('0'..'7')
| '\\' ('0'..'7') ('0'..'7')
| '\\' ('0'..'7')
;
fragment
UNICODE_ESC
: '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
;
WS : ( ' '
| '\t'
| '\r'
| '\n'
) {$channel=HIDDEN;}
;
当然你需要改进它,但我认为使用这种结构很容易在解析器中插入代码来做你想要的(一种令牌流)。在ANTLRWorks调试中尝试一下,看看会发生什么。
对于您的输入,这是解析树:
编辑:我将其更改为支持空列表。
答案 1 :(得分:0)
使用类构造函数中的文件启动扫描程序。然后对于nextWord方法,执行此操作,
public static nextWord(){
return(sc.findInLine("\\w+"));
}
您可以使用上述示例使用Scanner类的findInLine方法并更改正则表达式模式来获取其他方法的代码。