/* G-Cows - scripting language for creation of web sites Copyright (C) 2002, 2003, 2004, 2005, 2006 Andrea Sozzi This file is part of G-Cows. G-Cows is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. G-Cows is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ %{ #include "common.H" #include "Xmalloc.H" #include "language.H" #include "parser.H" #include "nest.H" #include typedef std::vector Buffers_vector; typedef Buffers_vector::iterator Buffers_iter; typedef std::vector Working_dirs_vector; typedef Working_dirs_vector::iterator Working_dirs_iter; typedef std::vector FILE_vec; typedef FILE_vec::iterator FILE_iter; static Buffers_vector buffers; static FILE_vec open_files; static Working_dirs_vector working_dirs; static int nest_level = 0; int cowsswitch (string new_buffer); int check_file (string file_name); void unput_brace (); %} %x cows_tag %x cows_script %x cows_type %x single_comm %x multi_comm GS [ \t] EGS [ \t\n] DG [0-9] %% %{ extern Tree *tree; static Nested_tags tags (INITIAL); Buffers_iter buffer; Working_dirs_iter w_dir; FILE_iter open_file; static bool inside_var_type = false; %} [^<\n]+ | "<"+{EGS}*[^ \t\n]+ { Msg::inst()->advance_line (yytext); if (tree->is_exec ()) tree->write_output (yytext); } { \n { Msg::inst()->advance_line (); if (tree->is_exec ()) { if (inside_var_type) ;// Unreachable else tree->write_output (yytext); } } \\\n { Msg::inst()->advance_line (); } } { \n { Msg::inst()->advance_line (); } } { "<"{EGS}*cows{EGS}+ { /* advance_line (yytext); tags.save_condition (cows_tag); tags.set_file_has_tags (); BEGIN (cows_tag); } "<"{EGS}*cows{EGS}*> { /* */ Msg::inst()->advance_line (yytext); tags.save_condition (cows_script); tags.set_file_has_tags (); BEGIN (cows_script); } } { "<"{EGS}*\/{EGS}*cows{EGS}*> { /* */ Msg::inst()->advance_line (yytext); BEGIN (tags.restore_condition ()); return END_SCRIPT; } } { "/>" { BEGIN (tags.restore_condition ()); } } { __NO_OUTPUT__ { if (tree->is_deps () || tree->is_fast_deps ()) { ((Deps_tree *)tree)->enter_silent_mode (); } } "__EXT__"{GS}*[^ \t\n]+ { if (tree->is_deps () || tree->is_fast_deps ()) { ((Deps_tree *)tree)->set_custom_ext (yytext); } } __ALWAYS__ { if (tree->is_deps () || tree->is_fast_deps ()) { ((Deps_tree *)tree)->always (); } } "__DEP__"{GS}*[^ \t\n]+ { if (tree->is_deps () || tree->is_fast_deps ()) { ((Deps_tree *)tree)->set_dep (yytext); } } } { \n { Msg::inst()->advance_line (); BEGIN (tags.restore_condition ()); } } { \n { Msg::inst()->advance_line (); } "*"+"/" { BEGIN (tags.restore_condition ()); } } { [^@e\\]+ | @[^@e\\]+ | "e"+[^e@n\\]+ | "e"n+[^e@d\\]+ | "en"d+[^e@t\\]+ | "end"t+[^e@y\\]+ | "endt"y+[^e@p\\]+ | "endty"p+[^e@\\]+ { Msg::inst()->advance_line (yytext); yylval.gen = new Gen_type (yytext); return TYPE_STRING; } "\\@" { //Msg::inst()->advance_line (yytext); yylval.gen = new Gen_type ("@"); return TYPE_STRING; } "\\\\" { //Msg::inst()->advance_line (yytext); yylval.gen = new Gen_type ("\\"); return TYPE_STRING; } "@@" { BEGIN (cows_script); return AT_ECHO; } "endtype"{EGS}*";" { Msg::inst()->advance_line (yytext); inside_var_type=false; BEGIN (tags.restore_condition ()); return END_TYPE; } . { Msg::inst()->advance_line (yytext); yylval.gen = new Gen_type (yytext); return TYPE_STRING; } } { "@@" { BEGIN (cows_type); return ';'; } "type"{EGS}*":" { Msg::inst()->advance_line (yytext); tags.save_condition (cows_type); BEGIN (cows_type); } "type"{EGS}*"("{EGS}*([_a-zA-Z][._a-zA-Z0-9]*){EGS}*")"{EGS}*":" { Msg::inst()->advance_line (yytext); tags.save_condition (cows_type); BEGIN (cows_type); inside_var_type=true; string var_to_type_in = string (yytext); unsigned int open_brace = var_to_type_in.find ('(')+1; unsigned int close_brace = var_to_type_in.find (')'); yylval.str = strdup ( (var_to_type_in.substr (open_brace, close_brace-open_brace)).c_str()); return VAR_TYPE; } "//" { tags.save_condition (single_comm); BEGIN (single_comm); } "/*" { tags.save_condition (multi_comm); BEGIN (multi_comm); } "undef" { return UNDEF; } "verbatim" { return VERBATIM; } "include" { unput ('e'); unput ('d'); unput ('u'); unput ('l'); unput ('c'); unput ('n'); unput ('i'); unput ('_'); unput ('{');} "_include" { return INCLUDE; } "echo" { return ECHO; } "print" { return PRINT; } "cmd" { return CMD; } "evalcmd" { return EVALCMD; } "exec" { return EXEC; } "evalexec" { return EVALEXEC; } "tobool" { return TOBOOL; } "toint" { return TOINT; } "tostring" { return TOSTRING; } "toarray" { return TOARRAY; } "isint" { return ISINT; } "isstring" { return ISSTRING; } "isarray" { return ISARRAY; } "if" { return IF; } "elif" { return ELIF; } "ifdef" { return IFDEF; } "elifdef" { return ELIFDEF; } "ifndef" { return IFNDEF; } "elifndef" { return ELIFNDEF; } "else" { return ELSE; } "for" { return FOR; } "foreach" { return FOREACH; } "while" { return WHILE; } "in" { return IN; } "date" { return DATE; } "fdate" { return FDATE; } "fsize" { return FSIZE; } "linkadjust" { return ADJ_LINK; } "inputfile" { return INPUT_FILE; } "absinputfile" { return ABS_INPUT_FILE; } "outputfile" { return OUTPUT_FILE; } "absoutputfile" { return ABS_OUTPUT_FILE; } "substring" { return SUBSTR; } "find" { return FIND; } "findfirstof" { return FINDFIRSTOF; } "findlastof" { return FINDLASTOF; } "findfirstnotof" { return FINDFIRSTNOTOF; } "findlastnotof" { return FINDLASTNOTOF; } "rfind" { return RFIND; } "char" { return CHAR; } "insert" { return INSERT; } "replace" { return REPLACE; } "replaceall" { return REPLACE_ALL; } "trim" { return TRIM; } "ltrim" { return LTRIM; } "rtrim" { return RTRIM; } "startswith" { return STARTSWITH; } "endswith" { return ENDSWITH; } "tolower" { return TO_LOWER; } "toupper" { return TO_UPPER; } "length" { return LENGTH; } "raiseerror" { return RAISEERR; } "raisewarning" { return RAISEWARN; } "term" { return TERM; } "tokenize" { return TOKENIZE; } "join" { return JOIN; } "delete" { return DELETE; } "push" { return PUSH; } "random" { return RANDOM; } "fileexists" { return FILEEXISTS; } "fill" { return FILL; } [_a-zA-Z][._a-zA-Z0-9]* { yylval.str = strdup (yytext); return VAR; } ">=" { return GE; } "<=" { return LE; } "==" { return EQ; } "~==" { return WEQ; } "!=" { return NEQ; } "~!=" { return WNEQ; } "+=" { return CPLUS; } "-=" { return CMINUS; } "*=" { return CTIMES; } "/=" { return CDIV; } "%=" { return CMOD; } "**=" { return CPOW; } "&&" { return AND; } "||" { return OR; } "**" { return POW; } "++" { return PP; } "--" { return MM; } {DG}+ { yylval.gen = new Gen_type (atoi (yytext)); return G_CONST; } \"("\\"("\\\\")*"\"")?("\\\\")?(([^"])|([^\\]"\\"("\\\\")*"\""))*\" { /* " */ Msg::inst()->advance_line (yytext); yylval.gen = new Gen_type (xstrndup (yytext + 1, strlen (yytext) - 2)); return G_CONST; } '("\\"("\\\\")*"\'")?("\\\\")?(([^'])|([^\\]"\\"("\\\\")*"\'"))*' { /* ' */ Msg::inst()->advance_line (yytext); yylval.gen = new Gen_type (xstrndup (yytext + 1, strlen (yytext) - 2)); return G_CONST; } `("\\"("\\\\")*"\`")?("\\\\")?(([^`])|([^\\]"\\"("\\\\")*"\`"))*` { Msg::inst()->advance_line (yytext); yylval.gen = new Gen_type (xstrndup (yytext + 1, strlen (yytext) - 2)); return G_CONST; } [;+*/%=!()[\]{},$<>] { return *yytext; } "-" { return '-'; } [ \t]+ /* Skip whitespaces */ . { /* This __MUST__ be the last rule */ Msg::inst()->error ("Parse error; unrecognized token " + string (yytext),"Parse error;" + string (yytext)); } } /* ! */ { <> { unput ('\n'); BEGIN (tags.restore_condition ()); } } <> { if ( (!tags.file_has_tags ()) && tree->is_fast_deps ()) { Msg::inst()->warning ( "Source file with no tags in fast mode"); } tags.unset_file_has_tags (); if ( nest_level <= 0 ) { tags.reset_conditions (); yyterminate (); } else { buffer = buffers.end (); w_dir = working_dirs.end (); open_file = open_files.end (); Msg::inst () -> restore_saved_buffer (); yy_delete_buffer (YY_CURRENT_BUFFER); yy_switch_to_buffer (*(--buffer)); if (chdir ((*(--w_dir)).c_str ())) Msg::inst()->sys_fatal ("can't change directory to " + string (*(w_dir)), *(w_dir)); fclose (*(--open_file)); buffers.erase (buffer); working_dirs.erase (w_dir); open_files.erase (open_file); if (tree->is_deps ()) ((Deps_tree *)tree)->undo_refresh (); nest_level--; unput ('}'); return END_FILE; } } %% int cowswitch (string new_buffer) { if (nest_level > 99) Msg::inst()->fatal ("include nested too deep", "include nested too deep"); FILE *new_file; if ( (new_file=fopen (new_buffer.c_str (), "r")) ) { open_files.push_back (new_file); Msg::inst()->set_parsed_file (new_buffer); yyin = new_file; working_dirs.push_back (get_w_dir ()); buffers.push_back (YY_CURRENT_BUFFER); yy_switch_to_buffer (yy_create_buffer (yyin, YY_BUF_SIZE)); nest_level++; } else { Msg::inst()->sys_error ("can't open file " + new_buffer, "open " + new_buffer); return EXIT_FAILURE; } return EXIT_SUCCESS; } int check_file (string file_name) { FILE *file = fopen (file_name.c_str (), "r"); if (file) { fclose (file); return EXIT_SUCCESS; } return EXIT_FAILURE; } void unput_brace () { unput ('}'); }