/* The LearningOnline Network with CAPA * CAPA lexer dfinition, heavily modified to become a LON-CAPA convertor * $Id: capaLexerDef.flex,v 1.15 2001/12/05 18:58:21 albertel Exp $ * * Copyright Michigan State University Board of Trustees * * This file is part of the LearningOnline Network with CAPA (LON-CAPA). * * LON-CAPA 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 of the License, or * (at your option) any later version. * * LON-CAPA 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 LON-CAPA; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * /home/httpd/html/adm/gpl.txt * * http://www.lon-capa.org/ */ /*------------------------------------------------------------------------*/ /* capaLexerDef.flex created by Isaac Tsai Jul 15 1996 */ /* added /END(variable) */ /* added /HIN .... /DIS(variable) ... */ /* Jan 15 1998 /{KeyWord}{KeyWord}{KeyWord} */ /* replaced by /DIS */ /* catch "No /END() statement found" */ /* catch "/DIS(")" and "/DIS(""")" errors " */ /* catch "/LET var = " */ /* add a new token EoL to indicate '\n' '\r''\n' and '\r' */ /* This file is based on flex 2.5.3, flex 2.3 apparantly cannot take it :-( */ /* DONE /RMAP() function July 14, 1998 */ /* DONE /AND /OR answer formats July 20, 1998 */ /* DONE /IF () /ENDIF July 26, 1998 */ /* DONE /WHILE () /ENDWHILE August 10 1998 */ /* DONE /VERB /ENDVERB Feb 20 1998 */ /*------------------------------------------------------------------------*/ /**************************************************************************/ %{ #include #include /* strtod(), strtol() */ #include #ifdef NeXT #include #else #include /* access() */ #endif #include "capaCommon.h" /* capa_access() */ #include "capaParser.h" /* _symbol structure def */ #include "lex_debug.h" /* defined RETURN(xxx) macro */ #ifdef YYSTYPE #undef YYSTYPE #endif #define YYSTYPE Symbol_p #include "capaToken.h" /* from YACC -d capaGrammarDef.y */ /* ============================================== begin of code */ #define LEX_BUFLEN (8*1024) /* lexical buffer size (for each opened file) */ #ifdef YYLMAX #undef YYLMAX #define YYLMAX 8192 #endif void yyfatalerror(char*msg); #define YY_FATAL_ERROR yyfatalerror #ifdef LEX_DBUG #define LLDBUG_PRL1(xx) { printf("Line %d ",Current_line[Input_idx]); printf(xx); fflush(stdout); } #define LLDBUG_PRL2(xx,yy) { printf("Line %d ",Current_line[Input_idx]); printf(xx,yy); fflush(stdout); } #define LLDBUG_PR1(xx) { printf(xx); fflush(stdout); } #define LLDBUG_PR2(xx,yy) { printf(xx,yy); fflush(stdout); } #define LLDBUG_PR3(xx,yy,zz) { printf(xx,yy,zz); fflush(stdout); } #else #define LLDBUG_PRL1(xx) { } #define LLDBUG_PRL2(xx,yy) { } #define LLDBUG_PR1(xx) { } #define LLDBUG_PR2(xx,yy) { } #define LLDBUG_PR3(xx,yy,zz) { } #endif #ifdef LEX_INPUT_DBUG #define LIDBUG_PR1(xx) { printf(xx); fflush(stdout); } #define LIDBUG_PR2(xx,yy) { printf(xx,yy); fflush(stdout); } #define LIDBUG_PR3(xx,yy,zz) { printf(xx,yy,zz); fflush(stdout); } #else #define LIDBUG_PR1(xx) { } #define LIDBUG_PR2(xx,yy) { } #define LIDBUG_PR3(xx,yy,zz) { } #endif #ifdef USE_DYNAMIC_SYMBOLS #define USE_DYNAMIC_LEXBUFS #endif Symbol *yylval; /* global pointer to symbol */ FILE *(Input_stream[MAX_OPENED_FILE]); /* <-- perhaps we can use linked list */ char Opened_filename[MAX_OPENED_FILE][QUARTER_K]; /* <-- perhaps we can use linked list */ int Input_idx; int Lexi_pos[MAX_OPENED_FILE]; /* Current position in the line */ #ifdef USE_DYNAMIC_LEXBUFS char *(Lexi_buf[MAX_OPENED_FILE]); /* Line Buffer for current file */ #else char Lexi_buf[MAX_OPENED_FILE][LEX_BUFLEN+4]; /* Line Buffer for current file */ #endif /* USE_DYNAMIC_LEXBUFS */ char String_buf[LEX_BUFLEN]; /* Constant String buffer <-- perhaps we can use char pointer */ char *Dynamic_buf; int Dynamic_buf_max; int Dynamic_buf_cur; static int End_of_input; static int Pcount, Bcount; /* static means only available in this file */ /* --------------------------------------------------------------------------- */ /* GLOBAL VARIABLES */ /* --------------------------------------------------------------------------- */ int Lexi_line; /* Current source file line number, counting from beginning */ extern int Current_line[MAX_OPENED_FILE]; int Func_idx; Symbol FuncStack[MAX_FUNC_NEST]; /* <-- perhaps we can use linked list */ int Array_idx; Symbol *ArraySymbList_p; Symbol *ArraySymbLast_p; Symbol *FmlSymbList_p; Symbol *FmlSymbLast_p; int FmlSymb_cnt; int Symb_count; int IFcount; WhileLoop_t WhileStack[MAX_FUNC_NEST]; /* <-- perhaps we can use linked list */ int While_idx, Wcount; int sccount; /* Semi-colon count for MAP and RMAP */ int HINTflag=0; int EXPflag=0; #ifdef USE_DYNAMIC_SYMBOLS Symbol *SymbList_p; Symbol *SymbLast_p; #else Symbol SymbArray[MAX_SYMB_COUNT]; #endif /* USE_DYNAMIC_SYMBOLS */ char *Current_char_p; /* Collect string constant */ extern char *EndText_p; extern char *StartText_p; extern Problem_t *LexiProblem_p; extern Problem_t *LastProblem_p; int first_run=1; int Stop_Parser; static int dosend=1; static int firstparam=1; #define FLEX #define YY_STACK_USED 1 /* for yy_push_state(), yy_pop_state() */ #ifdef FLEX int capaL_unput(); int capaL_input(); /* YY_INPUT() Controls scanner input. By default, YY_INPUT reads from the file-pointer yyin. Its action is to place up to max_size characters in the character array buf and return in the integer variable result either the number of characters read or the constant YY_NULL to indicate EOF. max_size is defined to be num_to_read = 8192 in liby Following is a sample redefinition of YY_INPUT, in the definitions section of the input file: %{ #undef YY_INPUT #define YY_INPUT(buf,result,max_size)\ {\ int c = getchar();\ result = (c == EOF) ? YY_NULL : (buf[0] = c, 1);\ } %} */ /* fgets() reads the input stream until n-1 bytes have been read OR a newline character is read and transferred to string OR an EOF (End-of-File) condition is encountered The string is then terminated with a NULL character. ii = fseek(FILE *stream,0L,SEEK_END) ; if(ii!=0) { error } leng = ftell(FILE *stream) + 1 ; fseek(FILE *stream,0L,SEEK_SET) ; Lexi_buf[Input_idx] = (char *)capa_malloc(sizeof(char)*leng,1); */ #ifdef AVOIDYYINPUT #define MAX_INCLUDE_DEPTH 10 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; #else #ifdef USE_DYNAMIC_LEXBUFS #define NEWYYINPUT #endif #ifdef NEWYYINPUT void newyy_input (char *buf,int *result,int max_size); #define YY_INPUT(buf,result,max_size) newyy_input(buf,&result,max_size) #else #ifdef USE_DYNAMIC_LEXBUFS #define YY_INPUT(buf,result,max_size) \ { int ii, leng, out_of_char; \ if (!Lexi_line) { /* was startup */ \ for(ii=0;ii < MAX_OPENED_FILE;ii++) { \ Lexi_buf[ii] = NULL; \ Lexi_pos[ii] = 0; \ Current_line[ii] = 0; \ } \ Input_idx = 0; \ first_run=0; \ yyin = Input_stream[Input_idx]; LIDBUG_PR1("<>\n"); \ } \ out_of_char = 0; \ if ( Lexi_buf[Input_idx] == NULL ) { \ Lexi_buf[Input_idx] = (char *)capa_malloc(sizeof(char)*LEX_BUFLEN+1,1); out_of_char=1; \ } else { \ if (!Lexi_buf[Input_idx][Lexi_pos[Input_idx]]) { /* test if the line buffer is empty or at the end */ \ out_of_char=1; \ } \ } \ if( out_of_char ) { \ if (fgets(Lexi_buf[Input_idx],LEX_BUFLEN-1,Input_stream[Input_idx])==NULL) { /* read in one line */ \ LIDBUG_PR2("<>\n",Input_idx); \ if( (Input_idx > 0) && ( Lexi_buf[Input_idx][Lexi_pos[Input_idx]] == '\0') ) { \ LIDBUG_PR2("<>\n",Input_idx); \ fclose(Input_stream[Input_idx]); \ capa_mfree((char *)Lexi_buf[Input_idx]); \ Lexi_buf[Input_idx] = NULL; \ Input_idx--; \ yyin = Input_stream[Input_idx]; \ /* (Lexi_pos[Input_idx])++; */ \ buf[0] = Lexi_buf[Input_idx][Lexi_pos[Input_idx]-1]; \ result = 1; \ } else { \ result = YY_NULL; /* End of File */ \ } \ } else { /* successfully read in one line */ \ if (Lexi_buf[Input_idx]==NULL) puts("Whatup?");\ leng = strlen(Lexi_buf[Input_idx]); \ LIDBUG_PR3("<>\n",leng,Input_idx); \ Lexi_pos[Input_idx] = 0; \ Lexi_line++; \ Current_line[Input_idx]++; \ (Lexi_pos[Input_idx])++; \ buf[0] = Lexi_buf[Input_idx][Lexi_pos[Input_idx]-1]; \ /* need to take care of return continuation conditions */ \ /* so, we return to one-char-at-a-time approach */ \ /* for(ii=0;ii>\n",Input_idx); */ \ (Lexi_pos[Input_idx])++; \ buf[0] = Lexi_buf[Input_idx][Lexi_pos[Input_idx]-1]; \ result = 1; \ } \ if (Stop_Parser==1) { \ result = YY_NULL; \ } \ } #else #define YY_INPUT(buf,result,max_size) \ { int ii, leng; \ if (!Lexi_line) { /* was startup */ \ for(ii=0;ii < MAX_OPENED_FILE;ii++) { \ Lexi_buf[ii][0]=0; \ Lexi_pos[ii] = 0; \ Current_line[ii] = 0; \ } \ Input_idx = 0; \ first_run=0; \ yyin = Input_stream[Input_idx]; LIDBUG_PR1("<>\n"); \ } \ if (!Lexi_buf[Input_idx][Lexi_pos[Input_idx]]) { /* test if the line buffer is empty or at the end */ \ if (fgets(Lexi_buf[Input_idx],LEX_BUFLEN-1,Input_stream[Input_idx])==NULL) { /* read in one line */ \ LIDBUG_PR2("<>\n",Input_idx); \ if( (Input_idx > 0) && ( Lexi_buf[Input_idx][Lexi_pos[Input_idx]] == '\0') ) { \ LIDBUG_PR2("<>\n",Input_idx); \ fclose(Input_stream[Input_idx]); \ Input_idx--; \ yyin = Input_stream[Input_idx]; \ /* (Lexi_pos[Input_idx])++; */ \ buf[0] = Lexi_buf[Input_idx][Lexi_pos[Input_idx]-1]; \ result = 1; \ } else { \ result = YY_NULL; /* End of File */ \ } \ } else { /* successfully read in one line */ \ leng = strlen(Lexi_buf[Input_idx]); \ LIDBUG_PR3("<>\n",leng,Input_idx); \ Lexi_pos[Input_idx] = 0; \ Lexi_line++; \ Current_line[Input_idx]++; \ (Lexi_pos[Input_idx])++; \ buf[0] = Lexi_buf[Input_idx][Lexi_pos[Input_idx]-1]; \ /* need to take care of return continuation conditions */ \ /* so, we return to one-char-at-a-time approach */ \ /* for(ii=0;ii>\n",Input_idx); */ \ (Lexi_pos[Input_idx])++; \ buf[0] = Lexi_buf[Input_idx][Lexi_pos[Input_idx]-1]; \ result = 1; \ } \ if (Stop_Parser==1) { \ result = YY_NULL; \ } \ } #endif /* USE_DYNAMIC_LEXBUFS */ #endif /*NEWYYINPUT*/ #endif /*AVOIDYYINPUT*/ #else #undef input #undef unput #endif int capa_eof(); %} Alpha [a-zA-Z_] KeyChar [A-Z] AlphaNum [a-zA-Z_0-9] Number [0-9] HexNumber [0-9a-fA-F] Space [ \t] Spaces ({Space}*) FileName (\"[^"\n]*\") Qchar ([0-9a-zA-Z \t!?\._,:;'"`~@#$%\^&\+\-\*=|\[\]{}()]) Operator ([=\+\-\*/%<>!&|,]) Identifier ([a-zA-Z_][a-zA-Z_0-9]*) EndLine ([\r][\n]|[\n]) %a 10500 %o 15000 %k 10000 %p 10000 %n 1000 %x S_COMMENT S_HINT S_HINTEXLAINX S_IMPORT S_EXPLAIN S_ENDX S_UNIT S_IGNORE %x S_SKIP S_VARIABLE S_LET S_DEFINE S_TEXT S_MAP S_FIGURE S_ANSWER %x S_STRING S_ANSCONTINUE S_TRUE_FALSE_STMT S_WHILE_SKIP %x S_NEXT_LINE S_VERB S_ECHO S_STRINGINANS %array %% { {EndLine} BEGIN S_IGNORE; [^\n]*$ BEGIN S_IGNORE; <> { capa_eof(); #ifndef AVOIDYYINPUT yyterminate(); #endif } } { {EndLine}{Spaces}"//"[^\n]*$ {LLDBUG_PRL2("[COMMENT<%s>]\n",yytext); send("# %s\n",&yytext[2]); } [^\n]*{EndLine} { send("\n"); BEGIN S_TEXT; } } { ^{Spaces}"/LET" | ^{Spaces}"/BEG" { LLDBUG_PRL1("[LET]"); Pcount = 0; BEGIN S_LET; start_mode(MODE_SCRIPT,NULL); } ^{Spaces}"/VERB" { LLDBUG_PRL1("[VERBATIM]"); BEGIN S_VERB; start_mode(MODE_OUTTEXT,NULL); send("
\n");
                                 }
