java - 表达式分词器

标签 java

我正在尝试创建一个读取表达式的分词器。当它获得 token 时,我打印类型和词素,它可以是运算符的数字。它目前单独打印每个字符,但我需要它一起打印两位数和十进制数字。这是我的代码。

    public class Tokenizer {
String type;
String lexeme;
/**
 * @param args the command line arguments
 */
void getToken(String expression, int i) {

        if (expression.charAt(i) == '+')
        {
            type = "operator";
            lexeme = "+";       
        }
        else if (expression.charAt(i) == '-')
        {
            type = "operator";
            lexeme = "-";
        }
        else if (expression.charAt(i) == '*')
        {
            type = "operator";
            lexeme = "*";
        }
        else if (expression.charAt(i) == '/')
        {
            type = "operator";
            lexeme = "/";
        }
        else if (expression.charAt(i) == ' ')
        {
            ; //empty statement. Does nothing if the character is white space
        }
        else 
        {
            type = "number";
            lexeme = Character.toString(expression.charAt(i));
        }
}
public static void main(String[] args) {
    // TODO code application logic here
    String expression = "3+66*2.5";
    Tokenizer tokenizer = new Tokenizer();
    for (int i = 0; i < expression.length(); i++)
    {
        tokenizer.getToken(expression, i);
        System.out.print("Type: " + tokenizer.type + "\t" + "Lexeme: " + tokenizer.lexeme + "\n");
    }
  }
}

示例输出 - 实际

Type: number    Lexeme: 3
Type: operator  Lexeme: +
Type: number    Lexeme: 6
Type: number    Lexeme: 6
Type: operator  Lexeme: *
Type: number    Lexeme: 2
Type: number    Lexeme: .
Type: number    Lexeme: 5

示例输出 - 预期

Type: number    Lexeme: 3
Type: operator  Lexeme: +
Type: number    Lexeme: 66
Type: operator  Lexeme: *
Type: number    Lexeme: 2.5

最佳答案

此语句会覆盖每次执行时的词法

 lexeme = Character.toString(expression.charAt(i));

应该是

lexeme += Character.toString(expression.charAt(i));

即识别出单个数字后,将其添加到词位中。

除此之外,您的 getToken 方法不正确,那么通过将 i 传递给它,您会假设词素只有一个字符长,实际上它可以是 1或更多,例如 662.5。所以你需要重新设计你的 Tokenizer 类。您应该使用表达式初始化 Tokenizer 对象,然后让它有一个无参数方法 getNextToken(),该方法根据需要进行多次迭代来识别 token ,然后返回它。它还应该有一个方法来检查是否还有任何输入,例如 hasMoreTokens()

这是您可以构建的东西

public class Tokenizer {
    int pos;
    char[] expression;

    Tokenizer(String expression) {
        this.expression = expression.toCharArray();
        this.pos = 0;
    }

    enum Type { OPERATOR, NUMBER, UNKNOWN }

    class Lexeme {
        String type, token;
        Lexeme(String type, String token) {
            this.type = type;
            this.token = token;
        }
    }

    Lexeme getNextToken() {
        StringBuilder token = new StringBuilder();
        boolean endOfToken = false;
        Type type = Type.UNKNOWN;
        while (!endOfToken && hasMoreTokens()) {
            while(expression[pos] == ' ' && hasMoreTokens())
                pos++;
            switch (expression[pos]) {
                case '+':
                case '-':
                case '*':
                case '/':
                    if(type != Type.NUMBER) {
                        type = Type.OPERATOR;
                        token.append(expression[pos]);
                        pos++;
                    }
                    endOfToken = true;
                    break;
                case ' ':
                    endOfToken = true;
                    pos++;
                    break;
                default:
                    if(Character.isDigit(expression[pos]) || expression[pos] == '.') {
                        token.append(expression[pos]);
                        type = Type.NUMBER;
                    } else {
                        System.out.println("Systax error at position: " + pos);
                    }
                    pos++;
                    break;
            }
        }
        return new Lexeme(type.name().toLowerCase(), token.toString());
    }

    boolean hasMoreTokens() {
        return pos < expression.length;
    }

    public static void main(String[] args) {
        String expression = "3+66*2.5";
        Tokenizer tokenizer = new Tokenizer(expression);
        while (tokenizer.hasMoreTokens()) {
            Lexeme nextToken = tokenizer.getNextToken();
            System.out.print("Type: " + nextToken.type + "\tLexeme: " + nextToken.token + "\n");
        }
    }
}

输出

Type: number    Lexeme: 3
Type: operator  Lexeme: +
Type: number    Lexeme: 66
Type: operator  Lexeme: *
Type: number    Lexeme: 2.5

关于java - 表达式分词器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18687769/

相关文章:

java - 模板和泛型。为什么我可以在 C++ 中执行以下操作,但不能在 Java 中执行?我该如何克服这个问题?

java - 使用 Java 通过 http 批量下载图像的好方法

java - 使用鼠标编辑形状位置

java - Android xml和Java : Get text from Edit Text,找不到符号错误

java - 在 Karaf 上设置 4096MB 以上的堆内存

java - 在 Spring Boot 中测试服务

java - 从 Google 日历获取事件时出现无效日期/时间异常

Java - 帮助我理解从子类访问 protected 成员(再次)

java - Glpk java 崩溃

Java application.properties 和 Kubernetes 环境变量。如何处理列表?