%{
/*
 * l2x.l     --- (flex) lexer for converting a LaTeX file to X 
 *           Written by Peter Wilson (Catholic University and NIST)
 *           Version 0.2, January 1995
 *           Revised July 1996
 *           -- replace myprint(tag) by tag_print(tag)
 *           -- added verb(atim) like capability
 */

/* Development of this software was funded by the United States Government,
 * and is not subject to copyright.
 */

#include <string.h>
#ifndef STRTYPES_H
#include "strtypes.h"
#endif
#ifndef L2XCOM_H
#include "l2xcom.h"
#endif
#include "l2xytab.h"     /* token codes from parser */
#include "l2xlib.h"      /* functions and global variables */
#include "l2xusrlb.h"    /* possibly useful strings and user-defined functions */


extern int opt_param;
extern int all_opt;
extern int opt_coord;
int got_opt_item = FALSE;
int got_a_dollar = FALSE;
int got_opt_param = FALSE;
int got_all_opt = FALSE;
int got_opt_coord = FALSE;


char verb_char;         /* delimeter for \verb command */
int result;
int kind;
int special_kind;
PSENTRY ptr;            /* pointer to sym entry */
int nl_count = 0;       /* number of consecutive new lines */
char a_newline[] = "\n";
char a_space[] = " ";
char vlenv[80];         /* name of verbatim-like environment */
int nopen_vbrace = 0;   /* no of unmatched open braces after verb-like command */

int nopen_noop = 0;     /* no of unmatched openers for no_op argument */
#define NOOPLBRAK 1
#define NOOPRBRAK 1
#define NOOPLBRACE 2
#define NOOPRBRACE 2
int noop_openc;        /* noop argument opening character ( [ or { )*/

#define LDA -1
#define LD0 0
#define LD1 1
#define LD2 2
#define LD3 3
#define LD4 4
#define LD5 5 
#define LD6 6
/*
 * LDEBUG > LDA: error prints:
 *        > LD0:               names not in command table
 *        > LD1:               newlines, returned useful tokens
 *        > LD2:               general tokens
 *        > LD3:               text dealt with in lexer
 *        > LD4:               comments
 *        > LD5:               stuff within verbatims
 *        > LD6:
 *
 */

%}

                                     /* whitespace and comments */
ws ([ \t])
newline (\n)
                     /* TeX comments from % through eol + any following whitespace */
tex_comment (%.*\n[ \t]*)
                                     /* general REs */
lbrace (\{)
rbrace (\})
lbrak (\[)
rbrak (\])
lparen (\()
rparen (\))
backslash (\\)
comma (",")
name ([a-zA-Z]+\*?)
integer (-?[0-9]+)
real (-?(([0-9]*\.[0-9]+)|([0-9]+\.[0-9]*)))
hash (#)
dollar ($)
ampersand (&)
twiddle (~)
underscore (_)
caret (^)
percent (%)
at (@)
slashspace (\\ )
                                       /* (La)TeX literals */
                                       /* general LaTeX commands */

verbatim (verbatim\*?)
command (\\[a-zA-Z]+\*?)
char_command (\\[^a-zA-Z\n])
begin_c (\\begin[ \t]*)
end_c (\\end[ \t]*)
verb (\\verb\*?)
                                           /* list items */
item (\\item[ \t]*)



%x VERBATIM_STATE
%x VERB_STATE
%x VERBATIM_LIKE
%x VERB_LIKE
%x NOOP
%%

      /*------------ Comments plus start and end document ---------------*/

{tex_comment} {
                 if (LDEBUG > LD4) {
                   print_debug_2s("(tex_comment):", yytext);
                 }
                 catl(yyleng, yytext);
                 do_newline();
                 if (leave_comments) {  /* leave in comments */
                   myprint(yytext);
                 }
               }


                 /* \begin{document} */
{begin_c}{lbrace}{ws}*document{ws}*{rbrace} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(t_BEGIN_DOCUMENT):", yytext);
                  }
                  yylval.pos = get_mode_sym(pos_bdoc);
                  return(BEGIN_DOCUMENT);
                }

                /* end of document \end{document} */
{end_c}{lbrace}{ws}*document{ws}*{rbrace} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(t_END_DOCUMENT):", yytext);
                  }
                  yylval.pos = get_mode_sym(pos_edoc);
                  return(END_DOCUMENT);
                }

                  


  /*----------------- verbatims -----------------------------------------*/
  /* Do most of the processing in the lexer */
  /* but pass token back to parser anyway */

                 /* \begin{verbatim} */
{begin_c}{lbrace}{ws}*{verbatim}{ws}*{rbrace} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(begin{verbatim}):", yytext);
                  }
                  BEGIN VERBATIM_STATE;
                  yylval.pos = get_mode_sym(pos_bvbm);
                  bverb = TRUE;
                  return(BEGIN_VERBATIM);
                }
                /* newline */
