package DBIx::MyParsePP; use strict; use DBIx::MyParsePP::Lexer; use DBIx::MyParsePP::Parser; use DBIx::MyParsePP::Query; our $VERSION = '0.50'; use constant MYPARSEPP_YAPP => 0; use constant MYPARSEPP_CHARSET => 1; use constant MYPARSEPP_VERSION => 2; use constant MYPARSEPP_SQL_MODE => 3; use constant MYPARSEPP_CLIENT_CAPABILITIES => 4; use constant MYPARSEPP_STMT_PREPARE_MODE => 5; my %args = ( charset => MYPARSEPP_CHARSET, version => MYPARSEPP_VERSION, sql_mode => MYPARSEPP_SQL_MODE, client_capabilities => MYPARSEPP_CLIENT_CAPABILITIES, stmt_prepare_mode => MYPARSEPP_STMT_PREPARE_MODE ); 1; sub new { my $class = shift; my $parser = bless ([], $class ); my $max_arg = (scalar(@_) / 2) - 1; foreach my $i (0..$max_arg) { if (exists $args{$_[$i * 2]}) { $parser->[$args{$_[$i * 2]}] = $_[$i * 2 + 1]; } else { warn("Unkown argument '$_[$i * 2]' to DBIx::MyParsePP->new()"); } } my $yapp = DBIx::MyParsePP::Parser->new(); $parser->[MYPARSEPP_YAPP] = $yapp; return $parser; } sub parse { my ($parser, $string) = @_; my $lexer = DBIx::MyParsePP::Lexer->new( string => $string, charset => $parser->[MYPARSEPP_CHARSET], version => $parser->[MYPARSEPP_VERSION], sql_mode => $parser->[MYPARSEPP_SQL_MODE], client_capabilities => $parser->[MYPARSEPP_CLIENT_CAPABILITIES], stmt_prepare_mode => $parser->[MYPARSEPP_CLIENT_CAPABILITIES] ); my $query = DBIx::MyParsePP::Query->new( lexer => $lexer ); my $yapp = $parser->[MYPARSEPP_YAPP]; my $result = $yapp->YYParse( yylex => sub { $lexer->yylex() }, yyerror => sub { $parser->error(@_, $query) } ); if (defined $result) { $query->setRoot($result->[0]); } return $query; } sub error { my ($parser, $yapp, $query) = @_; $query->setActual($yapp->YYCurval); $query->setExpected($yapp->YYExpect); } 1; __END__ =head1 NAME DBIx::MyParsePP - Pure-perl SQL parser based on MySQL grammar and lexer =head1 SYNOPSIS use DBIx::MyParsePP; use Data::Dumper; my $parser = DBIx::MyParsePP->new(); my $query = $parser->parse("SELECT 1"); print Dumper $query; print $query->toString(); =head1 DESCRIPTION C is a pure-perl SQL parser that implements the MySQL grammar and lexer. The grammar was automatically converted from the original C file by removing all the C code. The lexer comes from C, completely translated in Perl almost verbatim. The grammar is converted into Perl form using L. =head1 CONSTRUCTOR C, C, C, C and C can be passed as arguments to the constructor. Please C to bring in the required constants and see L for information. =head1 METHODS C provides C which takes the string to be parsed. The result is a L object which contains the result from the parsing. Queries can be reconstructed back into SQL by calling the C method. =head1 SPECIAL CONSIDERATIONS The file containing the grammar C is about 5 megabytes in size and takes a while to load. Compex statements take a while to parse, e.g. the first Twins query from the MySQL manual can only be parsed at a speed of few queries per second per 1GHz of CPU. If you require a full-speed parsing solution, please take a look at L, which requires a GCC compiler and produces more concise parse trees. The parse trees produced by C contain one leaf for every grammar rule that has been matched, even rules that serve no useful purpose. Therefore, parsing event simple statements such as C