^{Spaces}"/HIN"{Alpha}*{Spaces}  { LLDBUG_PRL1("[HIN]"); 
                               /*    start_mode(MODE_HINT, "");*/
                                   if (!HINTflag) {
                                     start_streams(HINT_DEST,1);
                                     HINTflag=-1;
                                   }
                                   change_destination(HINT_DEST);
				   BEGIN S_HINT; 
                                 }
^{Spaces}"/EXP"{Alpha}*{Spaces}  { 
                                   if (!EXPflag) {
                                     start_streams(EXP_DEST,1);
                                     EXPflag=-1;
                                   }
                                   change_destination(EXP_DEST);
                                   LLDBUG_PRL1("[EXP]"); Current_char_p = String_buf;  BEGIN S_EXPLAIN; }
^{Spaces}"/IMP"{Alpha}*{Space}+  { LLDBUG_PRL1("[IMP]"); BEGIN S_IMPORT; end_mode(); }
^{Spaces}"/END"                  { LLDBUG_PRL1("[END]");  
                                    if ( (LexiProblem_p !=NULL) && 
					 (LexiProblem_p->question != NULL) && 
					 (LexiProblem_p->ans_type == 0)) {
				      EndText_p=strsave(LexiProblem_p->question);
				      LexiProblem_p=NULL;
				    } else {
				      EndText_p=NULL;
				    }
				    End_of_input = 1; BEGIN S_IGNORE; 
                                  }
