#################################################################### # # This file was generated using Parse::Yapp version 1.05. # # Don't edit this file, use source file instead. # # ANY CHANGE MADE HERE WILL BE LOST ! # #################################################################### package NATE::Log::Parser; use vars qw ( @ISA ); use strict; @ISA= qw ( Parse::Yapp::Driver ); #Included Parse/Yapp/Driver.pm file---------------------------------------- { # # Module Parse::Yapp::Driver # # This module is part of the Parse::Yapp package available on your # nearest CPAN # # Any use of this module in a standalone parser make the included # text under the same copyright as the Parse::Yapp module itself. # # This notice should remain unchanged. # # (c) Copyright 1998-2001 Francois Desarmenien, all rights reserved. # (see the pod text in Parse::Yapp module for use and distribution rights) # package Parse::Yapp::Driver; require 5.004; use strict; use vars qw ( $VERSION $COMPATIBLE $FILENAME ); $VERSION = '1.05'; $COMPATIBLE = '0.07'; $FILENAME=__FILE__; use Carp; #Known parameters, all starting with YY (leading YY will be discarded) my(%params)=(YYLEX => 'CODE', 'YYERROR' => 'CODE', YYVERSION => '', YYRULES => 'ARRAY', YYSTATES => 'ARRAY', YYDEBUG => ''); #Mandatory parameters my(@params)=('LEX','RULES','STATES'); sub new { my($class)=shift; my($errst,$nberr,$token,$value,$check,$dotpos); my($self)={ ERROR => \&_Error, ERRST => \$errst, NBERR => \$nberr, TOKEN => \$token, VALUE => \$value, DOTPOS => \$dotpos, STACK => [], DEBUG => 0, CHECK => \$check }; _CheckParams( [], \%params, \@_, $self ); exists($$self{VERSION}) and $$self{VERSION} < $COMPATIBLE and croak "Yapp driver version $VERSION ". "incompatible with version $$self{VERSION}:\n". "Please recompile parser module."; ref($class) and $class=ref($class); bless($self,$class); } sub YYParse { my($self)=shift; my($retval); _CheckParams( \@params, \%params, \@_, $self ); if($$self{DEBUG}) { _DBLoad(); $retval = eval '$self->_DBParse()';#Do not create stab entry on compile $@ and die $@; } else { $retval = $self->_Parse(); } $retval } sub YYData { my($self)=shift; exists($$self{USER}) or $$self{USER}={}; $$self{USER}; } sub YYErrok { my($self)=shift; ${$$self{ERRST}}=0; undef; } sub YYNberr { my($self)=shift; ${$$self{NBERR}}; } sub YYRecovering { my($self)=shift; ${$$self{ERRST}} != 0; } sub YYAbort { my($self)=shift; ${$$self{CHECK}}='ABORT'; undef; } sub YYAccept { my($self)=shift; ${$$self{CHECK}}='ACCEPT'; undef; } sub YYError { my($self)=shift; ${$$self{CHECK}}='ERROR'; undef; } sub YYSemval { my($self)=shift; my($index)= $_[0] - ${$$self{DOTPOS}} - 1; $index < 0 and -$index <= @{$$self{STACK}} and return $$self{STACK}[$index][1]; undef; #Invalid index } sub YYCurtok { my($self)=shift; @_ and ${$$self{TOKEN}}=$_[0]; ${$$self{TOKEN}}; } sub YYCurval { my($self)=shift; @_ and ${$$self{VALUE}}=$_[0]; ${$$self{VALUE}}; } sub YYExpect { my($self)=shift; keys %{$self->{STATES}[$self->{STACK}[-1][0]]{ACTIONS}} } sub YYLexer { my($self)=shift; $$self{LEX}; } ################# # Private stuff # ################# sub _CheckParams { my($mandatory,$checklist,$inarray,$outhash)=@_; my($prm,$value); my($prmlst)={}; while(($prm,$value)=splice(@$inarray,0,2)) { $prm=uc($prm); exists($$checklist{$prm}) or croak("Unknow parameter '$prm'"); ref($value) eq $$checklist{$prm} or croak("Invalid value for parameter '$prm'"); $prm=unpack('@2A*',$prm); $$outhash{$prm}=$value; } for (@$mandatory) { exists($$outhash{$_}) or croak("Missing mandatory parameter '".lc($_)."'"); } } sub _Error { print "Parse error.\n"; } sub _DBLoad { { no strict 'refs'; exists(${__PACKAGE__.'::'}{_DBParse})#Already loaded ? and return; } my($fname)=__FILE__; my(@drv); open(DRV,"<$fname") or die "Report this as a BUG: Cannot open $fname"; while() { /^\s*sub\s+_Parse\s*{\s*$/ .. /^\s*}\s*#\s*_Parse\s*$/ and do { s/^#DBG>//; push(@drv,$_); } } close(DRV); $drv[0]=~s/_P/_DBP/; eval join('',@drv); } #Note that for loading debugging version of the driver, #this file will be parsed from 'sub _Parse' up to '}#_Parse' inclusive. #So, DO NOT remove comment at end of sub !!! sub _Parse { my($self)=shift; my($rules,$states,$lex,$error) = @$self{ 'RULES', 'STATES', 'LEX', 'ERROR' }; my($errstatus,$nberror,$token,$value,$stack,$check,$dotpos) = @$self{ 'ERRST', 'NBERR', 'TOKEN', 'VALUE', 'STACK', 'CHECK', 'DOTPOS' }; #DBG> my($debug)=$$self{DEBUG}; #DBG> my($dbgerror)=0; #DBG> my($ShowCurToken) = sub { #DBG> my($tok)='>'; #DBG> for (split('',$$token)) { #DBG> $tok.= (ord($_) < 32 or ord($_) > 126) #DBG> ? sprintf('<%02X>',ord($_)) #DBG> : $_; #DBG> } #DBG> $tok.='<'; #DBG> }; $$errstatus=0; $$nberror=0; ($$token,$$value)=(undef,undef); @$stack=( [ 0, undef ] ); $$check=''; while(1) { my($actions,$act,$stateno); $stateno=$$stack[-1][0]; $actions=$$states[$stateno]; #DBG> print STDERR ('-' x 40),"\n"; #DBG> $debug & 0x2 #DBG> and print STDERR "In state $stateno:\n"; #DBG> $debug & 0x08 #DBG> and print STDERR "Stack:[". #DBG> join(',',map { $$_[0] } @$stack). #DBG> "]\n"; if (exists($$actions{ACTIONS})) { defined($$token) or do { ($$token,$$value)=&$lex($self); #DBG> $debug & 0x01 #DBG> and print STDERR "Need token. Got ".&$ShowCurToken."\n"; }; $act= exists($$actions{ACTIONS}{$$token}) ? $$actions{ACTIONS}{$$token} : exists($$actions{DEFAULT}) ? $$actions{DEFAULT} : undef; } else { $act=$$actions{DEFAULT}; #DBG> $debug & 0x01 #DBG> and print STDERR "Don't need token.\n"; } defined($act) and do { $act > 0 and do { #shift #DBG> $debug & 0x04 #DBG> and print STDERR "Shift and go to state $act.\n"; $$errstatus and do { --$$errstatus; #DBG> $debug & 0x10 #DBG> and $dbgerror #DBG> and $$errstatus == 0 #DBG> and do { #DBG> print STDERR "**End of Error recovery.\n"; #DBG> $dbgerror=0; #DBG> }; }; push(@$stack,[ $act, $$value ]); $$token ne '' #Don't eat the eof and $$token=$$value=undef; next; }; #reduce my($lhs,$len,$code,@sempar,$semval); ($lhs,$len,$code)=@{$$rules[-$act]}; #DBG> $debug & 0x04 #DBG> and $act #DBG> and print STDERR "Reduce using rule ".-$act." ($lhs,$len): "; $act or $self->YYAccept(); $$dotpos=$len; unpack('A1',$lhs) eq '@' #In line rule and do { $lhs =~ /^\@[0-9]+\-([0-9]+)$/ or die "In line rule name '$lhs' ill formed: ". "report it as a BUG.\n"; $$dotpos = $1; }; @sempar = $$dotpos ? map { $$_[1] } @$stack[ -$$dotpos .. -1 ] : (); $semval = $code ? &$code( $self, @sempar ) : @sempar ? $sempar[0] : undef; splice(@$stack,-$len,$len); $$check eq 'ACCEPT' and do { #DBG> $debug & 0x04 #DBG> and print STDERR "Accept.\n"; return($semval); }; $$check eq 'ABORT' and do { #DBG> $debug & 0x04 #DBG> and print STDERR "Abort.\n"; return(undef); }; #DBG> $debug & 0x04 #DBG> and print STDERR "Back to state $$stack[-1][0], then "; $$check eq 'ERROR' or do { #DBG> $debug & 0x04 #DBG> and print STDERR #DBG> "go to state $$states[$$stack[-1][0]]{GOTOS}{$lhs}.\n"; #DBG> $debug & 0x10 #DBG> and $dbgerror #DBG> and $$errstatus == 0 #DBG> and do { #DBG> print STDERR "**End of Error recovery.\n"; #DBG> $dbgerror=0; #DBG> }; push(@$stack, [ $$states[$$stack[-1][0]]{GOTOS}{$lhs}, $semval ]); $$check=''; next; }; #DBG> $debug & 0x04 #DBG> and print STDERR "Forced Error recovery.\n"; $$check=''; }; #Error $$errstatus or do { $$errstatus = 1; &$error($self); $$errstatus # if 0, then YYErrok has been called or next; # so continue parsing #DBG> $debug & 0x10 #DBG> and do { #DBG> print STDERR "**Entering Error recovery.\n"; #DBG> ++$dbgerror; #DBG> }; ++$$nberror; }; $$errstatus == 3 #The next token is not valid: discard it and do { $$token eq '' # End of input: no hope and do { #DBG> $debug & 0x10 #DBG> and print STDERR "**At eof: aborting.\n"; return(undef); }; #DBG> $debug & 0x10 #DBG> and print STDERR "**Dicard invalid token ".&$ShowCurToken.".\n"; $$token=$$value=undef; }; $$errstatus=3; while( @$stack and ( not exists($$states[$$stack[-1][0]]{ACTIONS}) or not exists($$states[$$stack[-1][0]]{ACTIONS}{error}) or $$states[$$stack[-1][0]]{ACTIONS}{error} <= 0)) { #DBG> $debug & 0x10 #DBG> and print STDERR "**Pop state $$stack[-1][0].\n"; pop(@$stack); } @$stack or do { #DBG> $debug & 0x10 #DBG> and print STDERR "**No state left on stack: aborting.\n"; return(undef); }; #shift the error token #DBG> $debug & 0x10 #DBG> and print STDERR "**Shift \$error token and go to state ". #DBG> $$states[$$stack[-1][0]]{ACTIONS}{error}. #DBG> ".\n"; push(@$stack, [ $$states[$$stack[-1][0]]{ACTIONS}{error}, undef ]); } #never reached croak("Error in driver logic. Please, report it as a BUG"); }#_Parse #DO NOT remove comment 1; } #End of include-------------------------------------------------- #line 11 "Parser.yp" # (the logspec to parse. Held in a package global variable so that # the cursor for m/\G.../cg is stable during the parse) our $Logspec; # (current depth of parenthesis nesting. Tracked by the lexer since # the matching outside of parens needs to include many different # kinds of characters as just one token, as needed for filesystem # paths, but the lexing inside parens is the traditional split into # words and symbols, as needed for the filter language) our $Paren_count; # (where the cursor was positioned in $Logspec before the last token # read. For better error reporting) our $Prev_pos; # (where the cursor was positioned in $Logspec when the current filter # started to be read. For recording the original filter text into the # target for debugging) our $Filter_start; sub new { my($class)=shift; ref($class) and $class=ref($class); my($self)=$class->SUPER::new( yyversion => '1.05', yystates => [ {#State 0 ACTIONS => { 'SCHEME' => 1 }, DEFAULT => -4, GOTOS => { 'Target' => 2, 'Logspec' => 4, 'Scheme' => 3 } }, {#State 1 DEFAULT => -5 }, {#State 2 DEFAULT => -1 }, {#State 3 ACTIONS => { 'PATH' => 6 }, DEFAULT => -6, GOTOS => { 'Path' => 5 } }, {#State 4 ACTIONS => { '' => 7, ";" => 8 } }, {#State 5 ACTIONS => { "(" => 10 }, DEFAULT => -8, GOTOS => { 'Filter' => 9 } }, {#State 6 DEFAULT => -7 }, {#State 7 DEFAULT => 0 }, {#State 8 ACTIONS => { 'SCHEME' => 1 }, DEFAULT => -4, GOTOS => { 'Target' => 11, 'Scheme' => 3 } }, {#State 9 DEFAULT => -3 }, {#State 10 DEFAULT => -9, GOTOS => { '@1-1' => 12 } }, {#State 11 DEFAULT => -2 }, {#State 12 ACTIONS => { "show" => 13, "package" => 15, "subname" => 14, "not" => 16, "(" => 17, "runid" => 19, "message" => 20, "level" => 22, "drop" => 23 }, GOTOS => { 'Field' => 18, 'Expr' => 21 } }, {#State 13 DEFAULT => -15 }, {#State 14 DEFAULT => -38 }, {#State 15 DEFAULT => -35 }, {#State 16 ACTIONS => { "show" => 13, "package" => 15, "subname" => 14, "not" => 16, "(" => 17, "runid" => 19, "message" => 20, "level" => 22, "drop" => 23 }, GOTOS => { 'Field' => 18, 'Expr' => 24 } }, {#State 17 ACTIONS => { "show" => 13, "package" => 15, "subname" => 14, "not" => 16, "(" => 17, "runid" => 19, "message" => 20, "level" => 22, "drop" => 23 }, GOTOS => { 'Field' => 18, 'Expr' => 25 } }, {#State 18 ACTIONS => { "!" => 28, "=" => 27 }, GOTOS => { 'String_Equal' => 26, 'Regex_Equal' => 29 } }, {#State 19 DEFAULT => -36 }, {#State 20 ACTIONS => { "isa" => 30 }, DEFAULT => -37 }, {#State 21 ACTIONS => { "or" => 31, "and" => 32, ")" => 33 } }, {#State 22 ACTIONS => { "!" => 36, "<" => 34, "in" => 37, ">" => 39, "=" => 35 }, GOTOS => { 'Number_Compare' => 38, 'Regex_Equal' => 40 } }, {#State 23 DEFAULT => -16 }, {#State 24 DEFAULT => -13 }, {#State 25 ACTIONS => { "or" => 31, "and" => 32, ")" => 41 } }, {#State 26 ACTIONS => { 'STRING' => 43 }, GOTOS => { 'String' => 42 } }, {#State 27 ACTIONS => { "~" => 44, 'REGEX' => -49, "=" => 45 }, DEFAULT => -47 }, {#State 28 ACTIONS => { "~" => 46, "=" => 47 } }, {#State 29 ACTIONS => { 'REGEX' => 48 } }, {#State 30 ACTIONS => { 'REGEX' => 50, 'STRING' => 43 }, GOTOS => { 'String' => 49 } }, {#State 31 ACTIONS => { "show" => 13, "package" => 15, "subname" => 14, "not" => 16, "(" => 17, "runid" => 19, "message" => 20, "level" => 22, "drop" => 23 }, GOTOS => { 'Field' => 18, 'Expr' => 51 } }, {#State 32 ACTIONS => { "show" => 13, "package" => 15, "subname" => 14, "not" => 16, "(" => 17, "runid" => 19, "message" => 20, "level" => 22, "drop" => 23 }, GOTOS => { 'Field' => 18, 'Expr' => 52 } }, {#State 33 DEFAULT => -10 }, {#State 34 ACTIONS => { "=" => 53 }, DEFAULT => -40 }, {#State 35 ACTIONS => { "~" => 44, 'REGEX' => -49, "=" => 54 }, DEFAULT => -42 }, {#State 36 ACTIONS => { "~" => 46, "=" => 55 } }, {#State 37 ACTIONS => { "call" => 56, "comment" => 57, "debug" => 58, "warn" => 59, "step" => 60, "case" => 62, 'error' => 63, "trace" => 64 }, GOTOS => { 'Level' => 61, 'Levels' => 65 } }, {#State 38 ACTIONS => { "call" => 56, "comment" => 57, "debug" => 58, "warn" => 59, "step" => 60, "case" => 62, 'error' => 63, "trace" => 64 }, GOTOS => { 'Level' => 66 } }, {#State 39 ACTIONS => { "=" => 67 }, DEFAULT => -45 }, {#State 40 ACTIONS => { 'REGEX' => 68 } }, {#State 41 DEFAULT => -14 }, {#State 42 DEFAULT => -21 }, {#State 43 DEFAULT => -39 }, {#State 44 DEFAULT => -50 }, {#State 45 ACTIONS => { 'REGEX' => -51 }, DEFAULT => -48 }, {#State 46 DEFAULT => -53 }, {#State 47 DEFAULT => -52 }, {#State 48 DEFAULT => -22 }, {#State 49 DEFAULT => -23 }, {#State 50 DEFAULT => -24 }, {#State 51 DEFAULT => -12 }, {#State 52 DEFAULT => -11 }, {#State 53 DEFAULT => -41 }, {#State 54 ACTIONS => { 'REGEX' => -51 }, DEFAULT => -43 }, {#State 55 ACTIONS => { 'REGEX' => -52 }, DEFAULT => -46 }, {#State 56 DEFAULT => -29 }, {#State 57 DEFAULT => -30 }, {#State 58 DEFAULT => -27 }, {#State 59 DEFAULT => -33 }, {#State 60 DEFAULT => -31 }, {#State 61 ACTIONS => { "." => 69 }, DEFAULT => -25 }, {#State 62 DEFAULT => -32 }, {#State 63 DEFAULT => -34 }, {#State 64 DEFAULT => -28 }, {#State 65 ACTIONS => { "," => 70 }, DEFAULT => -19 }, {#State 66 DEFAULT => -18 }, {#State 67 DEFAULT => -44 }, {#State 68 DEFAULT => -17 }, {#State 69 ACTIONS => { "." => 71 } }, {#State 70 ACTIONS => { "call" => 56, "comment" => 57, "debug" => 58, "warn" => 59, "step" => 60, "case" => 62, 'error' => 63, "trace" => 64 }, GOTOS => { 'Level' => 72 } }, {#State 71 ACTIONS => { "call" => 56, "comment" => 57, "debug" => 58, "warn" => 59, "step" => 60, "case" => 62, 'error' => 63, "trace" => 64 }, GOTOS => { 'Level' => 73 } }, {#State 72 DEFAULT => -26 }, {#State 73 DEFAULT => -20 } ], yyrules => [ [#Rule 0 '$start', 2, undef ], [#Rule 1 'Logspec', 1, sub #line 42 "Parser.yp" { [$_[1]] } ], [#Rule 2 'Logspec', 3, sub #line 44 "Parser.yp" { [@{$_[1]}, $_[3]] } ], [#Rule 3 'Target', 3, sub #line 48 "Parser.yp" { NATE::Log::Target->new_by_scheme($_[1], $Logspec, path => $_[2], filter => $_[3]); } ], [#Rule 4 'Scheme', 0, undef ], [#Rule 5 'Scheme', 1, undef ], [#Rule 6 'Path', 0, undef ], [#Rule 7 'Path', 1, undef ], [#Rule 8 'Filter', 0, undef ], [#Rule 9 '@1-1', 0, sub #line 65 "Parser.yp" { $Filter_start = $Prev_pos; } ], [#Rule 10 'Filter', 4, sub #line 67 "Parser.yp" { [substr($Logspec, $Filter_start, pos($Logspec)-$Filter_start), $_[3] ]} ], [#Rule 11 'Expr', 3, sub #line 72 "Parser.yp" { "$_[1] && $_[3]" } ], [#Rule 12 'Expr', 3, sub #line 74 "Parser.yp" { "$_[1] || $_[3]" } ], [#Rule 13 'Expr', 2, sub #line 76 "Parser.yp" { "!$_[2]" } ], [#Rule 14 'Expr', 3, sub #line 78 "Parser.yp" { "($_[2])" } ], [#Rule 15 'Expr', 1, sub #line 80 "Parser.yp" { "(return 1)" } ], [#Rule 16 'Expr', 1, sub #line 82 "Parser.yp" { "(return 0)" } ], [#Rule 17 'Expr', 3, sub #line 84 "Parser.yp" { "(\$args->level $_[2] $_[3])" } ], [#Rule 18 'Expr', 3, sub #line 86 "Parser.yp" { "(\$args->levelint $_[2] $NATE::Log::Level{$_[3]})" } ], [#Rule 19 'Expr', 3, sub #line 88 "Parser.yp" { "(\$args->level =~ /(?:" . join('|',@{$_[3]}) . ")/)" } ], [#Rule 20 'Expr', 6, sub #line 90 "Parser.yp" { "(\$args->levelint >= $$NATE::Log::Level{$_[3]} && \$args->levelint <= $$NATE::Log::Level{$_[6]})" } ], [#Rule 21 'Expr', 3, sub #line 92 "Parser.yp" { "(\$args->$_[1] $_[2] $_[3])" } ], [#Rule 22 'Expr', 3, sub #line 94 "Parser.yp" { "(\$args->$_[1] $_[2] $_[3])" } ], [#Rule 23 'Expr', 3, sub #line 96 "Parser.yp" { "(UNIVERSAL::isa(\$args->message,$_[3]))"} ], [#Rule 24 'Expr', 3, sub #line 98 "Parser.yp" { "(ref(\$args->message) =~ $_[3])" } ], [#Rule 25 'Levels', 1, sub #line 102 "Parser.yp" { [$_[1]] } ], [#Rule 26 'Levels', 3, sub #line 104 "Parser.yp" { [@{$_[1]}, $_[3]] } ], [#Rule 27 'Level', 1, undef ], [#Rule 28 'Level', 1, undef ], [#Rule 29 'Level', 1, undef ], [#Rule 30 'Level', 1, undef ], [#Rule 31 'Level', 1, undef ], [#Rule 32 'Level', 1, undef ], [#Rule 33 'Level', 1, undef ], [#Rule 34 'Level', 1, undef ], [#Rule 35 'Field', 1, undef ], [#Rule 36 'Field', 1, undef ], [#Rule 37 'Field', 1, undef ], [#Rule 38 'Field', 1, undef ], [#Rule 39 'String', 1, sub #line 114 "Parser.yp" { # (include 'q' prefix to make double quoted # strings be treated more like single-quoted # strings and make brace-quoted strings be # proper perl "q" . $_[1] } ], [#Rule 40 'Number_Compare', 1, sub #line 121 "Parser.yp" { '<' } ], [#Rule 41 'Number_Compare', 2, sub #line 122 "Parser.yp" { '<=' } ], [#Rule 42 'Number_Compare', 1, sub #line 123 "Parser.yp" { '==' } ], [#Rule 43 'Number_Compare', 2, sub #line 124 "Parser.yp" { '==' } ], [#Rule 44 'Number_Compare', 2, sub #line 125 "Parser.yp" { '>=' } ], [#Rule 45 'Number_Compare', 1, sub #line 126 "Parser.yp" { '>' } ], [#Rule 46 'Number_Compare', 2, sub #line 127 "Parser.yp" { '!=' } ], [#Rule 47 'String_Equal', 1, sub #line 130 "Parser.yp" { 'eq' } ], [#Rule 48 'String_Equal', 2, sub #line 131 "Parser.yp" { 'eq' } ], [#Rule 49 'Regex_Equal', 1, sub #line 134 "Parser.yp" { '=~' } ], [#Rule 50 'Regex_Equal', 2, sub #line 135 "Parser.yp" { '=~' } ], [#Rule 51 'Regex_Equal', 2, sub #line 136 "Parser.yp" { '=~' } ], [#Rule 52 'Regex_Equal', 2, sub #line 137 "Parser.yp" { '!~' } ], [#Rule 53 'Regex_Equal', 2, sub #line 138 "Parser.yp" { '!~' } ] ], @_); bless($self,$class); } #line 141 "Parser.yp" sub parse_logspec { my ($class, $logspec, %opts) = @_; local $Logspec = $logspec; local $Paren_count = 0; local $Prev_pos=0; my $parser = $class->new(); my $targets = $parser->YYParse(yylex => \&real_logspec_yylex, yyerror => \&logspec_yyerror, %opts); return $targets; } sub real_logspec_yylex { my (@retval) = logspec_yylex(); return @retval; } sub logspec_yylex { LOOP: { $Prev_pos=pos($Logspec) || 0; if ($Paren_count) { # lexing specific to 'filter' section if ($Logspec =~ /\G(\"(?:\\.|[^\\\"])*\")/cg) { # Double quoted string return ('STRING',$1); } if ($Logspec =~ /\G(\'(?:\\.|[^\\\'])*\')/cg) { # Single quoted string return ('STRING',$1); } if ($Logspec =~ /\G(\{(?:\\.|[^\\\}])*\})/cg) { # Brace-quoted string. {foo} becomes q{foo} for perl's sake return ('STRING',$1); } if ($Logspec =~ /\G(\/(?:\\.|[^\\\/])*\/)/cg) { # Regular expression return ('REGEX',$1); } } else { # lexing for path section if ($Logspec =~ /\G<\s*(.+?)\s*>/cg) { # Logging scheme name return ('SCHEME', $1); } if ($Logspec =~ /\G([^;\(\)\<\>\{\}\[\]]+)/cg) { # A path for this scheme, which is any string of text # which does not interfere with other syntax, i.e. does # not interfere with: # ';' for indicating start of next logspec # '<' '>' for indicating a scheme # '(' ')' for indicating a filter # '{' '}' '[' ']' for future use return ('PATH', $1); } } # Parsing common to path and (filter) if ($Logspec =~ /\G\s+/cg) { # whitespace redo LOOP; } if ($Logspec =~ /\G\(/cg) { # Open paren $Paren_count++; return ('(','('); } if ($Logspec =~ /\G\)/cg) { # Close paren $Paren_count--; return (')', ')'); } if ($Logspec =~ /\G(\w+|.)/cg) { # Any keyword and any symbol not matched above. (Only some # keywords and symbols will be valid for filter mode and # none will be valid for path mode, but the parser # will emit a reasonable syntax error if it encounters such # things). # Keywords are made to be lower case so that they cannot # collide with STRING, REGEX, etc. above. As a side effect, # the filter language is case insensitive. return (lc($1), lc($1)); } # At this point we didn't even match /\G\s/ or /\G./cg, and so # must be at end of string. return ('', undef); } } sub logspec_yyerror { my ($parser) = @_; my $value = $parser->YYCurval(); my $type = $parser->YYCurtok(); if (!defined($value)) { die("Unexpected end of logspec \"$Logspec\"\n"); } else { my $phrase = ($type eq $value) ? "'$value'" : "a ".lc($type)." (\"$value\")"; die("Syntax error. Did not expect $phrase at offset $Prev_pos in logspec \"$Logspec\"\n") } } 1;