summaryrefslogtreecommitdiff
path: root/pidl/expr.yp
diff options
context:
space:
mode:
Diffstat (limited to 'pidl/expr.yp')
-rw-r--r--pidl/expr.yp150
1 files changed, 150 insertions, 0 deletions
diff --git a/pidl/expr.yp b/pidl/expr.yp
new file mode 100644
index 0000000000..a8074875ff
--- /dev/null
+++ b/pidl/expr.yp
@@ -0,0 +1,150 @@
+# 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);
+}