学術的な意味では、正規表現はプログラミング言語として認められますか?
私の好奇心のための動機は、SOの質問尋ね、私はただ見「Xを行うとregexができますか?」そして、それらを使用する可能性のある解決策について一般的な意味で何が言えるのだろうかと思いました。
私は基本的に「正規表現チューリングは完了していますか?」
学術的な意味では、正規表現はプログラミング言語として認められますか?
私の好奇心のための動機は、SOの質問尋ね、私はただ見「Xを行うとregexができますか?」そして、それらを使用する可能性のある解決策について一般的な意味で何が言えるのだろうかと思いました。
私は基本的に「正規表現チューリングは完了していますか?」
回答:
正規表現は、形式言語理論で「正規言語」として知られる文字列およびその他のテキスト情報を解析するために使用される特定の形式の文法です。これらはプログラミング言語ではありません。これらは、コーディングの省略形であり、実装するのが非常に面倒であり、時々不可解な見た目の正規表現よりもさらに複雑です。
プログラミング言語は通常、チューリング完全な言語として定義されます。そのような言語は、計算可能な機能を処理できなければなりません。正規表現はこのカテゴリに該当しません。
正規表現のような言語が必要な場合は、Jを試してください。
討論の参加者がXとYの異なる定義を使用する場合、「is X a Y」タイプの質問に答えることは困難です。一部の定義では、答えは「はい」であり、一部の定義では、答えは「いいえ」である可能性があります。特に、答えが異なる定義が異なる技術的な詳細に依存する場合。また、このディスカッションにはいくつかの誤った情報が含まれているため、より長い回答をお待ちください。
「プログラミング言語」とはどういう意味ですか?
簡単な答えは、「プログラムの作成に使用される言語」です。もちろんですが、どのようなプログラムですか?何作成するために使用することができ、言語に関するいくつかのプログラムの種類を、しかし、プログラムのではない他の種類?極端な場合を説明する2つの具体例を次に示します。
1)Mと呼ばれる架空の言語は次のように機能します。プログラムに1つの文字「m」が含まれている場合、マインスイーパのゲームが作成されます。それ以外はすべて構文エラーです。
直感的には、これは「プログラミング言語」と言うことではありません。しかし、Mのマーケティング部門は、プログラムの作成に使用できるため、技術的に定義を満たしていると主張できます。確かに、コンパイラはいくつかの重要な部分をあなたのために行いますが、それはコンパイラがすることですよね?C言語のコンパイラは、いくつかの単純な単語を多数のプロセッサ命令に変換します。Mコンパイラーはさらに先へ進み、作業をさらに簡単にします。
2)有名なTurbo Pascalのオリジナルバージョンをインストールすると、多くの種類のプログラムを作成できます。ただし、必要なAPIが存在しないため、Webブラウザーで実行するゲームを作成することはできません。
それでは、Turbo Pascalをプログラミング言語にしているのに、Mにはないものは何ですか?簡単に言えば、MよりもPascalの方が多くのことができます。しかし、Webブラウザーで実行される掃海艇ゲームを作成するM.NETがあるとします。これで、PascalでできることとM.NETでできないことができましたが、M.NETでできることとPascalでできないこともあります。Pascalの利点を重要視し、M.NETの利点を無関係と考える必要があるのはなぜですか?
答えは、Pascalですべての種類のアルゴリズムを書くことができるが、MまたはM.NETでアルゴリズムを書くことはできないということです。確かに、Mはコマンド「m」をコンパイルし、Cはコマンド「strcmp」をコンパイルします。しかし、「strcmp」をより大きなコンテキストに置くことができます。たとえば、2つのファイルを行ごとに比較したり、1000個の文字列を読んでアルファベット順に並べ替えたり、... そして、プログラミング言語の本質をなすのは、アルゴリズムで特定のコマンドを使用するまさにその能力です。
アルゴリズムとは正確には何ですか、さらに重要なことは、「任意のアルゴリズム」とは何ですか コンピューターサイエンスでは、チューリング完全という言葉を使用します。アイデアは、それぞれがすべてをシミュレートできるコンピューター言語のセットがあるということです。これらの言語の1つがチューリングマシンです。Pascalがあり、Cがあり、Javaがあり、Pythonがあり、Lispがあり、Smalltalkがあり、XSLTさえあります。架空のMとM.NETはありません。これについては、適切なコンピューターサイエンスコースを提供しているどの大学でも詳しく学ぶことができますが、アイデアはチューリング完全言語で何でもできるということです。必要最小限のAPIを提供すれば、別のチューリング完全言語でできること。(PascalにWebブラウザーAPIを提供すると、Webブラウザーであらゆる種類のゲームを作成できます。MにWebブラウザーAPIを提供しても、Minesweeperを作成できるのはまだです。)プログラミング言語からすべてのAPIを削除すると、重要なものが残ります。
「正規表現」とはどういう意味ですか?
異なるプログラミング言語は、それらをわずかに異なる方法で実装します。しかし、元のアイデアは、正規表現がいわゆる正規言語を表現するというものでした。ここではプログラミング言語について話すのではなく、(疑似)人間の言語について話すことに注意してください。「ba」、「baba」、「bababa」などの単語だけで構成される言語を話すエキゾチックな部族を見つけたとします。この言語は、「1回以上繰り返される音節「ba」」として、または「(ba)+」として正規表現を使用して、口頭で説明できます。
正規表現は、「nothing」、「this letter」、「this、続いてthat」、「this or that」、「this、繰り返された1回以上」、「not this」を表現することになっています。-それが数学的な定義です。それ以外は、以前のコンポーネントから作成された便利なショートカットです。たとえば、「this、two or three times」は「this、then this、after(this or nothing)」と翻訳できますが、「baba」よりも「ba {2,3}」と書く方が便利です(ba)?」
実際には、「正規表現」の典型的な実装はこれ以上のものを実装しています。例えば、数学的定義、「ABA」、「aabaa」、「aaabaaa」の言語などに用い-続く「」Sの任意の数、「B」に続く、同じ A」の数を「s」は通常の言語ではありません。ただし、今日使用されている多くの「正規表現」は、「(a +)b \ 1」と書かれた「以前と同じもの」という追加の概念を使用して検出できます。この追加の概念を使用すると、素数の文字で構成される単語を検出するなど、いくつかのクールなことができます。それでも、アルゴリズムを実行することはできません...理由の説明のために、
それで、元のトピックに戻ります:正規表現(Chomsky階層の正規言語を記述する表現、または前者に加えて\ 1操作として定義される)はプログラミング言語(チューリング完全として定義される)ですか?答えはノーです。いいえ、あなたが実装することはできません任意のアルゴリズムを正規表現を使用して、および実装する能力任意のアルゴリズムは、コンピュータサイエンスを勉強し、人々は通常、プログラミング言語の本質として理解するものです。
もちろん、誰でも異なる定義を主張することで答えを変えることができます。最初に書いたように、ここでは技術的な詳細が重要です。あなたがそれらを間違えた場合、あなたは間違った答えを得る。
また、技術的な詳細に興味がない場合は、答えは次のようになります。プログラムを作成するために正規表現を使用できますか?いいえ。なぜプログラミング言語と呼ぶのですか?(ただし、このような回答がダウンロードされ、ここで削除されたため、この長いバージョンを作成しました。)
編集:また、誰でも「正規表現」の新しいバリアントを実装するライブラリを作成でき、いくつかの新しい機能が追加されています。ある時点で、システム全体がチューリング完全になるには、新しい機能で十分かもしれません。些細な例は、新しい構文を使用してチューリング完全言語を埋め込むことです。しかし、それはあまり明白ではありません。たぶんそれはすでに起こった。
.Netでは、Regexは、代替とルックアラウンドのさまざまな組み合わせを使用して、複数の形式の条件を処理できるだけでなく、独自のスタックを操作することもできます。
(?xm)
(?>
<(?<Tagname>table)[^>]*>
)
(?(Tagname)
(
</(?(?!\k'Tagname')(?<-Tagname>))*\k'Tagname'>(?<-Tagname>)
|
(?>
<(?<Tagname>[a-z][^\s>]*)[^>]*>
)
|
[^<]+
)+?
(?(Tagname)(?!))
)
これは、たとえば、HTMLテーブルを取得するために作成した小さなスニペットです。他の正規表現エンジンとは異なり、これはキャプチャコレクションのスタック(プッシュ、ピーク、ポップ)を制御し、ネストされたオブジェクトを処理できます。私はもっと複雑なものを持っていますが、それはかなり独自のものです。
この例では、プログラミング言語の基本的な要件をすべて満たしていると見なすことができます。変数、インラインメモリ、条件、入力および出力があり、複数の正規表現コンパイルエンジン(この場合は.Net)の1つを使用してコンパイルします。
(NEVER)への過剰使用squawkingへの対応パースHTML正規表現で、私は先に行って、私が投稿することができますことをあらかじめ入力された応答を掲載:解析HTML
他の例(単なるデモンストレーション)は次のとおりです。
Function Regex("<(td>)((?:[^<]*(?(?!</\1)<))*)</\1")
Group(0) = "<"
Group(1) = "td>"
Group(0) += Group(1)
Group(2) = LoopMethod()
Group(0) += Group(2)
Group(0) += "</" & Group(1)
Return Group()
End Function
Function LoopMethod()
retGroup = ""
Do
tmpGroup = Everything that is NOT an Opening HTML Delimeter
If the Text following tmpGroup Does NOT Equal "</" & Group(1) Then
tmpGroup += "<"
retGroup += tmpGroup
Else
Exit Do
End If
Loop
Return retGroup
End Function
繰り返しますが、HTMLオウムの場合:HTMLの解析
これは、ループと条件(アルゴリズム?)を実行する単純な正規表現を示しています。欠けている唯一のものは、実際の数学的計算です。これは、通常の「(。*?)」メソッドよりも効率的にTDセルをプルするだけの、より詳細な正規表現です。
しかし、Regexの愛好家であり、自称マスターであるとしても、Regexがプログラミング言語であることをだれにも言うことはしません。私自身に対する私自身の主張は、それはスタンドアロンではなく、別のプログラミング言語エンジンによってサポートされながら、独自のエンジンで実行する必要があるということです。
以前の回答で説明したように、正規表現の検索/置換はチューリング完全なプログラミング言語ではありませんが、正規表現で置換する繰り返しアクションを使用できる場合、はい、正規表現を使用してチューリングマシンをエンコードできます:
その結果、同じ検索を使用して計算可能な関数を計算し、javascriptの正規表現を何度も置き換えることができます。
チューリング完全性を証明するには、正規表現の検索/置換でチューリングマシンをエンコードするだけで十分です。エディターの状態は次のとおりであると仮定します。
0000#12345:01-5:0#0000000
リーダーが付いたシンボルのテープとして読むことができます:
[left symbols]#[set of states]:[set of symbols]-[current state]:[current symbol]#[right symbols]
状態5で0を読み取り、1を書き込み、状態を3に変更して左に移動するルールの場合、次の表記を使用して抽象化します。
5:0 => 1, 3:[left]
前の表記法を検索正規表現にエンコードします。
(\d)#(1)(2)(3)(4)(5):(0)(1)-5:0#
およびその置換式(javascriptのような)
#12345:01-$4:$1#$8
さて、今では多くのルールをエンコードする方法は?正規表現の検索にはor
演算子との連結を使用し|
、結果を置換で組み合わせ、グループ番号をオフセットで数値化します。たとえば、4つのルールのセットを考えてみましょう。
5:0 => 1, 3:left
3:0 => 1, 5:right
5:1 => 1, 5:right
3:1 => 1: 3:stop
検索でそれらをエンコードし、式を置き換えます。
Search:
(\d)#(1)(2)(3)(4)(5):(0)(1)-5:0#|#(1)(2)(3)(4)(5):(0)(1)-3:0#(\d)|#(1)(2)(3)(4)(5):(0)(1)-5:1#(\d)|#(1)(2)(3)(4)(5):(0)(1)-3:1#
Replace by:
$15$23#12345:01-$4$13$21$27:$1$16$24$31#$8
お気に入りのJavaScriptエンジンで試してみてください。
function turingstep(s) {
return s.replace(/(\d)#(1)(2)(3)(4)(5):(0)(1)-5:0#|#(1)(2)(3)(4)(5):(0)(1)-3:0#(\d)|#(1)(2)(3)(4)(5):(0)(1)-5:1#(\d)|#(1)(2)(3)(4)(5):(0)(1)-3:1#/g,"$15$23#12345:01-$4$13$21$27:$1$16$24$31#$8");
}
var tape = "0000#12345:01-5:0#0000000"
for(var i = 0; i < 6; i++) {
console.log(tape)
tape = turingstep(tape)
}