%{
/*
* 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 */
/* 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);
}
/* 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);
}
}
/* 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);
}
}