Java 表达式标记器

Java 表达式标记器,java,Java,我正在尝试创建一个读取表达式的标记器。当它得到标记时,我打印类型和词素,这是一个运算符的数字。它目前单独打印每个字符,但我需要它一起打印两位数和十进制数字。这是我的密码 public class Tokenizer { String type; String lexeme; /** * @param args the command line arguments */ void getToken(String expression, int i) { if (exp

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

    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");
    }
  }
}
样本输出-预期
此语句在每次执行时覆盖词素

 lexeme = Character.toString(expression.charAt(i));
应该是

lexeme += Character.toString(expression.charAt(i));
i、 识别一个数字后,将其添加到词素中

除此之外,您的
getToken
方法是不正确的,然后通过将
i
传递给它,您假定一个词素只有一个字符长,实际上它可以是1个或多个,例如
66
2.5
。因此,您需要重新设计
标记器
类。您应该使用表达式初始化标记器对象,然后让它具有一个无参数方法
getNextToken()
,该方法根据需要进行多次迭代以识别标记,然后返回它。它还应该有一个方法来检查是否还有任何输入,比如
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");
        }
    }
}

此语句在每次执行时覆盖词素

 lexeme = Character.toString(expression.charAt(i));
应该是

lexeme += Character.toString(expression.charAt(i));
i、 识别一个数字后,将其添加到词素中

除此之外,您的
getToken
方法是不正确的,然后通过将
i
传递给它,您假定一个词素只有一个字符长,实际上它可以是1个或多个,例如
66
2.5
。因此,您需要重新设计
标记器
类。您应该使用表达式初始化标记器对象,然后让它具有一个无参数方法
getNextToken()
,该方法根据需要进行多次迭代以识别标记,然后返回它。它还应该有一个方法来检查是否还有任何输入,比如
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");
        }
    }
}

你可能需要重新设计你的课程,整个过程。您必须读取未知数量的字符,并将当前索引存储在对象中的某个位置问题标题不是问题…您试图实现什么?我有个主意,但我需要你解释。我要做的是让
getToken()
尝试在
表达式的开头匹配1个或多个字符,并返回“已使用”的字符数。因此,不要使用一堆正则表达式,而是尝试将它们全部匹配,然后选择最长的匹配,或者第一个匹配,或者其他任何匹配。(通常是最长比赛中的第一场获胜。)在这一点上,你基本上是在做
lex
所做的事情,在这个基本思想上进行了几十年的模块化扩展。你可能需要重新设计你的类,整个事情。您必须读取未知数量的字符,并将当前索引存储在对象中的某个位置问题标题不是问题…您试图实现什么?我有个主意,但我需要你解释。我要做的是让
getToken()
尝试在
表达式的开头匹配1个或多个字符,并返回“已使用”的字符数。因此,不要使用一堆正则表达式,而是尝试将它们全部匹配,然后选择最长的匹配,或者第一个匹配,或者其他任何匹配。(通常是最长比赛中的第一场获胜。)在这一点上,你基本上是在做
lex
所做的事情,在这个基本想法上进行了几十年的扩展。我认为这对我没有帮助。这应该很简单。赋值是使用getToken()方法生成一个标记器类,仅此而已。@Daniel实际上这很简单,它只是纠正了您自己代码中的设计缺陷并对其进行了一点改进,但“simple”是相对的:/。。。无论如何,关键是
getToken()
——正如它的名字所说——必须识别一个洞标记,并且一个标记必须有一个或多个字符。为此,您必须在该方法中迭代1次或更多次,但目前没有。@Daniel我已经添加了
getNextToken()
方法的基本实现(如果需要,您可以将其重命名为
getToken()
),感谢您的努力。在把代码通读了几遍之后,我对它有了理解。你帮了我很大的忙,我的朋友!我认为这对我没什么帮助。这应该很简单。赋值是使用getToken()方法生成一个标记器类,仅此而已。@Daniel实际上这很简单,它只是纠正了您自己代码中的设计缺陷并对其进行了一点改进,但“simple”是相对的:/。。。无论如何,关键是
getToken()
——正如它的名字所说——必须识别一个洞标记,并且一个标记必须有一个或多个字符。为此,您必须在该方法中迭代1次或更多次,但目前没有。@Daniel我已经添加了
getNextToken()
方法的基本实现(如果需要,您可以将其重命名为
getToken()
),感谢您的努力。在把代码通读了几遍之后,我对它有了理解。你帮了我很大的忙,我的朋友!