nexmon – Rev 1

Subversion Repositories:
Rev:
# expr.yp
# Copyright (C) 2006 Jelmer Vernooij <jelmer@samba.org>
# Published under the GNU GPL
# 
%left   '->'
%right  '!' '~'
%left   '*' '/' '%'
%left   '+' '-'
%left   '<<' '>>'
%left   '>' '<'
%left   '==' '!='
%left   '&'
%left   '|'
%left   '&&'
%left   '||'
%left   '?' ':'
%left   NEG DEREF ADDROF INV
%left   '.'

%%
exp:
        NUM
        |
        TEXT                { "\"$_[1]\"" }
        |
        func
        |
        var
        |
        '~' exp %prec INV   { "~$_[2]" }
        |
        exp '+' exp         { "$_[1] + $_[3]" }
        |
        exp '-' exp         { "$_[1] - $_[3]" }
        |
        exp '*' exp         { "$_[1] * $_[3]" }
        |
        exp '%' exp         { "$_[1] % $_[3]" }
        |
        exp '<' exp         { "$_[1] < $_[3]" }
        |
        exp '>' exp         { "$_[1] > $_[3]" }
        |
        exp '|' exp         { "$_[1] | $_[3]" }
        |
        exp '==' exp        { "$_[1] == $_[3]" }
        |
        exp '<=' exp        { "$_[1] <= $_[3]" }
        |
        exp '=>' exp        { "$_[1] => $_[3]" }
        |
        exp '<<' exp        { "$_[1] << $_[3]" }
        |
        exp '>>' exp        { "$_[1] >> $_[3]" }
        |
        exp '!=' exp        { "$_[1] != $_[3]" }
        |
        exp '||' exp        { "$_[1] || $_[3]" }
        |
        exp '&&' exp        { "$_[1] && $_[3]" }
        |
        exp '&' exp         { "$_[1] & $_[3]" }
        |
        exp '?' exp ':' exp { "$_[1]?$_[3]:$_[5]" }
        |
        '~' exp             { "~$_[1]" }
        |
        '!' exp             { "not $_[1]" }
        |
        exp '/' exp         { "$_[1] / $_[3]" }
        |
        '-' exp %prec NEG   { "-$_[2]" }
        |
        '&' exp %prec ADDROF { "&$_[2]" }
        |
        exp '^' exp         { "$_[1]^$_[3]" }
        |
        '(' exp ')'         { "($_[2])" }
;

possible_pointer:
        VAR                              { $_[0]->_Lookup($_[1]) }
        |
        '*' possible_pointer %prec DEREF { $_[0]->_Dereference($_[2]); "*$_[2]" }
;

var:
        possible_pointer    { $_[0]->_Use($_[1]) }
        |
        var '.' VAR         { $_[0]->_Use("$_[1].$_[3]") }
        |
        '(' var ')'         { "($_[2])" }
        |
        var '->' VAR        { $_[0]->_Use("*$_[1]"); $_[1]."->".$_[3] }
;


func:
        VAR '(' opt_args ')' { "$_[1]($_[3])" }
;

opt_args:
        #empty
        { "" }
        |
        args
;

exp_or_possible_pointer:
        exp
        |
        possible_pointer
;

args:
        exp_or_possible_pointer
        |
        exp_or_possible_pointer ',' args { "$_[1], $_[3]" }
;

%%

package Parse::Pidl::Expr;

sub _Lexer {
        my($parser)=shift;

        $parser->YYData->{INPUT}=~s/^[ \t]//;

        for ($parser->YYData->{INPUT}) {
                if (s/^(0x[0-9A-Fa-f]+)//) {
                        $parser->YYData->{LAST_TOKEN} = $1;
                        return('NUM',$1);
                }
                if (s/^([0-9]+(?:\.[0-9]+)?)//) {
                        $parser->YYData->{LAST_TOKEN} = $1;
                        return('NUM',$1);
                }
                if (s/^([A-Za-z_][A-Za-z0-9_]*)//) {
                        $parser->YYData->{LAST_TOKEN} = $1;
                        return('VAR',$1);
                }
                if (s/^\"(.*?)\"//) {
                        $parser->YYData->{LAST_TOKEN} = $1;
                        return('TEXT',$1); 
                }
                if (s/^(==|!=|<=|>=|->|\|\||<<|>>|&&)//s) {
                        $parser->YYData->{LAST_TOKEN} = $1;
                        return($1,$1);
                }
                if (s/^(.)//s) {
                        $parser->YYData->{LAST_TOKEN} = $1;
                        return($1,$1);
                }
        }
}

sub _Use($$)
{
        my ($self, $x) = @_;
        if (defined($self->YYData->{USE})) {
                return $self->YYData->{USE}->($x);
        }
        return $x;
}

sub _Lookup($$) 
{
        my ($self, $x) = @_;
        return $self->YYData->{LOOKUP}->($x);
}

sub _Dereference($$)
{
        my ($self, $x) = @_;
        if (defined($self->YYData->{DEREFERENCE})) {
                $self->YYData->{DEREFERENCE}->($x);
        }
}

sub _Error($)
{
        my ($self) = @_;
        if (defined($self->YYData->{LAST_TOKEN})) {
                $self->YYData->{ERROR}->("Parse error in `".$self->YYData->{FULL_INPUT}."' near `". $self->YYData->{LAST_TOKEN} . "'");
        } else {
                $self->YYData->{ERROR}->("Parse error in `".$self->YYData->{FULL_INPUT}."'");
        }
}

sub Run {
        my($self, $data, $error, $lookup, $deref, $use) = @_;

        $self->YYData->{FULL_INPUT} = $data;
        $self->YYData->{INPUT} = $data;
        $self->YYData->{LOOKUP} = $lookup;
        $self->YYData->{DEREFERENCE} = $deref;
        $self->YYData->{ERROR} = $error;
        $self->YYData->{USE} = $use;

        return $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error);
}