# 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: { "" } | 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); }