^{Spaces}"/START"[^\n]*          { LLDBUG_PRL1("[START]");  
                                    if (LexiProblem_p !=NULL && 
					LexiProblem_p->question != NULL) {
				      StartText_p=strsave(LexiProblem_p->question);
				    } else {
				      StartText_p=NULL;
				    }
				    BEGIN S_TEXT;
                                  }
                                  
^{Spaces}"/END"{Spaces}[\(]{Spaces}      { LLDBUG_PRL1("[END()]"); BEGIN S_ENDX; }
^"/DEF"                       { Bcount = 0; BEGIN S_DEFINE; RETURN(CAPA_DEF); }
^{Spaces}"/ANS"               { LLDBUG_PRL2("[ANS(%s)]",yytext); 
                                Pcount = 0; 
                                BEGIN S_ANSWER; 
                                end_mode();
				start_mode(MODE_ANSWER,NULL);
                                send("]\n",While_idx);
                                
                                top_item = While_idx - 1;
                                if( top_item < 0 ) { /* strange things must have happened here! */
                                  
                                } else {
                                  input_idx = WhileStack[top_item].input_idx;
                                  file_pos = WhileStack[top_item].pos_idx;
                                  Current_line[input_idx] = WhileStack[top_item].line_idx;
                                  Lexi_pos[input_idx] = 0;
                                  fseek(Input_stream[input_idx],file_pos,SEEK_SET);
                                  fgets(Lexi_buf[input_idx],LEX_BUFLEN-1,Input_stream[input_idx]);
                                  While_idx--;
                                }
                                BEGIN S_TEXT;
                              }
"/WHILE"                      |
^{Spaces}"/WHILE"             { long int file_pos;
                                int      leng;
                                LLDBUG_PRL2("[WHILE While_idx=<%d>]\n",While_idx);
                                leng = strlen(Lexi_buf[Input_idx]);  /* length of current line */
                                /* <-- because we use fgets() to read input, 
                                       thus ftell() will give the starting position of next line */
                                WhileStack[While_idx].input_idx = Input_idx;
                                file_pos = ftell(Input_stream[Input_idx]);
                                file_pos -= leng;  /* calibrate the current line length */
                                WhileStack[While_idx].pos_idx = file_pos;  /* begin of current line */
                                WhileStack[While_idx].line_idx = Current_line[Input_idx];
                                While_idx++;  /* advance the stack pointer */
                                
                                BEGIN S_TRUE_FALSE_STMT; RETURN(CAPA_WHILE); 
                                
                              }
^{Spaces}"/IF"                { int i;
				IFcount++;
                                LLDBUG_PRL2("[IF ]",IFcount);
				BEGIN S_TRUE_FALSE_STMT;
				if ( IFcount == 1) {
 				  start_streams(DEFAULT_DEST, 2);
                                  change_destination(DEFAULT_DEST);
				  watch_mode[current_dest][1]=1;
				}
				end_mode_stream(DEFAULT_DEST, 0);
				start_mode_stream(DEFAULT_DEST,1,MODE_SCRIPT,NULL);
				for(i=1;i]\n",IFcount);
				end_mode_stream(DEFAULT_DEST,0);
				for(i=1;i\n",
				      cached_data[current_cache].str);
				send_stream(1,"} else {");
                              }
^{Spaces}"/ENDIF"([^\n])*     { int i;
				IFcount--;
				end_mode_stream(DEFAULT_DEST,0);
				for(i=0;i");
				send_stream(1,"}");
				if (IFcount == 0) {
				  if (watch_mode[current_dest][1]) {
				    end_streams(DEFAULT_DEST,1);
 				  } else {
				    end_streams(DEFAULT_DEST,0);
				  }
                                  change_destination(DEFAULT_DEST);
				}
				delete_cache();
				LLDBUG_PRL2("[ENDIF ]\n",IFcount); 
                              }
"/AND"                        { LLDBUG_PRL1("[AND]"); /*implict in LON-CAPA*/}
"/DIS"                        { /* since S_VARIABLE treat {Space} as null, so here we do not match ( */
                                /* so that between /DIS and ( can have as many {Space} as we want */
                                LLDBUG_PR1("[DIS<]");
                                init_funcstack();
                                Pcount = 0; BEGIN S_VARIABLE; 
				start_delayed();
                              }
"/OR"                         { LLDBUG_PRL1("[OR]"); BEGIN S_ANSCONTINUE;  RETURN(ANS_OR); }
{EndLine}                     { LLDBUG_PR1("[EoL within S_TEXT]\n"); /* end of the whole text line */ 
                                send("\n"); }
[\\]{Space}*{EndLine}         { LLDBUG_PR2("[\\EoL continue](%s)",yytext); /* continuation on next line */ }                       
^{Spaces}"//"[^\n]*$		      { LLDBUG_PRL2("[COMMENT<%s>]\n",yytext);
                                        start_mode(MODE_SCRIPT,NULL); 
                                        send("# %s\n",&yytext[2]);
					BEGIN S_COMMENT;
                                      }

[^/\n\\]+$  |
[/]         | 
[\\]                          {  start_mode(MODE_OUTTEXT,NULL);
                                LLDBUG_PR2("[TEXT_LINE<%s>]",yytext);
				send(yytext);
			      }
([^/\n])+[/] |
([^/\n])+[\\]                 { /* matches anything until a '/' or a '\' */
                                start_mode(MODE_OUTTEXT,NULL);
                                LLDBUG_PR2("[TEXT_LINE( )<%s>]",yytext);
                                
                                yyless(yyleng-1); /* push back the last char */
                                BEGIN S_TEXT;
				send(yytext);
                              }
<>                       { 
#ifdef AVOIDYYINPUT
                                char    warn_msg[ONE_K];

                                if ( (--include_stack_ptr < 0) || Stop_Parser) {
				  if (Stop_Parser) {
                                    if ( LexiProblem_p!=NULL &&
					 LexiProblem_p->question != NULL)
				      EndText_p=strsave(LexiProblem_p->question);
				    while (include_stack_ptr >= 0) {
				      yy_delete_buffer( YY_CURRENT_BUFFER );
				      yy_switch_to_buffer(
						 include_stack[include_stack_ptr]);
				      --include_stack_ptr;
				    }
				  } else {
				    sprintf(warn_msg,
					"at End-of-File, a /END is needed.\n");
				    capa_msg(MESSAGE_ERROR,warn_msg);
				  }
				  free_problems(LexiProblem_p);
				  LexiProblem_p=NULL;
				  yyterminate();
				} else {
				  yy_delete_buffer( YY_CURRENT_BUFFER );
				  yy_switch_to_buffer(include_stack[include_stack_ptr]);
				}
#else                              
				char    warn_msg[ONE_K];
                                if (!Stop_Parser) { 
				 sprintf(warn_msg,"at End-of-File, a /END is needed.\n");
				 capa_msg(MESSAGE_ERROR,warn_msg);
				} else {
				  if (LexiProblem_p != NULL &&
				      LexiProblem_p->question != NULL)
				    EndText_p=strsave(LexiProblem_p->question);
				}
                                capa_eof(); 
				yyterminate();
#endif
                              }
}


{
{Alpha}{AlphaNum}*    { /* DONE: add codes to handle /END() */
				char *question_end=NULL;
				End_of_input = 1;
				if (EndText_p!=NULL) capa_mfree((char*)EndText_p);
				if ((LexiProblem_p!=NULL) &&
				    (LexiProblem_p->question != NULL) &&
				    (LexiProblem_p->ans_type == 0)) {
				  question_end=strsave(LexiProblem_p->question);
				}
                                if( yyleng > 0 ) {
                                  
                                  LLDBUG_PRL2("[END()<%s>]\n",yytext);
                                  /*yylval = find_identifier(yytext);*/
                                
                                  switch(yylval->s_type) {
                                    case IDENTIFIER:
                                    case I_VAR: case I_CONSTANT:
                                    case R_VAR: case R_CONSTANT:
                                         break;
                                    case S_VAR: case S_CONSTANT:
                                         EndText_p = strsave(yylval->s_str);
					 if (question_end) {
					   int leng; char *new_end;
					   leng = strlen(EndText_p) + 
					     strlen(question_end) + 1;
					   new_end = capa_malloc(sizeof(char), leng);
					   strcat(new_end, question_end);
					   strcat(new_end, EndText_p);  
					   capa_mfree(EndText_p);  
					   capa_mfree(question_end);  
					   EndText_p=new_end;
					 }
                                         break;
                                    default: break;
                                  }
                                }
                                BEGIN S_IGNORE;   RETURN(CAPA_END);
                              }
{Space}*                      { /* ignore spaces */ }
[\)]                          { /* a right paren */ 
                                if ( (LexiProblem_p != NULL) &&
				     (LexiProblem_p->question != NULL) && 
				     (LexiProblem_p->ans_type == 0)) {
				  EndText_p=strsave(LexiProblem_p->question);
				} else {
				  EndText_p=NULL;
				}
                                BEGIN S_IGNORE;   
				RETURN(CAPA_END);  
                              }
}

