4

私は Java で正規表現を使用する方法を学びたいと思っており、次のタスクを見つけました: BNF 形式のこれらの基準に基づいて、指定された入力文字列が有効な算術用語であるかどうかをチェックするクラスを作成します。

term = [Vz]summand|[Vz]summand addOp term
summand = factor | factor mulOp summand
factor = number | '('term')'
number = digit | digit number
digit = '0'|'1'|...|'9'
vz = '+'|'-'
addOp = '+'|'-'
mulOp = '*'|'/'

これらのルールを使用して、さまざまなタイプに似たいくつかのパターンを作成しました。

static Pattern vz = Pattern.compile("[+-]");
static Pattern addOp = Pattern.compile("[+-]");
static Pattern multOp = Pattern.compile("[*/]");
static Pattern digit= Pattern.compile("[0-9]");
static Pattern number = Pattern.compile(digit.pattern()+"+");
static Pattern factor = Pattern.compile(number.pattern()+"|("+term.pattern()+")");
static Pattern summand = Pattern.compile(factor.pattern()+"|"+factor.pattern()+ multOp.pattern()+"\n");
static Pattern term = Pattern.compile(vz.pattern()+"?"+summand.pattern()+"|"
        +vz.pattern()+"?"+summand.pattern()+addOp.pattern()+"\n");

そして、あなたはすでに私の問題を見ています: 私は factor の定義で項を最初に定義せずに参照しています. 残念ながら、私はそれを切り替えることはできません。だから私の質問は:

そのような方法でパターンを参照する可能性はありますか? または、パターンを参照して後で定義する他のものはありますか?

4

1 に答える 1

4

問題は、BNF が文脈自由文法 (正規表現で記述される言語よりも複雑な言語を記述する) を定義していることです。BNF ルールを正規表現パターンとしてすぐに使用するのではなく、別のアプローチを考え出す必要があります。

特に、括弧の正しい入れ子は規則的ではありません。一部の正規表現エンジンは、これらのマッチングを可能にする (非正規の) 機能をサポートしていますが、多くの場合、正規表現は非常に長くなり、維持できなくなります。Java にこれらの機能があるかどうかは、現時点ではわかりません (たとえば、PCRE と .NET にはあります)。

目の前のタスクを解決したい場合は、解析を手動で作成する必要があります。正規表現を学習したい場合は、別の言語で学習するか、別のタスクを探す必要があります。ただし、正規表現のスキルを向上させるための優れた情報源は次のとおりです。

Vz楽しみのために (また、エンジンが必要な機能をサポートしている場合でも、正規表現がこれに適したツールではない理由を示すために)、上記の BNF に対応する正規表現を次に示します (ルールを除いて、一部の場合)。私はそれを動作させることができなかった奇妙な理由):

^(((\d+|[(](?1)[)])|(?3)[*\/](?2))|(?2)[+-](?1))$

(?n)再帰的にnthサブパターン (括弧を左から右に開くことによってカウントされます)との一致を試みます。

PHP では動作しませんが、PCRE の実装には、再帰を使用する際のバックトラッキングの問題があると思います。オンラインの PCRE テスターは、一部の入力例を正しく処理しているように見えました。xここでは、いくつかの注釈を付けたフリースペース モード ( ) です。

^
(                # term (?1)
  (              # summand (?2)
    (            # factor (?3)
      \d+        # number
    |
      [(](?1)[)] # (term)
    )            # end of factor
  |
    (?3)[*/](?2) # factor mulOp summand
  )              # end of summand
|
  (?2)[+-](?1)   # summand addOp term
)                # end of term
$
于 2012-12-09T22:06:06.140 に答える