<?xml version="1.0" encoding="windows-1252"?>
<node id="678124" title="Re: Parsing with perl - Regexes and beyond" created="2008-04-03 04:51:18" updated="2008-04-03 00:51:18">
<type id="11">
note</type>
<author id="171588">
BrowserUk</author>
<data>
<field name="doctext">
&lt;blockquote&gt;&lt;i&gt;&lt;/i&gt;&lt;/blockquote&gt;
&lt;p&gt;How would Chomsky categorise this? (Update: Corrected c&amp;p typo per [Erez] post below.)

&lt;code&gt;
#! perl -slw
use strict;

$|++;

my %ops = (
    '+' =&gt; sub{ $_[ 0 ] + $_[ 1 ] },
    '-' =&gt; sub{ $_[ 0 ] - $_[ 1 ] },
    '*' =&gt; sub{ $_[ 0 ] * $_[ 1 ] },
    '/' =&gt; sub{ $_[ 0 ] / $_[ 1 ] },
    '**'=&gt; sub{ $_[ 0 ] ** $_[ 1 ] },
);

my @presedence = (
    qr[\*\*],
    qr[\*|/],
    qr[\+|-],
);

my $reVar = qr[[a-z]+];
my $reConst = qr[ [+-]? (?:\d+\.)? \d+ (?: [eE] [+-]? \d+ )? ]x;
my $reArg = qr[$reVar|$reConst];
my $reOps = qr[@{[ join '|', map{ quotemeta } keys %ops ]}];
my $reTokenise = qr[\s*($reArg)(?:\s*($reOps))?];

sub parseEvalExpr {
    my $expr = shift;

    if( $expr =~ m[$reOps \s+ $reArg \s+ $reOps]x ) {
        for my $opset ( @presedence ) {
            return "($expr)" 
                if $expr =~ s[ ( $reArg \s+ $opset \s+ $reArg ) ]{($1)}x;
        }
    }
    my @tokens = $expr =~ m[$reTokenise]g;
    pop @tokens unless defined $tokens[ $#tokens ];
    while( @tokens &gt; 1 ) {
        ( my( $arg1, $op, $arg2 ), @tokens ) = @tokens;
        unshift @tokens, $ops{ $op }-&gt;( $arg1, $arg2 );
    }
    return $tokens[ 0 ];
}

while( &lt;DATA&gt; ) {
    chomp;
    my $testResult = eval;
    printf "'$_' = ";
    warn "Unbalanced parens '$_'" and next unless tr[(][] == tr[)][];
    while( m[[()\s]] ) {
        s[ \( ( [^()]+ ) \) ]{ parseEvalExpr( $1 ) }xe while m[[()]];
        $_ = parseEvalExpr( $_ );
    }
    print;
    printf STDERR "*** Discrepancy! Eval gets: %s\n", $testResult 
        unless $_ eq $testResult;
}

__DATA__
1 + 2
2 - 1
2 * 1
1 / 2
(((7 + 5) * (9 + 13)) / ((4 + 3) * (17 - 2 + 3)))
23 ** 2
1.1e10 ** -10
1 + 2 * 3
3 + 2 ** 2 ** 2 * 3
&lt;/code&gt;

&lt;p&gt;Output&lt;code&gt;
c:\test&gt;expr_parser.pl
'1 + 2' = 3
'2 - 1' = 1
'2 * 1' = 2
'1 / 2' = 0.5
'(((7 + 5) * (9 + 13)) / ((4 + 3) * (17 - 2 + 3)))' = 2.0952380952381
'23 ** 2' = 529
'1.1e10 ** -10' = 3.85543289429532e-101
'1 + 2 * 3' = 7
'3 + 2 ** 2 ** 2 * 3' = 51

&lt;/code&gt;


&lt;div class="pmsig"&gt;&lt;div class="pmsig-171588"&gt;
&lt;hr /&gt;
&lt;font size=1 &gt;
&lt;div&gt;Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.&lt;/div&gt;
&lt;div&gt;"Science is about questioning the status quo. Questioning authority". &lt;/div&gt;
&lt;div&gt;In the absence of evidence, opinion is indistinguishable from prejudice.&lt;/div&gt;
&lt;div&gt;[http://news.bbc.co.uk/1/hi/education/6202877.stm|"Too many &amp;#91;&amp;#93; have been sedated by an oppressive environment of political correctness and risk aversion."]&lt;/div&gt;
&lt;/font&gt;

&lt;/div&gt;&lt;/div&gt;</field>
<field name="root_node">
678119</field>
<field name="parent_node">
678119</field>
</data>
</node>