{
[/][Dd][Ii][Ss]{Space}*[\(]{Space}*  {  yy_push_state(S_HINTEXLAINX); }
[^/\n]+[/\\]                    { char  *aptr = yytext;
                                  yyless(yyleng-1);
				  send(aptr);
                                }
[/]                            { send("/"); }
[\\]                           { send("\\"); }
[\\]{Space}*[\n]               { LLDBUG_PR1("[\\CR hint explain continue]"); /* Hint and explain continuation */ }
[^/\n\\]+$                     {char  *aptr = yytext;
                                send(aptr);
                               }
}
{
{EndLine}                     {  LLDBUG_PR1("[CR hint]");
                                 send("\n"); 
                                 change_destination(DEFAULT_DEST);
                                 BEGIN S_TEXT;
                              }
}
{
{EndLine}                     {  LLDBUG_PR1("[CR explain]");
                                 send("\n"); 
                                 change_destination(DEFAULT_DEST);
                                 BEGIN S_TEXT;
                              }
}

{
{Alpha}{AlphaNum}*            {send("${%s}",yytext);}
{Space}+                      { }
[)]                           {  yy_pop_state(); }
}

{
{FileName}{Space}*             { char *endquote;
                                 end_mode();
				 start_mode(MODE_IMPORT,NULL);
				 /* Get rid of leading and trailing quotes */
				 endquote = strrchr(yytext,'\"');
                                 *endquote = '\0';
                                 if (yytext[1] == '/') {
                                    send("%s%s",import_prefix,&yytext[1]);
                                 } else {
                                    send("%s",&yytext[1]);
                                 }
				 end_mode();
				 BEGIN S_SKIP;
                               }
{Identifier}{Space}*           { end_mode();
				 start_mode(MODE_IMPORT,NULL);
				 send("$%s",yytext);
				 end_mode();
                                 BEGIN S_SKIP;
			       }
}

