Recursive Regular Expressions
catonmat.net
catonmat.net
my $regex = qr/0(??{$regex})*1/; # (1)
rather be my $regex = qr/0(??{$regex})?1/; # (2)
? Otherwise it matches many other strings (e.g. 001011) in addition to 0^n 1^n; you actually want it to match zero or one times instead of zero or more. Unfortunately the explaination why (1) works is a bit faulty.I didn't know recursive regexes before, thanks for the article.
I was thinking about ? but wrote it down as * without realizing that * may insert several $regex$regex... thus breaking the regex.
You're right that I was surprised because I hadn't heard of recursive regular expressions in Perl before.
Update: I just remembered that extended regular expressions can even recognize recursive languages. Here is a regex that decides if the number is a prime:
perl -lne '(1x$_) !~ /^1?$|^(11+?)\1+$/ && print "$_ is prime"'
This goes beyond context-free, therefore I couldn't just say "context-free" carelessly in the article.I am completely unfamiliar with Perl and its regular expressions, but from your article and this comment I get the impression that they are Turing-complete, which would mean they're capable of describing any formal language as well as doing any "doable" computation. Is that correct?
I am not exactly sure if they are Turing-complete. The code in (??{code}) can be anything, so I guess, they are.
There's an odd misconception in the computing world that writing compilers is hard. This view is fueled by the fact that people don't write compilers very often. People used to think writing CGI code was hard. Well, it is hard, if you do it in C without any tools. I don't know anyone who writes CGI code in C anymore. If we wrote compilers as often as we write shopping carts, or web forums, or wikis, there would be just as many tools available to make the job easy. (And just like web tools, only 10% of them would be worth using. That's evolution in action.)
—Allison Randal, "Parrot Compiler Tools"
Source: http://www.lohutok.net/
We can make some fuzzy guesses whether or not the program terminates or not in other state/symbol combinations.
http://en.wikipedia.org/wiki/Busy_beaver
If we ever did write said program that could determine whether any /arbitrary/ program is infinite, then we have solved the halting problem. And that would be quite something.
Allison's point is instead that the combination of the perception that compilers are difficult and the relative paucity of tools to make writing compilers easier is a vicious cycle which writing better tools might fix.
Lua's LPeg lets you create simple recursive grammars to solve problems that are often hard with regular expressions (e.g., matching balanced parentheses). It's the one library from Lua I find myself seriously missing when programming in other languages.
Perl5 backported "named captures" from perl6:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw(switch say);
#use locale;
#use re 'debug';
my $expression = qr{
(?(DEFINE)
(?<expr> (?&space)* (?&term) (?&space)* (?&opterm)? (?&space)* ; (?&space)* )
(?<term> (?&identifier)
| (?&number)
| (?&string)
)
(?<opterm> (?&space)* (?&operator) (?&space)* (?&term) (?&space)* (?&opterm)? (?&space)* )
(?<operator> [=+*/-] )
(?<identifier> [A-Za-z_][A-Za-z0-9_]+ )
(?<number> [0-9]+ )
(?<string> (?"e) ( (?&char) | (?&bsquote) )*? (?"e) )
(?<quote> \" )
(?<char> [^\\\"] )
(?<bsquote> \\. )
(?<space> [ \t] )
)
(?&expr)
}x;
while (<>) {
chomp;
if ( /^ $expression $/x ) {
say "Correct expression: $_";
}else {
say "Incorrect expression: $_";
}
}