%{
/*
grammar used to build the parser,
Copyright (C) 1991 Raphael Cerf (e-mail:
[email protected])
This file is part of xetal.
This program 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 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <search.h>
#include "proto.h"
#include "glbl.h"
#include "str.h"
#include "stack.h"
/* output macros */
/* flag for output */
#define out (mode!=-1 || d_macrodef) && (mode!=1 || d_math) && d_ok
/* deleted text */
#define noprint(x) { int i; char *p=S; \
sprintf x ; \
c_skipped+=strlen(S); \
if (do_fill) { \
while ((*p!=(char)NULL)) { \
if (*p=='\n') ; \
else if (*p=='\t') ; \
else { \
*p=c_fill; \
} \
p++; \
} \
fprintf(stdout, "%s", S); \
} \
}
/* displayed text */
#define doprint(x) { sprintf x; fprintf(stdout, "%s", S); }
/* general output macro */
#define print(x, v) { if (out && v) doprint(x) \
else noprint(x) }
%}
/*
* shift-reduces expected
*/
/*%expect 108*/
/*
* stack type
*/
%union {
char *y_str; /* string */
char y_chr; /* character */
int y_int; /* integer */
}
/*
* terminal symbols
*/
%token SLASH
%token NULL_COMMAND
%token FFEED OTHER
%token <y_chr> '{' '}' '[' ']'
%token <y_str> BLS BLSNL
%token <y_chr> LETTER DIGIT
%token <y_chr> SLASHED
%token <y_str> BGIN END INCLUSION COMMAND UNKNOWN COMMENT
%token <y_str> VERB VERBATIM
%token <y_str> DEF CTLSEQ0 CTLSEQ1 CTLSEQ2 CTLSEQ3 CATCODE
%token <y_str> LATEX_DEF LATEX_DEFENV
%token <y_str> READ SETBOX FONT
%token <y_str> ASSIGN
%token <y_str> LATEX_PAR
%token <y_str> INT_PAR DIMEN_PAR GLUE_PAR MUGLUE_PAR TOKEN_PAR
%token <y_str> REGISTER
%token <y_str> OPERATION
%token <y_str> BOX
%token <y_str> DOLLAR DDOLLAR OPARE CPARE OBRAC CBRAC
%token <y_str> ANYTHING ANY_NOT_SLASH
%token <y_str> NOMBRE LETTRES CARACTERES REEL FILENAME
%token <y_str> ACCENT
%token <y_str> H1O1O_COMMAND
%token <y_str> H1O1_COMMAND H1O2_COMMAND
%token <y_str> H1OO1_COMMAND
%token <y_str> H1O_COMMAND H2O_COMMAND
%token <y_str> H2_COMMAND H3_COMMAND
%token <y_str> HO1_COMMAND HO2_COMMAND
%token <y_str> HOO1_COMMAND
%token <y_str> HO_COMMAND
%token <y_str> INCLUDEONLY
%token <y_str> INDENV SLOPENV MINIENV PICTENV
%token <y_str> K1_COMMAND H1_COMMAND
%token <y_str> KO1_COMMAND
%token <y_str> K_COMMAND H_COMMAND
%token <y_str> LISTENV FIGENV TABBENV TABUENV BIBLENV
%token <y_str> MATHENV TEXTENV
/*
* non terminal symbols
*/
%type <y_chr> r_accent
%type <y_int> def_mode
%type <y_str> environnement
%type <y_str> environnement_name
%type <y_str> lettres, fln
%type <y_str> filename
%type <y_str> math_environnement
%type <y_int> math_mode
%type <y_chr> operator
%type <y_chr> signe_ponctuation
%type <y_chr> special
%type <y_int> text_mode
%%
tex
: start lignes nl
| start lignes end start_END lignes start_N
;
start
:
{ start_file(); }
;
lignes
:
| entites
;
entites
: entite
| entites entite
;
entite
: anything
| any_not_slash
| mot
| phrase
| lettre
| ponctuation
| macro
| assignment
| catcode_def
| commande
| commentaire
| groupe
| separateur
| reste
| error
{ empty_S_stack(); mode=0; start_N(); }
;
anything
: ANYTHING
{
print((S, "%s", $1), d_anything);
}
;
any_not_slash
: ANY_NOT_SLASH
{
print_seq($1, d_mot && (mode!=0 || d_text));
}
;
mot
: LETTRES
{
print((S, "%s", $1), d_mot && (mode!=0 || d_text))
}
;
phrase
: CARACTERES
{
print((S, "%s", $1), d_mot && (mode!=0 || d_text))
}
;
lettre
: LETTER
{
print((S, "%c", $1), d_mot && (mode!=0 || d_text))
}
;
ponctuation
: signe_ponctuation
{
print((S, "%c", $1), d_punct && (mode!=0 || d_text))
}
;
signe_ponctuation
: '.' { $$='.'; }
| ',' { $$=','; }
| ';' { $$=';'; }
| ':' { $$=':'; }
| '!' { $$='!'; }
| '?' { $$='?'; }
| '`' { $$='`'; }
| '\'' { $$='\''; }
| SLASH { $$='\\'; }
| '\"' { $$='\"'; }
;
macro
: start_SQ2 def o_spnl ctlseq o_spnl start_N def_mode oa lignes ca
{ mode=$7; }
| latex_def start_ARG o_spnl hg_argument def_mode ho_argument hg_argument start_N
{ mode=$5; }
| latex_defenv start_ARG o_spnl hg_argument def_mode ho_argument hg_argument o_spnl hg_argument start_N
{ mode=$5; }
;
start_SQ2
:
{ start_SQ2(); }
;
def
: DEF
{ print((S, "%s", $1), d_command) }
;
o_spnl
:
| spaces
| spaces_newline
;
spaces
: BLS
{ if (d_bls) print((S, "%s", $1), d_bl)
else print((S, "%s", " "), d_bl) }
;
spaces_newline
: BLSNL
{ print_blnl($1); }
;
ctlseq
: CTLSEQ0
{ print_seq($1, d_command); }
| CTLSEQ1
{ print_seq($1, d_command); }
| CTLSEQ2
{ print_seq($1, d_command); }
| CTLSEQ3
{ print_seq($1, d_command); }
| slashed o_ctlseq
;
slashed
: SLASHED
{ if (!do_fill_slash) print((S, "%c", $1), d_slashed)
else print((S, "%c%c", '\\', $1), d_slashed) }
;
o_ctlseq
:
| ctlseq
;
start_N
:
{ start_N(); }
;
def_mode
:
{ $$=mode; mode=-1; }
oa
: '{'
{ if (do_fill_acco) print((S, "%c", $1), d_command) }
;
ca
: '}'
{ if (do_fill_acco) print((S, "%c", $1), d_command) }
;
latex_def
: LATEX_DEF
{ print((S, "%s", $1), d_command) }
;
start_ARG
:
{ start_ARG(); }
;
hg_argument
: d_no entite d_yes
;
ho_argument
: o_spnl
| o_spnl ob start_O_ARG d_no lignes d_yes cbrac start_N o_spnl
;
start_O_ARG
:
{ start_O_ARG(); }
;
ob
: '['
{ print((S, "%c", '['), d_command) }
;
d_no
:
{ d_ok=0; }
;
d_yes
:
{ d_ok=1; }
;
cbrac
: CBRAC
{ print((S, "%c", ']'), d_command) }
;
latex_defenv
: LATEX_DEFENV
{ print((S, "%s", $1), d_command) }
;
assignment
: variable start_CAR def_mode o_spnl equal o_spnl value start_N
{ mode=$3; }
| variable start_CAR def_mode o_spnl start_N
{ mode=$3; }
| operation o_spnl variable start_CAR def_mode o_by value start_N
{ mode=$5; }
| start_SQ1 read o_spnl ctlseq start_N
| start_SQ1 setbox o_spnl ctlseq start_N o_spnl o_equal o_spnl entite
| start_SQ1 font o_spnl ctlseq start_N o_spnl equal o_spnl filename
{ str_destroy($9); }
| start_SQ3 assign o_spnl o_ctlseq start_N o_spnl def_mode o_equal entite
{ mode=$7; }
;
variable
: LATEX_PAR
{ print((S, "%s", $1), d_command) }
| INT_PAR
{ print((S, "%s", $1), d_command) }
| DIMEN_PAR
{ print((S, "%s", $1), d_command) }
| GLUE_PAR
{ print((S, "%s", $1), d_command) }
| MUGLUE_PAR
{ print((S, "%s", $1), d_command) }
| TOKEN_PAR
{ print((S, "%s", $1), d_command) }
| start_NB register nombre_unknown start_N
;
start_NB
:
{ start_NB(); }
;
register
: REGISTER
{ print((S, "%s", $1), d_command) }
;
nombre_unknown
: nombre
| unknown_command
;
nombre
: NOMBRE
{ print((S, "%s", $1), d_command) }
;
unknown_command
: UNKNOWN
{ print((S, "%s", $1), d_command) }
;
start_CAR
:
{ start_CAR(); }
;
equal
: '='
{ print((S, "%s", "="), d_command) }
;
value
: entite
;
operation
: OPERATION
{ print((S, "%s", $1), d_command) }
;
o_by
: o_spnl
| o_spnl by o_spnl
;
by
: LETTRES
{
if (strcmp($1, "by")!=0) {
fprintf(stderr, "by expected\n");
}
print((S, "%s", $1), d_command)
}
;
start_SQ1
:
{ start_SQ1(); }
;
read
: READ
{ print((S, "%s", $1), d_command) }
;
setbox
: SETBOX
{ print((S, "%s", $1), d_command) }
;
font
: FONT
{ print((S, "%s", $1), d_command) }
;
start_SQ3
:
{ start_SQ3(); }
;
assign
: ASSIGN
{ print((S, "%s", $1), d_command) }
;
o_equal
: o_spnl
| o_spnl equal o_spnl
;
catcode_def
: start_SQ0 catcode ctlseq start_N def_mode o_spnl equal o_spnl value
{ mode=$5; }
;
start_SQ0
:
{ start_SQ0(); }
;
catcode
: CATCODE
{ print((S, "%s", $1), d_command) }
;
commande
: begin_end_section
| verb
| math
| box
| accent
| s_command
| k_command
| h_command
| ho_command start_ARG ho_argument start_N
| k1_command start_ARG o_spnl kg_argument start_N
| ko1_command start_ARG ho_argument kg_argument start_N
| h1_command start_ARG o_spnl hg_argument start_N
| h2_command start_ARG o_spnl hg_argument o_spnl hg_argument start_N
| h3_command start_ARG o_spnl hg_argument o_spnl hg_argument o_spnl hg_argument start_N
| ho1_command start_ARG ho_argument hg_argument start_N
| ho2_command start_ARG ho_argument hg_argument o_spnl hg_argument start_N
| h1o1_command start_ARG o_spnl hg_argument ho_argument hg_argument start_N
| h1o2_command start_ARG o_spnl hg_argument ho_argument hg_argument o_spnl hg_argument start_N
| h1o_command start_ARG o_spnl hg_argument ho_argument start_N
| h2o_command start_ARG o_spnl hg_argument o_spnl hg_argument ho_argument start_N
| hoo1_command start_ARG ho_argument ho_argument hg_argument start_N
| h1oo1_command start_ARG o_spnl hg_argument ho_argument ho_argument hg_argument start_N
| h1o1o_command start_ARG o_spnl hg_argument ho_argument hg_argument ho_argument start_N
| inclusion
| unknown_command
;
begin_end_section
: bgin start_BE_ARG o_spnl oa environnement ca lignes end start_BE_ARG o_spnl oa environnement ca
{ if (strcmp($5, $12)!=0) {
fprintf(stderr, "%s | %s not matching in begin_end\n", $5, $12);
exit(2);
}
str_destroy($5);
str_destroy($12);
}
;
bgin
: BGIN
{ print((S, "%s", $1), d_command) }
;
start_BE_ARG
:
{ start_BE_ARG(); }
;
environnement
: environnement_name
{ $$=strdup($1);
print((S, "%s", $1), d_command) }
;
environnement_name
: TEXTENV
| LISTENV
| FIGENV
| TABBENV
| TABUENV
| BIBLENV
| INDENV
| SLOPENV
| MINIENV
| PICTENV
| VERBATIM
| UNKNOWN
;
end
: END
{ print((S, "%s", $1), d_command) }
;
verb
: VERB
{ char *p, sch, o;
int l;
p=$1+5;/* suppress \verb in string p */
if (*p=='*') p++;
sch=*p;p++;o=*p;*p=(char)NULL;
print((S, "%s", $1), d_command)
*p=o;l=strlen(p);
*(p+l-1)=(char)NULL;
print_seq(p, d_mot && (mode!=0 || d_text));
print((S, "%c", sch), d_command)
}
;
math
: bgin start_BE_ARG o_spnl oa math_environnement ca math_mode entites end start_BE_ARG o_spnl oa math_environnement ca
{ mode=$7;
if (strcmp($5, $13)!=0) {
fprintf(stderr, "%s | %s not matching in begin_end\n", $5, $13);
exit(2);
}
str_destroy($5);
str_destroy($13);
}
| math_mode dollar entites dollar
{ mode=$1; }
| math_mode ddollar entites ddollar
{ mode=$1; }
| math_mode opare entites cpare
{ mode=$1; }
| math_mode obrac entites cbrac
{ mode=$1; }
;
math_environnement
: MATHENV
{ $$=strdup($1);
print((S, "%s", $1), d_command) }
;
math_mode :
{ $$=mode; mode=1; n_formule++; }
;
dollar
: DOLLAR
{ print((S, "%c", '$'), d_command) }
;
ddollar
: DDOLLAR
{ print((S, "%c%c", '$', '$'), d_command) }
;
opare
: OPARE
{ print((S, "%c", '('), d_command) }
;
cpare
: CPARE
{ print((S, "%c", ')'), d_command) }
;
obrac
: OBRAC
{ print((S, "%c", '['), d_command) }
;
box
: start_SQ1 box_name text_mode start_N groupe
{ mode=$3; }
| start_SQ1 box_name o_spnl ctlseq start_N text_mode groupe
{ mode=$6; }
;
box_name
: BOX
{ print((S, "%s", $1), d_command) }
;
text_mode
: o_spnl
{ $$=mode; if (mode!=-1) mode=0; }
;
groupe
: oa lignes ca
;
accent
: r_accent o_spnl
{
if (d_accent) {
if (s_accent==(char)NULL) {
print((S, "%c", $1), (mode!=0 || d_text))
} else {
print((S, "%c%c", s_accent, $1), (mode!=0 || d_text))
} } }
;
r_accent
: ACCENT
{ $$=$1[1]; }
s_command
: COMMAND
{ print((S, "%s", $1), d_command) }
;
k_command
: K_COMMAND
{ print((S, "%s", $1), d_command) }
;
h_command
: H_COMMAND
{ print((S, "%s", $1), d_command) }
;
ho_command
: HO_COMMAND
{ print((S, "%s", $1), d_command) }
;
k1_command
: K1_COMMAND
{ print((S, "%s", $1), d_command) }
;
kg_argument
: entite
;
ko1_command
: KO1_COMMAND
{ print((S, "%s", $1), d_command) }
;
h1_command
: H1_COMMAND
{ print((S, "%s", $1), d_command) }
;
h2_command
: H2_COMMAND
{ print((S, "%s", $1), d_command) }
;
h3_command
: H3_COMMAND
{ print((S, "%s", $1), d_command) }
;
ho1_command
: HO1_COMMAND
{ print((S, "%s", $1), d_command) }
;
ho2_command
: HO2_COMMAND
{ print((S, "%s", $1), d_command) }
;
h1o1_command
: H1O1_COMMAND
{ print((S, "%s", $1), d_command) }
;
h1o2_command
: H1O2_COMMAND
{ print((S, "%s", $1), d_command) }
;
h1o_command
: H1O_COMMAND
{ print((S, "%s", $1), d_command) }
h2o_command
: H2O_COMMAND
{ print((S, "%s", $1), d_command) }
;
hoo1_command
: HOO1_COMMAND
{ print((S, "%s", $1), d_command) }
;
h1oo1_command
: H1OO1_COMMAND
{ print((S, "%s", $1), d_command) }
;
h1o1o_command
: H1O1O_COMMAND
{ print((S, "%s", $1), d_command) }
;
inclusion
: INCLUDEONLY start_FLN filename start_N
{ char *p=$3;int i, old_n_ionly;
if (n_ionly==-1) n_ionly=0;
old_n_ionly=n_ionly;
if ((if_name[n_ionly++]=strtok(p, ","))!=(char *)NULL) {
p=(char *)NULL;
while ((if_name[n_ionly++]=strtok(p, ","))!=(char *)NULL);
n_ionly--;
for (i=old_n_ionly; i<n_ionly; i++) {
if_name[i]=strdup(if_name[i]);
} }
str_destroy($3);
}
| inclusion_command start_FLN filename start_N
{ int i;
if (do_incl) {
FILE *fd=(FILE *)NULL;
char i_name[W_LGTH];
strcpy(i_name, $3);
for (i=0; i<n_ionly; i++) {
if (strcmp(i_name,if_name[i])==0) break;
}
if (i==n_ionly) {
if (d_warning)
fprintf(stderr, "%s not included\n", i_name);
} else {
strcat(i_name, ".tex");
if ((fd=fopen($3, "r"))==(FILE *)NULL) {
if ((fd=fopen(i_name, "r"))==(FILE *)NULL) {
if (d_warning)
fprintf(stderr, "Can't read file: %s\n", $3);
}
} }
if (fd!=(FILE *)NULL) {
fich_t n_fich;
n_fich.name=strdup($3);
n_fich.fd=fd;
n_fich.line=lineno;
#ifdef FLEX_SCANNER
n_fich.last_string=(char *)Input();
#else
n_fich.last_char=(char)Input();
#endif
f_push(&n_fich);
*f_in=fd;
f_name=n_fich.name;
lineno=0L;
if (d_fname==0) d_fname=-1;
if (d_nl) doprint((S, "%s", "\n"))
start_file();
inclusion_file();
} }
str_destroy($3);
}
;
start_FLN
:
{ start_FLN(); }
;
filename
: oa lettres ca
{ $$=$2; }
| oa fln ca
{ $$=$2; }
| o_spnl lettres
{ $$=$2; }
| o_spnl fln
{ $$=$2; }
| o_spnl UNKNOWN
{ $$=strdup($2); }
;
lettres
: LETTRES
{ $$=strdup($1); }
;
fln
: FILENAME
{ $$=strdup($1); }
;
inclusion_command
: INCLUSION
{ print((S, "%s", $1), d_command) }
;
commentaire
: COMMENT
{
$1[strlen($1)-1]=(char)NULL;
print((S, "%s", $1), d_comment)
print_nl();
}
;
separateur
: spaces
| spaces_newline
;
reste
: operator
{ print((S, "%c", $1), d_operator) }
| special
{ print((S, "%c", $1), d_special) }
| slashed
| other
;
operator
: '+' { $$='+'; }
| '-' { $$='-'; }
| '*' { $$='*'; }
| '/' { $$='/'; }
| '=' { $$='='; }
| '|' { $$='|'; }
| '<' { $$='<'; }
| '>' { $$='>'; }
| '(' { $$='('; }
| ')' { $$=')'; }
| '@' { $$='@'; }
| '[' { $$='['; }
| ']' { $$=']'; }
;
special
: '#' { $$='#'; }
| '%' { $$='%'; }
| '&' { $$='&'; }
| '\\' { $$='\\'; }
| '^' { $$='^'; }
| '_' { $$='_'; }
| '~' { $$='~'; }
;
other
: OTHER
{ print((S, "\\ASCII:%d ", yylval.y_chr), d_warning) }
| FFEED
{ print((S, "%c", 12), d_mot && (mode!=0 || d_text)) }
;
nl
:
{ if (d_nl) doprint((S, "%s", "\n")) }
;
start_END
:
{ start_END(); }
;
%%
/*
* yyerror function for LEX
*/
yyerror(s)
char *s;
{
if (d_error) {
if ((strcmp("", f_name)!=0))
fprintf(stderr, "[%s:%d] %s\n", f_name, lineno+1, s);
else fprintf(stderr, "[%d] %s", lineno+1, s);
}
}
/*
* display new file name
*/
int start_file()
{
if (n_nl && ((lineno+1) % N == 0)) {
if ((strcmp("", f_name)==0) || (d_fname==0))
doprint((S, "[%d] ", lineno+1))
else {
if (d_fname==-1) d_fname=0;
doprint((S, "[%s:%d] ", f_name, lineno+1))
} } else if (n_nl) {
if (d_fname==-1) d_fname=0;
if (strcmp("", f_name)!=0) doprint((S, "[%s] ", f_name))
}
}
/*
* ouput a \n with line number if necessary
*/
print_nl()
{
if (d_nl) doprint((S, "%s", "\n"))
if (n_nl && ((lineno+2) % N == 0)) {
if ((strcmp("", f_name)==0) || (d_fname==0))
doprint((S, "[%d] ", lineno+2))
else {
if (d_fname==-1) d_fname=0;
doprint((S, "[%s:%d] ", f_name, lineno+2))
} }
lineno++;
}
/*
* output a sequence containing blanks
* and possibly a \n
*/
print_blnl(s)
char *s;
{
char *p=strchr(s, '\n');
*p=(char)NULL;
if (strlen(s)>0)
if (d_bls) print((S, "%s", s), d_bl)
else print((S, "%s", " "), d_bl)
*p='\n';
if (d_nl) doprint((S, "%s", "\n"))
if (n_nl && ((lineno+2) % N == 0)) {
if ((strcmp("", f_name)==0) || (d_fname==0)) {
doprint((S, "[%d] ", lineno+2))
} else {
if (d_fname==-1) d_fname=0;
doprint((S, "[%s:%d] ", f_name, lineno+2))
} }
if (*(p+1)!=(char)NULL)
if (d_bls) print((S, "%s", p+1), d_bl)
else print((S, "%s", " "), d_bl)
lineno++;
}
/*
* output a sequence of characters
* eventually containing several \n
*/
print_seq(p, flg)
char *p;
int flg;
{
char *q;
q=p;
while (*q!=(char)NULL) {
while (*q!='\n' && *q!=(char)NULL) q++;
if (*q=='\n') {
*q=(char)NULL;
if (strlen(p)>0) print((S, "%s", p), flg)
print_nl();
p=++q;
} else {
if (strlen(p)>0) print((S, "%s", p), flg)
} }
}