#!/usr/bin/perl # http://perlmonks.org/?node_id=1189605 use strict; use warnings; $| = 1; sub err { die "ERROR: ", s/\G/<@_>/r, "\n" } sub crossmap { my ($left, $right) = @_; [ map { my $prefix = $_ ; map $prefix.$_, @$right } @$left ]; } sub expr { my $answer = [ '' ]; print("\ndebug ", s/\G/<>/r, " end " ), $answer = /\G\|/gc ? [ @$answer, @{ expr() } ] : /\G\d+/gc ? crossmap $answer, [ $& ] : /\G\[\d+\]/gc ? crossmap $answer, [ $& =~ /\d/g ] : /\G\(/gc ? ( crossmap($answer, expr()), /\G\)/gc || err "missing ')'")[0] : return $answer while 1; } while() { chomp; print "$_ => "; my $answer = expr(); /\G\z/gc or err "incomplete parse"; local $" = ','; print "@$answer\n"; } __DATA__ (65|70) (3[678]|4[1678]) 5[45] (6[4569]|7[01]) #### (65|70) => debug <>(65|70) end debug (<>65|70) end debug (65<>|70) end debug (65|<>70) end debug (65|70<>) end debug (65|70<>) end debug (65|70)<> end 65,70 (3[678]|4[1678]) => debug <>(3[678]|4[1678]) end debug (<>3[678]|4[1678]) end debug (3<>[678]|4[1678]) end debug (3[678]<>|4[1678]) end debug (3[678]|<>4[1678]) end debug (3[678]|4<>[1678]) end debug (3[678]|4[1678]<>) end debug (3[678]|4[1678]<>) end debug (3[678]|4[1678])<> end 36,37,38,41,46,47,48 5[45] => debug <>5[45] end debug 5<>[45] end debug 5[45]<> end 54,55 (6[4569]|7[01]) => debug <>(6[4569]|7[01]) end debug (<>6[4569]|7[01]) end debug (6<>[4569]|7[01]) end debug (6[4569]<>|7[01]) end debug (6[4569]|<>7[01]) end debug (6[4569]|7<>[01]) end debug (6[4569]|7[01]<>) end debug (6[4569]|7[01]<>) end debug (6[4569]|7[01])<> end 64,65,66,69,70,71