{
[Pp][Ll][Uu][Ss]             { LLDBUG_PR1("[PLUS]"); add_delayed("+");}
[Mm][Ii][Nn][Uu][Ss]         { LLDBUG_PR1("[MINUS]"); add_delayed("-");}

[Cc][Ss]                     { LLDBUG_PR1("[CS]"); send("cs");}
[Cc][Ii]                     { LLDBUG_PR1("[CI]"); send("ci");}
[Mm][Cc]                     { LLDBUG_PR1("[MC]"); send("mc");}
[Ff][Mm][Ll]                 { LLDBUG_PR1("[FORMULA]"); send("fml"); }

[Oo][Nn]                     |
[Yy][Ee][Ss]                 { LLDBUG_PR1("[ON]"); send("on");}
[Oo][Ff][Ff]                 |
[Nn][Oo]                     { LLDBUG_PR1("[OFF]"); send("off");}
[Ff][Mm][Tt]                 { LLDBUG_PR1("[FMT]"); }
[Uu][Nn][Ff][Mm][Tt]         { LLDBUG_PR1("[UNFMT]"); }

[,=]                  { LLDBUG_PR2("[symbol(%s)]",yytext);}
[%]                  { LLDBUG_PR2("[symbol(%s)]",yytext); 
                       if (dosend==1) send("%s",yytext);
                       if (dosend==2) add_delayed("%%%s",yytext);
                     }
[:@#-]                  { LLDBUG_PR2("[symbol(%s)]",yytext); 
                          if (dosend==1) send("%s",yytext);
                          if (dosend==2) add_delayed("%s",yytext);
                        }
"<"                          { LLDBUG_PR2("[symbol(%s)]",yytext);
                               if (dosend==1) send("%s",yytext);
                               if (dosend==2) add_delayed("%s",yytext);
                             }
">"                          { LLDBUG_PR2("[symbol(%s)]",yytext);
                               if (dosend==1) send("%s",yytext);
                               if (dosend==2) add_delayed("%s",yytext);
                             }

[Pp][Cc][Rr]                 |
[Hh][Gg][Rr]                 { if (firstparam) {
				firstparam=0; 
			       } else {
				add_delayed("\" />\n\t");
			       }
                               add_delayed("\n\t");
			       }
			       add_delayed("\n\t");
			       }
			       add_delayed("\n\t");
			       dosend=1;
			       flush_delayed();
			       if (firstparam!=1) send("\" />\n");
			       send("\t\n");
                         /* Fill in Hints */ 
			       if ( !is_dest_empty(HINT_DEST) ) {
			         send("\n\t\n\t");
                                 end_streams(HINT_DEST,0);
                                 HINTflag=0;
                                 send("\t\n\t\n\n");
			       }
			       send("\n\n");

			       if ( !is_dest_empty(EXP_DEST) ) {
			         send("\n\t\n");
                                 end_streams(EXP_DEST,0);
                                 EXPflag=0;
                                 send("\t\n\n");
                               }
                             }
}

