# Copyright (c) Philippe Verdret, 1999 require 5.005; use strict qw(vars); use strict qw(refs); use strict qw(subs); package Parse::LexEvent; $Parse::LexEvent::VERSION = '2.21'; use Parse::ALex; @Parse::LexEvent::ISA = qw(Parse::ALex); my $lexer = __PACKAGE__->clone; sub prototype { $lexer or __PACKAGE__->SUPER::prototype } #################################################################### my %TEMPLATE = (); $TEMPLATE{'HEADER_STRING_PART'} = q@ { pos($LEX_BUFFER) = $LEX_POS; my $textLength = 0; my $content = ''; # PARSE:{ %% $SKIP ne '' ? WITH_SKIP_PART() : '' %% if ($LEX_POS == $LEX_LENGTH) { $self->[%%$EOI%%] = 1; $LEX_TOKEN = $Parse::Token::EOI; return $Parse::Token::EOI; } # @; $TEMPLATE{'HEADER_STREAM_PART'} = q@ { pos($LEX_BUFFER) = $LEX_POS; my $LEX_FH = $$LEX_FHR; my $textLength = 0; my $content = ''; # PARSE:{ %% $SKIP ne '' ? WITH_SKIP_PART() : '' %% if ($LEX_POS == $LEX_LENGTH) { if ($self->[%%$EOI%%]) # if EOI { $LEX_TOKEN = $Parse::Token::EOI; return $Parse::Token::EOI; } else { READ:{ do { $LEX_BUFFER = <$LEX_FH>; if (defined($LEX_BUFFER)) { pos($LEX_BUFFER) = $LEX_POS = 0; $LEX_LENGTH = CORE::length($LEX_BUFFER); $LEX_RECORD++; %%$SKIP ne '' ? WITH_SKIP_LAST_READ_PART() : '' %% } else { $self->[%%$EOI%%] = 1; $LEX_TOKEN = $Parse::Token::EOI; return $Parse::Token::EOI; } } while ($LEX_POS == $LEX_LENGTH); }# READ } } @; $TEMPLATE{'FOOTER_PART'} = q! }# PARSE $self # return the lexer instance } !; $TEMPLATE{'WITH_SKIP_PART'} = q@ if ($LEX_POS < $LEX_LENGTH and $LEX_BUFFER =~ /\G(?:%%$SKIP%%)/cg) { $textLength = pos($LEX_BUFFER) - $LEX_POS; # length $& $LEX_OFFSET += $textLength; $LEX_POS += $textLength; } @; $TEMPLATE{'WITH_SKIP_LAST_READ_PART'} = q@ if ($LEX_BUFFER =~ /\G(?:%%$SKIP%%)/cg) { # skip this pattern $textLength = pos($LEX_BUFFER) - $LEX_POS; # length $& $LEX_OFFSET += $textLength; $LEX_POS += $textLength; } else { last READ; } @; $lexer->template(Parse::Template->new(%TEMPLATE)); # code template my $LEXER_SUB = $lexer->_map('LEXER_SUB'); sub parse { &{$_[0]->[$LEXER_SUB]} } 1; __END__ =head1 NAME C<Parse::LexEvent> - Generator of event-oriented lexical analyzers (1.00 ALPHA) =head1 SYNOPSIS use Parse::LexEvent; sub string { print $_[0]->name, ": $_[1]\n"; } sub comment { print $_[0]->name, ": $_[1]\n"; } sub remainder { print $_[0]->name, ": $_[1]\n"; } $lexer = Parse::LexEvent->new()->configure( From => \*DATA, Tokens => [ Type => 'Simple', Name => 'ccomment', Handler => 'comment', Regex => '//.*\n', Type => 'Delimited', Name => 'comment', Handler => 'comment', Start => '/[*]', End => '[*]/', Type => 'Quoted', Name => 'squotes', Handler => 'string', Quote => qq!\'!, Type => 'Quoted', Name => 'dquotes', Handler => 'string', Quote => qq!\"!, Type => 'Simple', Name => 'remainder', Regex => '(?s:[^/\'\"]+)', ReadMore => 1, ] )->parse(); __END__ /* C comment */ // C++ comment var d = "string in double quotes"; var s = 'string in single quotes'; var i = 10; var y = 100; =head1 DESCRIPTION C<Parse::LexEvent> generates lexical analyzers in the fashion of C<Parse::Lex>, but the generated analyzers emit an event at the finish of recognition of each token. This event corresponds to the call of a procedure whose name is that of the token. It is possible to give a different name to this procedure by making use of the C<Handler> parameter when defining a token. An application using C<Parse::LexEvent> must define the required procedures. These procedures take the token object as first argument and the recognized character string as the second. C<Parse::LexEvent> inherits from C<Parse::ALex> and possesses all the methods described in the documentation of the C<Parse::Lex> class, except for the methods C<analyze()>, C<every()> C<next()>, and C<nextis()>. =head2 Methods =over 4 =item parse() This method runs the analysis of data specified by C<from()>. =back =head1 EXAMPLES cparser.pl - This analyzer recognizes three types of structures: C ou C++ comments, strings within quotation marks, and the rest. It emits an event specific to each. You can use it, for example, to analyze C, C++ or Javascript programs. =head1 SEE ALSO C<Parse::Lex>, C<Parse::Token>. =head1 AUTHOR Philippe Verdret. =head1 COPYRIGHT Copyright (c) 1999 Philippe Verdret. All rights reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.