在Java(StreamTokenizer)中进行分词时如何处理运算符

|| 我正在用Java写一个令牌处理程序,该令牌处理程序必须处理运算符,并且令牌之间的空格字符不是必需的。 我需要将\“ <= \”之类的东西识别为令牌,同时还要识别\“ <\”和\“ = \”。 现在我有:
if (token == \'<\')
        if (nextToken == \'=\')
            this.tokenList.add(27); // <=
        else
            // add 2 tokens separately
无论如何,StreamTokenizer可以自己执行此操作吗?我已经阅读了API,但没有任何显示。 我可以指定可以算作一个的令牌组合吗?理想情况下,getNextToken可以一次删除两个令牌。 谢谢!
已邀请:
“ѭ1”为您提供的是基本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)生成的代码很有帮助。着重于他们如何处理“前瞻”,这就是您在这里要问的问题。 除非这是一个不允许您使用解析器生成器的作业问题,否则使用解析器生成器将获得更好的结果。
看起来ѭ1在基本方面有点。 我建议您在StreamTokenizer的基础上构建一个词法分析器。该词法分析器将执行的工作是为您提供通常意义上的实际标记流。也就是说,“ 6”将作为单个令牌而不是两个单独的令牌给出。 更好的是,对StreamTokenizer进行bin,并编写一个直接查看字符的词法分析器。 StreamTokenizer所做的工作很少,无法解析高级语法。
nextToken()
将跳过空白,因此
++
+ +
将被识别为相同!
StreamTokenizer是处理此问题的非常基本的工具。 您可以创建自己的lookAhead函数来解决您的目的。 您读了一个\'<\',然后进行超前查询,如果没有,则调用\'= \' - 按指示行动 您可以使用堆栈来保存以前的状态。 PS:如果使用更大的表达式,这将变得更加复杂,并且如果您确实想要更多的功能,则应该深入研究词法分析器和解析器。

要回复问题请先登录注册