# fortran2c.yp - yapp version of converting FORTRAN to C %left '.and.' '.or.' %right '.not.' %nonassoc '.eq.' '.ne.' '.eqv.' '.neqv.' %nonassoc '.ge.' '.le.' '.gt.' '.lt.' %left '+' '-' %left '*' '/' %% exp : exp '+' exp { "(($_[1]) + ($_[3]))" } | exp '-' exp { "(($_[1]) - ($_[3]))" } | exp '*' exp { "(($_[1]) * ($_[3]))" } | exp '/' exp { "(($_[1]) / ($_[3]))" } | exp '.and.' exp { "(($_[1]) && ($_[3]))" } | exp '.or.' exp { "(($_[1]) || ($_[3]))" } | exp '.eq.' exp { "(($_[1]) == ($_[3]))" } | exp '.ne.' exp { "(($_[1]) != ($_[3]))" } | exp '.eqv.' exp { "(($_[1]) == ($_[3]))" } | exp '.neqv.' exp { "(($_[1]) != ($_[3]))" } | exp '.lt.' exp { "(($_[1]) < ($_[3]))" } | exp '.gt.' exp { "(($_[1]) > ($_[3]))" } | exp '.le.' exp { "(($_[1]) <= ($_[3]))" } | exp '.ge.' exp { "(($_[1]) >= ($_[3]))" } | '.not.' exp { "(!($_[2]))" } | '(' exp ')' { $_[2] } | 'NUM' { $_[1] } | 'NAME' '(' arglist ')' { $_[1] . $_[3] } ; arglist : exp { "[($_[1])-1]" } | arglist ',' exp { "[($_[3])-1]$_[1]" } ; %% use warnings; use strict; sub lex { /\G\s+/gc, return /\G((\d+(\.\d*)?|\.\d+)([Ee][-+]?\d+)?)/gc ? (NUM => $1) : /\G(\.(?:and|or|eqv?|ne|neqv|lt|gt|le|ge|not)\.)/gc ? $1 : /\G(\w+)/gc ? (NAME => $1) : /\G(\w+|.)/gc ? $1 : '' for $_[0]->YYData->{in}; } sub error { for ($_[0]->YYData->{in}) { substr $_, pos(), 0, '<-- HERE '; die "parse ERROR: $_\n"; } } my $code = '.not.foo(1,bar(2)+1,3).and.baz(4,5)'; @ARGV and $code = "@ARGV"; my $parser = new fortran2c; $parser->YYData->{in} = $code; my $answer = $parser->YYParse(yylex => \&lex, yyerror => \&error) or die "syntax error\n"; print "$answer\n"; __END__ # Makefile all: fortran2c.pl %.pl: %.yp yapp -v -s -b '/usr/bin/perl' -o $@ $< chmod +x $@