Veamos un ejemplo:
nereida:~/src/perl/YappWithDefaultAction/examples> cat -n ./alias.pl 1 #!/usr/bin/perl -w 2 use strict; 3 use Parse::Eyapp; 4 5 my $grammar = q{ 6 %right '=' 7 %left '-' '+' 8 %left '*' '/' 9 %left NEG !10 %tree bypass alias 11 12 %% 13 line: $exp { $_[1] } 14 ; 15 16 exp: 17 %name NUM 18 $NUM 19 | %name VAR 20 $VAR 21 | %name ASSIGN 22 $VAR '=' $exp 23 | %name PLUS 24 exp.left '+' exp.right 25 | %name MINUS 26 exp.left '-' exp.right 27 | %name TIMES 28 exp.left '*' exp.right 29 | %name DIV 30 exp.left '/' exp.right 31 | %no bypass UMINUS 32 '-' $exp %prec NEG 33 | '(' exp ')' { $_[2] } /* Let us simplify a bit the tree */ 34 ; 35 36 %% 37 38 sub _Error { 39 exists $_[0]->YYData->{ERRMSG} 40 and do { 41 print $_[0]->YYData->{ERRMSG}; 42 delete $_[0]->YYData->{ERRMSG}; 43 return; 44 }; 45 print "Syntax error.\n"; 46 } 47 48 sub _Lexer { 49 my($parser)=shift; 50 51 $parser->YYData->{INPUT} 52 or $parser->YYData->{INPUT} = <STDIN> 53 or return('',undef); 54 55 $parser->YYData->{INPUT}=~s/^\s+//; 56 57 for ($parser->YYData->{INPUT}) { 58 s/^([0-9]+(?:\.[0-9]+)?)// 59 and return('NUM',$1); 60 s/^([A-Za-z][A-Za-z0-9_]*)// 61 and return('VAR',$1); 62 s/^(.)//s 63 and return($1,$1); 64 } 65 } 66 67 sub Run { 68 my($self)=shift; 69 $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error, 70 #yydebug =>0xFF 71 ); 72 } 73 }; # end grammar 74 75 76 Parse::Eyapp->new_grammar( 77 input=>$grammar, 78 classname=>'Alias', 79 firstline =>7, 80 ); 81 my $parser = Alias->new(); 82 $parser->YYData->{INPUT} = "a = -(2*3+5-1)\n"; 83 my $t = $parser->Run; 84 $Parse::Eyapp::Node::INDENT=0; !85 print $t->VAR->str."\n"; # a 86 print "***************\n"; !87 print $t->exp->exp->left->str."\n"; # 2*3+5 88 print "***************\n"; !89 print $t->exp->exp->right->str."\n"; # 1Este programa produce la salida:
nereida:~/src/perl/YappWithDefaultAction/examples> ./alias.pl TERMINAL *************** PLUS(TIMES(NUM,NUM),NUM) *************** NUMEl efecto de la opción alias en una regla como:
27 | %name TIMES 28 exp.left '*' exp.rightes crear dos métodos
left
y right
en la clase TIMES
.
El método left
permite acceder al hijo izquierdo del nodo en el AST
y el método right
al hijo derecho.
El efecto de la opción alias en una regla como:
21 | %name ASSIGN 22 $VAR '=' $expes crear dos métodos en la clase
ASSIGN
denominados
VAR
y exp
los cuales permiten acceder a los
correspondientes hijos de uno nodo ASSIGN
.
Los métodos son construidos durante la compilación de la gramática. Por tanto, las modificaciones al AST que el programa introduzca en tiempo de ejecución (por ejemplo la supresión de hijos de ciertos nodos) invalidarán el uso de estos métodos.