【发布时间】:2018-07-02 16:40:40
【问题描述】:
使用 StreamTokenizer 我正在编写一个词法分析器,它将标记一个数学表达式。
作为输入,我给出表达式(1+π)²(1−π)²+(5.3−-2)/6。
我希望它被标记为 ( 1 + π ) ² ( 1 - π ) ² + ( 5.3 − - 2 ) / 6
但我得到( 1 +π ) ² ( 1 -π ) ² + ( 5.3 −-2 ) / 6。
我知道我需要在输出的某些地方插入乘法运算符,稍后再做。
/* s: The inputted expression */
public static String tokenize(String s)[] throws IOException
{
StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(s));
tokenizer.parseNumbers();
tokenizer.wordChars('a', 'z');
tokenizer.wordChars('A', 'Z');
tokenizer.wordChars('A', 'Z');
tokenizer.wordChars(SQUARED, SQUARED); // the superscript 2
tokenizer.wordChars(PI, PI);
tokenizer.wordChars(SUB.charAt(0), SUB.charAt(0)); // subtract (takeaway)
tokenizer.wordChars(NEG.charAt(0), NEG.charAt(0)); // negate
tokenizer.wordChars('/', '/');
tokenizer.wordChars('*', '*');
tokenizer.wordChars('+', '+');
tokenizer.ordinaryChar(',');
tokenizer.ordinaryChar('/'); // do not consider / as comment start
ArrayList<String> tokBuf = new ArrayList<>();
while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
switch (tokenizer.ttype) {
case StreamTokenizer.TT_NUMBER:
tokBuf.add(String.valueOf(tokenizer.nval));
break;
case StreamTokenizer.TT_WORD:
tokBuf.add(tokenizer.sval);
break;
default:
tokBuf.add(String.valueOf((char) tokenizer.ttype));
}
}
String ret[] = new String[tokBuf.size()];
ret = tokBuf.toArray(ret);
return ret;
}
【问题讨论】:
-
StringTokenizer会将--视为单个令牌。您为这项工作使用了错误的工具。 -
@EJP 我用了两种不同的减法符号,一个小一个大;它们是不同的代码点
-
无论如何,@EJP 是正确的。
StreamTokenizer是错误的工具。它可以处理的语法非常有限。此外,Javadoc 不是很清楚,并且有强烈的迹象表明它不会正确处理0x00FF以上的代码点(或根本不处理?)。编写自己的简单状态驱动词法分析器会更好,您可以在其中根据您的要求调整行为。否则,您只是在需要精细木工凿子的地方尝试使用钝头螺丝刀。 -
几乎要说同样的话。
StreamTokenizer或 Java 中的其他两个标记器类太简单了。它们是可爱的想法,但仅适用于简单的问题,也许是学生或其他东西。如果您想使用工具而不是从头开始编写自己的工具,请查看Antlr 4antlr.org