| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
1
|
|
|
1
|
|
5
|
use Moops; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# PODNAME: MarpaX::Languages::M4::Impl::Parser |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
# ABSTRACT: M4 Marpa parser |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
# |
|
8
|
|
|
|
|
|
|
# Expose only the base implementation of parse() method |
|
9
|
|
|
|
|
|
|
# required by MarpaX::Languages::M4::Role::Parser |
|
10
|
|
|
|
|
|
|
# |
|
11
|
1
|
|
|
1
|
|
92111
|
class MarpaX::Languages::M4::Impl::Parser { |
|
|
1
|
|
|
1
|
|
27
|
|
|
|
1
|
|
|
|
|
9
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
56
|
|
|
|
1
|
|
|
|
|
281
|
|
|
|
1
|
|
|
|
|
1494
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
1254
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
8
|
|
|
|
1
|
|
|
|
|
62
|
|
|
|
1
|
|
|
|
|
9
|
|
|
|
1
|
|
|
|
|
45
|
|
|
|
1
|
|
|
|
|
6
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
91
|
|
|
|
1
|
|
|
|
|
29
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
9
|
|
|
|
1
|
|
|
|
|
4199
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
7
|
|
|
|
1
|
|
|
|
|
703
|
|
|
|
1
|
|
|
|
|
3479
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
135
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
8
|
|
|
|
1
|
|
|
|
|
324
|
|
|
|
1
|
|
|
|
|
6018
|
|
|
|
1
|
|
|
|
|
11
|
|
|
|
1
|
|
|
|
|
550
|
|
|
|
1
|
|
|
|
|
2313
|
|
|
|
1
|
|
|
|
|
6
|
|
|
|
1
|
|
|
|
|
1102
|
|
|
|
1
|
|
|
|
|
2294
|
|
|
|
1
|
|
|
|
|
7
|
|
|
|
1
|
|
|
|
|
110630
|
|
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
22
|
|
|
|
1
|
|
|
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
41
|
|
|
|
1
|
|
|
|
|
6
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
107
|
|
|
|
1
|
|
|
|
|
6835
|
|
|
|
0
|
|
|
|
|
0
|
|
|
12
|
1
|
|
|
1
|
|
365
|
use MarpaX::Languages::M4::Impl::Parser::Actions; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
12
|
|
|
13
|
1
|
|
|
1
|
|
56
|
use MarpaX::Languages::M4::Type::Macro -all; |
|
|
1
|
|
|
|
|
51
|
|
|
|
1
|
|
|
|
|
7
|
|
|
14
|
1
|
|
|
1
|
|
878
|
use MarpaX::Languages::M4::Impl::Value; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
4
|
|
|
15
|
1
|
|
|
1
|
|
423
|
use Marpa::R2; # 2.103_004; |
|
|
1
|
|
|
|
|
123594
|
|
|
|
1
|
|
|
|
|
21
|
|
|
16
|
1
|
|
|
1
|
|
52
|
use Scalar::Util qw/readonly/; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
86
|
|
|
17
|
1
|
|
|
1
|
|
7
|
use Types::Common::Numeric -all; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
10
|
|
|
18
|
|
|
|
|
|
|
# |
|
19
|
|
|
|
|
|
|
# --nesting_limit (SHOULD) take care of that |
|
20
|
|
|
|
|
|
|
# |
|
21
|
1
|
|
|
1
|
|
5732
|
no warnings 'recursion'; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
263
|
|
|
22
|
|
|
|
|
|
|
|
|
23
|
1
|
|
|
|
|
13
|
our $VERSION = '0.019'; # VERSION |
|
24
|
|
|
|
|
|
|
|
|
25
|
1
|
|
|
|
|
3
|
our $AUTHORITY = 'cpan:JDDPAUSE'; # AUTHORITY |
|
26
|
|
|
|
|
|
|
|
|
27
|
1
|
|
|
|
|
3
|
our $BASE_GRAMMAR = q{ |
|
28
|
|
|
|
|
|
|
inaccessible is ok by default |
|
29
|
|
|
|
|
|
|
:default ::= action => ::first |
|
30
|
|
|
|
|
|
|
lexeme default = latm => 1 |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# |
|
33
|
|
|
|
|
|
|
# Note: this part of the grammar is giving ambiguity |
|
34
|
|
|
|
|
|
|
# but we do not mind because the effect is always |
|
35
|
|
|
|
|
|
|
# the same: global concatenatation |
|
36
|
|
|
|
|
|
|
# |
|
37
|
|
|
|
|
|
|
argumentsGroup ::= tokens action => createArgumentsGroup rank => 1 |
|
38
|
|
|
|
|
|
|
| argumentsGroup LPAREN argumentsGroup RPAREN argumentsGroup action => mergeArgumentsGroup |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
arguments ::= argumentsGroup action => firstArg |
|
41
|
|
|
|
|
|
|
| arguments (COMMA) argumentsGroup action => nextArg |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
tokens ::= token* action => create |
|
44
|
|
|
|
|
|
|
event '^token' = predicted <token> # This event is to force $r->read() to not advance its location |
|
45
|
|
|
|
|
|
|
event 'token$' = completed <token> |
|
46
|
|
|
|
|
|
|
token ::= WORD |
|
47
|
|
|
|
|
|
|
| macro |
|
48
|
|
|
|
|
|
|
| QUOTEDSTRING |
|
49
|
|
|
|
|
|
|
| CHARACTER |
|
50
|
|
|
|
|
|
|
| COMMENT |
|
51
|
|
|
|
|
|
|
| ANYTHING |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
macro ::= MACRO # Never lexeme_read'ed |
|
54
|
|
|
|
|
|
|
| MACRO_ARGS macroArguments # Ditto |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
event 'macroArguments$' = completed <macroArguments> |
|
57
|
|
|
|
|
|
|
macroArguments ::= (LPAREN) arguments (RPAREN) |
|
58
|
|
|
|
|
|
|
macroArguments ::= (NOPARAM) action => fakeOneVoidParam |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
_ANYTHING ~ [\s\S] |
|
61
|
|
|
|
|
|
|
_NOTHING ~ [^\s\S] |
|
62
|
|
|
|
|
|
|
WORD ~ _NOTHING |
|
63
|
|
|
|
|
|
|
MACRO ~ _NOTHING |
|
64
|
|
|
|
|
|
|
MACRO_ARGS ~ _NOTHING |
|
65
|
|
|
|
|
|
|
QUOTEDSTRING ~ _NOTHING |
|
66
|
|
|
|
|
|
|
CHARACTER ~ _NOTHING |
|
67
|
|
|
|
|
|
|
COMMENT ~ _NOTHING |
|
68
|
|
|
|
|
|
|
# |
|
69
|
|
|
|
|
|
|
# ANYTHING will automatically eat a character each time we resume the SLIF: we |
|
70
|
|
|
|
|
|
|
# do not want this to happen |
|
71
|
|
|
|
|
|
|
# |
|
72
|
|
|
|
|
|
|
:lexeme ~ <ANYTHING> pause => before event => '^ANYTHING' |
|
73
|
|
|
|
|
|
|
ANYTHING ~ _ANYTHING |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
_WS ~ [\s] |
|
76
|
|
|
|
|
|
|
_WS_any ~ _WS* |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
:lexeme ~ <LPAREN> priority => 1 pause => before event => '^LPAREN' |
|
79
|
|
|
|
|
|
|
LPAREN ~ '(' _WS_any |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
:lexeme ~ <RPAREN> priority => 1 pause => before event => '^RPAREN' |
|
82
|
|
|
|
|
|
|
RPAREN ~ ')' |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
:lexeme ~ <NOPARAM> priority => 1 |
|
85
|
|
|
|
|
|
|
NOPARAM ~ '(' _WS_any ')' |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# |
|
88
|
|
|
|
|
|
|
# Quote from the spec (M4 POSIX): |
|
89
|
|
|
|
|
|
|
# If a macro name is followed by a <left-parenthesis>, its arguments are the <comma>-separated tokens |
|
90
|
|
|
|
|
|
|
# between the <left-parenthesis> and the matching <right-parenthesis>. Unquoted white-space characters |
|
91
|
|
|
|
|
|
|
# preceding each argument shall be ignored. All other characters, including trailing white-space characters, |
|
92
|
|
|
|
|
|
|
# are retained. |
|
93
|
|
|
|
|
|
|
# <comma> characters enclosed between <left-parenthesis> and <right-parenthesis> characters do not delimit arguments. |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
:lexeme ~ <COMMA> priority => 1 |
|
96
|
|
|
|
|
|
|
COMMA ~ ',' _WS_any |
|
97
|
|
|
|
|
|
|
}; |
|
98
|
|
|
|
|
|
|
|
|
99
|
1
|
|
|
|
|
1
|
our $BYTOKEN_G = do { |
|
100
|
|
|
|
|
|
|
my $g = Marpa::R2::Scanless::G->new( |
|
101
|
1
|
|
|
|
|
2
|
{ source => \do {":start ::= tokens\n$BASE_GRAMMAR"} |
|
|
1
|
|
|
|
|
47
|
|
|
102
|
|
|
|
|
|
|
} |
|
103
|
|
|
|
|
|
|
); |
|
104
|
|
|
|
|
|
|
}; |
|
105
|
1
|
|
|
|
|
204949
|
our $BYMACROARGUMENTS_G = do { |
|
106
|
|
|
|
|
|
|
my $g = Marpa::R2::Scanless::G->new( |
|
107
|
1
|
|
|
|
|
4
|
{ source => \do {":start ::= macroArguments\n$BASE_GRAMMAR"} |
|
|
1
|
|
|
|
|
30
|
|
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
); |
|
110
|
|
|
|
|
|
|
}; |
|
111
|
|
|
|
|
|
|
|
|
112
|
0
|
|
|
|
|
0
|
BEGIN { |
|
113
|
|
|
|
|
|
|
# |
|
114
|
|
|
|
|
|
|
# Marpa internal optimisation: we do not want the closures to be rechecked every time |
|
115
|
|
|
|
|
|
|
# we call $r->value(). This is a static information, although determined at run-time |
|
116
|
|
|
|
|
|
|
# the first time $r->value() is called on a recognizer. |
|
117
|
|
|
|
|
|
|
# |
|
118
|
1
|
|
|
1
|
|
7
|
no warnings 'redefine'; |
|
|
1
|
|
|
0
|
|
2
|
|
|
|
1
|
|
|
|
|
439
|
|
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
sub Marpa::R2::Recognizer::registrations { |
|
121
|
2024
|
|
|
2024
|
0
|
3882
|
my $recce = shift; |
|
122
|
2024
|
100
|
|
|
|
5312
|
if (@_) { |
|
123
|
2022
|
|
|
|
|
4795
|
my $hash = shift; |
|
124
|
2022
|
50
|
33
|
|
|
16005
|
if (! defined($hash) || |
|
|
|
|
33
|
|
|
|
|
|
125
|
|
|
|
|
|
|
ref($hash) ne 'HASH' || |
|
126
|
14154
|
|
|
|
|
36579
|
grep {! exists($hash->{$_})} qw/ |
|
127
|
|
|
|
|
|
|
NULL_VALUES |
|
128
|
|
|
|
|
|
|
REGISTRATIONS |
|
129
|
|
|
|
|
|
|
CLOSURE_BY_SYMBOL_ID |
|
130
|
|
|
|
|
|
|
CLOSURE_BY_RULE_ID |
|
131
|
|
|
|
|
|
|
RESOLVE_PACKAGE |
|
132
|
|
|
|
|
|
|
RESOLVE_PACKAGE_SOURCE |
|
133
|
|
|
|
|
|
|
PER_PARSE_CONSTRUCTOR |
|
134
|
|
|
|
|
|
|
/) { |
|
135
|
|
|
|
|
|
|
Marpa::R2::exception( |
|
136
|
|
|
|
|
|
|
"Attempt to reuse registrations failed:\n", |
|
137
|
|
|
|
|
|
|
" Registration data is not a hash containing all necessary keys:\n", |
|
138
|
0
|
0
|
|
|
|
0
|
" Got : " . ((ref($hash) eq 'HASH') ? join(', ', sort keys %{$hash}) : '') . "\n", |
|
|
0
|
|
|
|
|
0
|
|
|
139
|
|
|
|
|
|
|
" Want: CLOSURE_BY_RULE_ID, CLOSURE_BY_SYMBOL_ID, NULL_VALUES, PER_PARSE_CONSTRUCTOR, REGISTRATIONS, RESOLVE_PACKAGE, RESOLVE_PACKAGE_SOURCE\n" |
|
140
|
|
|
|
|
|
|
); |
|
141
|
|
|
|
|
|
|
} |
|
142
|
2022
|
|
|
|
|
5391
|
$recce->[Marpa::R2::Internal::Recognizer::NULL_VALUES] = $hash->{NULL_VALUES}; |
|
143
|
2022
|
|
|
|
|
4660
|
$recce->[Marpa::R2::Internal::Recognizer::REGISTRATIONS] = $hash->{REGISTRATIONS}; |
|
144
|
2022
|
|
|
|
|
3927
|
$recce->[Marpa::R2::Internal::Recognizer::CLOSURE_BY_SYMBOL_ID] = $hash->{CLOSURE_BY_SYMBOL_ID}; |
|
145
|
2022
|
|
|
|
|
3978
|
$recce->[Marpa::R2::Internal::Recognizer::CLOSURE_BY_RULE_ID] = $hash->{CLOSURE_BY_RULE_ID}; |
|
146
|
2022
|
|
|
|
|
5087
|
$recce->[Marpa::R2::Internal::Recognizer::RESOLVE_PACKAGE] = $hash->{RESOLVE_PACKAGE}; |
|
147
|
2022
|
|
|
|
|
4068
|
$recce->[Marpa::R2::Internal::Recognizer::RESOLVE_PACKAGE_SOURCE] = $hash->{RESOLVE_PACKAGE_SOURCE}; |
|
148
|
2022
|
|
|
|
|
4440
|
$recce->[Marpa::R2::Internal::Recognizer::PER_PARSE_CONSTRUCTOR] = $hash->{PER_PARSE_CONSTRUCTOR}; |
|
149
|
|
|
|
|
|
|
} |
|
150
|
|
|
|
|
|
|
return { |
|
151
|
2024
|
|
|
|
|
19423
|
NULL_VALUES => $recce->[Marpa::R2::Internal::Recognizer::NULL_VALUES], |
|
152
|
|
|
|
|
|
|
REGISTRATIONS => $recce->[Marpa::R2::Internal::Recognizer::REGISTRATIONS], |
|
153
|
|
|
|
|
|
|
CLOSURE_BY_SYMBOL_ID => $recce->[Marpa::R2::Internal::Recognizer::CLOSURE_BY_SYMBOL_ID], |
|
154
|
|
|
|
|
|
|
CLOSURE_BY_RULE_ID => $recce->[Marpa::R2::Internal::Recognizer::CLOSURE_BY_RULE_ID], |
|
155
|
|
|
|
|
|
|
RESOLVE_PACKAGE => $recce->[Marpa::R2::Internal::Recognizer::RESOLVE_PACKAGE], |
|
156
|
|
|
|
|
|
|
RESOLVE_PACKAGE_SOURCE => $recce->[Marpa::R2::Internal::Recognizer::RESOLVE_PACKAGE_SOURCE], |
|
157
|
|
|
|
|
|
|
PER_PARSE_CONSTRUCTOR => $recce->[Marpa::R2::Internal::Recognizer::PER_PARSE_CONSTRUCTOR] |
|
158
|
|
|
|
|
|
|
}; |
|
159
|
|
|
|
|
|
|
} ## end sub registrations |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub Marpa::R2::Scanless::R::registrations { |
|
162
|
2024
|
|
|
2024
|
|
5197
|
my $slr = shift; |
|
163
|
2024
|
|
|
|
|
4393
|
my $thick_g1_recce = |
|
164
|
|
|
|
|
|
|
$slr->[Marpa::R2::Internal::Scanless::R::THICK_G1_RECCE]; |
|
165
|
2024
|
|
|
|
|
7477
|
return $thick_g1_recce->registrations(@_); |
|
166
|
|
|
|
|
|
|
} ## end sub Marpa::R2::Scanless::R::registrations |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
} |
|
169
|
|
|
|
|
|
|
|
|
170
|
1
|
|
|
|
|
74624
|
has _parse_level => ( |
|
171
|
|
|
|
|
|
|
is => 'rwp', |
|
172
|
|
|
|
|
|
|
isa => PositiveOrZeroInt, |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
# trigger => 1, |
|
175
|
|
|
|
|
|
|
default => 0 |
|
176
|
|
|
|
|
|
|
); |
|
177
|
|
|
|
|
|
|
|
|
178
|
1
|
0
|
|
1
|
|
2992
|
method _trigger__parse_level (PositiveOrZeroInt $parse_level, @rest) { |
|
|
1
|
0
|
|
1
|
|
2
|
|
|
|
1
|
0
|
|
0
|
|
127
|
|
|
|
1
|
0
|
|
|
|
5
|
|
|
|
1
|
0
|
|
|
|
3
|
|
|
|
1
|
0
|
|
|
|
145
|
|
|
|
1
|
|
|
|
|
2667
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
179
|
|
|
|
|
|
|
# |
|
180
|
|
|
|
|
|
|
# GNU testing of nesting_limit is another implementation, this |
|
181
|
|
|
|
|
|
|
# has no meaning for us. So, even if supported, this option does |
|
182
|
|
|
|
|
|
|
# nothing: the trigger is NOT enabled. |
|
183
|
|
|
|
|
|
|
# |
|
184
|
0
|
|
|
|
|
0
|
my $nesting_limit = $self->impl_nestingLimit; |
|
185
|
0
|
0
|
0
|
|
|
0
|
if ( $nesting_limit > 0 && $parse_level > $nesting_limit ) { |
|
186
|
0
|
|
|
|
|
0
|
$self->impl_raiseException( |
|
187
|
|
|
|
|
|
|
sprintf( 'Nesting limit of %d exceeded', $nesting_limit ) ); |
|
188
|
|
|
|
|
|
|
} |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
|
|
191
|
1
|
50
|
|
1
|
|
2285
|
method parser_parse (Str $input --> Str) { |
|
|
1
|
50
|
|
1
|
|
3
|
|
|
|
1
|
50
|
|
164
|
|
129
|
|
|
|
1
|
50
|
|
|
|
6
|
|
|
|
1
|
50
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
85
|
|
|
|
1
|
|
|
|
|
409
|
|
|
|
164
|
|
|
|
|
2060
|
|
|
|
164
|
|
|
|
|
676
|
|
|
|
164
|
|
|
|
|
737
|
|
|
|
164
|
|
|
|
|
574
|
|
|
|
164
|
|
|
|
|
423
|
|
|
|
164
|
|
|
|
|
705
|
|
|
|
164
|
|
|
|
|
313
|
|
|
192
|
|
|
|
|
|
|
# |
|
193
|
|
|
|
|
|
|
# We will modify the buffer in-place, therefore we want to |
|
194
|
|
|
|
|
|
|
# have OUR version of the input. |
|
195
|
|
|
|
|
|
|
# In addition, this will solve the eventual problem of $input |
|
196
|
|
|
|
|
|
|
# being a read-only variable |
|
197
|
|
|
|
|
|
|
# |
|
198
|
164
|
|
|
|
|
359
|
my $work = $input; |
|
199
|
164
|
|
|
|
|
3163
|
return $self->_parseByTokens( \$work ); |
|
200
|
|
|
|
|
|
|
} |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
# |
|
203
|
|
|
|
|
|
|
# By token => ConsumerOf['MarpaX::Languages::M4::Role::Value by default'] |
|
204
|
|
|
|
|
|
|
# By arguments => ArrayRef[ConsumerOf['MarpaX::Languages::M4::Role::Value']] |
|
205
|
|
|
|
|
|
|
# |
|
206
|
1
|
50
|
33
|
1
|
|
19676
|
method _parseByGrammar (Ref['SCALAR'] $inputRef, PositiveOrZeroInt $pos, InstanceOf['Marpa::R2::Scanless::G'] $g, Undef|M4Macro $macro? --> Undef|Dict[pos => PositiveOrZeroInt, value => ConsumerOf['MarpaX::Languages::M4::Role::Value']]) { |
|
|
1
|
50
|
33
|
1
|
|
2
|
|
|
|
1
|
50
|
|
1
|
|
165
|
|
|
|
1
|
50
|
|
1
|
|
6
|
|
|
|
1
|
50
|
|
1
|
|
2
|
|
|
|
1
|
50
|
|
2018
|
|
122
|
|
|
|
1
|
50
|
|
|
|
9
|
|
|
|
1
|
50
|
|
|
|
3
|
|
|
|
1
|
50
|
|
|
|
93
|
|
|
|
1
|
50
|
|
|
|
6
|
|
|
|
1
|
50
|
|
|
|
1
|
|
|
|
1
|
50
|
|
|
|
110
|
|
|
|
1
|
100
|
|
|
|
5
|
|
|
|
1
|
50
|
|
|
|
2
|
|
|
|
1
|
100
|
|
|
|
2151
|
|
|
|
1
|
|
|
|
|
2816
|
|
|
|
2018
|
|
|
|
|
20158
|
|
|
|
2018
|
|
|
|
|
6076
|
|
|
|
2018
|
|
|
|
|
6347
|
|
|
|
2018
|
|
|
|
|
6683
|
|
|
|
2018
|
|
|
|
|
5863
|
|
|
|
2018
|
|
|
|
|
4393
|
|
|
|
2018
|
|
|
|
|
14714
|
|
|
|
2018
|
|
|
|
|
5964
|
|
|
|
2018
|
|
|
|
|
5523
|
|
|
|
2018
|
|
|
|
|
2980
|
|
|
|
2018
|
|
|
|
|
7119
|
|
|
|
2018
|
|
|
|
|
6250
|
|
|
|
2018
|
|
|
|
|
6050
|
|
|
|
2018
|
|
|
|
|
4090
|
|
|
|
2018
|
|
|
|
|
10477
|
|
|
|
2018
|
|
|
|
|
6694
|
|
|
|
2018
|
|
|
|
|
5519
|
|
|
|
1854
|
|
|
|
|
2987
|
|
|
|
1854
|
|
|
|
|
5967
|
|
|
|
2018
|
|
|
|
|
39453
|
|
|
207
|
|
|
|
|
|
|
|
|
208
|
2018
|
|
|
|
|
3755
|
my $maxPos = length( ${$inputRef} ) - 1; |
|
|
2018
|
|
|
|
|
5533
|
|
|
209
|
|
|
|
|
|
|
# |
|
210
|
|
|
|
|
|
|
# Protect the case of empty string. |
|
211
|
|
|
|
|
|
|
# This is affecting all parsing levels. |
|
212
|
|
|
|
|
|
|
# |
|
213
|
2018
|
100
|
|
|
|
5544
|
if ( $pos > $maxPos ) { |
|
214
|
1
|
|
|
|
|
18
|
return; |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
# |
|
217
|
|
|
|
|
|
|
# Get the lexemes ordering |
|
218
|
|
|
|
|
|
|
# |
|
219
|
2017
|
|
|
|
|
8925
|
my @lexemeNames = $self->parser_tokensPriority(); |
|
220
|
|
|
|
|
|
|
# |
|
221
|
|
|
|
|
|
|
# In the context of a macroArguments, unquoted parenthesis |
|
222
|
|
|
|
|
|
|
# have higher priorities over everything, except quoted string |
|
223
|
|
|
|
|
|
|
# and comment. |
|
224
|
|
|
|
|
|
|
# |
|
225
|
2017
|
100
|
|
|
|
111328
|
if ( $g == $BYMACROARGUMENTS_G ) { |
|
226
|
1854
|
|
|
|
|
8024
|
unshift( @lexemeNames, 'NOPARAM', 'LPAREN', 'RPAREN', 'COMMA' ); |
|
227
|
|
|
|
|
|
|
} |
|
228
|
|
|
|
|
|
|
|
|
229
|
2017
|
|
|
|
|
36932
|
my $value = MarpaX::Languages::M4::Impl::Value->new(); |
|
230
|
2017
|
|
|
|
|
68612
|
my %rc = ( pos => $pos, value => $value ); |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
# |
|
233
|
|
|
|
|
|
|
# Instanciate and start recognizer |
|
234
|
|
|
|
|
|
|
# |
|
235
|
2017
|
|
|
|
|
18000
|
my $r = Marpa::R2::Scanless::R->new( |
|
236
|
|
|
|
|
|
|
{ grammar => $g, |
|
237
|
|
|
|
|
|
|
semantics_package => 'MarpaX::Languages::M4::Impl::Parser::Actions', |
|
238
|
|
|
|
|
|
|
exhaustion => 'event', |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
# trace_terminals => 1, |
|
241
|
|
|
|
|
|
|
# trace_values => 1 |
|
242
|
|
|
|
|
|
|
} |
|
243
|
|
|
|
|
|
|
); |
|
244
|
|
|
|
|
|
|
# |
|
245
|
|
|
|
|
|
|
# $prevPos is used only for logging |
|
246
|
|
|
|
|
|
|
# |
|
247
|
2017
|
|
|
|
|
681443
|
my $prevPos = $rc{pos} = $pos; |
|
248
|
|
|
|
|
|
|
# |
|
249
|
|
|
|
|
|
|
# The stream itself is of no importance. |
|
250
|
|
|
|
|
|
|
# We use Marpa to drive the context, nothing more. |
|
251
|
|
|
|
|
|
|
# But is it NOT a hasard that I use the constant '(': |
|
252
|
|
|
|
|
|
|
# when doing a recursive call using |
|
253
|
|
|
|
|
|
|
# the macroByarguments grammar, Marpa will expect this |
|
254
|
|
|
|
|
|
|
# character at the first read, EVEN |
|
255
|
|
|
|
|
|
|
# if we paused before it. |
|
256
|
|
|
|
|
|
|
# |
|
257
|
2017
|
|
|
|
|
9195
|
$r->read( \'(' ); |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
again: |
|
260
|
4440
|
|
|
|
|
233644
|
while ( $rc{pos} <= $maxPos ) { |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
# $self->logger_debug( '[%d..%d/%d] 20 first characters: %s', |
|
263
|
|
|
|
|
|
|
# $rc{pos}, $rc{pos}, $maxPos, |
|
264
|
|
|
|
|
|
|
# substr( ${$inputRef}, $rc{pos}, 20 ) ); |
|
265
|
|
|
|
|
|
|
|
|
266
|
23409
|
|
|
|
|
41132
|
my %expected = map { $_ => 1 } @{ $r->terminals_expected }; |
|
|
186963
|
|
|
|
|
2714551
|
|
|
|
23409
|
|
|
|
|
65928
|
|
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
# $self->logger_debug( |
|
269
|
|
|
|
|
|
|
# '[%d..%d/%d] Expected terminals: %s', |
|
270
|
|
|
|
|
|
|
# $rc{pos}, $rc{pos}, $maxPos, |
|
271
|
|
|
|
|
|
|
# [ keys %expected ] |
|
272
|
|
|
|
|
|
|
# ); |
|
273
|
|
|
|
|
|
|
|
|
274
|
23409
|
100
|
|
|
|
106006
|
if ( $r->exhausted ) { |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
# $self->logger_debug( '[%d..%d/%d] Parse is exhausted', |
|
277
|
|
|
|
|
|
|
# $rc{pos}, $rc{pos}, $maxPos ); |
|
278
|
|
|
|
|
|
|
|
|
279
|
1823
|
|
|
|
|
20017
|
last; |
|
280
|
|
|
|
|
|
|
} |
|
281
|
|
|
|
|
|
|
|
|
282
|
21586
|
|
|
|
|
285953
|
my $lexemeValue; |
|
283
|
|
|
|
|
|
|
my $lexemeLength; |
|
284
|
21586
|
|
|
|
|
0
|
my $lexeme; |
|
285
|
|
|
|
|
|
|
|
|
286
|
21586
|
|
|
|
|
0
|
my $QuotedstringValue; |
|
287
|
21586
|
|
|
|
|
0
|
my $QuotedstringLength; |
|
288
|
21586
|
|
|
|
|
68384
|
my $isQuotedString = false; |
|
289
|
|
|
|
|
|
|
|
|
290
|
21586
|
|
|
|
|
78419
|
my $CommentValue; |
|
291
|
|
|
|
|
|
|
my $CommentLength; |
|
292
|
21586
|
|
|
|
|
40783
|
my $isComment = false; |
|
293
|
|
|
|
|
|
|
|
|
294
|
21586
|
|
|
|
|
74830
|
my $canCollectArguments = true; |
|
295
|
21586
|
100
|
|
|
|
91899
|
if ( $g == $BYMACROARGUMENTS_G ) { |
|
296
|
16948
|
|
|
|
|
30800
|
my $blockOk = false; |
|
297
|
|
|
|
|
|
|
try { |
|
298
|
|
|
|
|
|
|
$isQuotedString |
|
299
|
16948
|
|
|
|
|
375149
|
= $self->parser_isQuotedstring( ${$inputRef}, |
|
300
|
|
|
|
|
|
|
$rc{pos}, |
|
301
|
16948
|
|
|
16948
|
|
418330
|
$maxPos, \$QuotedstringValue, \$QuotedstringLength ); |
|
302
|
|
|
|
|
|
|
$isComment |
|
303
|
16948
|
|
|
|
|
272955
|
= $self->parser_isComment( ${$inputRef}, $rc{pos}, |
|
304
|
16948
|
|
|
|
|
397989
|
$maxPos, \$CommentValue, \$CommentLength ); |
|
305
|
16948
|
|
100
|
|
|
426204
|
$canCollectArguments = !$isQuotedString && !$isComment; |
|
306
|
16948
|
|
|
|
|
41256
|
$blockOk = true; |
|
307
|
16948
|
|
|
|
|
139422
|
}; |
|
308
|
16948
|
50
|
|
|
|
263075
|
if ( !$blockOk ) { |
|
309
|
0
|
|
|
|
|
0
|
goto return_error; |
|
310
|
|
|
|
|
|
|
} |
|
311
|
|
|
|
|
|
|
} |
|
312
|
|
|
|
|
|
|
|
|
313
|
21586
|
|
|
|
|
49164
|
foreach (@lexemeNames) { |
|
314
|
112029
|
100
|
|
|
|
290110
|
if ( $_ eq 'NOPARAM' ) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
315
|
16948
|
100
|
66
|
|
|
46684
|
if ( exists( $expected{NOPARAM} ) |
|
316
|
|
|
|
|
|
|
&& $canCollectArguments ) |
|
317
|
|
|
|
|
|
|
{ |
|
318
|
1854
|
|
|
|
|
4193
|
pos( ${$inputRef} ) = $rc{pos}; |
|
|
1854
|
|
|
|
|
6380
|
|
|
319
|
1854
|
100
|
|
|
|
3758
|
if ( ${$inputRef} =~ /\G\(\s*\)/s ) { |
|
|
1854
|
|
|
|
|
11386
|
|
|
320
|
15
|
|
|
|
|
40
|
$lexeme = 'NOPARAM'; |
|
321
|
15
|
|
|
|
|
30
|
$lexemeValue = substr( ${$inputRef}, $-[0], |
|
|
15
|
|
|
|
|
121
|
|
|
322
|
|
|
|
|
|
|
$+[0] - $-[0] ); |
|
323
|
15
|
|
|
|
|
77
|
$lexemeLength = $+[0] - $-[0]; |
|
324
|
15
|
|
|
|
|
50
|
last; |
|
325
|
|
|
|
|
|
|
} |
|
326
|
|
|
|
|
|
|
} |
|
327
|
|
|
|
|
|
|
} |
|
328
|
|
|
|
|
|
|
elsif ( $_ eq 'LPAREN' ) { |
|
329
|
16933
|
100
|
66
|
|
|
60674
|
if ( exists( $expected{LPAREN} ) |
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
330
|
|
|
|
|
|
|
&& $canCollectArguments |
|
331
|
12860
|
|
|
|
|
22610
|
&& do { pos( ${$inputRef} ) = $rc{pos}; 1 } |
|
|
12860
|
|
|
|
|
41295
|
|
|
|
12860
|
|
|
|
|
40825
|
|
|
332
|
12860
|
|
|
|
|
53345
|
&& ${$inputRef} =~ /\G\(\s*/ |
|
333
|
|
|
|
|
|
|
) |
|
334
|
|
|
|
|
|
|
{ |
|
335
|
1870
|
|
|
|
|
4288
|
$lexeme = 'LPAREN'; |
|
336
|
1870
|
|
|
|
|
14509
|
$lexemeLength = $+[0] - $-[0]; |
|
337
|
|
|
|
|
|
|
$lexemeValue |
|
338
|
1870
|
|
|
|
|
4717
|
= substr( ${$inputRef}, $-[0], $lexemeLength ); |
|
|
1870
|
|
|
|
|
9092
|
|
|
339
|
1870
|
|
|
|
|
4091
|
last; |
|
340
|
|
|
|
|
|
|
} |
|
341
|
|
|
|
|
|
|
} |
|
342
|
|
|
|
|
|
|
elsif ( $_ eq 'RPAREN' ) { |
|
343
|
15063
|
100
|
66
|
|
|
49590
|
if ( exists( $expected{RPAREN} ) |
|
|
|
|
100
|
|
|
|
|
|
344
|
|
|
|
|
|
|
&& $canCollectArguments |
|
345
|
10990
|
|
|
|
|
41741
|
&& substr( ${$inputRef}, $rc{pos}, 1 ) eq ')' ) |
|
346
|
|
|
|
|
|
|
{ |
|
347
|
1869
|
|
|
|
|
3879
|
$lexeme = 'RPAREN'; |
|
348
|
1869
|
|
|
|
|
3585
|
$lexemeValue = ')'; |
|
349
|
1869
|
|
|
|
|
3187
|
$lexemeLength = 1; |
|
350
|
1869
|
|
|
|
|
3304
|
last; |
|
351
|
|
|
|
|
|
|
} |
|
352
|
|
|
|
|
|
|
} |
|
353
|
|
|
|
|
|
|
elsif ( $_ eq 'COMMA' ) { |
|
354
|
13194
|
100
|
100
|
|
|
41309
|
if ( exists( $expected{COMMA} ) && $canCollectArguments ) |
|
355
|
|
|
|
|
|
|
{ |
|
356
|
9025
|
|
|
|
|
14526
|
pos( ${$inputRef} ) = $rc{pos}; |
|
|
9025
|
|
|
|
|
20097
|
|
|
357
|
9025
|
100
|
|
|
|
15573
|
if ( ${$inputRef} =~ /\G,\s*/s ) { |
|
|
9025
|
|
|
|
|
30947
|
|
|
358
|
2666
|
|
|
|
|
4966
|
$lexeme = 'COMMA'; |
|
359
|
2666
|
|
|
|
|
4014
|
$lexemeValue = substr( ${$inputRef}, $-[0], |
|
|
2666
|
|
|
|
|
26427
|
|
|
360
|
|
|
|
|
|
|
$+[0] - $-[0] ); |
|
361
|
2666
|
|
|
|
|
17067
|
$lexemeLength = $+[0] - $-[0]; |
|
362
|
2666
|
|
|
|
|
5641
|
last; |
|
363
|
|
|
|
|
|
|
} |
|
364
|
|
|
|
|
|
|
} |
|
365
|
|
|
|
|
|
|
} |
|
366
|
|
|
|
|
|
|
else { |
|
367
|
49891
|
100
|
100
|
|
|
207650
|
if ( $g == $BYMACROARGUMENTS_G && $_ eq 'QUOTEDSTRING' ) { |
|
|
|
100
|
100
|
|
|
|
|
|
368
|
|
|
|
|
|
|
# |
|
369
|
|
|
|
|
|
|
# Already done in the context of macro arguments grammar |
|
370
|
|
|
|
|
|
|
# |
|
371
|
9654
|
100
|
|
|
|
20881
|
if ($isQuotedString) { |
|
372
|
4068
|
|
|
|
|
6070
|
$lexeme = $_; |
|
373
|
4068
|
|
|
|
|
7206
|
$lexemeValue = $QuotedstringValue; |
|
374
|
4068
|
|
|
|
|
5763
|
$lexemeLength = $QuotedstringLength; |
|
375
|
4068
|
|
|
|
|
7794
|
last; |
|
376
|
|
|
|
|
|
|
} |
|
377
|
|
|
|
|
|
|
} |
|
378
|
|
|
|
|
|
|
elsif ( $g == $BYMACROARGUMENTS_G && $_ eq 'COMMENT' ) { |
|
379
|
|
|
|
|
|
|
# |
|
380
|
|
|
|
|
|
|
# Already done in the context of macro arguments grammar |
|
381
|
|
|
|
|
|
|
# |
|
382
|
10528
|
100
|
|
|
|
25514
|
if ($isComment) { |
|
383
|
5
|
|
|
|
|
11
|
$lexeme = $_; |
|
384
|
5
|
|
|
|
|
9
|
$lexemeValue = $CommentValue; |
|
385
|
5
|
|
|
|
|
9
|
$lexemeLength = $CommentLength; |
|
386
|
5
|
|
|
|
|
10
|
last; |
|
387
|
|
|
|
|
|
|
} |
|
388
|
|
|
|
|
|
|
} |
|
389
|
|
|
|
|
|
|
else { |
|
390
|
|
|
|
|
|
|
# |
|
391
|
|
|
|
|
|
|
# QUOTEDSTRING is not already done if not |
|
392
|
|
|
|
|
|
|
# in the context of macro arguments grammar |
|
393
|
|
|
|
|
|
|
# Ditto for COMMENT. |
|
394
|
|
|
|
|
|
|
# |
|
395
|
29709
|
|
|
|
|
83813
|
my $method = 'parser_is' . ucfirst( lc($_) ); |
|
396
|
29709
|
|
|
|
|
73021
|
my $blockOk = false; |
|
397
|
29709
|
|
|
|
|
100416
|
my $isToken; |
|
398
|
|
|
|
|
|
|
try { |
|
399
|
29709
|
|
|
|
|
634105
|
$isToken = $self->$method( ${$inputRef}, $rc{pos}, |
|
400
|
29709
|
|
|
29709
|
|
691309
|
$maxPos, \$lexemeValue, \$lexemeLength ); |
|
401
|
29705
|
|
|
|
|
761513
|
$blockOk = true; |
|
402
|
29709
|
|
|
|
|
168918
|
}; |
|
403
|
29709
|
100
|
|
|
|
444848
|
if ( !$blockOk ) { |
|
404
|
4
|
|
|
|
|
241
|
goto return_error; |
|
405
|
|
|
|
|
|
|
} |
|
406
|
29705
|
100
|
|
|
|
84409
|
if ($isToken) { |
|
407
|
11089
|
|
|
|
|
18857
|
$lexeme = $_; |
|
408
|
11089
|
|
|
|
|
21959
|
last; |
|
409
|
|
|
|
|
|
|
} |
|
410
|
|
|
|
|
|
|
} |
|
411
|
|
|
|
|
|
|
} |
|
412
|
|
|
|
|
|
|
} |
|
413
|
|
|
|
|
|
|
# |
|
414
|
|
|
|
|
|
|
# Nothing ? |
|
415
|
|
|
|
|
|
|
# |
|
416
|
21582
|
50
|
|
|
|
62630
|
if ( Undef->check($lexeme) ) { |
|
417
|
0
|
|
|
|
|
0
|
goto return_error; |
|
418
|
|
|
|
|
|
|
} |
|
419
|
|
|
|
|
|
|
# |
|
420
|
|
|
|
|
|
|
# If it is a word, check if this is eventually a macro |
|
421
|
|
|
|
|
|
|
# |
|
422
|
21582
|
100
|
|
|
|
241719
|
if ( $lexeme eq 'WORD' ) { |
|
423
|
3089
|
|
|
|
|
6368
|
my $thisMacro; |
|
424
|
|
|
|
|
|
|
my $lparenPos; |
|
425
|
3089
|
100
|
|
|
|
7948
|
if ($self->parser_isMacro( |
|
426
|
3089
|
|
|
|
|
59519
|
${$inputRef}, $rc{pos}, $maxPos, |
|
427
|
|
|
|
|
|
|
$lexemeValue, $lexemeLength, \$thisMacro, |
|
428
|
|
|
|
|
|
|
\$lparenPos |
|
429
|
|
|
|
|
|
|
) |
|
430
|
|
|
|
|
|
|
) |
|
431
|
|
|
|
|
|
|
{ |
|
432
|
2441
|
|
|
|
|
97055
|
my $canTrace = $self->_canTrace($thisMacro); |
|
433
|
2441
|
|
|
|
|
98825
|
my $macroCallId |
|
434
|
|
|
|
|
|
|
= $self->impl_macroExecuteHeader( $thisMacro, |
|
435
|
|
|
|
|
|
|
$canTrace ); |
|
436
|
|
|
|
|
|
|
# |
|
437
|
|
|
|
|
|
|
# Collect macro arguments |
|
438
|
|
|
|
|
|
|
# |
|
439
|
2441
|
|
|
|
|
20569
|
my @args = (); |
|
440
|
|
|
|
|
|
|
|
|
441
|
2441
|
100
|
|
|
|
6919
|
if ( $lparenPos >= 0 ) { |
|
442
|
|
|
|
|
|
|
|
|
443
|
1854
|
|
|
|
|
32208
|
$self->_set__parse_level( $self->_parse_level + 1 ); |
|
444
|
1854
|
|
|
|
|
99875
|
my $dict = $self->_parseByGrammar( |
|
445
|
|
|
|
|
|
|
$inputRef, $lparenPos, |
|
446
|
|
|
|
|
|
|
$BYMACROARGUMENTS_G, $thisMacro |
|
447
|
|
|
|
|
|
|
); |
|
448
|
1853
|
|
|
|
|
162109
|
$self->_set__parse_level( $self->_parse_level - 1 ); |
|
449
|
1853
|
50
|
|
|
|
81173
|
if ( Undef->check($dict) ) { |
|
450
|
0
|
|
|
|
|
0
|
goto return_error; |
|
451
|
|
|
|
|
|
|
} |
|
452
|
1853
|
|
|
|
|
21981
|
@args = $dict->{value}->value_elements; |
|
453
|
1853
|
|
|
|
|
91648
|
$lexemeLength = $dict->{pos} - $rc{pos}; |
|
454
|
|
|
|
|
|
|
} |
|
455
|
|
|
|
|
|
|
# |
|
456
|
|
|
|
|
|
|
# It is the reponsability of implementation to make sure |
|
457
|
|
|
|
|
|
|
# that a macro never croaks. |
|
458
|
|
|
|
|
|
|
# |
|
459
|
|
|
|
|
|
|
$lexemeValue |
|
460
|
2440
|
|
|
|
|
44226
|
= $self->impl_macroExecuteNoHeader( $thisMacro, |
|
461
|
|
|
|
|
|
|
$macroCallId, $canTrace, @args ); |
|
462
|
|
|
|
|
|
|
# |
|
463
|
|
|
|
|
|
|
# Eventual postmatch length |
|
464
|
|
|
|
|
|
|
# |
|
465
|
|
|
|
|
|
|
$lexemeLength |
|
466
|
|
|
|
|
|
|
+= $thisMacro->macro_postMatchLengthExecute( $self, |
|
467
|
2438
|
|
|
|
|
22072
|
${$inputRef}, $rc{pos} + $lexemeLength, $maxPos ); |
|
|
2438
|
|
|
|
|
45627
|
|
|
468
|
|
|
|
|
|
|
# |
|
469
|
|
|
|
|
|
|
# Input is changing |
|
470
|
|
|
|
|
|
|
# |
|
471
|
2438
|
100
|
|
|
|
10333
|
if ( M4Macro->check($lexemeValue) ) { |
|
472
|
|
|
|
|
|
|
# |
|
473
|
|
|
|
|
|
|
# Protect the case of M4Macro |
|
474
|
|
|
|
|
|
|
# |
|
475
|
15
|
|
|
|
|
493
|
$lexeme = 'ANYTHING'; |
|
476
|
|
|
|
|
|
|
} |
|
477
|
|
|
|
|
|
|
else { |
|
478
|
|
|
|
|
|
|
# $self->logger_debug( |
|
479
|
|
|
|
|
|
|
# '[%d..%d/%d] Input is changing: replace %s by %s', |
|
480
|
|
|
|
|
|
|
# $rc{pos}, |
|
481
|
|
|
|
|
|
|
# $rc{pos}, |
|
482
|
|
|
|
|
|
|
# $maxPos, |
|
483
|
|
|
|
|
|
|
# substr( |
|
484
|
|
|
|
|
|
|
# ${$inputRef}, $rc{pos}, $lexemeLength |
|
485
|
|
|
|
|
|
|
# ), |
|
486
|
|
|
|
|
|
|
# $lexemeValue |
|
487
|
|
|
|
|
|
|
# ); |
|
488
|
|
|
|
|
|
|
substr( |
|
489
|
2423
|
|
|
|
|
13340
|
${$inputRef}, $rc{pos}, |
|
490
|
2423
|
|
|
|
|
34618
|
$lexemeLength, $lexemeValue |
|
491
|
|
|
|
|
|
|
); |
|
492
|
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
# $self->logger_debug( '[%d..%d/%d] New input: %s', |
|
494
|
|
|
|
|
|
|
# $rc{pos}, $rc{pos}, $maxPos, ${$inputRef} ); |
|
495
|
|
|
|
|
|
|
|
|
496
|
2423
|
|
|
|
|
4550
|
$maxPos = length( ${$inputRef} ) - 1; |
|
|
2423
|
|
|
|
|
9979
|
|
|
497
|
2423
|
|
|
|
|
103272
|
goto again; |
|
498
|
|
|
|
|
|
|
} |
|
499
|
|
|
|
|
|
|
} |
|
500
|
|
|
|
|
|
|
else { |
|
501
|
|
|
|
|
|
|
# $self->logger_debug( |
|
502
|
|
|
|
|
|
|
# '[%d..%d/%d] %s is not an acceptable macro call', |
|
503
|
|
|
|
|
|
|
# $rc{pos}, $rc{pos}, $maxPos, $lexemeValue ); |
|
504
|
|
|
|
|
|
|
} |
|
505
|
|
|
|
|
|
|
} |
|
506
|
|
|
|
|
|
|
# |
|
507
|
|
|
|
|
|
|
# When _parse_level is zero, the current token has been fully |
|
508
|
|
|
|
|
|
|
# parsed, and its output is to |
|
509
|
|
|
|
|
|
|
# to be immediately "flushed". |
|
510
|
|
|
|
|
|
|
# We do not need to do a lexeme_read(), nor a resume in this case: |
|
511
|
|
|
|
|
|
|
# we know where we are. |
|
512
|
|
|
|
|
|
|
# |
|
513
|
19156
|
100
|
|
|
|
78460
|
if ( $self->_parse_level > 0 ) { |
|
514
|
16277
|
|
|
|
|
60715
|
$r->lexeme_read( $lexeme, 0, 1, $lexemeValue ); |
|
515
|
16277
|
|
|
|
|
1532901
|
$prevPos = $rc{pos}; |
|
516
|
16277
|
|
|
|
|
80668
|
$rc{pos} += $lexemeLength; |
|
517
|
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
# $self->logger_debug( '[%d->%d/%d] %s: %s', |
|
519
|
|
|
|
|
|
|
# $prevPos, $rc{pos}, $maxPos, $lexeme, $lexemeValue ); |
|
520
|
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
# |
|
522
|
|
|
|
|
|
|
# We can safely ignore the events from lexeme_read(), |
|
523
|
|
|
|
|
|
|
# because we made sure in the grammar that resume() will |
|
524
|
|
|
|
|
|
|
# NOT advance the position, thanks to those events: |
|
525
|
|
|
|
|
|
|
# |
|
526
|
|
|
|
|
|
|
# ^token |
|
527
|
|
|
|
|
|
|
# ^ANYTHING |
|
528
|
|
|
|
|
|
|
# macroArguments$ |
|
529
|
|
|
|
|
|
|
# token$ |
|
530
|
|
|
|
|
|
|
# |
|
531
|
|
|
|
|
|
|
# macroArguments$, if it happens will always be standalone. |
|
532
|
|
|
|
|
|
|
# token$, when it happen, can be mixed with ^token or |
|
533
|
|
|
|
|
|
|
# ^ANYTHING. |
|
534
|
|
|
|
|
|
|
# |
|
535
|
|
|
|
|
|
|
# Please note that we do not use resume(). |
|
536
|
|
|
|
|
|
|
# |
|
537
|
|
|
|
|
|
|
} |
|
538
|
|
|
|
|
|
|
else { |
|
539
|
|
|
|
|
|
|
# |
|
540
|
|
|
|
|
|
|
# We are at the top level: flush to current diversion |
|
541
|
|
|
|
|
|
|
# |
|
542
|
|
|
|
|
|
|
# $self->logger_debug( '[%d->%d/%d] %s: %s', |
|
543
|
|
|
|
|
|
|
# $prevPos, $rc{pos}, $maxPos, $lexeme, $lexemeValue ); |
|
544
|
|
|
|
|
|
|
|
|
545
|
2879
|
|
|
|
|
52509
|
my $tmpValue = MarpaX::Languages::M4::Impl::Value->new() |
|
546
|
|
|
|
|
|
|
->value_push($lexemeValue); |
|
547
|
2879
|
|
|
|
|
177976
|
$self->impl_appendValue( |
|
548
|
|
|
|
|
|
|
$tmpValue->value_concat->value_firstElement ); |
|
549
|
2879
|
|
|
|
|
7114
|
$prevPos = $rc{pos}; |
|
550
|
2879
|
|
|
|
|
17586
|
$rc{pos} += $lexemeLength; |
|
551
|
|
|
|
|
|
|
} |
|
552
|
|
|
|
|
|
|
} |
|
553
|
|
|
|
|
|
|
|
|
554
|
2010
|
100
|
|
|
|
8785
|
if ( $self->_parse_level > 0 ) { |
|
555
|
|
|
|
|
|
|
# |
|
556
|
|
|
|
|
|
|
# We are in the context of a recursive call: the output |
|
557
|
|
|
|
|
|
|
# is of concern for a macro that called us. |
|
558
|
|
|
|
|
|
|
# |
|
559
|
1856
|
|
|
|
|
4245
|
local $MarpaX::Languages::M4::Impl::Parser::macro = $macro; |
|
560
|
|
|
|
|
|
|
# |
|
561
|
|
|
|
|
|
|
# For $r->value() optimisations |
|
562
|
|
|
|
|
|
|
# |
|
563
|
1856
|
|
|
|
|
3327
|
state $registrations = undef; |
|
564
|
|
|
|
|
|
|
|
|
565
|
1856
|
100
|
|
|
|
4894
|
if (defined($registrations)) { |
|
566
|
1855
|
|
|
|
|
7956
|
$r->registrations($registrations); |
|
567
|
|
|
|
|
|
|
} |
|
568
|
1856
|
|
|
|
|
10109
|
my $valueRef = $r->value; |
|
569
|
1856
|
100
|
|
|
|
196603
|
if (! defined($registrations)) { |
|
570
|
1
|
|
|
|
|
5
|
$registrations = $r->registrations(); |
|
571
|
|
|
|
|
|
|
} |
|
572
|
1856
|
100
|
66
|
|
|
6324
|
if ( Undef->check($valueRef) || Undef->check( ${$valueRef} ) ) { |
|
|
1855
|
|
|
|
|
25278
|
|
|
573
|
1
|
|
|
|
|
19
|
goto return_error; |
|
574
|
|
|
|
|
|
|
} |
|
575
|
|
|
|
|
|
|
|
|
576
|
1855
|
|
|
|
|
15419
|
$rc{value} = ${$valueRef}; |
|
|
1855
|
|
|
|
|
5968
|
|
|
577
|
|
|
|
|
|
|
} |
|
578
|
|
|
|
|
|
|
else { |
|
579
|
|
|
|
|
|
|
# |
|
580
|
|
|
|
|
|
|
# We are at the top level: the output has already been |
|
581
|
|
|
|
|
|
|
# "flushed" to whatever the current diversion said to. |
|
582
|
|
|
|
|
|
|
# |
|
583
|
|
|
|
|
|
|
} |
|
584
|
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
# $self->logger_debug( '[%d..%d/%d] => %s', |
|
586
|
|
|
|
|
|
|
# $rc{pos}, $rc{pos}, $maxPos, \%rc ); |
|
587
|
|
|
|
|
|
|
|
|
588
|
2009
|
|
|
|
|
89169
|
return \%rc; |
|
589
|
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
return_error: |
|
591
|
|
|
|
|
|
|
# |
|
592
|
|
|
|
|
|
|
# We propagate the undef to all levels except number 0 |
|
593
|
|
|
|
|
|
|
# |
|
594
|
5
|
100
|
|
|
|
36
|
if ( $self->_parse_level > 0 ) { |
|
595
|
1
|
50
|
33
|
|
|
34
|
if ( $self->_parse_level == 1 && $self->impl_eoi ) { |
|
596
|
|
|
|
|
|
|
# |
|
597
|
|
|
|
|
|
|
# We want the parsing to stop now |
|
598
|
|
|
|
|
|
|
# |
|
599
|
1
|
|
|
|
|
26
|
$self->impl_raiseException('EOF during argument collection'); |
|
600
|
|
|
|
|
|
|
} |
|
601
|
0
|
|
|
|
|
0
|
return; |
|
602
|
|
|
|
|
|
|
} |
|
603
|
|
|
|
|
|
|
else { |
|
604
|
4
|
|
|
|
|
183
|
return \%rc; |
|
605
|
|
|
|
|
|
|
} |
|
606
|
|
|
|
|
|
|
} |
|
607
|
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
# |
|
609
|
|
|
|
|
|
|
# M4 says that a token is processed as soon as it is recognized. |
|
610
|
|
|
|
|
|
|
# So we loop on token recognition |
|
611
|
|
|
|
|
|
|
# |
|
612
|
1
|
50
|
33
|
1
|
|
3364
|
method _parseByTokens (Ref['SCALAR'] $inputRef --> Str) { |
|
|
1
|
50
|
|
1
|
|
4
|
|
|
|
1
|
50
|
|
164
|
|
154
|
|
|
|
1
|
50
|
|
|
|
6
|
|
|
|
1
|
50
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
203
|
|
|
|
1
|
|
|
|
|
14421
|
|
|
|
164
|
|
|
|
|
1920
|
|
|
|
164
|
|
|
|
|
588
|
|
|
|
164
|
|
|
|
|
918
|
|
|
|
164
|
|
|
|
|
775
|
|
|
|
164
|
|
|
|
|
285
|
|
|
|
164
|
|
|
|
|
1530
|
|
|
|
164
|
|
|
|
|
357
|
|
|
613
|
|
|
|
|
|
|
|
|
614
|
164
|
|
|
|
|
3237
|
my $rc = $self->_parseByGrammar( $inputRef, 0, $BYTOKEN_G ); |
|
615
|
161
|
100
|
|
|
|
12221
|
if ( !Undef->check($rc) ) { |
|
616
|
160
|
|
|
|
|
1926
|
return substr( ${$inputRef}, $rc->{pos} ); |
|
|
160
|
|
|
|
|
4026
|
|
|
617
|
|
|
|
|
|
|
} |
|
618
|
|
|
|
|
|
|
|
|
619
|
1
|
|
|
|
|
13
|
return ${$inputRef}; |
|
|
1
|
|
|
|
|
17
|
|
|
620
|
|
|
|
|
|
|
} |
|
621
|
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
} |
|
623
|
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
1; |
|
625
|
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
__END__ |
|
627
|
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
=pod |
|
629
|
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
=encoding UTF-8 |
|
631
|
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
=head1 NAME |
|
633
|
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
MarpaX::Languages::M4::Impl::Parser - M4 Marpa parser |
|
635
|
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
=head1 VERSION |
|
637
|
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
version 0.019 |
|
639
|
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
=head1 AUTHOR |
|
641
|
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
Jean-Damien Durand <jeandamiendurand@free.fr> |
|
643
|
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
|
645
|
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
This software is copyright (c) 2015 by Jean-Damien Durand. |
|
647
|
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
|
649
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
|
650
|
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
=cut |