package main; # ... my $command; eval { $command = CommandFactory->create ($input_string); # returns the right subclass of Command }; #trap non-existent commands if ($@) {printandprompt("command not recognized");} if ($command->parse_syntax) { # check for syntax errors eval { $command->execute; }; # trap semantic errors, e.g. "user doesn't exist" if ($@) { print $@; # maybe die if need be } } else { printandprompt $command->syntax_string; } package CommandFactory; sub create { my $class = shift; my $str = shift; my ($cmd, @args) = split $str; my $cmd_class = "Command::" . ucfirst ($cmd); return $cmd_class->new(@args); } package Command; use vars qw/$SYNTAX/; # ... sub new { my $class = shift; my @args = @_; my $self = {args => \@args}; bless $self, $class; } sub _syntax { my $self = shift; no strict 'refs'; my $class = ref ($self) || $self; return ${"$class::SYNTAX"}; } sub parse_syntax { my $self = shift; # check $self->{args} against $self->_syntax # then parse the arguments into $self fields # return false on error # alternatively "die" and catch the exception } package Command::Msg; use Command; use base 'Command'; use vars qw/$SYNTAX/; $SYNTAX = { options => { player => { required => 1, arg => 'string', } loudness => { required => 0, arg => 'int' } } arguments => { min => 1, } }; sub execute { my $self = shift; # send $self->{msg} to $self->{player} with $self->{loudness} }