Javaで正規表現を使用して、オペランドおよび+-*/$
演算子[例:]としてのアルファベットで構成される中置記法を検証することを考えています。A+B-(C/D)$(E+F)
より良い方法はありますか?使用できる正規表現パターンはありますか?
3 に答える
私は の言語構文に精通していませんinfix
が、文字列内のすべての文字が有効であることを単純に検証する最初のパス検証チェックを確実に行うことができます (つまり、許容される文字 = 、A-Z
、+
、-
、*
、/
および) 。以下は、有効な文字をチェックする Java プログラムであり、括弧のバランスが取れていない (入れ子になっている可能性がある) かどうかをチェックする関数も含まれています。$
(
)
import java.util.regex.*;
public class TEST {
public static void main(String[] args) {
String s = "A+B-(C/D)$(E+F)";
Pattern regex = Pattern.compile(
"# Verify that a string contains only specified characters.\n" +
"^ # Anchor to start of string\n" +
"[A-Z+\\-*/$()]+ # Match one or more valid characters\n" +
"$ # Anchor to end of string\n",
Pattern.COMMENTS);
Matcher m = regex.matcher(s);
if (m.find()) {
System.out.print("OK: String has only valid characters.\n");
} else {
System.out.print("ERROR: String has invalid characters.\n");
}
// Verify the string contains only balanced parentheses.
if (checkParens(s)) {
System.out.print("OK: String has no unbalanced parentheses.\n");
} else {
System.out.print("ERROR: String has unbalanced parentheses.\n");
}
}
// Function checks is string contains any unbalanced parentheses.
public static Boolean checkParens(String s) {
Pattern regex = Pattern.compile("\\(([^()]*)\\)");
Matcher m = regex.matcher(s);
// Loop removes matching nested parentheses from inside out.
while (m.find()) {
s = m.replaceFirst(m.group(1));
m.reset(s);
}
regex = Pattern.compile("[()]");
m = regex.matcher(s);
// Check if there are any erroneous parentheses left over.
if (m.find()) {
return false; // String has unbalanced parens.
}
return true; // String has balanced parens.
}
}
これは文法を検証しませんが、明らかに悪い文字列を除外するための最初のテストとして役立つ場合があります。
やり過ぎかもしれませんが、ANTLR (http://www.antlr.org/) などの本格的なパーサー ジェネレーターの使用を検討することもできます。ANTLR を使用すると、自動的に Java コードを生成するルールを作成できます。入力に有効な文字しかないと仮定すると、これは構文解析の問題です。それ以外の場合は、最初に字句解析で文字ストリームを検証する必要があります。
構文解析の場合、次のようなルールがある場合があります。
PLUS : '+' ;
etc...
expression:
term ( ( PLUS | MINUS | MULTIPLY | DIVIDE )^ term )*
;
term:
constant
| OPENPAREN! expression CLOSEPAREN!
;
定数は整数/実数です。ANTLR で生成されたパーサー コードが入力をパーサー ルールと一致させることができない場合、例外がスローされるため、コードが有効かどうかを判断できます。
おそらく再帰的 PCRE でそれを行うことができます..しかし、これは PITA である可能性があります。
検証するだけなので、非常に簡単に実行できます。スタックを使用し、すべての要素を 1 つずつプッシュして、有効な式を削除します。
たとえば、いくつかのルールを定義します。
- 演算子は、スタックの一番上にアルファベットがある場合にのみ許可されます
- アルファベットまたは括弧は、スタックの一番上に演算子がある場合にのみ許可されます
- スタックが空の場合、すべてが許可されます
それから:
- 閉じ括弧に遭遇した場合は、開き括弧までのすべてを削除してください。
- アルファベットに遭遇した場合は、式を削除してください
式を削除するたびに、ダミーのアルファベットを追加します。前の手順を繰り返します。結果がアルファベットの場合、式は有効です。
またはそのようなもの..