在Java中标记化时如何处理操作符(StreamTokenizer)



我正在用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 &解析器

相关内容

  • 没有找到相关文章

最新更新