This repository has been archived by the owner on Feb 3, 2021. It is now read-only.
/
Actions.pm
131 lines (105 loc) · 3.3 KB
/
Actions.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
class NQP::Actions is HLL::Actions;
our @BLOCK := Q:PIR { %r = new ['ResizablePMCArray'] };
method TOP($/) { make $<statementlist>.ast; }
method statementlist($/) {
my $past := PAST::Stmts.new( :node($/) );
if $<statement> {
for $<statement> { $past.push( $_.ast ); }
}
make $past;
}
method statement($/) {
my $past;
if $<EXPR> { $past := $<EXPR>.ast; }
elsif $<statement_control> { $past := $<statement_control>.ast; }
else { $past := 0; }
make $past;
}
method xblock($/) {
my $pblock := $<pblock>.ast;
$pblock.blocktype('immediate');
make PAST::Op.new( $<EXPR>.ast, $pblock, :pasttype('if'), :node($/) );
}
method pblock($/) {
make $<blockoid>.ast;
}
method blockoid($/) {
my $past := $<statementlist>.ast;
my $BLOCK := @BLOCK.shift;
$BLOCK.push($past);
$BLOCK.node($/);
make $BLOCK;
}
method newpad($/) {
our @BLOCK;
@BLOCK.unshift( PAST::Block.new( PAST::Stmts.new() ) );
}
## Statement control
method statement_control:sym<if>($/) {
my $count := +$<xblock> - 1;
my $past := $<xblock>[$count].ast;
if $<else> {
my $else := $<else>[0].ast;
$else.blocktype('immediate');
$past.push($else);
}
# build if/then/elsif structure
while $count > 0 {
$count--;
my $else := $past;
$past := $<xblock>[$count].ast;
$past.push($else);
}
make $past;
}
## Terms
method term:sym<identifier>($/) {
my $past := $<args>.ast;
$past.name(~$<ident>);
make $past;
}
method args($/) { make $<arglist>.ast; }
method arglist($/) {
my $past := PAST::Op.new( :pasttype('call'), :node($/) );
if $<EXPR> {
my $expr := $<EXPR>.ast;
if $expr.name eq 'infix:<,>' {
for $expr.list { $past.push($_); }
}
else { $past.push($expr); }
}
make $past;
}
method term:sym<value>($/) { make $<value>.ast; }
method circumfix:sym<( )>($/) { make $<EXPR>.ast; }
method circumfix:sym<ang>($/) { make $<quote_EXPR>.ast; }
method circumfix:sym<{ }>($/) { make $<pblock>.ast; }
method postcircumfix:sym<[ ]>($/) {
make PAST::Var.new( $<EXPR>.ast , :scope('keyed_int') );
}
method value($/) {
my $past := $<quote>
?? $<quote>.ast
!! PAST::Val.new( :value($<integer>.ast) );
make $past;
}
method quote:sym<apos>($/) { make $<quote_EXPR>.ast; }
method quote:sym<dblq>($/) { make $<quote_EXPR>.ast; }
method quote:sym<qq>($/) { make $<quote_EXPR>.ast; }
method quote:sym<q>($/) { make $<quote_EXPR>.ast; }
method quote:sym<Q>($/) { make $<quote_EXPR>.ast; }
## Operators
# These will eventually go in NQP::Grammar.
NQP::Grammar.O(':prec<y=>, :assoc<unary>', '%methodop');
NQP::Grammar.O(':prec<x=>, :assoc<unary>', '%autoincrement');
NQP::Grammar.O(':prec<w=>, :assoc<left>', '%exponentiation');
NQP::Grammar.O(':prec<v=>, :assoc<unary>', '%symbolic_unary');
NQP::Grammar.O(':prec<u=>, :assoc<left>', '%multiplicative');
NQP::Grammar.O(':prec<t=>, :assoc<left>', '%additive');
NQP::Grammar.O(':prec<r=>, :assoc<list>', '%concatenation');
NQP::Grammar.O(':prec<i=>, :assoc<right>', '%assignment');
NQP::Grammar.O(':prec<g=>, :assoc<list>, :nextterm<nulltermish>', '%comma');
NQP::Grammar.O(':prec<f=>, :assoc<list>', '%list_infix');
method nulltermish($/) {
make $<noun> ?? $<noun>.ast !! 0;
}