I have built a perl based application which can translate natural language to sql query and I'm testing it on Windows 7 using but here after running my perl script "sq-hal.pl"(code is given below) it unable to load the parser. Given below is the encountered error :

Establishing connection to DBI:mysql:student ... Creating the parser... Reading table names... Table names: XS_Tk__Callback_Call error:Undefined subroutine &main::column_names_to +_parser_st r called at parser.pl line 38. Tk::Error: Undefined subroutine &main::column_names_to_parser_str call +ed at pars er.pl line 38. Parse::RecDescent::BEGIN at grammar_func.pl line 52 main::load_parser at parser.pl line 38 main::load_data at splash.pl line 81 Tk::After::once at C:/Dwimperl/perl/site/lib/Tk/After.pm line 90 [once,[{},after#27,10,once,[\&main::load_data]]] ("after" script)

Given below are the scripts, Can anyone here help me in resolving this error?

# sq-hal.pl use strict; # Required Modules use Tk; use Tk::Table; use Tk::Text; use Tk::Photo; use Tk::Balloon; # Global variables use vars qw ( $user_input ); # English query typed by the user use vars qw ( $win_sq_hal ); # the main window for SQGNL use vars qw ( $parser ); # SQGNL parser which contains all th +e grammar use vars qw ( $results ); # results of SQGNL parsing of the En +glish query use vars qw ( $save_parser ); # whether parser need to be required + at the end (0 or 1) use vars qw ( @learn_strs ); # temporary hold new grammar to be l +earned use vars qw ( $results_table ); # table to display database records use vars qw ( $status_text ); # status bar text to be displayed use vars qw ( $default_status_text ); # default status bar text use vars qw ( $txt_output ); # text area where the output of SQGN +L is displayed # SQGNL configuration variables use vars qw ( $user ); # user name to login to the database use vars qw ( $passwd ); # password for the database login use vars qw ( $db_source ); # database source use vars qw ( $db_type ); # type of database use vars qw ( $learn_enabled ); # enable/disable learning grammar (0 + - disable, 1 - enable) use vars qw ( $rows_displayed ); # number of rows from the results qu +ery to be displayed to the user use vars qw ( $config_file_found ); # status of the configuration file + (0 or 1) # Modular level variables my $txt_input; # text area for users to type the query # Combine all the required files and # load the subroutines from various files do "configure.pl"; # configuration window definitions load_config(); # load the configuration data from a file do "parser.pl"; # SQ-HAL parser definitions do "splash.pl"; # splash sceen definitions do "database.pl"; # definitions for various database functionalit +ies # if the configuration file is not found then # (either due to first-time running or confgureation file got deleted) # show the SQGNL confiugration window to get required info if ($config_file_found == 0) { show_config(); } do "login.pl"; # get database login password save_config(); # user name might have changed when login scree +n is # called. So save the new configuration data do "db_structure.pl"; # window definition to show/get database s +tructure do "create_sql.pl"; # window definition to create SQL statemen +ts manually do "learning.pl"; # window definition to display new grammar + to be learnt do "relationships.pl"; # window definition to display/get table r +elationships ### Show the splash screen while loading the parser ### ### as the parser may take some time to load ### show_splash(); ### Create and show the main SQGNL window ### create_main_window(); # Display the spalsh screen and load parser grammar in the background sub create_main_window { $win_sq_hal = MainWindow->new; # create the main SQGNL window $win_sq_hal->appname("SQGNL"); $win_sq_hal->title("SQGNL: The Natural Language to SQL Translator" +); ### maximize and position the SQGNL main window ### my $w = $win_sq_hal->screenwidth()-10; # window width = screen +width my $h = $win_sq_hal->screenheight()-100; # window height = screen + height $win_sq_hal->geometry("${w}x${h}+0+20"); ### define and place window controls ### my $tooltip = $win_sq_hal->Balloon( -statusbar => $status_text ); my $win_sq_hal1 = $win_sq_hal->Frame( -relief => 'flat', -borderwidth => 10) ->pack( -ipadx => 10, -fill => 'both', -expand => 1); $win_sq_hal1->Label( -text => "Type your question below:", -anchor => "sw") ->pack( -fill => "x"); ### user input text area ----------------------------------------- +------ $txt_input = $win_sq_hal1->Scrolled( 'Text', -scrollbars => 'e', -height => 2, -wrap => "word") ->pack( -side => "top", -fill => "x", -expand => 0); $tooltip->attach($txt_input, -msg => "Type your English query here and then pr +ess Tranlate button."); my $fra_buttons1 = $win_sq_hal1->Frame->pack( -side => 'top', -fill => 'x', -expand => 0 ); ### button to activate translate the English query --------------- +------ my $cmd_translate = $fra_buttons1->Button( -text => "Translate th +e query to SQL", -command => \&parse_inpu +t) ->pack( -side => "left", -ipadx => 10, -anchor => "ne"); $tooltip->attach($cmd_translate, -msg => "Translate the English query into SQL."); ### button to clear the content in the query text area ----------- +------ my $cmd_clear = $fra_buttons1->Button( -text => "Clear", -command => sub { ### delete everything i +n the text area ### $txt_input->delete("1.0 +", "end"); } ) ->pack( -side => "left", -ipadx => 10, -padx => 10, -anchor => "ne"); $tooltip->attach($cmd_clear, -msg => "Clear the text in the English query area +."); ### button to bring up the create_sql window --------------------- +------ my $cmd_create_sql = $fra_buttons1->Button( -text => "Create your +own SQL", -command => \&show_create +_sql) ->pack( -side => "right", -ipadx => 10, -anchor => "ne"); $tooltip->attach($cmd_create_sql, -msg => "Bring up the window where you can create + your own SQL statements with ease."); my $fra_output = $win_sq_hal1->Frame->pack( -side => 'top', -fill => 'x', -expand => 0 ); ### text area to display output results -------------------------- +------ $txt_output = $fra_output->Scrolled( 'Text', -scrollbars => 'e', -height => 3, -wrap => "word") ->pack( -side => "left", -anchor => "nw", -fill => "x", -expand => 1); $tooltip->attach($txt_output, -msg => "Translated SQL statments are displayed h +ere. You may can modify this and press execute button\n to see the results +of the SQL statment"); ### button to execute SQL in the txt_output area ----------------- +------ my $cmd_exec = $fra_output->Button( -text => "Execute SQL", -command => sub { ### copy the content of th +e txt_output ### ### (SQL statement) to the + varaiable $results ### $results = $txt_output->ge +t("1.0", "end"); ### execute SQL and show t +he results ### if ( $results ne "") { show_data(); } } ) ->pack( -side => "right", -ipadx => 10, -pady => 10, -anchor => "ne"); $tooltip->attach($cmd_exec, -msg => "Execute the SQL statment and display the + results."); ### $status_text bar text area ----------------------------------- +------ $default_status_text = "SQ-HAL: The Natural Language to SQL Transl +ator"; $status_text = $default_status_text; $win_sq_hal->Label( -textvariable => \$status_text, -relief => "sunken", -anchor => "nw", -borderwidth => 2) ->pack( -side => "top", -fill => "x", -padx => 10, -expand => 0); my $fra_buttons2 = $win_sq_hal1->Frame ->pack( -side => "bottom"); ### button to bring up the database structure window ------------- +------ my $cmd_database = $fra_buttons2->Button( -text => "Database", -underline => 1, -command => \&show_databa +se) ->pack( -fill => "x", -ipadx => 20, -padx => 10, -pady => 5, -side => "left", -expand => 0); $tooltip->attach($cmd_database, -msg => "Display the current database structure." +); ### button to bring up the configuration window ------------------ +------ my $cmd_config = $fra_buttons2->Button( -text => "Configure", -underline => 2, -command => \&show_config) ->pack( -fill => "x", -side => "left", -ipadx => 20, -padx => 10, -pady => 5, -expand => 0); $tooltip->attach($cmd_config, -msg => "Configure SQ-HAL."); ### button to exit to the system --------------------------------- +------ my $cmd_exit = $fra_buttons2->Button( -text => "Exit", -underline => 1, -command => \&exit_sq_hal ) ->pack( -fill => "x", -ipadx => 40, -padx => 10, -pady => 5, -side => "left"); $tooltip->attach($cmd_exit, -msg => "End SQ-HAL and Exit to the system."); ### table to display results from the SQL statements ------------- +------ $results_table = $win_sq_hal1->Table( -rows => 1, -columns => 1, -scrollbars => "se", -relief => "groove", -borderwidth => 2, -fixedrows => 1) ->pack( -side => "top", -fill => "both", -expand => 1); $tooltip->attach($results_table, -msg => "Display data retrieved from the database +."); ### exit the program when destroying this main window ############ +###### $win_sq_hal->bind("<Destroy>", \&exit_sq_hal); ### set the focus to the query entering area ### $txt_input->focus; ### display this window and start handling events ### MainLoop; } # parse user input and show results sub parse_input { ### update the statusbar text ### $status_text = "Translating the English statement to a SQL stateme +nt..."; $win_sq_hal->update(); ### the input and output files and commented lines below ### ### are used for testing purposes only ### #my $inputFile = "data.txt"; #my $outputFile = "output.txt"; #open(DATA, "< $inputFile") || die $!; #open(OUT, "> $outputFile") || die $!; #while (<DATA>) #{ # if (!/^#/ && !/^[\s]*\n/) # Ignore commented lines and +empty lines # { # print "> "; # sleep 1; # print; ### copy the English query to the variable $user_input ### $user_input = $txt_input->get("1.0", "end"); ### remove special characters from the input ### $user_input =~ s/[:.'?!]//g; ### translate the user query to SQL ### eval{ $results = $parser->translate("\L$user_input"); }; ### clear the current content of the output area and insert new tr +anslated SQL ### $txt_output->delete("1.0", "end"); $txt_output->insert("end", $results); $_ = $results; ### if the first word of the results is "SELECT" then it is an + ### ### SQL statement. Otherwise it is and untranslated error message + ### if (/^SELECT/) { ### display the SQL statement in bule colour ### $txt_output->configure( -foreground => "blue" ); ### execute SQL and show the results ### show_data(); ### if there are anything to be leart, then display the learni +ng window ### if ($#learn_strs >= 0) { show_learn(); } } else ### English query not translated into SQL ### { ### if the learning is enabled, then add this English query ## +# ### to the query list that to be learnt ## +# if ($learn_enabled) { $learn_strs[++$#learn_strs] = "\L$user_input"; } ### display the error message in red ### $txt_output->configure( -foreground => "red" ); } ### update window controls ### $win_sq_hal->update(); ### save the results in the outupt file ### #print OUT $user_input, $results, "\n"; # } #} ### close all the open files ### #close(DATA); #close(OUT); ### update the statusbar with default text ### $status_text = $default_status_text; $win_sq_hal->update(); } # retrieve data from the database and display on to the screen sub show_data() { ### change the mouse icon to be busy icon ### $win_sq_hal->Busy; ### update statusbar text ### $status_text = "Retrieving data from the database..."; $txt_output->configure( -foreground => "blue" ); $win_sq_hal->update(); ### execute the SQL results ### ### this will update the results table as well ### execute_sql( $results ); ### update status bar text back to default ### $status_text = $default_status_text; ### change the mouse icon back to normal ### $win_sq_hal->Unbusy; } ### used as a flag to determine the exit function is called once ### ### multiple calls to the function is posible if the user press ### ### exit button as well as destorying the window calls the func. ### my $already_exited = 0; # exit SQGNL by disconnecting from the database and saving the parser sub exit_sq_hal { ### do not repeat this subroutine twice ### if ($already_exited) { return } $already_exited = 1; ### change the mouse icon to be busy icon ### $win_sq_hal->Busy; ### disconnect the current database connection ### disconnect_from_db(); ### if required, save the parser to a file ### if ($save_parser) { ### update statusbar text $status_text = "Saving the parser to a file. Please wait..."; $win_sq_hal->update; save_parser(); } ### save database structure to a file ### #save_db_info(); ### exit to the system ### exit; }
# parser.pl use strict; # Global variables use vars qw( %table_columns ); use vars qw( %table_relationships ); # Modular level variables ### Following variables used to test this parser only ### my $dataFile = "data1.txt"; ### Input Data file (for testing) + ### my $outputFile = "output.txt"; ### Output results file (for testin +g) ### my $debug_on = 0; ### Enable testing of this parser + ### my $trace_on = 0; ### Enable tracing the parser outpu +t ### my $grammar; ### SQGNL parser grammar + ### my $parser_file; ### name of the file which contains + parser object ### # combine table names into parser accepted string sub load_parser { $parser_file = "sq_hal_${db_type}_${db_source}_${user}"; ### replace invalid names in the file name ### $parser_file =~ s/[\\\/:*?<>|]//g; ### if parser file not found then load grammar ### if (!eval{require "${parser_file}.pm"}) { print "Creating the parser...\n"; ### Create the grammar ### $grammar = do "grammar.pl" or warn "Bad Grammar!"; ### Replace table_names ### my $tables_str = table_names_to_parser_str(); $grammar =~ s/TABLES/$tables_str/; ### Replace column names ### my $columns_str = column_names_to_parser_str(); $grammar =~ s/FIELDS/$columns_str/; } else { print "Loading the parser from the file '${parser_file}.pm'... +\n"; do "grammar_func.pl"; } ### initialize variables such as database structure, etc. ### initialize_vars(); use Parse::RecDescent; ## Enable tracing of the parser ### if ($trace_on) { $RD_TRACE = 1; } ### Load the parser from the file or ### ### create the parser if the file is not available ### $parser = eval{require "${parser_file}.pm"} ? $parser_file->new() : Parse::RecDescent->new($grammar) or warn "Bad Parser!"; ### if the parser file is not found, then the parser need to be sa +ved ### if (!eval{require "${parser_file}.pm"}) { $save_parser = 1; } ### if testing this parser only then do the following code ### if ($debug_on) { ### Open the input data file open(DATA, "< $dataFile") || die $!; open(OUT, "> $outputFile") || die $!; $| = 1; ### Parse each line of data ### while (<DATA>) { if (!/^#/ && !/^[\s]*\n/) ### Ignore commented or empty + lines ### { print "> "; #sleep 1; print; ### Translate the grammar ### my $SQL = $parser->translate("\L$_"); ### Print the translated output to the screen and outp +ut file ### print "$_$SQL\n"; print OUT "> $_$SQL\n"; } else { print OUT "$_"; } } ### Close files ## close(DATA); close(OUT); ### Exit to the system ### exit; } } # save the parser to a file sub save_parser() { print "Saving the parser to the file '${parser_file}.pm'..."; ### if exist, then delete the parser file ### if (eval{require "${parser_file}.pm"}) { eval { unlink "${parser_file}.pm"; }; } ### save the parser to file ### eval { $parser->Save($parser_file); }; ### do not need to save the parser in the near future again ### $save_parser = 0; } # learn new rule by the parser sub extend_parser { my ($rule, $str) = ($_[0], $_[1]); ### parser rule and the new le +arn string ### my $grammar = qq{ $rule : $str }; ### new grammar to be learn ## +# $parser->Extend($grammar); ### extend the parser grammar +### #$save_parser = 1; ### parser has been changed and therefore nee +d to save ### ### print the newly learn grammar ### print "Learn grammar:\n$grammar\n"; } # initialize table relationships and table-column relationships sub initialize_vars { @table_columns{get_table_names()} = (); foreach my $table (keys(%table_columns)) { my %tmp; @tmp{get_column_names($table)} = (); foreach (keys(%tmp)) { $tmp{$_} = "1"; } $table_columns{$table} = { %tmp }; } ### load the table relationships from the file ### if (open(DB, "${parser_file}.db")) { ### read each of the table relationship ### while (<DB>) { chomp($_); next unless s/^(.*?):\s*//; my $tbl1 = qq{$1}; for my $field ( split /;/ ) { my ($tbl2, $val) = split(",", $field); $table_relationships{ qq{$tbl1} }{ qq{$tbl2} } = qq{$v +al}; } } close(DB); ### close the file ### } } # combine table names into parser accepted string sub save_db_info() { open(DB, "> ${parser_file}.db"); ### save each table relationship to a file foreach my $tbl1 (keys(%table_relationships)) { print DB "$tbl1:"; foreach (keys(%{$table_relationships{$tbl1}})) { print DB "$_,", $table_relationships{$tbl1}{$_},";" ; } print DB "\n"; } close(DB); ### close the file ### } # combine table names into parser accepted string sub table_names_to_parser_str() { print "Reading table names...\n"; ### Get table names for the current database ### %table_columns = (); @table_columns{get_table_names()} = (); print " Table names: ", join(", ", keys(%table_columns)), "\n\n +"; ### Create the parser recognised string ### my $tables_str = ""; foreach my $table ( keys(%table_columns) ) { ### table words need to be lower case ### my $table_words = "\L${table}?"; $tables_str .= "/${table_words}/{'${table}'}|"; } chop($tables_str); ### Remove the last '|' character ### return $tables_str; } # combine all table columns into parser accepted string sub column_names_to_parser_str() { use Lingua::EN::Inflect ':ALL'; ### read column names for each table ### my $columns_str = ""; foreach ( keys(%table_columns) ) { if ( $_ ) { print "Read column names for '$_'...\n"; my $current_table = $_; ### Get the column names for the given table ### my @columns = get_column_names($_); print " Column names: ", join(", ", @columns), "\n\n"; ### Create parser recognised string ### foreach my $column (@columns) { ### column words need to be lower case ### my $column_words = "\L" . PL_N($column) . "|$column"; $columns_str .= "/${column_words}/{'${column}'}|"; } } } chop($columns_str); ### Remove the last "|" character ### return $columns_str; } 1; ### so the 'do' command succeeds ###
# splash.pl use strict; # Modular level variables use vars qw( $win_splash ); # window handle for this splash scree +n my $PARSER_FILE = "parser.pl"; # name of the parser file my $splash_shown = 0; # splash screen is already shown or n +ot my $splash_info; # message to be displayed on the spla +sh screen # Display the spalsh screen and load parser grammar in the background sub show_splash { ### do not show the splash screen if already shown ### ### we do not want to load the grammar twice ### if ($splash_shown == 1) { return 0; } $splash_shown = 1; ### splash screen has been shown ### ### create splash screen ### $win_splash = MainWindow->new(); ### do no show the title bar for the splash screen ### $win_splash->overrideredirect(1); $win_splash->configure( -background => "white"); $win_splash->configure( -borderwidth => 1); ### center this window ### my $h = 270; ### window height ### my $w = 360; ### window width ### my $x = int(($win_splash->screenwidth()-$w)/2); ### x positi +on ### my $y = int(($win_splash->screenheight()-100-$h)/2); ### y positi +on ### $win_splash->geometry("${w}x${h}+${x}+${y}"); ### create window controls ### my $img_sq_hal = $win_splash->Photo( -file => 'splash.gif'); ### SQGNL image ### $win_splash->Label( -borderwidth => 0, -image => $img_sq_hal )->pack; ### display area for splash screen messages ### $win_splash->Label( -textvariable => \$splash_info, -background => "white") ->pack( -fill => "x", -side => "top"); ### Exit button - to exit to the system ### $win_splash->Button( -text => " Exit ", -background => "white", -borderwidth => 0, -command => sub { exit }) ->pack( -fill => "x", -side => "top"); ### show spalsh screen ### $win_splash->update(); $win_splash->raise(); # start loading the parser immediately after displaying the splash + screen ### $win_splash->after(10, \&load_data); MainLoop; } # Load initial data and the parser at startup sub load_data { ### connect to the database ### $splash_info = 'Connecting to the database...'; $win_splash->update(); ### if unsuccessful database connection, then exit the program ### if (! connect_to_db($db_type, $db_source, $user, $passwd )) { exit; } ### load SQGNL parser ### $splash_info = 'Loading SQ-HAL parser...'; $win_splash->update(); load_parser(); ### Destroy the splash screen ### $win_splash->destroy(); } 1; # so the 'do' command succeeds

In reply to Unable to load the parser by amitkumarj441

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.