0

Java 式のパーサーを作成しようとしていますが、何らかの理由で浮動小数点値を一致させることができません。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であるため、これは成功しません。A=3478000 と B=-2.7 で '[foo, A, bar, B]` を返すはずです。数字の両方の部分を正規表現の一致として含めることができていないだけかもしれませんが、そうではないかもしれません。

正規表現からアトミック グループと所有格を削除しようとしましたが、何も変わりませんでした。

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();
    }

}
4

1 に答える 1

1

式のミニ言語の詳細に応じて、正規表現を使用して可能なことの限界に近づいているか、それを超えています。また、「解析」に成功したとしても、「グループ」部分文字列を意味のある式にマッピングするという問題が残ります。

私のアドバイスは、まったく異なるアプローチを取ることです。既存の式ライブラリを見つけて使用するか、ANTLR や Javacc などのパーサー ジェネレーターを使用して式の解析を実装します。

于 2013-01-01T00:41:50.100 に答える