-
Notifications
You must be signed in to change notification settings - Fork 0
/
Cplusplus3.eyp
166 lines (113 loc) · 2.9 KB
/
Cplusplus3.eyp
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
%{
our $VERSION = '0.01';
use base q{DebugTail};
%}
%strict
%token ID INT NUM
%right '='
%left '+'
%tree bypass
%expect 0 1 # 0 shift-reduce conflicts, 1 reduce-reduce conflict
%%
prog:
%name EMPTY
/* empty */
| %name PROG
prog stmt
;
stmt:
%name EXP
expr ';'
| %name DECL
decl
;
expr:
%name EXPID
ID decexpconflict
| %name NUM
NUM
| %name TYPECAST
INT '(' expr ')' /* typecast */
| %name PLUS
expr '+' expr
| %name ASSIGN
expr '=' expr
;
decl:
%name DECLARATOR
INT declarator ';'
| %name DECLARATORINIT
INT declarator '=' expr ';'
;
declarator:
%name DECID
ID decexpconflict
| '(' declarator ')'
;
decexpconflict:
/* empty. Just to solve the reduce-reduce conflict */
{
my $self = shift;
if (${$self->input()} =~ m{^[)\s]*[;=]\s*}) {
$self->YYSetReduce(')', 'DECID' );
}
else {
$self->YYSetReduce(')', 'EXPID' );
}
}
;
%%
__PACKAGE__->lexer(
sub {
my $self = shift;
for (${$self->input()}) {
s{^(\s*)}{};
return ('', undef) unless $_;
return ('INT', $1) if s{^(int\b)}{};
return ('ID', $1) if (s{^([a-zA-Z_]\w*)}{});
return ('NUM', $1) if s/^(\d+)//;
return ($1, $1) if s/^(.)//;
}
return ('',undef);
}
);
unless (caller()) {
my $prompt = 'Try first "int (x) = 2;" then "int (x) + 2;" '.
'(press <CR><CTRL-D> to finish): ';
__PACKAGE__->main($prompt)
}
####################################################
=head1 SYNOPSIS
Compile it with
eyapp -b '' Cplusplus
Run it with:
./Cplusplus.pm -t
try with inputs:
int (x) = 2;
int (x) + 2;
the result will be the generated abstract sytax tree
=head1 C++ Ambiguities
This grammar models a problematic part of the C++ grammar—the ambiguity between certain
declarations and statements. For example,
int (x) = y+z;
parses as either an expr or a stmt.
Eyapp detects this as a reduce/reduce conflict:
State 17 contains 1 reduce/reduce conflict
State 17:
expr -> ID . (Rule 5)
declarator -> ID . (Rule 11)
')' [reduce using rule 11 (declarator)]
$default reduce using rule 5 (expr)
The C++ rule is: take it as a declaration if it looks as a declaration,
otherwise is an expression.
This Eyapp parser solves the problem by dynamically changing the parser.
=head1 SEE ALSO
=over 2
=item * The file C<Cplusplus2.eyp> in C<examples/debuggintut>
=item * L<http://www.gnu.org/software/bison/manual/html_mono/bison.html#GLR-Parsers>
=item * L<http://en.wikipedia.org/wiki/Significantly_Prettier_and_Easier_C%2B%2B_Syntax>
=item * L<http://www.csse.monash.edu.au/~damian/papers/PS/ModestProposal.ps>
=item * L<http://www.nobugs.org/developer/parsingcpp/>
=item * Edward Willink's "Meta-Compilation for C++" PhD thesis at L<http://www.computing.surrey.ac.uk/Research/CSRG/fog/FogThesis.pdf>
=back
=cut