#!/usr/bin/perl use feature "unicode_strings"; use open IO => ":encoding(UTF-8)", ":std"; use Data::Dumper; undef $/; $Data::Dumper::Indent=0; $Data::Dumper::Terse=1; $Data::Dumper::Useqq=1; my $program = <>; $program =~ s/^#\N*+(?:\n|\z)//mg; # remove comments unless ($program =~ /^\S*+\n/s) { $program =~ /^\S*+(.)/s; my $e = $1; if (!defined $e) { print STDERR "error: there must be both an initial string, and rules\n"; } else { $e = Dumper $e; print STDERR "error: initial string must be followed by a newline (not $e)\n"; } exit 65; } my @program = split /\s+/, $program; my $datastring = shift @program; my $used_chars; my $sym = qr/\p{Cased_Letter}|\$/; # Verify the syntax of the data string. unless ($datastring =~ /^$sym*+$/s) { $datastring =~ s/$sym//g; print STDERR "error: data string contains invalid characters: '$datastring'\n"; exit 65; } $used_chars{$_}++ for split //, $datastring; # Parse the rules, verifying their syntax too. my %rules; for my $rule (@program) { unless ($rule=~/^([01]$sym):($sym*+)$/s) { print STDERR "error: cannot parse rule '$rule'\n"; exit 65; } my $rulebody = $rules{$1} = $2; if ($1 eq '$') { print STDERR "error: cannot define rules for the halt symbol\n"; exit 65; } $used_chars{$_}++ for split //, $rulebody; } # Verify that all the rules that should exist do. for my $oddness (0..1) { for my $used_char (keys %used_chars) { $used_char eq '$' and next; unless (defined $rules{"$oddness$used_char"}) { print STDERR "error: no definition for oddness/character '$oddness$used_char'\n"; exit 65; } } } # Now we can start executing the program. while ($datastring !~ /\$/) { my $oddness = 0; my $new_datastring = ''; for my $char (split //, $datastring) { $new_datastring .= $rules{"$oddness$char"}; $char =~ /\p{Uppercase_Letter}/ and $oddness ^= 1; } print "$datastring [$oddness]\n"; $datastring = $new_datastring; } print "$datastring\n"; if ($datastring =~ /\$[^\$]*+\$/) { print STDERR "error: undefined behaviour: two \$ in data string\n"; exit 3; } exit 0;