use strict; my $sql = <<'--SQL--'; select case when a=b then 'c' else 'd' end "tough_one", e as "even tougher" from mytable --SQL-- use HOP::Lexer 'make_lexer'; my @sql = $sql; my $lexer = make_lexer( sub { shift @sql }, # iterator [ WORD => qr/\w+/i ], [ DQWORD => qr/"\w+"/ ], [ DQUOTED => qr/"[^"]+"/ ], [ QUOTED => qr/'[^']*'/ ], [ COMMA => qr/,/ ], [ SPACE => qr/\s+/, sub {} ], ); # parse my @out; push @out, $_ while $_ = $lexer->(); # Data::Dump the output (elaborated in order to produce compact results) use Data::Dumper; $Data::Dumper::Indent = 0; $Data::Dumper::Terse = 1; ($\, $,) = ("\n", ",\n"); print map { Dumper $_ } @out; #### ['WORD','select'], ['WORD','case'], ['WORD','when'], ['WORD','a'], '=', ['WORD','b'], ['WORD','then'], '\'', ['WORD','c'], '\'', ['WORD','else'], '\'', ['WORD','d'], '\'', ['WORD','end'], '"', ['WORD','tough_one'], '"', ['COMMA',','], ['WORD','e'], ['WORD','as'], '"', ['WORD','even'], ['WORD','tougher'], '"', ['WORD','from'], ['WORD','mytable'] #### ['WORD','select'], ['WORD','case'], ['WORD','when'], ['WORD','a'], '=', ['WORD','b'], ['WORD','then'], ['QUOTED', '\'c\''], ['WORD','else'], ['QUOTED','\'d\''], ['WORD','end'], ['DQWORD','"tough_one"'], ['COMMA',','], ['WORD','e'], ['WORD','as'], ['DQUOTED','"even tougher"'], ['WORD','from'], ['WORD','mytable']