{
{Alpha}{AlphaNum}*             { LLDBUG_PR2("[ID<%s>]",yytext);
                                 LLDBUG_PR2("[SYMB CNT=<%d>]", Symb_count); 
                                 if (dosend==1) send("$%s",yytext); 
                                 if (dosend==2) add_delayed("$%s",yytext); 
                               }

{Alpha}{AlphaNum}*{Space}*[(]  { if (dosend==1) send("&%s",yytext);
                                 if (dosend==2) add_delayed("&%s",yytext);
				 Pcount++;
                               }
{Alpha}{AlphaNum}*{Space}*[\[]  {  char aline[MAX_FUNC_NAME];
                                   int  i;   
                                   for(i=0;i < (yyleng-1); i++) {
                                     if( yytext[i] == ' ' || yytext[i] == '\t' || 
                                         yytext[i] == 0   || yytext[i] == '[' )    break;
                                     aline[i] = yytext[i];
                                   }
                                   aline[i] = 0;
                                   LLDBUG_PR2("[ARRAY<%s>]",aline);
                                   
                                   yylval = (Symbol *) capa_malloc(1, sizeof(Symbol)); /* *** */
                                   yylval->s_name = strsave(aline); /* free it in parser() */
                                   yylval->s_type = ARRAY_ID;
                                   
                                   yyless(yyleng-1); /* <-- push back char '[' */
                                   RETURN(ARRAY_ID);
                               }
{Number}*"\."{Number}*[Ee]"+"{Number}+ |
{Number}*"\."{Number}*[Ee]{Number}+    |
{Number}*"\."{Number}*[Ee]"-"{Number}+ |
{Number}+[Ee]"+"{Number}+ |
{Number}+[Ee]{Number}+    |
{Number}+[Ee]"-"{Number}+ |
{Number}+"\."{Number}*    |
"\."{Number}+             {  LLDBUG_PR2("[REAL<%s>]",yytext);
			     if(dosend==1) send("%s",yytext);
			     if(dosend==2) add_delayed("%s",yytext);
			  }

{Number}+                 {  LLDBUG_PR2("[INT<%s>]",yytext);
                             if (dosend==1) send("%s",yytext);
                             if (dosend==2) add_delayed("%s",yytext);
			  }
[\[]                      { LLDBUG_PR1("[dis let ans map '[']");         return(yytext[0]); }
[\]]                      { LLDBUG_PR1("[dis let ans map ']']");         return(yytext[0]); }
{Space}+                  { /* LLDBUG_PR1("[SP ignored]");  Ignore Spaces */ }
}

{
[\"]                      { LLDBUG_PR1("[TF,V,LET,MAP str\" ]"); 
                            Current_char_p = String_buf; 
			    send("'");
                            yy_push_state(S_STRING);
                          }
}

{
[\"]                      { LLDBUG_PR1("[ANS str\" ]"); 
                            Current_char_p = String_buf; 
                            yy_push_state(S_STRINGINANS);
                          }
}

{
[\(]                      { LLDBUG_PR1("[let if ans map (]"); 
                            Pcount++; 
			    if (Pcount > 1 ) {
			      if (dosend==1) send(yytext);
			      if (dosend==2) add_delayed(yytext);
			    } 
                          }
}

{
[\(]                      { LLDBUG_PR1("[let (]"); 
                            Pcount++; 
			    send(yytext);
                          }
}

[:]{Number}+[EeFf]   { 
                             end_delayed();
                             send("&format(");
                             flush_delayed();
                             send(",'%s')",yytext+1);
                           }
[:]{Number}+[EeFf]   { 
                             if (dosend) send("\" format=\"%s",yytext+1);
                           }

{
[;]   { 
        if (sccount==0) {
          send(",[\\");
          sccount++;
        } else if (sccount==1) {
          send("],[");
          sccount++;
        }
       }
[,]     {
        if (sccount==1) {
          send(",\\");
        } else {
          send(",");
        }
      }
[\)]  {
        LLDBUG_PR1("[) in MAP]"); Pcount--; 
        if(Pcount==0) {
          BEGIN S_SKIP; 
        }
        /* you might need a ; in the string below */
        send("]%c;\n",yytext[0]);
        sccount=0;
      }
}

{
"=="                { LLDBUG_PR1("[==]"); send(yytext);  }
"!="                { LLDBUG_PR1("[!=]"); send(yytext);  }
">"                 { LLDBUG_PR1("[>]");  send(yytext);  }
">="                { LLDBUG_PR1("[>=]"); send(yytext);  }
"<"                 { LLDBUG_PR1("[<]");  send(yytext);  }
"<="                { LLDBUG_PR1("[<=]"); send(yytext);  }
"&&"                { LLDBUG_PR1("[&&]"); send(yytext);  }
"||"                { LLDBUG_PR1("[||]"); send(yytext);  }
"//"                { if(Pcount==0) {
			 send("; #");
			 BEGIN S_ECHO;
                      }
                    }
[%]                 {send("%%");}
{Operator}          { LLDBUG_PR2("[Op(%c) in VAR,TF_STMT,LET]",yytext[0]); send(yytext); }
}



{
[\)]                     { LLDBUG_PR1("[)]"); 
                           Pcount--; 
                           if(Pcount == 0) {
                              BEGIN S_TEXT; 
                              flush_delayed();
                           } else {
                              send(yytext); 
                           }
                         }
[\\]{Space}*{EndLine}    { LLDBUG_PR2("[\\EoL continue in S_VARIABLE (DIS?)](%s)",yytext); /* continuation on next line */ }                       
{EndLine}                { LLDBUG_PR1("[EoL within /dis()]\n"); }
.                   { char warn_msg[WARN_MSG_LENGTH]; 
                      sprintf(warn_msg,"When use a VARIABLE, an unexpected char [%c] is encountered.\n",yytext[0]);
                      capa_msg(MESSAGE_ERROR,warn_msg);
                    }
}

{
[\)]                     { 
                           LLDBUG_PRL1("[) in TRUE_FALSE]");
			   Pcount--; 
			   if(Pcount == 0)  {
				stop_cache();
				send_stream(0,"\">\n");
				send_stream(1,") {\n");
				BEGIN S_NEXT_LINE;
			   }
			 }
[\\]{Space}*{EndLine}    { 
			   LLDBUG_PR2("[\\EoL continue in S_TRUE_FALSE_STMT](%s)",yytext); /* continuation on next line */ 
			 }                       
{EndLine}                { 
			   LLDBUG_PR1("[EoL within /IF()]\n"); RETURN(EoL);
			 }
.                   { 
		      char warn_msg[WARN_MSG_LENGTH]; 
                      sprintf(warn_msg,"In /IF(), an unexpected char [%c] is encountered.\n",yytext[0]);
                      capa_msg(MESSAGE_ERROR,warn_msg);
                    }
}

{
[\\][\\]            { /*char  *aptr = yytext;
			while( *aptr )   *Current_char_p++ = *aptr++;*/
                      send(yytext);
                    }
[\\][\"]            { /**Current_char_p++ = '"';*/ send("\\\"");  }
[\\]{Space}*[\n]    { LLDBUG_PR2("[\\CR continue in S_STRING](%s)",yytext); /* continuation on next line */ }                       
[\"]                { /* end of a string constant --   */
                      send("'");
		      yy_pop_state();
		    }
[%]                 { /*Escape percent signs so that vasprintf doesn't choke */
                      send("%%");
                    }
{EndLine}           { /* check for termination of string constant */
                      char warn_msg[WARN_MSG_LENGTH];
                      
                      sprintf(warn_msg,"STRING not terminated properly, an EoL encountered in the middle.\n%s\n",String_buf);
                      capa_msg(MESSAGE_ERROR,warn_msg);
                      yy_pop_state();
                    }
.                   { /*char  *aptr = yytext;
			while( *aptr )   *Current_char_p++ = *aptr++;*/
                      send(yytext);
                    }
}

{
[\\][\\]            { /*char  *aptr = yytext;
			while( *aptr )   *Current_char_p++ = *aptr++;*/
                      if (dosend==1) send("%s",yytext);
		      if (dosend==2) add_delayed("%s",yytext);
                    }
[\\][\"]            { /**Current_char_p++ = '"';*/ 
                      if (dosend==1) send("%s",yytext);
		      if (dosend==2) add_delayed("%s",yytext);
                    }
[\\]{Space}*[\n]    { LLDBUG_PR2("[\\CR continue in S_STRING](%s)",yytext); /* continuation on next line */ }                       
[\"]                { /* end of a string constant --   */
		      yy_pop_state();
		    }
{EndLine}           { /* check for termination of string constant */
                      char warn_msg[WARN_MSG_LENGTH];
                      
                      sprintf(warn_msg,"STRING not terminated properly, an EoL encountered in the middle.\n%s\n",String_buf);
                      capa_msg(MESSAGE_ERROR,warn_msg);
                      yy_pop_state();
                    }
.                   { /*char  *aptr = yytext;
			while( *aptr )   *Current_char_p++ = *aptr++;*/
                      if (dosend==1) send("%s",yytext);
		      if (dosend==2) add_delayed("%s",yytext);
                    }
}

[\)]                  { LLDBUG_PR1("[) in LET]"); Pcount--;send(yytext); }

{
[^\n]+$                      {       }
{EndLine}                    { BEGIN S_TEXT; }
}

{
[^\n]+$                      { send(yytext); }
{EndLine}                    { send(yytext); BEGIN S_TEXT; }
}

{
[\\]{Space}*{EndLine}        { LLDBUG_PR1("[\\EoL let ans map]"); /* continuation */ }
{EndLine}                    { LLDBUG_PR1("[EoL END let ans map]\n"); 
                               if(Pcount == 0) BEGIN S_TEXT; 
                               send(";%s",yytext); 
                             }
}

{
{Space}+                 { /* ignore white spaces */ }
[\\]{Space}*{EndLine}    { /* continuation */ }
{EndLine}                { /* end of answer and/or other answers */ LLDBUG_PR1("[complete an answer]"); 
                           BEGIN S_TEXT; }
"/AND"                   { LLDBUG_PR1("[AND]"); /* implicit in LON-CAPA */ }
"/OR"                    { LLDBUG_PR1("[OR]");  RETURN(ANS_OR);  }
}

{
([.]*){EndLine}          { /* this ignores everything until it hits an EoL */
                           LLDBUG_PRL2("[ skip \'%s\' until EoL]\n",yytext); 
                           BEGIN S_TEXT;
                         }
}

{
^{Spaces}"/WHILE"[^\n]*{EndLine}        { Wcount++;
                                          LLDBUG_PRL2("[SkipWHILE /WHILE ]\n",Wcount);   
                                        }
^{Spaces}"/ENDWHILE"[^\n]*{EndLine}     { 
                                          if(Wcount==0) {
                                             LLDBUG_PRL2("[SkipWHILE->/ENDWHILE ]\n",Wcount);
                                             BEGIN S_TEXT;
                                          } else {
                                             Wcount--;
                                             LLDBUG_PRL2("[SkipWHILE /ENDWHILE ]\n",Wcount);
                                          }
                                        }
{EndLine}                { LLDBUG_PRL1("[SkipWHILE a CR]\n");       }                         
[^\n]*$                  { LLDBUG_PRL2("[SkipWHILE anything ]",Wcount);   }
}

{
^{Spaces}"/ENDVERB" { LLDBUG_PRL1("[END VERB]\n"); 
		      BEGIN S_TEXT;
		      puts("\n
\n"); end_mode(); } .*|{EndLine} { send(yytext); } } %% /* ========================================================================================== */ extern void begin_while_skip() { Wcount=0; While_idx--; /* while is FALSE, pop it out from stack */ BEGIN S_WHILE_SKIP; } extern void begin_next_line() { BEGIN S_NEXT_LINE; } extern void begin_var() { BEGIN S_VARIABLE; } extern void begin_let() { BEGIN S_LET; } extern void begin_def() { BEGIN S_DEFINE; } extern void begin_ans() { BEGIN S_ANSWER; } extern void begin_map() { BEGIN S_MAP; } extern void begin_ignore() { BEGIN S_IGNORE; } extern void begin_text() { BEGIN S_TEXT; } extern void begin_question() { LLDBUG_PR1("[]"); IFcount = 0; While_idx=0; /* initialize some stacks */ End_of_input = 0; YY_FLUSH_BUFFER; BEGIN S_TEXT; } extern void end_problemset() { End_of_input = 0; YY_FLUSH_BUFFER; BEGIN S_TEXT; } /* ========================================================================================== */ #define NUM_KEY 2 int match_keyword(key) char *key; { char *keyword[NUM_KEY] = {"/DIS", "/DIR" }; int i; for(i=0;i < NUM_KEY; i++) { if( !strncmp(keyword[i], key, 4) ) { return (1); } } return (0); } int match_functionid(key) char *key; { char *keyword[NUM_KEY] = {"/DIS", "/DIR" }; int i; for(i=0;i < NUM_KEY; i++) { if( !strncmp(keyword[i], key, 4) ) { return (1); } } return (0); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void init_funcstack() { int ii; for(ii=0;ii>\n"); if (!Lexi_line) { /* was startup */ for(Input_idx=0;Input_idx < MAX_OPENED_FILE;Input_idx++) { /* for(ii=0;ii= MAX_INCLUDE_DEPTH ) { sprintf(warn_msg,"Includes nested too deeply" ); capa_msg(MESSAGE_ERROR,warn_msg); return; } include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER; yyin = fopen( fname, "r" ); yy_switch_to_buffer( yy_create_buffer( yyin, YY_BUF_SIZE ) ); } void parse_filename(char *line) { char *start, fname[MAX_BUFFER_SIZE], warn_msg[WARN_MSG_LENGTH]; int ii,len; start = index(line, '\"'); /*** hpux complained */ if( start == NULL ) { sprintf(warn_msg,"/IMP was not given a filename.\n"); capa_msg(MESSAGE_ERROR,warn_msg); return; } start++; len = strlen(start) - 1; ii = 0; while( start[ii] != '\"' ) fname[ii++] = start[ii]; fname[ii] = 0; LLDBUG_PR2("[parse_filename<%s>]\n",fname); change_file(fname); } void parse_import_id(char *line) { char fname[QUARTER_K], warn_msg[WARN_MSG_LENGTH]; int ii, dup_open; Symbol *symb_p; int no_error = 0; ii = 0; while( line[ii] != '\0' && line[ii] != ' ' && line[ii] != '\n' && line[ii] != '\t' ) fname[ii++] = line[ii]; fname[ii] = 0; LLDBUG_PR2("[parse_import_id<%s>]\n",fname); /*symb_p = find_identifier(fname);*/ switch (symb_p->s_type) { case IDENTIFIER: sprintf(warn_msg,"/IMP %s, var is not defined.\n", fname); capa_msg(MESSAGE_ERROR,warn_msg); break; case I_VAR: case I_CONSTANT: case R_VAR: case R_CONSTANT: sprintf(warn_msg,"var cannot be a number.\n"); capa_msg(MESSAGE_ERROR,warn_msg); break; case S_VAR: case S_CONSTANT: sprintf(fname,"%s",symb_p->s_str); no_error = 1; break; } if( no_error ) change_file(fname); } #else void parse_filename(char *line) { char *start, fname[QUARTER_K], warn_msg[WARN_MSG_LENGTH]; int ii, len, dup_open; /* printf("IMPORT %s\n", line); */ start = index(line, '\"'); /*** hpux complained */ if( start != NULL ) { start++; len = strlen(start) - 1; ii = 0; while( start[ii] != '\"' ) { fname[ii] = start[ii]; ii++; } fname[ii] = 0; LLDBUG_PR2("[parse_filename<%s>]\n",fname); if(Input_idx < (MAX_OPENED_FILE -1)) { dup_open = 0; /* -- no need to check duplicated opening a file for(ii=0;ii]\n",fname); /*symb_p = find_identifier(fname);*/ switch (symb_p->s_type) { case IDENTIFIER: sprintf(warn_msg,"/IMP %s, var is not defined.\n", fname); capa_msg(MESSAGE_ERROR,warn_msg); break; case I_VAR: case I_CONSTANT: case R_VAR: case R_CONSTANT: sprintf(warn_msg,"var cannot be a number.\n"); capa_msg(MESSAGE_ERROR,warn_msg); break; case S_VAR: case S_CONSTANT: sprintf(fname,"%s",symb_p->s_str); no_error = 1; break; } if( no_error ) { if(Input_idx < (MAX_OPENED_FILE -1) ) { dup_open = 0; /* no need to check duplicated opening a file for(ii=0;iiDynamic_buf_max) { char *temp_text; Dynamic_buf_max=(Dynamic_buf_cur+len)*2; temp_text=(char*)capa_malloc(sizeof(char),Dynamic_buf_max); strncpy(temp_text,Dynamic_buf,Dynamic_buf_max); free(Dynamic_buf); Dynamic_buf=temp_text; } for(ii=0;ii>\n"); } out_of_char = 0; if ( Lexi_buf[Input_idx] == NULL ) { Lexi_buf[Input_idx] = (char *)capa_malloc(sizeof(char)*LEX_BUFLEN+1,1); out_of_char=1; } else { if (!Lexi_buf[Input_idx][Lexi_pos[Input_idx]]) { /* test if the line buffer is empty or at the end */ out_of_char=1; } } if( out_of_char ) { if (fgets(Lexi_buf[Input_idx],LEX_BUFLEN-1,Input_stream[Input_idx])==NULL) { /* read in one line */ LIDBUG_PR2("<>\n",Input_idx); if( (Input_idx > 0) && ( Lexi_buf[Input_idx][Lexi_pos[Input_idx]] == '\0') ) { LIDBUG_PR2("<>\n",Input_idx); fclose(Input_stream[Input_idx]); capa_mfree((char *)Lexi_buf[Input_idx]); Lexi_buf[Input_idx] = NULL; Input_idx--; yyin = Input_stream[Input_idx]; /* (Lexi_pos[Input_idx])++; */ buf[0] = Lexi_buf[Input_idx][Lexi_pos[Input_idx]-1]; *result = 1; } else { *result = YY_NULL; /* End of File */ } } else { /* successfully read in one line */ leng = strlen(Lexi_buf[Input_idx]); LIDBUG_PR3("<>\n", leng,Input_idx); Lexi_pos[Input_idx] = 0; Lexi_line++; Current_line[Input_idx]++; (Lexi_pos[Input_idx])++; buf[0] = Lexi_buf[Input_idx][Lexi_pos[Input_idx]-1]; /* need to take care of return continuation conditions */ /* so, we return to one-char-at-a-time approach */ /* for(ii=0;ii>\n",Input_idx); */ (Lexi_pos[Input_idx])++; buf[0] = Lexi_buf[Input_idx][Lexi_pos[Input_idx]-1]; *result = 1; } if (Stop_Parser==1) *result = YY_NULL; } int capa_eof() { #ifdef AVOIDYYINPUT if ( --include_stack_ptr < 0 ) yyterminate(); else { yy_delete_buffer( YY_CURRENT_BUFFER ); yy_switch_to_buffer(include_stack[include_stack_ptr]); } #else if(Input_idx == 0) { fclose(Input_stream[Input_idx]); capa_mfree((char *)Lexi_buf[Input_idx]); /*free_problems(LexiProblem_p);*/ LexiProblem_p=NULL; /* printf("\nCAPA EOF\n"); fflush(stdout); */ } end_mode(); return (0); #endif /*AVOIDYYINPUT*/ } /* ------------ */ /* =========================================================== */