in reply to Parse:RecDescent grammar help
I would imagine you would need something like this. Each target language would have its own set of dispatch methods. The major issue I see with your generic syntax is that you appear to be using newlines as the statement terminators. Update thekestrels excellent post made me feel obligated to lift my game!
use Parse::RecDescent; use Data::Dumper; my $data =<<'DATA'; $string = 'Hello World' $integer = 1234 $decimal = 1.234 @ary = [ 'foo', "bar", 123, 1.23 ] %hash = { foo => 'bar', "baz" => 123 } DATA my $grammar =<<'GRAMMAR'; SV : '$' HV : '%' AV : '@' VARNAME : /\w+/ QV : /"/ /[^"]*/ /"/ { [ 'char', $item[2] ] } | /'/ /[^']*/ /'/ { [ 'char', $item[2] ] } INT : /\d+/ { [ 'int', $item[1] ] } FLOAT : /\d*\.\d+/ { [ 'float', $item[1] ] } SCALAR : QV | FLOAT | INT LIST : SCALAR /,/ { $item[1] } | SCALAR { $item[1] } HASHBIT : VARNAME /=>/ SCALAR { [ @item[1,3] ] } | QV /=>/ SCALAR { [ @item[1,3] ] } HASHLIST : HASHBIT /,/ { $item[1] } | HASHBIT { $item[1] } EQUALS : '=' start : statement(s) statement : assign_scalar | assign_array | assign_hash assign_scalar : SV VARNAME EQUALS SCALAR { [ @item[0,2,4] ] } assign_array : AV VARNAME EQUALS '[' LIST(s) ']' { [ @item[0,2,5] ] } assign_hash : HV VARNAME EQUALS '{' HASHLIST(s) '}' { [ @item[0,2,5] ] } GRAMMAR my $parser = Parse::RecDescent->new($grammar); my $lang = Language::C->new(); my $parse_tree = $parser->start($data); print Dumper $parse_tree; for my $item( @$parse_tree ) { my $method = $item->[0]; $lang->$method(@$item); } package Language::C; sub new { bless {}, shift } sub assign_scalar { my ( $self, $function, $varname, $value ) = @_; if ( $value->[0] eq 'int' ) { print "int $varname = $value->[1];\n"; } elsif ( $value->[0] eq 'float' ) { print "double $varname = $value->[1];\n"; } else { print qq!char $varname!.qq![] = "$value->[1]";\n!; } } sub assign_array { print Data::Dumper::Dumper \@_ } sub assign_hash { print Data::Dumper::Dumper \@_ }
cheers
tachyon
|
|---|