Regexp-Grammars
view release on metacpan or search on metacpan
lib/Regexp/Grammars.pm view on Meta::CPAN
my $logfile = q{-};
my $log_where = "for regex grammar defined at $source_file line $source_line";
$grammar_spec =~ s{ ^ [^#]* < logfile: \s* ([^>]+?) \s* > }{
$logfile = _timestamp($1);
# Presence of <logfile:...> implies compile-time logging...
$compiletime_debugging_requested = 1;
*Regexp::Grammars::LOGFILE = _open_log('>',$logfile, $log_where );
# Delete <logfile:...> directive...
q{};
}gexms;
# Look ahead for any run-time debugging or timeout requests...
my $runtime_debugging_requested
= $grammar_spec =~ m{
^ [^#]*
< debug: \s* (run | match | step | try | on | same ) \s* >
| \$DEBUG (?! \s* (?: \[ | \{) )
}xms;
my $timeout_requested
= $grammar_spec =~ m{
^ [^#]*
< timeout: \s* \d+ \s* >
}xms;
# Standard actions set up and clean up any regex debugging...
# Before entire match, set up a stack of attempt records and report...
my $pre_match_debug
= $runtime_debugging_requested
? qq{(?{; *Regexp::Grammars::LOGFILE
= Regexp::Grammars::_open_log('>>','$logfile', '$log_where');
Regexp::Grammars::_init_try_stack(); })}
: qq{(?{; *Regexp::Grammars::LOGFILE
= Regexp::Grammars::_open_log('>>','$logfile', '$log_where'); })}
;
# After entire match, report whether successful or not...
my $post_match_debug
= $runtime_debugging_requested
? qq{(?{;Regexp::Grammars::_debug_matched(0,\\%/,'<grammar>',\$^N)})
|(?>(?{;Regexp::Grammars::_debug_handle_failures(0,'<grammar>'); }) (?!))
}
: q{}
;
# Remove comment lines...
$grammar_spec =~ s{^ ([^#\n]*) \s \# [^\n]* }{$1}gxms;
# Subdivide into rule and token definitions, preparing to process each...
# REWRITE THIS, USING (PROBABLY NEED TO REFACTOR ALL GRAMMARS TO REUSe
# THESE COMPONENTS:
# (?<PARAMLIST> \( \s* (?&PARAMS)? \s* \) | (?# NOTHING ) )
# (?<PARAMS> (?&PARAM) \s* (?: , \s* (?&PARAM) \s* )* ,? )
# (?<PARAM> (?&VAR) (?: \s* = \s* (?: (?&LITERAL) | (?&PARENCODE) ) )? )
# (?<LITERAL> (?&NUMBER) | (?&STRING) | (?&VAR) )
# (?<VAR> : (?&IDENT) )
my @defns = split m{
(< (obj|)(rule|token) \s*+ :
\s*+ ((?:${IDENT}::)*+) (?: ($IDENT) \s*+ = \s*+ )?+
($IDENT)
\s* >)
}xms, $grammar_spec;
# Extract up list of names of defined rules/tokens...
# (Name is every 6th item out of every seven, skipping the first item)
my @subrule_names = @defns[ map { $_ * 7 + 6 } 0 .. ((@defns-1)/7-1) ];
my @defns_copy = @defns[1..$#defns];
my %subrule_names;
# Build a look-up table of subrule names, checking for duplicates...
my $defn_line = $source_line + $defns[0] =~ tr/\n//;
my %first_decl_explanation;
for my $subrule_name (@subrule_names) {
my ($full_decl, $objectify, $type, $qualifier, $name, $callname, $body) = splice(@defns_copy, 0, 7);
if (++$subrule_names{$subrule_name} > 1) {
_debug_notify( warn =>
"Redeclaration of <$objectify$type: $subrule_name>",
"at $source_file line $defn_line",
"will be ignored.",
@{ $first_decl_explanation{$subrule_name} },
q{},
);
}
else {
$first_decl_explanation{$subrule_name} = [
"(Hidden by the earlier declaration of <$objectify$type: $subrule_name>",
" at $source_file line $defn_line)"
];
}
$defn_line += ($full_decl.$body) =~ tr/\n//;
}
# Add the built-ins...
@subrule_names{'ws', 'hk', 'matchpos', 'matchline'} = (1) x 4;
# An empty main rule will never match anything...
my $main_regex = shift @defns;
if ($main_regex =~ m{\A (?: \s++ | \(\?\# [^)]* \) | \# [^\n]++ )* \z}xms) {
_debug_notify( error =>
"No main regex specified before rule definitions",
"in regex grammar declared at $source_file line $source_line",
"Grammar will never match anything.",
"(Or did you forget a <grammar:...> specification?)",
q{},
);
}
# Compile the regex or grammar...
my $regex = q{};
my $grammar_name;
my $is_grammar;
# Is this a grammar specification?
if ($main_regex =~ $GRAMMAR_DIRECTIVE) {
# Normalize grammar name and report...
$grammar_name = $+{grammar_name};
if ($grammar_name !~ /::/) {
( run in 1.900 second using v1.01-cache-2.11-cpan-71847e10f99 )