<VERBATIM_STATE>{newline} { catl(yyleng, yytext);
                  do_newline();
                  if (LDEBUG > LD3) {
                    print_debug_2s("(newline in verbatim):", yytext);
                  }
                  verbatim_print(yytext);
                }
                 /* backslash */
<VERBATIM_STATE>{backslash} { catl(yyleng, yytext);
                  if (LDEBUG > LD5) {
                    print_to_err(yytext);
                  }
                  verbatim_print(yytext);
                }
                /* any characters other than newline and backslash */
<VERBATIM_STATE>[^\n\\]+ { catl(yyleng, yytext);
                  if (LDEBUG > LD5) {
                    print_to_err(yytext);
                  }
                  verbatim_print(yytext);
                }
                /* \end{verbatim} */
<VERBATIM_STATE>{end_c}{lbrace}{ws}*{verbatim}{ws}*{rbrace} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(end{verbatim}):", yytext);
                  }
                  BEGIN 0;
                  yylval.pos = get_mode_sym(pos_evbm);
                  return(END_VERBATIM);
                }

                    /* \verb (and its trailing character) */
{verb}. { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(verb):", yytext);
                  }
                  BEGIN VERB_STATE;
                  verb_char = yytext[yyleng-1];
                  yylval.pos = get_mode_sym(pos_bv);
                  return(BEGIN_VERB);
                }

                   /* chars inside \verb */
<VERB_STATE>.   { catl(yyleng, yytext);
                  if (LDEBUG > LD5) {
                    print_to_err(yytext);
                  }
                  if (verb_char != yytext[0] ) {
                    myprint(yytext);
                  }
                  else {                 /* end of verb environment */
                    BEGIN 0;
                    yylval.pos = get_mode_sym(pos_ev);
                    return(END_VERB);
                  }
                }

                   /* newlines not allowed within verb */
<VERB_STATE>{newline}    { catl(yyleng, yytext);
                  nl_count++;
                  if (LDEBUG > LD5) {
                    print_to_err(yytext);
                  }
                  BEGIN 0;
                  yyerror("Error: \"verb\" ended by a newline");
                  do_newline();
                  myprint(a_newline);
                  yylval.pos = get_mode_sym(pos_ev);
                  return(END_VERB);
                }

                /* VERB LIKE command stuff */
                   /* { (open brace) */
<VERB_LIKE>{lbrace} { catl(yyleng, yytext);
                      nopen_vbrace++;
                      if (LDEBUG > LD5) {
                        print_to_err(yytext);
                      }
                      if (nopen_vbrace == 1) {    /* start of argument */
                        yylval.pos = get_mode_sym(pos_lbrace);
                        return(LBRACE);
                      }
                      else {                      /* part of argument */
                        verbatim_print(yytext);
                      }
                    }
                   
                  /* } (close brace) */
<VERB_LIKE>{rbrace} { catl(yyleng, yytext);
                      nopen_vbrace--;
                      if (LDEBUG > LD5) {
                        print_to_err(yytext);
                      }
                      if (nopen_vbrace == 0) {    /* end of argument */
                        BEGIN 0;                  /* change state */
                        yylval.pos = get_mode_sym(pos_rbrace);
                        return(RBRACE);
                      }
                      else {                      /* part of argument */
                        verbatim_print(yytext);
                      }
                    }

                 /* newline  */
