如何更改正则表达式以正确匹配浮点文字?

时间:2013-01-01 00:17:46

标签: java regex parsing

我正在尝试为java表达式创建解析器,但由于某种原因,我无法匹配浮点值。我使用的是从{/ p>获得的java.util.Matcher

Matcher token = Pattern.compile(
        "(\\w[\\w\\d]*+)|" + //identifiers as group 1
        "((?:(?>[1-9][0-9]*+\\.?[0-9]*+)|(?>\\.[0-9]++))(?:[Ee][+-]?[0-9]++)?)|" + //literal numbers
        "([^\\w\\d\\s]*+)" //operators as group 3
    ).matcher();

这是为了匹配标识符,浮点值或运算符(我仍然需要优化匹配的那部分,但稍后会优化匹配的那部分)。但是,我在那个

中遇到了问题

下面是使用该表达式的代码,该代码用于获取所有标识符,数字和运算符,注册vars中的所有数字,并放置所有标识符,每个数字的相应值,以及tokens中的所有运算符的顺序与原始字符串中的顺序相同。

但是,这样做不成功,因为对于像foo 34.78e5 bar -2.7这样的输入字符串,结果列表是'[34,A ,, bar ,, - ,2,B,]',其中A = - 78000.0和B = -0.7。它应该返回'[foo,A,bar,B]`,A = 3478000,B = -2.7。我相信它可能只是因为未能将数字的两个部分都包含在正则表达式的匹配中,但情况可能并非如此。

我已经尝试从正则表达式中移除原子分组和后果,但这并没有改变任何东西。

LinkedList<String> tokens = new LinkedList<String>();
HashMap<String, Double> vars = new HashMap<String, Double>();
VariableNamer varNamer = new VariableNamer();

for(Matcher token = Pattern.compile(
                        "(\\w[\\w\\d]*+)|" + //variable names as group 1
                        "((?:(?:[1-9][0-9]*+\\.?[0-9]*+)|(?:\\.[0-9]++))(?:[Ee][+-]?[0-9]++)?)|" +
                                             //literal numbers as group 2
                        "([^\\w\\d\\s]*+)"   //operators as group 3
                ).matcher(expression); token.find();){

        if(token.group(2) != null) { //if its a literal number, register it in vars and substitute a string for it
            String name = varNamer.next();

            if (
                    tokens.size()>0 &&
                    tokens.get(tokens.size()-1).matches("[+-]") &&
                    tokens.size()>1?tokens.get(tokens.size()-2).matches("[^\\w\\d\\s]"):true
                    )

                vars.put(name, tokens.pop().equals("+")?Double.parseDouble(token.group()):-Double.parseDouble(token.group()));
            else
                vars.put(name, Double.parseDouble((token.group())));

            tokens.addLast(name);
        } else {
            tokens.addLast(token.group());
        }
    }

这里是VariableNamer

import java.util.Iterator;

public class VariableNamer implements Iterator<String>{

    StringBuffer next = new StringBuffer("A");

    @Override
    public boolean hasNext() {
        return true;
    }

    @Override
    public String next() {
        try{
            return next.toString();
        }finally{
            next.setCharAt(next.length()-1, (char) (next.charAt(next.length()-1) + 1));

            for(int idx = next.length()-1; next.charAt(idx) + 1 > 'Z' && idx > 0; idx--){
                next.setCharAt(idx, 'A');
                next.setCharAt(idx - 1, (char) (next.charAt(idx - 1) + 1));
            }

            if (next.charAt(0) > 'Z'){
                next.setCharAt(0, 'A');
                next.insert(0, 'A');
            }
        }
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }

}

1 个答案:

答案 0 :(得分:1)

根据表达式迷你语言的详细信息,它要么接近使用正则表达式的限制,要么超出限制。即使你在“解析”中取得成功,你仍然会将“组”子串映射成一个有意义的表达式。

我的建议是采取完全不同的方法。查找/使用现有的表达式库,或使用ANTLR或Javacc等解析器生成器实现表达式解析。