Das Problem dabei ist, dass Sprachen verschachtelte Klammern (erfordert oder in der Tat etwas verschachtelt, IOW alles, was Rekursion) enthält, Regelmäßig sind sie zumindest kontextfrei. Dies bedeutet, dass sie nicht mit einer regulären Grammatik beschrieben werden können. Reguläre Ausdrücke sind eine kompakte Notation für reguläre Grammatiken. Ergo, verschachtelte Klammern können nicht durch reguläre Ausdrücke beschrieben werden.
Allerdings sprechen wir hier nicht über reguläre Ausdrücke, wir sprechen über Regexp
s. Während ihre Semantik und Syntax (sehr) lose auf regulären Ausdrücken basieren, sind sie sehr unterschiedlich und besonders viel mächtiger. Abhängig von dem speziellen Geschmack von , den Sie verwenden, können oder können sie nicht in der Lage sein, Rekursion auszudrücken und somit verschachtelte Klammern zu parsen. Perl Regex
, zum Beispiel kann verschachtelte Klammern analysieren.Ich bin mir nicht sicher, ob Rubys Regexp
es kann, aber das ist mir egal, weil die Art und Weise, wie Regexp
mächtiger als reguläre Ausdrücke sind, im Allgemeinen dadurch erreicht wird, dass immer mehr Syntax auf ihnen verschraubt wird.
Dies verwandelt reguläre Ausdrücke, die einfach zu sein sind, in unverständliche Monster. (Wenn Sie auf einen Blick erkennen können, was der Perl Regex
von @Anon tut, dann gehen Sie dafür. Aber ich kann nicht und daher bevorzuge ich es nicht zu verwenden.)
Ich bevorzuge einen leistungsfähigeren Parser, eher als ein Komplex Regexp
.
In diesem Fall haben Sie eine kontextfreie Sprache, daher können Sie einen sehr einfachen rekursiven Sink-Parser verwenden. Sie können Ihren rekursiven Descent-Parser weiter vereinfachen, indem Sie die Unterabschnitte regulär mit einem regulären Ausdruck behandeln. Schließlich, wenn Sie die Rekursion im Rekursiver Abstieg mit Iteration + Mutation ersetzen und geschickten Einsatz von Ruby boolean Semantik machen, wird der gesamte Parser grundsätzlich kondensiert bis zu dieser einzigen Zeile:
while str.gsub!(/\([^()]*?\)/, ''); end
Was ich glaube nicht, ist schade.
Hier ist die ganze Sache mit einiger zusätzlichen Entfernung von doppelten Leerzeichen und (natürlich) eine Testsuite:
require 'test/unit'
class TestParenthesesRemoval < Test::Unit::TestCase
def test_that_it_removes_even_deeply_nested_parentheses
str = 'This is (was?) some ((heavily) parenthesized (but not overly so
(I hope))) text with (superflous) parentheses:)(.'
res = 'This is some text with parentheses:)(.'
while str.gsub!(/\([^()]*?\)/, ''); end
str.squeeze!(' ')
assert_equal res, str
end
end
Was, wenn es eine ungleiche Anzahl von Öffnungs- und Schließ Tags wie in '(foo) bar) 'oder wenn es keine Paare wie in' foo gibt) (bar'? – Gumbo
Ich muss diesen scenerio nicht berücksichtigen. – TenJack