<VERB_LIKE>{newline} { catl(yyleng, yytext);
                       do_newline();
                       if (LDEBUG > LD3) {
                         print_debug_2s("(newline in verb-like):", yytext);
                       }
                       verbatim_print(yytext);
                     }

                 /* any other character */
<VERB_LIKE>.        { catl(yyleng, yytext);
                      if (LDEBUG > LD5) {
                        print_to_err(yytext);
                      }
                      verbatim_print(yytext);
                    }


                 /* VERBATIM LIKE environment stuff */

                    /* \end{something} */
<VERBATIM_LIKE>{end_c}{lbrace}{ws}*{name}{ws}*{rbrace} { catl (yyleng, yytext);
                      nl_count = 0;
                      get_env_name(yytext);
                      if (strcmp(vlenv, env_name) == 0) { /* close verbatim like */
                        if (LDEBUG > LD1) {
                          print_debug_2s("(end):", yytext);
                          print_debug_2s("env_name= ", env_name);
                        }
                        result = lookup_entry(env_name, END_VENV);
                        if (result > 0) { /* found it */
                          ptr = get_mode_sym(result);
                          yylval.pos = ptr;
                          kind = command_type(ptr);
                          BEGIN 0;
                          return(kind);
                        }
                        else {           /* got problems, end env name not in table */
   warning_3s("END_VENV",env_name,"not in command table. Expect input/output errors from now on");
                          BEGIN 0;
                          verbatim_print(yytext);
                        }
                      }
                      else {      /* not end of verbatim-like env */
                        verbatim_print(yytext);
                      }
                    }

                /* newline */
<VERBATIM_LIKE>{newline} { catl(yyleng, yytext);
                  do_newline();
                  if (LDEBUG > LD3) {
                    print_debug_2s("(newline in verbatim-like):", yytext);
                  }
                  verbatim_print(yytext);
                }

                 /* any other character */
<VERBATIM_LIKE>.      { catl(yyleng, yytext);
                        if (LDEBUG > LD5) {
                          print_to_err(yytext);
                        }
                        verbatim_print(yytext);
                      }
                         
  /*---------------------------No Op processing---------------------------*/

                  /* open brace */
<NOOP>{lbrace} { catl(yyleng, yytext);
                   if (LDEBUG > LD5) {
                     print_to_err(yytext);
                   }
                   if (noop_openc == NOOPLBRACE) {
                     nopen_noop++;
                   }
                }

                  /* open bracket */
<NOOP>{lbrak} { catl(yyleng, yytext);
                   if (LDEBUG > LD5) {
                     print_to_err(yytext);
                   }
                   if (noop_openc == NOOPLBRAK) {
                     nopen_noop++;
                   }
                }

                  /* close brace */
<NOOP>{rbrace} { catl(yyleng, yytext);
                   if (LDEBUG > LD5) {
                     print_to_err(yytext);
                   }
                   if (noop_openc == NOOPLBRACE) {
                     nopen_noop--;
                     if (nopen_noop <= 0) {
                       if (LDEBUG > LD3) {
                         print_to_err("(Closing NO_OP on brace)");
                       }
                       nopen_noop = 0;
                       in_noop = FALSE;
                       start_noop = FALSE;
                       BEGIN 0;
                       yylval.pos = get_mode_sym(pos_rbrace);
                       return(RBRACE);
                     }
                   }
                }

                  /* close bracket */
<NOOP>{rbrak} { catl(yyleng, yytext);
                   if (LDEBUG > LD5) {
                     print_to_err(yytext);
                   }
                   if (noop_openc == NOOPLBRAK) {
                     nopen_noop--;
                     if (nopen_noop <= 0) {
                       if (LDEBUG > LD3) {
                         print_to_err("(Closing NO_OP on bracket)");
                       }
                       nopen_noop = 0;
                       in_noop = FALSE;
                       start_noop = FALSE;
                       BEGIN 0;
                       got_opt_param = FALSE;
                       return(END_ANOPT);
                     }
                   }
                }


                /* newline */
<NOOP>{newline} { catl(yyleng, yytext);
                  do_newline();
                  if (LDEBUG > LD3) {
                    print_debug_2s("(newline in a no op):", yytext);
                  }
                }

                 /* any other character */
