我正在用Java编写一个标记器,它必须处理操作符,并且标记之间的空白字符是不必要的。
我需要识别像"<="这样的符号,同时还要识别"<"one_answers"="。
现在我有:
if (token == '<')
if (nextToken == '=')
this.tokenList.add(27); // <=
else
// add 2 tokens separately
是否有任何方式为StreamTokenizer做这个自己?我已经通读了API,但是我什么也没看到。
我可以指定可以算作一个的令牌组合吗?理想情况下,getNextToken会同时删除这两个令牌。
谢谢!
StreamTokenizer
为您提供的是基本Lexer的功能。你必须使用这些来制作你的高端版本。
你必须非常明智地使用nextToken()
和pushBack()
。例如,在下面我正在照顾<
, <<
和<=
。如果您看到操作符<
,则在流中向前查找线索,如果没有找到后面的<
或=
,则将向前查找令牌推回流中。
>>示例代码
import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;
public class LexerTest
{
private StringReader r;
public LexerTest(StringReader stringReader) {
r = stringReader;
}
public static void main(String[] args) throws IOException
{
String s = "test = test1 + (test2 * test3 * (test4 - 2);";
new LexerTest(new StringReader(s)).printTokens();
System.out.println("n### Test 2 ###n");
s = "test = if(test1 < test2){ test3 = (test4 - 2);}";
new LexerTest(new StringReader(s)).printTokens();
System.out.println("n### Test 3 ###n");
s = "test = if(test1 <= test2){ test3 = (test4 - 2);}";
new LexerTest(new StringReader(s)).printTokens();
System.out.println("n### Test 4 ###n");
s = "test = if(test1 < test2){ test3 = (test4 << 2);}";
new LexerTest(new StringReader(s)).printTokens();
}
private void printTokens() throws IOException
{
StreamTokenizer st = new StreamTokenizer(r);
st.eolIsSignificant(true);
int token = st.nextToken();
while (token != StreamTokenizer.TT_EOF)
{
token = st.nextToken();
switch (token)
{
case StreamTokenizer.TT_NUMBER:
double num = st.nval;
System.out.println("Number found: " + num);
break;
case StreamTokenizer.TT_WORD:
String word = st.sval;
System.out.println("Word found: " + word);
break;
case '+':
break;
case '-':
break;
case '/':
break;
case '*':
break;
case '<':
{
int t = st.nextToken();
switch(t)
{
case '=':
System.out.println("<=");
break;
case '<':
System.out.println("<<");
break;
default:
st.pushBack();
System.out.println("<");
break;
}
}
}
}
}
}
对于所提供的标记器类来说,这不是典型的场景。更像是一个完全成熟的解析器必须处理的事情。即使您需要手工构建这样的标记器,您也会发现学习由javacc或antlr等解析器生成器生成的代码是很有教育意义的。关注他们如何处理"向前看",这就是你在这里要问的。
除非这是一个不允许使用解析器生成器的家庭作业问题,否则使用解析器生成器将获得更好的结果。
看起来StreamTokenizer
有点偏基础。
我建议你在StreamTokenizer之上构建一个词法分析器。这个词法分析器所做的是为您提供通常意义上的实际令牌流。也就是说,<=
将作为单个令牌给出,而不是两个单独的令牌。
更好的是,bin StreamTokenizer并编写一个仅直接查看字符的词法分析器。对于解析高级语法,StreamTokenizer做得太少了。
nextToken()
将跳过空白,因此++
和+ +
将被识别为相同!
StreamTokenizer是处理此问题的非常基本的工具。
你可以创建自己的lookAhead函数来解决你的问题。
你读取一个'<',然后调用你的forward,看看是否有'='-采取相应行动
你可以使用堆栈来保存你之前的状态。
PS:更大的表达式会变得更复杂,如果你想要更多的功能,当然你应该深入研究lexers &解析器