我正在用Java编写一个必须处理运算符的标记化器,并且没有必要在标记之间使用空格。
我需要识别像“< =”这样的标记,同时还要识别“<”和“=”。
现在我有:
if (token == '<')
if (nextToken == '=')
this.tokenList.add(27); // <=
else
// add 2 tokens separately
StreamTokenizer有没有自己做到这一点?我已阅读API,但我没有看到任何内容。
我可以指定可以算作一个令牌的组合吗?理想情况下,getNextToken会立即删除两个令牌。
谢谢!
答案 0 :(得分:3)
StreamTokenizer
为您提供的是基本Lexer的功能。您必须使用它们来制作高端版本。
您必须非常明智地使用nextToken()
和pushBack()
。例如,下面我正在处理<
,<<
和<=
。如果您看到一个运算符<
,那么请在流中向前查找线索,如果找不到以下<
或=
,则将前瞻标记推回到流中
<强>&GT;&GT;示例代码
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;
}
}
}
}
}
}
希望这会有所帮助。
答案 1 :(得分:2)
这不是所提供的tokenizer类的典型场景。更像是一个完全成熟的解析器必须处理的东西。即使您需要手动构建这样的标记化器,您也可能会发现研究由解析器生成器(如javacc或antlr)生成的代码具有教育意义。关注他们如何处理“前瞻”,这就是你在这里所要求的。
除非这是一个不允许使用解析器生成器的作业问题,否则使用解析器生成器会得到更好的结果。
答案 2 :(得分:0)
看起来StreamTokenizer
有点基本了。
我建议你在StreamTokenizer之上构建一个词法分析器。这个词法分析器会做的是给你一个通常意义上的实际标记流。也就是说,<=
将作为单个令牌提供,而不是两个单独的令牌。
更好的是,bin StreamTokenizer并编写一个只直接查看字符的词法分析器。 StreamTokenizer对于解析高级语法几乎没有用。
答案 3 :(得分:0)
nextToken()
会跳过空格,因此++
和+ +
会被识别为相同的内容!
答案 4 :(得分:0)
StreamTokenizer是处理此问题的非常基本的工具。
您可以创建自己的lookAhead功能来解决您的目的。
你读了'&lt;'然后打电话给你的前瞻,如果有'=' - 据此采取行动
您可以使用堆栈来保存以前的状态。
PS:对于更大的表达式,这会变得更加复杂。如果你想要更多的功能肯定你应该深入研究词法分析器&amp;解析器