<NOOP>.      { catl(yyleng, yytext);
                        if (LDEBUG > LD5) {
                          print_to_err(yytext);
                        }
                      }
                         
  /*----------------------------Default processing------------------------*/

          /*----------------------- list items ---------------------------*/

                 /* item */
{item} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(t_ITEM):", yytext);
                  }
                  return(ITEM);
                }

                     /* item[ */
{item}{lbrak} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(t_ITEM_AND_BRAK):", yytext);
                  }
                  got_opt_item = TRUE;
                  return(ITEM_AND_BRAK);
                }


  /*------------------------------ commands ------------------------------*/

                /* (La)TeX backslash followed by a single space */
{backslash}[ ] { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD4) {
                    print_debug_2s("(slashspace):", yytext);
                  }  /* 6/96 change myprint to tag_print */
                  ptr = get_mode_sym(pos_bss);
                  tag_print(get_t(ptr));
                  tag_print(get_et(ptr));
                }

                /* (La)TeX backslash followed by a newline */
{backslash}[\n] { catl(yyleng, yytext);
                  nl_count++;
                  yylval.string = strsave(yytext);
                  do_newline();
                  if (LDEBUG > LD1) {
                    fprintf(filerr, "\n LD(slashnewline): next line is %d\n", lineno);
                    fflush(filerr);
                  }
                  ptr = get_mode_sym(pos_bss);
                  tag_print(get_t(ptr));
                  tag_print(get_et(ptr));
                  if (!pretty_print) {
                    myprint(a_newline);
                  }
                }

                 /* \one non-alphabetic character */
{char_command} {catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(char_command):", yytext);
                  }
                  result = lookup_entry(yytext, CHAR_COMMAND);
                  if (result >= 0) {         /* found it */
                    ptr = get_mode_sym(result);
                    kind = command_type(ptr);
                    yylval.pos = ptr;
                    return(kind);
                  }
                  else {
                    yylval.string = strsave(yytext);
                    if (LDEBUG > LD1) {
                      print_debug_1s("(as t_OTHER_COMMAND)");
                    }
                    if (LDEBUG > LD0) {
                      print_debug_undef(yylval.string, " (as CHAR_COMMAND)");
                    }
                    return(OTHER_COMMAND);
                 }
               }

                   /* special processing for \\* command */
{backslash}{backslash}[ \t]*\* { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(char_command):", yytext);
                  }
                  result = lookup_entry("\\\\", CHAR_COMMAND);
                  if (result >= 0) {         /* found it */
                    ptr = get_mode_sym(result);
                    kind = command_type(ptr);
                    yylval.pos = ptr;
                    return(kind);
                  }
                  else {
                    yylval.string = strsave(yytext);
                    if (LDEBUG > LD1) {
                      print_debug_1s("(as t_OTHER_COMMAND)");
                    }
                    if (LDEBUG > LD0) {
                      print_debug_undef(yylval.string, " (as CHAR_COMMAND)");
                    }
                    return(OTHER_COMMAND);
                 }
               }



                  /* a command \something or \something* */
{command} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(command):", yytext);
                  }
                  result = lookup_entry(yytext, DONT_CARE);
                  if (result >= 0) {         /* found it */
                    ptr = get_mode_sym(result);
                    kind = command_type(ptr);
                    yylval.pos = ptr;
                    switch (get_user_type(ptr)) {
                      case SPECIAL_COMMAND: {
                        special_kind = get_special_token(ptr);
                        if (special_kind == COMMAND) {
                          warning_3s("SPECIAL_COMMAND",yytext,"not yet implemented");
                        }
                        if (special_kind >= MIN_CODE_SPECIAL) {
                          return(kind);
                        }
                        else {
                          return(special_kind);
                        }
                        break;
                      }
                      case SPECIAL_SECTIONING: {
                        special_kind = get_special_token(ptr);
                        if (special_kind == COMMAND) {
                          warning_3s("SPECIAL_SECTIONING",yytext,"not yet implemented");
                        }
                        if (special_kind >= MIN_CODE_SPECIAL) {
                          return(kind);
                        }
                        else {
                          return(special_kind);
                        }
                        break;
                      }
                      case VCOMMAND: {               /* verb-like */
                        BEGIN VERB_LIKE;
                        nopen_vbrace = 0;
                        break;
                      }
                    }  /* end switch */
                    return(kind);
                  }
                  else {
                    yylval.string = strsave(yytext);
                    if (LDEBUG > LD1) {
                      print_debug_1s("(as t_OTHER_COMMAND)");
                    }
                    if (LDEBUG > LD0) {
                      print_debug_undef(yylval.string, " (as a command type)");
                    }
                    return(OTHER_COMMAND);
                  }
               }


    /*-------------------- Environments ---------------------------*/

                  /* \begin{something} */
{begin_c}{lbrace}{ws}*{name}{ws}*{rbrace} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(begin):", yytext);
                  }
                  get_env_name(yytext);
                  if (LDEBUG > LD1) {
                    print_debug_2s("env_name= ", env_name);
                  }
                  result = lookup_entry(env_name, BEGIN_ENV);
                  if (result >= 0) {             /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    kind = command_type(ptr);
                    return(kind);
                  }
                  result = lookup_entry(env_name, BEGIN_LIST_ENV);
                  if (result >= 0) {             /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    kind = command_type(ptr);
                    return(kind);
                  }
                  result = lookup_entry(env_name, BEGIN_PICTURE_CC);
                  if (result >= 0) {             /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    kind = command_type(ptr);
                    return(kind);
                  }
                  result = lookup_entry(env_name, BEGIN_VENV);
                  if (result >= 0) {          /* found it */
                    BEGIN VERBATIM_LIKE;      /* switch into verbatim-like mode */
                    bverb = TRUE;
                    strcpy(vlenv, env_name);     /* remember environment name */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    kind = command_type(ptr);
                    return(kind);
                  }
                  result = lookup_entry(env_name, SPECIAL_BEGIN_ENV);
                  if (result >= 0) {             /* found it */
                    ptr = get_mode_sym(result); 
                    yylval.pos = ptr;
                    special_kind = get_special_token(ptr);
                    if (special_kind == COMMAND) {
                      warning_3s("SPECIAL_BEGIN_ENV",env_name,"not yet implemented"); 
                    }
                    if (special_kind >= MIN_CODE_SPECIAL) {
                      return(command_type(ptr));
                    }
                    else {
                      return(special_kind);
                    }
                  }
                  result = lookup_entry(env_name, SPECIAL_BEGIN_LIST);
                  if (result >= 0) {             /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    special_kind = get_special_token(ptr);
                    if (special_kind == COMMAND) {
                      warning_3s("SPECIAL_BEGIN_LIST",env_name,"not yet implemented"); 
                    }
                    if (special_kind >= MIN_CODE_SPECIAL) {
                      return(command_type(ptr));
                    }
                    else {
                      return(special_kind);
                    }
                  }
                  yylval.string = strsave(yytext);
                    if (LDEBUG > LD1) {
                      print_debug_1s("(as t_OTHER_BEGIN)");
                    }
                    if (LDEBUG > LD0) {
                      print_debug_undef(yylval.string, " (as begin something)");
                    }
                  return(OTHER_BEGIN);
                }

                  /* \end{something} */
{end_c}{lbrace}{ws}*{name}{ws}*{rbrace} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(end):", yytext);
                  }
                  get_env_name(yytext);
                  if (LDEBUG > LD1) {
                    print_debug_2s("env_name= ", env_name);
                  }
                  result = lookup_entry(env_name, END_ENV);
                  if (result >= 0) {             /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    kind = command_type(ptr);
                    return(kind);
                  }
                  result = lookup_entry(env_name, END_LIST_ENV);
                  if (result >= 0) {             /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    kind = command_type(ptr);
                    return(kind);
                  }
                  result = lookup_entry(env_name, END_PICTURE);
                  if (result >= 0) {             /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    kind = command_type(ptr);
                    return(kind);
                  }
                  result = lookup_entry(env_name, SPECIAL_END_ENV);
                  if (result >= 0) {             /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    special_kind = get_special_token(ptr);
                    if (special_kind == COMMAND) {
                      warning_3s("SPECIAL_END_ENV",env_name,"not yet implemented"); 
                    }
                    if (special_kind >= MIN_CODE_SPECIAL) {
                      return(command_type(ptr));
                    }
                    else {
                      return(special_kind);
                    }
                  }
                  result = lookup_entry(env_name, SPECIAL_END_LIST);
                  if (result >= 0) {             /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    special_kind = get_special_token(ptr);
                    if (special_kind == COMMAND) {
                      warning_3s("SPECIAL_END_ENV",env_name,"not yet implemented"); 
                    }
                    if (special_kind >= MIN_CODE_SPECIAL) {
                      return(command_type(ptr));
                    }
                    else {
                      return(special_kind);
                    }
                  }
                  yylval.string = strsave(yytext);
                    if (LDEBUG > LD1) {
                      print_debug_1s("(as t_OTHER_END)");
                    }
                    if (LDEBUG > LD0) {
                      print_debug_undef(yylval.string, " (as end something)");
                    }
                  return(OTHER_END);
                }


          /*--------------------- Miscellaneous stuff -----------------------*/


                /* an open brace { */
{lbrace}    { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(t_LBRACE):", yytext);
                  }
                  if (start_noop) {
                       if (LDEBUG > LD3) {
                         print_to_err("(Starting NO_OP on brace)");
                       }
                    start_noop = FALSE;
                    in_noop = TRUE;
                    nopen_noop = 1;
                    noop_openc = NOOPLBRACE;
                    BEGIN NOOP;
                  }
                  yylval.pos = get_mode_sym(pos_lbrace);
                  return(LBRACE);
                }

                /* a close brace } */
{rbrace}   { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(t_RBRACE):", yytext);
                  }
                  yylval.pos = get_mode_sym(pos_rbrace);
                  return(RBRACE);
                }

                /* an open bracket [ */
{lbrak}     { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(t_LBRAK):", yytext);
                  }
                  if (opt_param) {
                    got_opt_param = TRUE;
                    opt_param = FALSE;
                    if (start_noop) {
                       if (LDEBUG > LD3) {
                         print_to_err("(Starting NO_OP on bracket)");
                       }
                      start_noop = FALSE;
                      in_noop = TRUE;
                      noop_openc = NOOPLBRAK;
                      BEGIN NOOP;
                    }
                    return(START_ANOPT);
                  }
                  else if (all_opt) {
                    got_all_opt = TRUE;
                    all_opt = FALSE;
                    return(START_ALLOPT);
                  }
                  else {
                    return(LBRAK);
                  }
                }

                /* a close bracket ] */
{rbrak}    { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(t_RBRAK):", yytext);
                  }
                  if (got_opt_item) {
                    got_opt_item = FALSE;
                    return(END_ITEM_BRAK);
                  }
                  else if (got_opt_param) {
                    got_opt_param = FALSE;
                    return(END_ANOPT);
                  }
                  else if (got_all_opt) {
                    got_all_opt = FALSE;
                    return(END_ALLOPT);
                  }
                  else {
                    return(RBRAK);
                  }
                }

         /*------------------- Special characters ----------------------*/

                 /* a naked hash # */
{hash} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(hash):", yytext);
                  }
                  result = lookup_entry(yytext, TEX_CHAR);
                  if (result >= 0) {                 /* found it */
                    ptr = get_mode_sym(result);
                    kind = command_type(ptr);
                    yylval.pos = ptr;
                    return(kind);
                  }
                  else {
                    yylval.string = strsave(yytext);
                    if (LDEBUG > LD1) {
                      print_debug_1s("(as t_OTHER)");
                    }
                    if (LDEBUG > LD0) {
                      print_debug_undef(yylval.string, " (as a special character)");
                    }
                    return(OTHER);
                  }
               }

                 /* a naked dollar $ */
{dollar} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(dollar):", yytext);
                    if (got_a_dollar) { print_debug_1s("(as t_END_DOLLAR)"); }
                    else { print_debug_1s("(as t_BEGIN_DOLLAR)"); }
                  }
                  if (got_a_dollar) {          /* a 'closing' $ */
                    got_a_dollar = FALSE;
                    yylval.pos = get_mode_sym(pos_edol);
                    return(END_DOLLAR);
                  }
                  else {                       /* an 'opening' $ */
                    got_a_dollar = TRUE;
                    yylval.pos = get_mode_sym(pos_bdol);
                    return(BEGIN_DOLLAR);
                 }
               }

                 /* a naked ampersand & */
{ampersand} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(ampersand):", yytext);
                  }
                  result = lookup_entry(yytext, TEX_CHAR);
                  if (result >= 0) {                 /* found it */
                    ptr = get_mode_sym(result);
                    kind = command_type(ptr);
                    yylval.pos = ptr;
                    return(kind);
                  }
                  else {
                    yylval.string = strsave(yytext);
                    if (LDEBUG > LD1) {
                      print_debug_1s("(as t_OTHER)");
                    }
                    if (LDEBUG > LD0) {
                      print_debug_undef(yylval.string, " (as a special character)");
                    }
                    return(OTHER);
                  }
               }


                 /* a naked twiddle ~ */
{twiddle} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(twiddle):", yytext);
                  }
                  result = lookup_entry(yytext, TEX_CHAR);
                  if (result >= 0) {                 /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    kind = command_type(ptr);
                    return(kind);
                  }
                  else {
                    yylval.string = strsave(yytext);
                    if (LDEBUG > LD1) {
                      print_debug_1s("(as t_OTHER)");
                    }
                    if (LDEBUG > LD0) {
                      print_debug_undef(yylval.string, " (as a special character)");
                    }
                    return(OTHER);
                  }
               }

                 /* a naked underscore _ */
{underscore} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(underscore):", yytext);
                  }
                  result = lookup_entry(yytext, TEX_CHAR);
                  if (result >= 0) {                 /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    kind = command_type(ptr);
                    return(kind);
                  }
                  else {
                    yylval.string = strsave(yytext);
                    if (LDEBUG > LD1) {
                      print_debug_1s("(as t_OTHER)");
                    }
                    if (LDEBUG > LD0) {
                      print_debug_undef(yylval.string, " (as a special character)");
                    }
                    return(OTHER);
                  }
               }

                 /* a naked caret ^ */
{caret} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(caret):", yytext);
                  }
                  result = lookup_entry(yytext, TEX_CHAR);
                  if (result >= 0) {                 /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    kind = command_type(ptr);
                    return(kind);
                  }
                  else {
                    yylval.string = strsave(yytext);
                    if (LDEBUG > LD1) {
                      print_debug_1s("(as t_OTHER)");
                    }
                    if (LDEBUG > LD0) {
                      print_debug_undef(yylval.string, " (as a special character)");
                    }
                    return(OTHER);
                  }
               }

                 /* a naked percent % */
{percent} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(percent):", yytext);
                  }
                  result = lookup_entry(yytext, TEX_CHAR);
                  if (result >= 0) {                 /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    kind = command_type(ptr);
                    return(kind);
                  }
                  else {
                    yylval.string = strsave(yytext);
                    if (LDEBUG > LD1) {
                      print_debug_1s("(as t_OTHER)");
                    }
                    if (LDEBUG > LD0) {
                      print_debug_undef(yylval.string, " (as a special character)");
                    }
                    return(OTHER);
                  }
               }

                 /* a naked at @ */
{at} { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD1) {
                    print_debug_2s("(at):", yytext);
                  }
                  result = lookup_entry(yytext, TEX_CHAR);
                  if (result >= 0) {                 /* found it */
                    ptr = get_mode_sym(result);
                    yylval.pos = ptr;
                    kind = command_type(ptr);
                    return(kind);
                  }
                  else {
                    yylval.string = strsave(yytext);
                    if (LDEBUG > LD1) {
                      print_debug_1s("(as t_OTHER)");
                    }
                    if (LDEBUG > LD0) {
                      print_debug_undef(yylval.string, " (as a special character)");
                    }
                    return(OTHER);
                  }
               }



                     /* name (alphabetic string(*) ) */
{name}        { catl(yyleng, yytext);
                  nl_count = 0;
                  yylval.string = strsave(yytext);
                  if (LDEBUG > LD1) {
                    print_debug_2s("(t_NAME):", yytext);
                  }
                  return(NAME);
                }

                     /* integer (digit string) */
{integer}        { catl(yyleng, yytext);
                  nl_count = 0;
                  yylval.string = strsave(yytext);
                  if (LDEBUG > LD2) {
                    print_debug_2s("(t_INTEGER):", yytext);
                  }
                  return(INTEGER);
                }

                     /* real (digits with one period) */
{real}          { catl(yyleng, yytext);
                  nl_count = 0;
                  yylval.string = strsave(yytext);
                  if (LDEBUG > LD2) {
                    print_debug_2s("(t_REAL):", yytext);
                  }
                  return(REAL);
                }

        
                 /* a comma */
{comma}         { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD2) {
                    print_debug_2s("(t_COMMA):", yytext);
                  }
                  return(COMMA);
                }

                 /* left parenthesis */
{lparen}        { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD2) {
                    print_debug_2s("(t_LPAREN):", yytext);
                  }
                  if (opt_coord) {
                    got_opt_coord = TRUE;
                    opt_coord = FALSE;
                    return(START_COORD);
                  }
                  else {
                    return(LPAREN);
                  }
                }

                 /* right parenthesis */
{rparen}        { catl(yyleng, yytext);
                  nl_count = 0;
                  if (LDEBUG > LD2) {
                    print_debug_2s("(t_RPAREN):", yytext);
                  }
                  if (got_opt_coord) {
                    got_opt_coord = FALSE;
                    return(END_COORD);
                  }
                  else {
                    return(RPAREN);
                  }
                }



                /* whitespace (except newline) print it out */
