From 04293aded24f2572b415ff671579af74b6b6c50b Mon Sep 17 00:00:00 2001 From: Hongwe Qiu Date: Sun, 22 May 2011 23:00:34 +0800 Subject: [PATCH] Compiler rewritten by nqprx can almost comiple now. But I don't know how to adjust the 'quote_EXPR' method. So none of the tests will pass right now. --- cardinal.pir | 31 +- src/compiler.pm | 4 + src/parser/actions.pm | 344 ++++++++------------- src/parser/grammar.pm | 509 +++++++++++--------------------- src/parser/quote_expression.pir | 6 +- 5 files changed, 301 insertions(+), 593 deletions(-) diff --git a/cardinal.pir b/cardinal.pir index e0768a9..d371828 100644 --- a/cardinal.pir +++ b/cardinal.pir @@ -34,58 +34,43 @@ object. .sub 'onload' :anon :load :init load_bytecode 'HLL.pbc' .local pmc hllns, parrotns, imports - hllns = get_hll_namespace + hllns = get_hll_namespace parrotns = get_root_namespace ['parrot'] - imports = split ' ', 'PAST PCT HLL Regex Hash' + imports = split ' ', 'PAST PCT HLL Regex Hash' parrotns.'export_to'(hllns, imports) .end .include 'src/gen_grammar.pir' .include 'src/parser/quote_expression.pir' .include 'src/gen_actions.pir' +.include 'src/gen_compiler.pir' .namespace [ 'cardinal';'Compiler' ] #no caridinal_group found on my machine #.loadlib 'cardinal_group' -=begin comment - .sub 'onload' :anon :load :init - .local pmc cardinalmeta, compilerclass, compiler - cardinalmeta = get_hll_global ['CardinalObject'], '!CARDINALMETA' - compilerclass = cardinalmeta.'new_class'('cardinal::Compiler', 'parent'=>'PCT::HLLCompiler') - $P2 = new 'CardinalString' $P2 = "" set_hll_global '$,', $P2 - compiler = compilerclass.'new'() - compiler.'language'('cardinal') - $P0 = get_hll_namespace ['cardinal';'Grammar'] - compiler.'parsegrammar'($P0) - $P0 = get_hll_namespace ['cardinal';'Grammar';'Actions'] - compiler.'parseactions'($P0) - - compiler.'commandline_banner'("Cardinal - Ruby for the Parrot VM\n\n") - compiler.'commandline_prompt'('crb(main):001:0> ') - - ## create a list of END blocks to be run + ## create a list of END blocks to be run $P0 = new 'CardinalArray' set_hll_global ['cardinal'], '@?END_BLOCKS', $P0 $P0 = new 'CardinalArray' - set_hll_global ['cardinal';'Grammar';'Actions'], '@?BLOCK', $P0 + set_hll_global ['cardinal';'Actions'], '@?BLOCK', $P0 $P1 = get_hll_global ['PAST';'Compiler'], '%valflags' $P1['CardinalString'] = 'e' .end - =item main(args :slurpy) :main +=item main(args :slurpy) :main Start compilation by passing any command line C to the cardinal compiler. - =cut +=cut .sub 'main' :main .param pmc args_str @@ -141,8 +126,6 @@ to the cardinal compiler. .return (retval) .end -=end comment - =back =cut diff --git a/src/compiler.pm b/src/compiler.pm index 9b482ac..5488e81 100644 --- a/src/compiler.pm +++ b/src/compiler.pm @@ -4,4 +4,8 @@ INIT { cardinal::Compiler.language('cardinal'); cardinal::Compiler.parsegrammar(cardinal::Grammar); cardinal::Compiler.parseactions(cardinal::Actions); + cardinal::Compiler.commandline_banner("Cardinal - Ruby for the Parrot VM\n\n"); + cardinal::Compiler.commandline_prompt('crb(main):001:0> '); } + +# vim: sw=4 ts=4 ft=perl6 expandtab diff --git a/src/parser/actions.pm b/src/parser/actions.pm index 057e0bb..8f91d92 100644 --- a/src/parser/actions.pm +++ b/src/parser/actions.pm @@ -1,22 +1,4 @@ -# Copyright (C) 2008, Parrot Foundation. -# $Id$ - -=begin comments - -cardinal::Grammar::Actions - ast transformations for cardinal - -This file contains the methods that are used by the parse grammar -to build the PAST representation of an cardinal program. -Each method below corresponds to a rule in F, -and is invoked at the point where C<{*}> appears in the rule, -with the current match object as the first argument. If the -line containing C<{*}> also has a C<#= key> comment, then the -value of the comment is passed as the second argument to the method. - -=end comments -=cut - -class cardinal::Grammar::Actions; +class cardinal::Actions is HLL::Actions; method TOP($/) { my $past := $.ast(); @@ -53,29 +35,30 @@ method TOP($/) { make $past; } -method comp_stmt($/,$key) { +method begin_block($/) { our $?BLOCK; our @?BLOCK; our $?BLOCK_SIGNATURED; - if $key eq 'open' { - if $?BLOCK_SIGNATURED { - $?BLOCK := $?BLOCK_SIGNATURED; - $?BLOCK_SIGNATURED := 0; - } - else { - $?BLOCK := PAST::Block.new( PAST::Stmts.new(), :node($/)); - my $block := PAST::Var.new(:scope('parameter'), :named('!BLOCK'), :name('!BLOCK'), :viviself('Undef')); - $?BLOCK.symbol($block.name(), :scope('lexical')); - $?BLOCK[0].push($block); - } - @?BLOCK.unshift($?BLOCK); - } - if $key eq 'close' { - my $past := @?BLOCK.shift(); - $?BLOCK := @?BLOCK[0]; - $past.push( $.ast() ); - make $past; + if $?BLOCK_SIGNATURED { + $?BLOCK := $?BLOCK_SIGNATURED; + $?BLOCK_SIGNATURED := 0; + } else { + $?BLOCK := PAST::Block.new(PAST::Stmts.new, :node($/)); + my $block := PAST::Var.new(:scope, :named, :name, :viviself); + $?BLOCK.symbol($block.name, :scope); + $?BLOCK[0].push($block); } + @?BLOCK.unshift($?BLOCK); +} + +method comp_stmt($/) { + our $?BLOCK; + our @?BLOCK; + our $?BLOCK_SIGNATURED; + my $past := @?BLOCK.shift(); + $?BLOCK := @?BLOCK[0]; + $past.push( $.ast() ); + make $past; } method stmts($/) { @@ -86,10 +69,6 @@ method stmts($/) { make $past; } -method basic_stmt($/, $key) { - make $/{$key}.ast(); -} - method stmt($/) { my $past := $.ast(); for $ { @@ -115,7 +94,7 @@ method stmt_mod($/) { } method expr($/) { - my $past := $.ast(); + my $past := $.ast(); if +$ { $past := PAST::Op.new( $past, :pirop('not'), :node($/) ); } @@ -128,7 +107,7 @@ method expr($/) { make $past; } -method return_stmt($/) { +method basic_stmt:sym($/) { my $past := $.ast(); $past.pasttype('inline'); $past.inline(' .return(%0)'); @@ -136,13 +115,13 @@ method return_stmt($/) { } ## not entirely sure what alias does, but this is a guess... -method alias($/) { +method basic_stmt:sym($/) { my $fname := $[0]; my $alias := $[1]; make PAST::Op.new( $alias, $fname, :pasttype('bind'), :node($/) ); } -method begin($/) { +method basic_stmt:sym($/) { my $past := $.ast(); my $sub := PAST::Compiler.compile( $past ); $sub(); @@ -150,7 +129,7 @@ method begin($/) { make PAST::Block.new( :node($/) ); } -method end($/) { +method basic_stmt:sym($/) { my $past := PAST::Block.new( $.ast(), :node($/) ); $past.blocktype('declaration'); my $sub := PAST::Compiler.compile( $past ); @@ -162,7 +141,7 @@ method end($/) { make $past; } -method indexed_assignment($/) { +method basic_stmt:sym($/) { my $keys; my $rhs := $.ast(); my $primary := $.ast(); @@ -181,7 +160,7 @@ method indexed_assignment($/) { make $past; } -method member_assignment($/) { +method basic_stmt:sym($/) { my $rhs := $.ast(); my $primary := $.ast(); @@ -192,7 +171,7 @@ method member_assignment($/) { make $past; } -method assignment($/) { +method basic_stmt:sym($/) { my $lhs := $.ast(); our $?BLOCK; my $name := $lhs.name(); @@ -230,16 +209,14 @@ method assignment($/) { make PAST::Op.new( $lhs, $rhs, :pasttype('bind'), :lvalue(1), :node($/) ); } -method lhs($/, $key) { - make $/{$key}.ast(); -} +method lhs($/) { make $.ast } method member_variable($/) { make $.ast(); # XXX fix field. } -method indexed($/) { +method post_primary_expr:sym($/) { my $args; if $ { $args := $[0].ast(); @@ -263,11 +240,9 @@ method variable($/) { make $past; } -method varname($/, $key) { - make $/{$key}.ast(); -} +method varname($/) { make $.ast } -method global($/) { +method vartype:sym($/) { my @namespace; our @?BLOCK; my $toplevel := @?BLOCK[0]; @@ -275,7 +250,7 @@ method global($/) { make PAST::Var.new( :name(~$/), :scope('package'), :namespace(@namespace), :viviself('Undef'), :node($/) ); } -method instance_variable($/) { +method vartype:sym($/) { our $?CLASS; our $?BLOCK; my $name := ~$/; @@ -300,7 +275,7 @@ method instance_variable($/) { make $past; } -method class_variable($/) { +method vartype:sym($/) { our $?CLASS; our $?BLOCK; my $name := ~$/; @@ -349,12 +324,12 @@ method local_variable($/) { make $past; } -method funcall($/) { +method basic_primary:sym($/) { my $past := $.ast(); make $past; } -method constant_variable($/) { +method vartype:sym($/) { my @a; my $name := ~$/; if $name eq 'Integer' { $name := "CardinalInteger"; } @@ -368,7 +343,7 @@ method constant_variable($/) { } -method if_stmt($/) { +method basic_stmt:sym($/) { my $cond := +$ - 1; my $comp := $[$cond].ast(); $comp.blocktype('immediate'); @@ -396,7 +371,7 @@ method if_stmt($/) { make $past; } -method unless_stmt($/) { +method basic_stmt:sym($/) { my $cond := $.ast(); my $body := $.ast(); $body.blocktype('immediate'); @@ -414,14 +389,14 @@ method else($/) { make $.ast(); } -method while_stmt($/) { +method basic_stmt:sym($/) { my $cond := $.ast(); my $body := $.ast(); $body.blocktype('immediate'); make PAST::Op.new( $cond, $body, :pasttype(~$), :node($/) ); } -method for_stmt($/) { +method basic_stmt:sym($/) { my $list := $.ast(); my $body := $.ast(); my $var := $.ast(); @@ -432,14 +407,9 @@ method for_stmt($/) { make PAST::Op.new( $list, $body, :pasttype('for'), :node($/) ); } -method control_command($/,$key) { - make PAST::Op.new( - :pasttype('call'), - :name(~$/), - ); -} +method basic_primary:sym($/) { make PAST::Op.new(:pasttype, :name(~$/)) } -method yield($/) { +method basic_primary:sym($/) { our $?BLOCK; our @?BLOCK; my $blockname; @@ -457,7 +427,7 @@ method yield($/) { make $call; } -method module($/) { +method basic_stmt:sym($/) { my $past := $.ast(); my $name := $.ast(); $past.namespace( $name.name() ); @@ -466,90 +436,74 @@ method module($/) { make $past; } -method begin_end($/) { +method basic_stmt:sym($/) { my $past := $.ast(); # XXX handle resque and ensure clauses make $past; } -method classdef($/,$key) { +method begin_class($/) { our $?CLASS; our @?CLASS; our $?INIT; - my $name := ~$; - if $key eq 'open' { - my $decl := PAST::Stmts.new(); - $decl.push( - PAST::Op.new( - :pasttype('bind'), - PAST::Var.new( - :name('$def'), - :scope('lexical') - ), - PAST::Op.new( - :pasttype('call'), - :name('!keyword_class'), - PAST::Val.new( :value($name) ) - ) - ) - ); - @?CLASS.unshift( $?CLASS ); - $?CLASS := $decl; - $?CLASS.unshift( PAST::Block.new() ); - } - else { - my $block := $.ast(); - $block.namespace($name); - $block.blocktype('declaration'); - $block.pirflags(':init :load'); + my $decl := PAST::Stmts.new; + $decl.push( + PAST::Op.new( + :pasttype, + PAST::Var.new(:name<$def>, :scope), + PAST::Op.new(:pasttype, :name, PAST::Val.new(:value(~$/))) + ) + ); + @?CLASS.unshift($?CLASS); + $?CLASS := $decl; + $?CLASS.unshift(PAST::Block.new); +} - $?CLASS.push( - PAST::Op.new( - :pasttype('callmethod'), - :name('register'), - PAST::Var.new( - :scope('package'), - :name('!CARDINALMETA'), - :namespace('CardinalObject') - ), - PAST::Var.new( - :scope('lexical'), - :name('$def') - ), - PAST::Val.new( - :value('CardinalObject'), - :named( PAST::Val.new( :value('parent') ) ) - ) - ) - ); +method basic_stmt:sym($/) { + our $?CLASS; + our @?CLASS; + our $?INIT; - unless defined( $?INIT ) { - $?INIT := PAST::Block.new(); - } - for @( $?CLASS ) { - if $_.WHAT() eq 'Block' { - $block.push( $_ ); - } - else { - $?INIT.push( $_ ); - } - } + my $block := $.ast; + $block.namespace(~$); + $block.blocktype('declaration'); + $block.pirflags(':init :load'); + + $?CLASS.push( + PAST::Op.new( + :pasttype, + :name, + PAST::Var.new(:scope, :name, :namespace), + PAST::Var.new(:scope, :name<$def>), + PAST::Val.new(:value, :named(PAST::Val.new(:value))) + ) + ); - # Restore outer class. - if +@?CLASS { - $?CLASS := @?CLASS.shift(); + unless defined( $?INIT ) { + $?INIT := PAST::Block.new(); + } + for @( $?CLASS ) { + if $_.WHAT() eq 'Block' { + $block.push( $_ ); } else { - $?CLASS := @?CLASS[0]; + $?INIT.push( $_ ); } + } - - make $block; + # Restore outer class. + if +@?CLASS { + $?CLASS := @?CLASS.shift(); } + else { + $?CLASS := @?CLASS[0]; + } + + make $block; } -method functiondef($/) { +method basic_stmt:sym($/) { my $past := $.ast(); my $name := $; my $arity := +$past[0]; @@ -626,7 +580,7 @@ method module_identifier($/) { make PAST::Var.new( :name(~$/), :scope('package'), :node($/) ); } -method methodcall($/) { +method post_primary_expr:sym($/) { my $op := $; my $past; if $ { @@ -646,10 +600,7 @@ method methodcall($/) { make $past; } -method do_block($/) { - my $past := $.ast(); - make $past; -} +method do_block($/) { make $.ast } method super_call($/) { my $past := $.ast(); @@ -679,15 +630,13 @@ method call_args($/) { method args($/) { my $past := PAST::Op.new( :pasttype('call'), :node($/) ); - for $ { + for $ { $past.push( $_.ast() ); } make $past; } -method basic_primary($/, $key) { - make $/{$key}.ast(); -} +method basic_primary:sym($/) { make $.ast } method primary($/) { my $past := $.ast(); @@ -701,44 +650,25 @@ method primary($/) { make $past; } -method post_primary_expr($/, $key) { - make $/{$key}.ast(); -} +method post_primary_expr:sym($/) { make $.ast } +method post_primary_expr:sym($/) { make $ ?? $[0].ast !! PAST::Op.new(:inline, :pasttype, :node($/)) } method scope_identifier($/) { make $.ast(); # XXX handle :: operator. } -method literal($/, $key) { - my $past; - if $key eq 'true' { - $past := PAST::Op.new(:inline("%t = get_hll_global 'true'"), :returns('Bool')); - } elsif $key eq 'false' { - $past := PAST::Op.new(:inline("%t = get_hll_global 'false'"), :returns('Bool')); - } elsif $key eq 'nil' { - $past := PAST::Op.new(:inline("%t = get_hll_global 'nil'"), :returns('NilClass')); - } elsif $key eq 'self' { - $past := PAST::Op.new(:inline('%r = self')); - } else { - $past := $/{$key}.ast(); - } - make $past; -} - -method pcomp_stmt($/) { - make $.ast(); -} +method literal:sym($/) { make PAST::Op.new(:inline('%t = get_hll_global "true"'), :returns) } +method literal:sym($/) { make PAST::Op.new(:inline('%t = get_hll_global "false"'), :returns) } +method literal:sym($/) { make PAST::Op.new(:inline('%t = get_hll_global "nil"'), :returns) } +method literal:sym($/) { make PAST::Op.new(:inline('%r = self')) } -method quote_string($/) { - make $.ast(); -} +method basic_primary:sym($/) { make $.ast } -method warray($/) { - make $.ast(); -} +method literal:sym($/) { make $.ast } +method literal:sym($/) { make $.ast } -method array($/) { +method literal:sym($/) { my $list; if $ { $list := $[0].ast(); @@ -751,7 +681,7 @@ method array($/) { make $list; } -method ahash($/) { +method literal:sym($/) { my $hash := PAST::Op.new( :name('hash'), :node($/) ); if $ { my $items := $[0].ast(); @@ -773,28 +703,17 @@ method assocs($/) { method assoc($/) { my $past := PAST::Op.new(:name('list'), :node($/)); - $past.push( $[0].ast() ); - $past.push( $[1].ast() ); + $past.push( $[0].ast() ); + $past.push( $[1].ast() ); make $past; } -method float($/) { - make PAST::Val.new( :value( ~$/ ), :returns('Float'), :node($/) ); -} +method literal:sym($/) { make PAST::Val.new(:value(~$/), :returns, :node($/)) } +method literal:sym($/) { make PAST::Val.new(:value(~$/), :returns, :node($/)) } +method literal:sym($/) { make $.ast } +method literal:sym($/) { make $.ast } -method integer($/) { - make PAST::Val.new( :value( ~$/ ), :returns('CardinalInteger'), :node($/) ); -} - -method string($/) { - make $.ast(); -} - -method regex($/) { - make $.ast(); -} - -method quote_expression($/, $key) { +method quote_EXPR($/, $key) { my $past; if $key eq 'quote_regex' { our $?NS; @@ -817,14 +736,13 @@ method quote_expression($/, $key) { :node( $/ ) ); for $ { - $past.push( $_.ast() ); + $past.push( $_.ast() ); } } } make $past; } - method quote_concat($/) { my $terms := +$; my $count := 1; @@ -864,26 +782,6 @@ method quote_term($/, $key) { make $past; } -method arg($/, $key) { - ## Handle the operator table - ## - if ($key eq 'end') { - make $.ast(); - } - else { - my $past := PAST::Op.new( :name($), - :pasttype($), - :pirop($), - :lvalue($), - :node($/) - ); - for @($/) { - $past.push( $_.ast() ); - } - make $past; - } -} - sub is_a_sub($name) { our $?BLOCK; our @?BLOCK; @@ -892,7 +790,7 @@ sub is_a_sub($name) { return 1; } else { - return0; + return 0; } } for @?BLOCK { @@ -913,10 +811,6 @@ sub is_a_sub($name) { return 0; } -# Local Variables: -# mode: cperl -# cperl-indent-level: 4 -# fill-column: 100 -# End: -# vim: expandtab shiftwidth=4: +=end comment +# vim: sw=4 ts=4 ft=perl6 expandtab diff --git a/src/parser/grammar.pm b/src/parser/grammar.pm index 5bf1c4e..07b95d9 100644 --- a/src/parser/grammar.pm +++ b/src/parser/grammar.pm @@ -1,5 +1,3 @@ -# $Id$ - =begin overview This is the grammar for cardinal written as a sequence of Perl 6 rules. @@ -15,120 +13,60 @@ grammar cardinal::Grammar is HLL::Grammar; token TOP { - [ $ || <.panic('Syntax error')> ] - {*} + [ $ || <.panic: "Syntax error"> ] } token comp_stmt { - {*} #= open + <.begin_block> - {*} #= close } +token begin_block { } + rule stmts { - <.term>?[ [<.term>+ | <.before > | $ | ] ]* {*} + <.terminator>?[ [<.terminator>+ | <.before > | $ | <.panic: "Unterminated statement">] ]* } -token term { \h*\n | \h*';' } +token terminator { \h*\n | \h*';' } token end_block { <.ws> [ 'end' | '}' ] } -token basic_stmt { - | {*} #= alias - | {*} #= classdef - | {*} #= functiondef - | {*} #= if_stmt - | {*} #= while_stmt - | {*} #= for_stmt - | {*} #= unless_stmt - | {*} #= module - | {*} #= begin_end - | {*} #= indexed_assignment - | {*} #= member_assignment - | {*} #= assignment - | {*} #= return_stmt - | {*} #= expr - | {*} #= begin - | {*} #= end -} +proto token basic_stmt { <...> } +token basic_stmt:sym { } -token return_stmt { - 'return' <.ws> {*} -} +token basic_stmt:sym { <.ws> } -rule alias { - 'alias' - {*} -} +rule basic_stmt:sym { } -token stmt { - <.ws> * - {*} -} +token stmt { <.ws> * } -token stmt_mod { - $=[if|while|unless|until] <.ws> - {*} -} - -rule expr { - [$=['!'|'not']]? [$=['and'|'or'] ]? - {*} -} - -rule begin { - 'BEGIN' '{' '}' - {*} -} +token stmt_mod { $=[if|while|unless|until] <.ws> } -rule end { - 'END' '{' '}' - {*} -} +rule expr { [$=['!'|'not']]? [$=['and'|'or'] ]? } -token indexed_assignment { - '[' $= ']' <.ws> '=' <.ws> $= - {*} -} +rule basic_stmt:sym { 'BEGIN' '{' '}' } +rule basic_stmt:sym { 'END' '{' '}' } -token member_assignment { - '.' $= <.ws> '=' <.ws> $= - {*} -} +token basic_stmt:sym { '[' $= ']' <.ws> '=' <.ws> $= } +token basic_stmt:sym { '.' $= <.ws> '=' <.ws> $= } -rule assignment { - $= '=' $= #XXX need to figure out multiple assignment - {*} +rule basic_stmt:sym { + $= '=' $=$ #XXX need to figure out multiple assignment } -token lhs { - | {*} #= varname -} +token lhs { } -token indexed { - '[' ? ']' - {*} -} +token post_primary_expr:sym { '[' ? ']' } -token member_variable { - '.' - {*} -} +token member_variable { '.' } -token methodcall { - $='.' - ? ? - {*} -} +token post_primary_expr:sym { $='.' ? ? } rule do_block { - | 'do' ? <.term>? <.before > 'end' {*} - | '{' ? <.term>? <.before > '}' {*} + | 'do' ? <.terminator>? <.before > 'end' + | '{' ? <.terminator>? <.before > '}' } -rule super_call { - 'super' - {*} -} +rule super_call { 'super' } token operation { 'class'| @@ -141,11 +79,12 @@ token operation { } #XXX UGLY! Refactor into maybe? +# ?after is not implemented in nqprx token call_args { - | [<.ws> ]**{1} {*} - | '()' [<.ws> ]? {*} - | [ <.after \s|\)> | <.before \s> ] [<.ws> ]? {*} - | '(' <.ws> <.ws> ')' [<.ws> ]? {*} + | [<.ws> ]**{1} + | '()' [<.ws> ]? + | [ | <.before \s> ] [<.ws> ]? + | '(' <.ws> <.ws> ')' [<.ws> ]? } rule do_args { @@ -154,7 +93,7 @@ rule do_args { rule sig_identifier { #XXX Should this be basic_primary or expr or what? - [ '=' ]? {*} + [ '=' ]? } rule block_signature { @@ -162,128 +101,91 @@ rule block_signature { | [',' ]* [',' ]? [',' ]? | [',' ]? | ? - ] {*} -} - -token variable { - {*} -} - -token varname { - - [ {*} #= global - | {*} #= class_variable - | {*} #= instance_variable - | {*} #= local_variable - | {*} #= constant_variable ] } -token funcall { - <.before \s|'('> <.before > {*} -} +token variable { } -rule args { - [',' ]* - {*} -} +token varname { } +proto token vartype { <...> } +token vartype:sym { } -token basic_primary { - | {*} #= literal - | {*} #= funcall - | {*} #= variable - | {*} #= pcomp_stmt - | {*} #= yield - | {*} #= control_command -} +token basic_primary:sym { <.before \s|'('> <.before > } -token primary { - * - {*} -} +rule args { [',' ]* } -token post_primary_expr { - | {*} #= indexed - | {*} #= call_args - | {*} #= methodcall - | '[' ? ']' {*} #= args -} +proto token basic_primary { <...> } +token basic_primary:sym { } -token pcomp_stmt { - '(' ')' - {*} -} +token term { } +token primary { * } + +proto token post_primary_expr { <...> } +token post_primary_expr:sym { } +token post_primary_expr:sym { '[' ~ ']' ? } +token basic_primary:sym { '(' ')' } -rule if_stmt { - 'if' <.then> - [ +rule basic_stmt:sym { + <.then> + [ ['elsif' <.then> - ]* + ]* ? 'end' - |] - {*} + |<.panic: "Syntax error in if statement">] } -token then { ':' | 'then' | ['then']? } +token then { ':' | 'then' | ['then']? } -rule while_stmt { +rule basic_stmt:sym { $=['while'|'until'] <.do> - + 'end' - {*} } -rule for_stmt { - 'for' 'in' <.do> - +rule basic_stmt:sym { + 'in' <.do> + 'end' - {*} } -token do { ':' | 'do' | ['do']? } +token do { ':' | 'do' | ['do']? } -rule unless_stmt { - 'unless' <.then> +rule basic_stmt:sym { + <.then> ? 'end' - {*} } -token else { - 'else' <.ws> - {*} -} +token else { 'else' <.ws> } -token control_command { - | 'next' {*} #= next - | 'break' {*} #= break - | 'redo' {*} #= redo +token basic_primary:sym { + | 'next' + | 'break' + | 'redo' } -token yield { - 'yield' {*} -} +token basic_primary:sym { } -rule module { - 'module' - +rule basic_stmt:sym { + + 'end' - {*} } -rule classdef { - 'class' {*} #= open - - 'end' {*} #= block +token begin_class { } + +rule basic_stmt:sym { + + + 'end' } -rule functiondef { - 'def' - +rule basic_stmt:sym { + + 'end' - {*} } rule argdecl { @@ -292,136 +194,77 @@ rule argdecl { ')']? } -token slurpy_param { - '*' - {*} -} +token slurpy_param { '*' } -token block_param { - '&' - {*} -} +token block_param { '&' } -rule begin_end { +rule basic_stmt:sym { 'begin' - + ['rescue' ? <.do> ]+ ['else' ]? ['ensure' ]? 'end' - {*} } token fname { <.identifier> <[=!?]>? } -token quote_string { - ['%q'|'%Q'] <.before <[<[_|({]>> - {*} -} - -token warray { - '%w' <.before <[<[({]>> - {*} -} +token literal:sym { ['%q'|'%Q'] > } +token literal:sym { '%w' <.before <[<[({]>> } -rule array { - '[' [ [',']? ]? ']' - {*} -} +rule literal:sym { '[' [ [',']? ]? ']' } -rule ahash { - '{' [ [',']? ]? '}' - {*} -} +rule literal:sym { '{' [ [',']? ]? '}' } -rule assocs { - [',' ]* - {*} -} +rule assocs { [',' ]* } -rule assoc { - '=>' - {*} -} +rule assoc { '=>' } -token identifier { - {*} -} +token identifier { } -token module_identifier { - <.before <[A..Z]>> - {*} -} +token module_identifier { <.before <[A..Z]>> } -token global { +token vartype:sym { '$' [ | | <[!@&`'+~=/\\,;.<>_*$?:"]> | + | '-'<[0adFiIlpvw]> ] - {*} } -token instance_variable { - '@' - {*} -} - -token class_variable { - '@@' - {*} -} +token vartype:sym { '@' } -token local_variable { - [ '::']* [ > | ] - {*} -} +token vartype:sym { '@@' } -token constant_variable { - <.before <[A..Z]>> <.ident> - {*} -} +# ?after is not implemented in npqrx +token local_variable { [ '::']* [ > | ] } -token literal { - | {*} #= float - | {*} #= integer - | {*} #= string - | {*} #= ahash - | {*} #= regex - | {*} #= quote_string - | {*} #= warray - | {*} #= array - | 'true' {*} #= true - | 'false' {*} #= false - | 'nil' {*} #= nil - | 'self' {*} #= self -} +token double_colon { '::' } -token float { - '-'? \d+ '.' \d+ - {*} -} +token vartype:sym { <.before <[A..Z]>> <.ident> } -token integer { - '-'? \d+ - {*} -} +token basic_primary:sym { } +proto token literal { <...> } +token literal:sym { } +token literal:sym { } +token literal:sym { } +token literal:sym { } +token literal:sym { '-'? \d+ '.' \d+ } +token literal:sym { '-'? \d+ } -token string { +token literal:sym { [ | <.before \'> | <.before '"' > ] - {*} } -token regex { +token literal:sym { <.before '/'> [ $=[]* - |] - {*} + |<.panic: 'Problem parsing regex'>] } token reserved_word { @@ -434,13 +277,15 @@ token reserved_word { |while|yield|__FILE__|__LINE__]>> } +#?after is not implemented in nqprx token ws { | '\\' \n ## a backslash at end of line - | \n ## a newline after a comma or operator is ignored + | \n ## a newline after a comma or operator is ignored | \h* ['#' \N* \n* ]? } INIT { + cardinal::Grammar.O(':prec', '%unary'); cardinal::Grammar.O(':prec', '%muldiv'); cardinal::Grammar.O(':prec', '%plusminus'); cardinal::Grammar.O(':prec', '%bsh'); @@ -452,82 +297,64 @@ INIT { cardinal::Grammar.O(':prec', '%or'); cardinal::Grammar.O(':prec', '%dotdot'); cardinal::Grammar.O(':prec', '%ternary'); - cardinal::Grammar.O(':prec, :assoc', '%assignment'); # lvalue? + cardinal::Grammar.O(':prec, :assoc', '%assignment'); cardinal::Grammar.O(':prec', '%defined'); } -token infix:sym<=> { ')> } - token prefix:sym { } -token infix:sym<+=> { } - -token infix:sym<-=> { } - -token infix:sym { ')> } - -token infix:sym<*=> { ')> } - -token infix:sym<%=> { ')> } - -token infix:sym<|=> { } - -token infix:sym<&=> { } - -token infix:sym<~=> { } - -token infix:sym«>>=» { ')> } - -token infix:sym«<<=» { ')> } - -token infix:sym<&&=> { ')> } - -token infix:sym<**=> { ')> } - -token infix:sym { , :pasttype')> } - -token infix:sym<..> { } - -token infix:sym<...> { } - -token infix:sym<||> { ')> } - -token infix:sym<&&> { ')> } - -token infix:sym<==> { } -token infix:sym { } -token infix:sym<=~> { } -token infix:sym { } -token infix:sym<===> { } -token infix:sym«<=>» { } - -token infix:sym«>» { } -token infix:sym«<» { } -token infix:sym«<=» { } -token infix:sym«>=» { } - -token infix:sym<|> { } -token infix:sym<^> { } - -token infix:sym<&> { } - -token infix:sym«<<» { } -token infix:sym«<>» { } - -token infix:sym<+> { } -token infix:sym<-> { } - -token infix:sym<*> { } -token infix:sym { } -token infix:sym<%> { ')> } - -#token 'prefix:+' is tighter('infix:*') { ... } -#token 'prefix:-' is equiv('prefix:+') { ... } -#token 'prefix:!' is equiv('prefix:+') { ... } -#token 'prefix:~' is equiv('prefix:+') { ... } - -#TODO -#token 'term:' is tighter('infix:*') -# is parsed(&primary) { ... } - -#token 'circumfix:( )' is equiv('term:') { ... } +token infix:sym<=> { ')> } +token infix:sym<+=> { } +token infix:sym<-=> { } +token infix:sym { ')> } +token infix:sym<*=> { ')> } +token infix:sym<%=> { ')> } +token infix:sym<|=> { } +token infix:sym<&=> { } +token infix:sym<~=> { } +token infix:sym«>>=» { ')> } +token infix:sym«<<=» { ')> } +token infix:sym<&&=> { ')> } +token infix:sym<**=> { ')> } + +token infix:sym { , :pasttype')> } + +token infix:sym<..> { } +token infix:sym<...> { } + +token infix:sym<||> { ')> } +token infix:sym<&&> { ')> } + +token infix:sym<==> { } +token infix:sym { } +token infix:sym<=~> { } +token infix:sym { } +token infix:sym<===> { } +token infix:sym«<=>» { } + +token infix:sym«>» { } +token infix:sym«<» { } +token infix:sym«<=» { } +token infix:sym«>=» { } + +token infix:sym<|> { } +token infix:sym<^> { } +token infix:sym<&> { } + +token infix:sym«<<» { } +token infix:sym«>>» { } + +token infix:sym<+> { } +token infix:sym<-> { } +token infix:sym<*> { } +token infix:sym { } +token infix:sym<%> { ')> } + +#token prefix:sym<+> { } +#token prefix:sym<-> { } +#token prefix:sym { } +#token prefix:sym<~> { } + +token circumfix:sym<( )> { '(' <.ws> ')' } + +# vim: sw=4 ts=4 ft=perl6 expandtab diff --git a/src/parser/quote_expression.pir b/src/parser/quote_expression.pir index 4518f02..2b4c592 100644 --- a/src/parser/quote_expression.pir +++ b/src/parser/quote_expression.pir @@ -26,7 +26,7 @@ .end -.sub 'quote_expression' :method +.sub 'quote_EXPR' :method .param string flags .param pmc options :slurpy :named @@ -175,9 +175,9 @@ pos += stoplen mob.'to'(pos) if null action goto succeed_done - $I0 = can action, 'quote_expression' + $I0 = can action, 'quote_EXPR' unless $I0 goto succeed_done - action.'quote_expression'(mob, key) + action.'quote_EXPR'(mob, key) succeed_done: .return (mob) fail: