Re: Autotrees !!
[email protected] (Damian Conway)
| Newsgroups | perl.recdescent |
|---|---|
| Message-ID | <[email protected]> |
Jeffrey asked:
> Is there an example of an OO processor that handles the parse
> tree that autotree produces?
I have a few, two of which I've appended below. I'll add them into the next
distribution too.
Damian
-----------cut-----------cut-----------cut-----------cut-----------cut----------
#! /usr/local/bin/perl -sw
# PARSE AND EVALUATE LOGICAL EXPRESSIONS WITH A AUTOGENERATED OO PARSE TREE
use Parse::RecDescent;
use Data::Dumper;
my $parse = Parse::RecDescent->new(<<'EOG');
<autotree>
expr : set | clear | disj
set : 'set' atom
clear : 'clear' atom
disj : <leftop: conj 'or' conj>
{ bless $item[-1], $item[0] }
conj : <leftop: unary 'and' unary>
{ bless $item[-1], $item[0] }
unary : neg | bracket | atom
bracket : '(' expr ')'
neg : 'not' unary
atom : /[a-z]+/i
EOG
while (<>)
{
my $tree = $parse->expr($_);
print Data::Dumper->Dump([$tree]);
print $tree->eval(), "\n" if $tree;
}
BEGIN {@var{qw(a c e)} = (1,1,1);}
sub returning
{
# local $^W;
# print +(caller(1))[3], " returning ($_[0])\n";
$_[0];
}
sub expr::eval { my $type = $_[0]->{set}||$_[0]->{clear}||$_[0]->{disj};
returning $type->eval() }
sub disj::eval { returning join '', map {$_->eval()} @{$_[0]} }
sub conj::eval { returning ! join '', map {! $_->eval()} @{$_[0]} }
sub unary::eval { my $type = $_[0]->{neg}||$_[0]->{bracket}||$_[0]->{atom};
returning $type->eval() }
sub bracket::eval { returning $_[0]->{expr}->eval() }
sub neg::eval { returning ! $_[0]->{unary}->eval() }
sub set::eval { returning $::var{$_[0]->{atom}->name()} = 1 }
sub clear::eval { returning $::var{$_[0]->{atom}->name()} = 0 }
sub atom::eval { returning $::var{$_[0]->{__VALUE__}} }
sub atom::name { returning $_[0]->{__VALUE__} }
-----------cut-----------cut-----------cut-----------cut-----------cut----------
#! /usr/local/bin/perl -w
use Parse::RecDescent;
# $RD_TRACE = 1;
my $parser = Parse::RecDescent->new(<<'EOGRAMMAR');
<autotree>
file: element(s)
element: command | literal
command: '\\' literal options(?) args(?)
options: '[' option(s? /,/) ']'
args: '{' element(s?) '}'
option: /[^][\\$&%#_{}~^ \t\n,]+/
literal: /[^][\\$&%#_{}~^ \t\n]+/
EOGRAMMAR
local $/;
my $tree = $parser->file(<DATA>);
use AutoDump;
#show $tree;
$tree->explain(0);
sub file::explain
{
my ($self, $level) = @_;
for (@{$self->{element}})
{
$_->explain($level);
print "\n";
}
}
sub element::explain
{
my ($self, $level) = @_;
($self->{command}||$self->{literal})->explain($level)
}
sub command::explain
{
my ($self, $level) = @_;
print "\t"x$level, "Command: $self->{literal}{__VALUE__}\n";
print "\t"x$level, "\tOptions:\n";
$self->{options}[0]->explain($level+2) if @{$self->{options}};
print "\t"x$level, "\tArgs:\n";
$self->{args}[0]->explain($level+2) if @{$self->{args}};
}
sub options::explain
{
my ($self, $level) = @_;
$_->explain($level) foreach @{$self->{__DIRECTIVE1__}};
}
sub args::explain
{
my ($self, $level) = @_;
$_->explain($level) foreach @{$self->{element}};
}
sub option::explain
{
my ($self, $level) = @_;
print "\t"x$level, "Option: $self->{__VALUE__}\n";
}
sub literal::explain
{
my ($self, $level) = @_;
print "\t"x$level, "Literal: $self->{__VALUE__}\n";
}
__DATA__
\documentclass[a4paper,11pt]{article}
\usepackage{latexsym}
\author{D. Conway}
\title{Parsing \LaTeX{}}
\begin{document}
\maketitle
\tableofcontents
\section{Description}
...is easy \footnote{But not \emph{necessarily} simple}.
\end{document}
-----------cut-----------cut-----------cut-----------cut-----------cut----------