[ \t]+    { catl(yyleng, yytext);
                  if (LDEBUG > LD4) {
                    print_debug_2s("(ws):", yytext);
                  }
                  if (collapse_ws) {    /* collapse whitespace */
                    myprint(a_space);
                  }
                  else {
                    myprint(yytext);
                  }
                }

                /* newline with leading and trailing spaces */
                /* 7/96  changed to enable paragraphs outside pretty mode */
{ws}*{newline}{ws}*       { catl(yyleng, yytext);
                  nl_count++;
                 /* yylval.string = strsave(yytext); */
                  do_newline();
                  if (LDEBUG > LD1) {
                    fprintf(filerr, "\n LD(newline): next line is %d\n", lineno);
                    fflush(filerr);
                  }
                  if (!pretty_print) {       /* not pretty printing */
                    myprint(yytext);
                    if (nl_count == 2) {     /* 6/96 added this */
                      yylval.pos = get_mode_sym(pos_para);
                      return(PARAGRAPH);
                    }
                  }
                  else {
                    if (nl_count == 2) {      /* (6/96 changed from >= 2 to == 2) a paragraph break */
                      yylval.pos = get_mode_sym(pos_para);
                      return(PARAGRAPH);
                    }
                    else {                    /* treat as space */
                      myprint(a_space);
                    }
                  }
                }



          /*----------- WHEN ALL ELSE FAILS --------------------*/

                 /* end of file */
<<EOF>>        { catl(yyleng, yytext);
                 if (LDEBUG > LD1) {
                   print_debug_1s("(end of file):\n");
                 }
                 yyerror("Lexer: Unexpected end of file");
                 return(END_OF_FILE);
               }

                /* anything else */
.              { catl(yyleng, yytext);
                  nl_count = 0;
                 result = lookup_entry(yytext, TEX_CHAR);
                 if (result >= 0) {           /* found it */
                   if (LDEBUG > LD1) {
                     print_debug_2s("(tex_char):", yytext);
                   }
                   ptr = get_mode_sym(result);
                   yylval.pos = ptr;
                   kind = command_type(ptr);
                   return(kind);
                 }
                 else {
                   yylval.string = strsave(yytext);
                   if (LDEBUG > LD4) {
                      print_debug_2s("(catch_all):", yytext);
                    }
                    return(OTHER);
                 }
               }

%%


