summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorkx <kx@radix-linux.su>2026-09-30 21:14:58 +0300
committerkx <kx@radix-linux.su>2026-09-30 21:14:58 +0300
commit5b1c65152f77e03a4800fceae32d16efe2dadc9c (patch)
treecaffe4b2235503cccfedfb772dc266cb311840b3 /src
parent8b354d2b9f2640d90705abd324a413a0d8fa3867 (diff)
downloadzubr-trunk.tar.xz
Version 4.1.0HEAD4.1.0trunk
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am29
-rw-r--r--src/closure.c429
-rw-r--r--src/defs.h.in573
-rw-r--r--src/error.c550
-rw-r--r--src/lalr.c956
-rw-r--r--src/lr0.c1035
-rw-r--r--src/main.c1372
-rw-r--r--src/mkpar.c619
-rw-r--r--src/output.c2071
-rw-r--r--src/port.c109
-rw-r--r--src/reader.c2769
-rw-r--r--src/skeleton.c663
-rw-r--r--src/symtab.c260
-rw-r--r--src/verbose.c584
-rw-r--r--src/warshall.c140
15 files changed, 12159 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..6d12124
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,29 @@
+
+bin_PROGRAMS = zubr
+
+zubr_SOURCES = \
+ main.c \
+ error.c \
+ closure.c \
+ warshall.c \
+ symtab.c \
+ skeleton.c \
+ lalr.c \
+ lr0.c \
+ mkpar.c \
+ verbose.c \
+ reader.c \
+ output.c \
+ port.c
+
+nodist_noinst_HEADERS = defs.h
+
+AM_CPPFLAGS = $(LIBMPUIO_CFLAGS)
+AM_CFLAGS = -Wall -Wextra -std=gnu23
+zubr_LDFLAGS = $(LIBMPUIO_LDFLAGS)
+zubr_LDADD = $(LIBMPUIO_LIBS)
+
+EXTRA_DIST = defs.h.in
+
+distclean-local:
+ -rm -rf $(DEPDIR)
diff --git a/src/closure.c b/src/closure.c
new file mode 100644
index 0000000..7213443
--- /dev/null
+++ b/src/closure.c
@@ -0,0 +1,429 @@
+
+/***************************************************************
+ CLOSURE.C
+
+ This file containts CLOSURE routine of ZUBR.
+
+ PART OF : ZUBR - Parsers generator for multiple syntax
+ language compilers .
+
+ COMPILE : .
+
+ NOTE : NONE .
+
+ Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+/*
+ This file contant RUSSIAN letters( code-page: UTF-8 )
+ ***************************************************************/
+
+#include <defs.h>
+
+#ifndef __NO_COMPILE
+
+
+int *itemset; /* use in lr0.c */
+int *itemsetend; /* use in lr0.c */
+unsigned *ruleset; /* use in lr0.c */
+
+static unsigned *first_derives;
+static unsigned *EFF;
+
+/************** Start of functions for debuging **************/
+
+#ifdef _DEBUG
+void print_closure( int n )
+/***************************************************************
+
+ Description : print closure
+
+ Concepts : print_closure() is used for debugging
+
+ Use Global Variable: int *itemset; | this file
+ int *itemsetend; | this file
+
+ Use Functions :
+
+ Parameters : int n
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int *isp;
+
+ mpu_fprintf( mpu_stdout, MPU_UCS2( "\n\nn = %d\n\n" ), n );
+ for( isp = itemset; isp < itemsetend; isp++ )
+ mpu_fprintf( mpu_stdout, MPU_UCS2( " %d\n" ), *isp );
+
+} /******* End of print_closure( int n ) *********************/
+
+
+void print_EFF( void )
+/***************************************************************
+
+ Description : print EFF
+
+ Concepts : print_EFF() is used for debugging
+
+ Use Global Variable: int nsyms; | main.c
+ int nvars; | main.c
+ int start_symbol; | main.c
+ char **symbol_name; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i, j;
+ register unsigned *rowp;
+ register unsigned word;
+ register unsigned mask;
+
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( "\n\nEpsilon Free Firsts\n" ) );
+
+ for( i = start_symbol; i < nsyms; i++ )
+ {
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( "\n%s" ), symbol_name[i] );
+ rowp = EFF + ((i - start_symbol) * SIZE_IN_INT( nvars ));
+ word = *rowp++;
+
+ mask = 1;
+ for( j = 0; j < nvars; j++ )
+ {
+ if( word & mask )
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( " %s" ),
+ symbol_name[start_symbol + j] );
+
+ mask <<= 1;
+ if( mask == 0 )
+ {
+ word = *rowp++;
+ mask = 1;
+ }
+
+ } /* End of for( j = 0; j < nvars; j++ ) */
+ } /* End of for( i = start_symbol; i < nsyms; i++ ) */
+
+} /******* End of print_EFF( void ) **************************/
+
+
+void print_first_derives( void )
+/***************************************************************
+
+ Description : print first derives
+
+ Concepts : print_first_derives() is used for debugging
+
+ Use Global Variable: int nrules; | main.c
+ int nsyms; | main.c
+ int start_symbol; | main.c
+ char **symbol_name; | main.c
+ static unsigned *first_derives; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+ register int j;
+ register unsigned *rp;
+ register unsigned cword;
+ register unsigned mask;
+
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( "\n\n\nFirst Derives\n" ) );
+
+ for( i = start_symbol; i < nsyms; i++ )
+ {
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( "\n%s derives\n" ), symbol_name[i] );
+ rp = first_derives + i * SIZE_IN_INT( nrules );
+ cword = *rp++;
+ mask = 1;
+ for( j = 0; j <= nrules; j++ )
+ {
+ if( cword & mask )
+ mpu_fprintf( mpu_stdout, MPU_UCS2( " %d\n" ), j );
+ mask <<= 1;
+ if( mask == 0 )
+ {
+ cword = *rp++;
+ mask = 1;
+ }
+ } /* End of for( j = 0; j <= nrules; j++ ) */
+ } /* End of for( i = start_symbol; i < nsyms; i++ ) */
+ mpu_fflush( mpu_stdout ); /* stdio.h */
+
+} /******* End of print_first_derives( void ) ****************/
+
+#endif
+
+/*************** End of functions for debuging ***************/
+
+
+void set_EFF( void )
+/***************************************************************
+
+ Description : set EFF
+
+ Concepts :
+
+ Use Global Variable: int nsyms; | main.c
+ int nvars; | main.c
+ int start_symbol; | main.c
+ int *ritem; | main.c
+ int *rrhs; | main.c
+ int **derives; | main.c
+ static unsigned *EFF; | this file
+
+ Use Functions : reflexive_transitive_closure (unsigned *, int);
+ | warshall.c
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register unsigned *row;
+ register int symbol;
+ register int *sp;
+ register int rowsize, i, rule;
+
+ rowsize = SIZE_IN_INT( nvars );
+ EFF = NEW2( nvars * rowsize, unsigned );
+
+ row = EFF;
+ for( i = start_symbol; i < nsyms; i++ )
+ {
+ sp = derives[i];
+ for( rule = *sp; rule > 0; rule = *++sp )
+ {
+ symbol = ritem[rrhs[rule]];
+ if( ISVAR(symbol) )
+ {
+ symbol -= start_symbol;
+ SETBIT( row, symbol );
+ }
+ }
+ row += rowsize;
+ }
+ reflexive_transitive_closure( EFF, nvars );
+
+#ifdef _DEBUG
+ print_EFF();
+#endif
+
+} /******* End of set_EFF( void ) ****************************/
+
+
+void set_first_derives( void )
+/***************************************************************
+
+ Description : set first derives
+
+ Concepts :
+
+ Use Global Variable: int nrules; | main.c
+ int nsyms; | main.c
+ int ntokens; | main.c
+ int nvars; | main.c
+ int start_symbol; | main.c
+ int **derives; | main.c
+ static unsigned *first_derives; | this file
+
+ Use Functions : void set_EFF( void ); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register unsigned *rrow;
+ register unsigned *vrow;
+ register int j;
+ register unsigned mask;
+ register unsigned cword;
+ register int *rp;
+
+ int rule;
+ int i;
+ int rulesetsize;
+ int varsetsize;
+
+ rulesetsize = SIZE_IN_INT( nrules );
+ varsetsize = SIZE_IN_INT( nvars );
+ first_derives = NEW2( nvars * rulesetsize, unsigned ) -
+ ntokens * rulesetsize;
+
+ set_EFF();
+
+ rrow = first_derives + ntokens * rulesetsize;
+ for( i = start_symbol; i < nsyms; i++ )
+ {
+ vrow = EFF + ((i - ntokens) * varsetsize);
+ cword = *vrow++;
+ mask = 1;
+ for( j = start_symbol; j < nsyms; j++ )
+ {
+ if( cword & mask )
+ {
+ rp = derives[j];
+ while( (rule = *rp++) >= 0 )
+ {
+ SETBIT( rrow, rule );
+ }
+ }
+
+ mask <<= 1;
+ if( mask == 0 )
+ {
+ cword = *vrow++;
+ mask = 1;
+ }
+ }
+
+ vrow += varsetsize;
+ rrow += rulesetsize;
+ }
+
+#ifdef _DEBUG
+ print_first_derives();
+#endif
+
+ FREE( EFF );
+
+} /******* End of set_first_derives( void ) ******************/
+
+
+void closure( int *nucleus, int n )
+/***************************************************************
+
+ Description : closure
+
+ Concepts :
+
+ Use Global Variable: int nrules; | main.c
+ int *ritem; | main.c
+ int *rrhs; | main.c
+ int *itemset; | this file
+ int *itemsetend; | this file
+ unsigned *ruleset; | this file
+ static unsigned *first_derives; | this file
+
+ Use Functions :
+
+ Parameters : int *nucleus, int n
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int ruleno;
+ register unsigned word;
+ register unsigned mask;
+ register int *csp;
+ register unsigned *dsp;
+ register unsigned *rsp;
+ register int rulesetsize;
+
+ int *csend;
+ unsigned *rsend;
+ int symbol;
+ int itemno;
+
+ rulesetsize = SIZE_IN_INT( nrules );
+ rsp = ruleset;
+ rsend = ruleset + rulesetsize;
+ for( rsp = ruleset; rsp < rsend; rsp++ ) *rsp = 0;
+
+ csend = nucleus + n;
+ for( csp = nucleus; csp < csend; ++csp )
+ {
+ symbol = ritem[*csp];
+ if( ISVAR(symbol) )
+ {
+ dsp = first_derives + symbol * rulesetsize;
+ rsp = ruleset;
+ while( rsp < rsend ) *rsp++ |= *dsp++;
+ }
+ }
+
+ ruleno = 0;
+ itemsetend = itemset;
+ csp = nucleus;
+ for( rsp = ruleset; rsp < rsend; ++rsp )
+ {
+ word = *rsp;
+ if( word == 0 ) ruleno += ZUBR_BITS_PER_INT;
+ else
+ {
+ mask = 1;
+ while( mask )
+ {
+ if( word & mask )
+ {
+ itemno = rrhs[ruleno];
+ while( csp < csend && *csp < itemno )
+ *itemsetend++ = *csp++;
+ *itemsetend++ = itemno;
+ while( csp < csend && *csp == itemno ) ++csp;
+ }
+ mask <<= 1;
+ ++ruleno;
+ }
+ }
+ }
+
+ while( csp < csend ) *itemsetend++ = *csp++;
+
+#ifdef _DEBUG
+ print_closure( n );
+#endif
+
+} /******* End of closure( int *nucleus, int n ) *************/
+
+
+void finalize_closure( void )
+/***************************************************************
+
+ Description : finalize closure
+
+ Concepts :
+
+ Use Global Variable: int nrules; | main.c
+ int ntokens; | main.c
+ int *itemset; | this file
+ unsigned *ruleset; | this file
+ static unsigned *first_derives; | this file
+
+ Use Functions :
+
+ Parameters :
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ FREE( itemset );
+ FREE( ruleset);
+ FREE( first_derives + ntokens * SIZE_IN_INT(nrules) );
+
+} /******* End of finalize_closure( void ) *******************/
+
+#endif /* __NO_COMPILE */
+
+/******************* END OF FILE CLOSURE.C *******************/
diff --git a/src/defs.h.in b/src/defs.h.in
new file mode 100644
index 0000000..9784f95
--- /dev/null
+++ b/src/defs.h.in
@@ -0,0 +1,573 @@
+
+/***************************************************************
+ DEFS.H
+
+ This file containt common declarations for ZUBR .
+
+ PART OF : ZUBR - Parsers generator for multiple syntax
+ language compilers .
+
+ COMPILE : .
+
+ NOTE : NONE .
+
+ Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+/*
+ This file contant RUSSIAN letters( code-page: UTF-8 )
+ ***************************************************************/
+
+#ifndef _DEFS_H
+#define _DEFS_H
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h> /* exit() */
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h> /* signal() */
+#endif
+
+#if HAVE_LIBMPU && HAVE_LIBMPUIO
+#include <libmpuio.h>
+#else
+#define __NO_COMPILE 1
+#endif
+
+#ifndef ZUBR_VERSION
+#define ZUBR_VERSION MPU_UCS2( "@ZUBR_VERSION@" )
+#endif
+#ifndef ZUBR_BITS_PER_INT
+#define ZUBR_BITS_PER_INT @ZUBR_BITS_PER_INT@
+#endif
+
+#ifndef NUL
+#define NUL 0
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __NO_COMPILE
+
+/***************************************************************
+ Определения PATH_SEPARATOR, DIR_SEPARATOR, IS_DIR_SEPARATOR
+ ***************************************************************/
+#ifndef PATH_SEPARATOR
+#define PATH_SEPARATOR ':'
+#endif
+
+#ifndef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#endif
+
+#ifndef IS_DIR_SEPARATOR
+#define IS_DIR_SEPARATOR(_c_) ((_c_) == ('/'))
+#endif
+
+#define COMMON_DIR_SEPARATOR ('/') /* Доступен в UNIX && Windows NT */
+
+#define MAXCHAR 0xffff /* maximum UCS-2 character value */
+#define MAXWORD 32767 /* 32767 maximum value of a short int */
+#define MINWORD (-32768) /* (-32767-1) minimum value of a short int */
+#define MAXTABLE 32500 /* от фонаря < SHRT_MAX */
+
+
+#undef _NOT_BIT_MACRO
+#undef _NON_COMPILE
+#if ZUBR_BITS_PER_INT == 64
+#define RPOW2 6
+/*************************************************************************
+
+ ... r[0]
+ --|------------------------------------------------------------------|
+ | 0000000000000000000000000000000000000000000000000000000000000000 |
+ --|------------------------------------------------------------------|
+ n: 63 0
+
+*************************************************************************/
+#else
+#if ZUBR_BITS_PER_INT == 32
+#define RPOW2 5
+/*************************************************************************
+
+ ... r[1] r[0]
+ --|----------------------------------|----------------------------------|
+ | 00000000000000000000000000000000 | 00000000000000000000000000000000 |
+ --|----------------------------------|----------------------------------|
+ n: 63 32 31 0
+
+ *************************************************************************/
+#else
+#if ZUBR_BITS_PER_INT == 16
+#define RPOW2 4
+/*************************************************************************
+
+ ... r[1] r[0]
+ --|------------------|------------------|
+ | 0000000000000000 | 0000000000000000 |
+ --|------------------|------------------|
+ n: 31 16 15 0
+
+ *************************************************************************/
+#else /* not (ZUBR_BITS_PER_INT == 16) */
+#define _NOT_BIT_MACRO 1
+#define _NON_COMPILE
+#endif /* ZUBR_BITS_PER_INT == 16 */
+#endif /* ZUBR_BITS_PER_INT == 32 */
+#endif /* ZUBR_BITS_PER_INT == 64 */
+
+#if !defined( _NOT_BIT_MACRO )
+#define SIZE_IN_INT(n) (((n)+(ZUBR_BITS_PER_INT-1))/ZUBR_BITS_PER_INT)
+#if defined( BIT ) || defined( SETBIT )
+#undef BIT
+#undef SETBIT
+#endif
+#define BIT(r,n) ((((r)[(n)>>RPOW2])>>((n)&(ZUBR_BITS_PER_INT-1)))&1)
+#define SETBIT(r,n) ((r)[(n)>>RPOW2]|=((unsigned)1<<((n)&(ZUBR_BITS_PER_INT-1))))
+#endif /* _NOT_BIT_MACRO */
+
+
+
+/******* character names ***********************************************/
+/* определены в configx.h
+ #define NUL '\0' - the null character
+ #define NEWLINE '\n' - line feed
+ #define SP ' ' - space
+ #define BS '\b' - backspace
+ #define HT '\t' - horizontal tab
+ #define VT '\013' - vertical tab
+ #define CR '\r' - carriage return
+ #define FF '\f' - form feed
+ #define QUOTE '\'' - single quote
+ #define DOUBLE_QUOTE '\"' - double quote
+ #define BACKSLASH '\\' - backslash
+ */
+
+/******* defines for constructing filenames ****************************/
+
+#define PROC_C_SUFFIX MPU_UCS2( ".c" )
+#define PROC_CPP_SUFFIX MPU_UCS2( ".cpp" )
+#define HEADER_SUFFIX MPU_UCS2( ".h" )
+#define CODE_SUFFIX MPU_UCS2( "_code" )
+#define DEFINES_SUFFIX MPU_UCS2( "_tab.h" )
+#define OUTPUT_SUFFIX MPU_UCS2( "_tab" )
+#define VERBOSE_SUFFIX MPU_UCS2( ".output" )
+#define MAX_SUFFIX_LEN 7 /* strlen( VERBOSE_SUFFIX ) */
+
+/******* keyword codes *************************************************/
+
+#define TOKEN 0
+#define LEFT 1
+#define RIGHT 2
+#define NONASSOC 3
+#define MARK 4
+#define TEXT 5
+#define TYPE 6
+#define START 7
+#define UNION 8
+#define IDENT 9
+
+
+/******* symbol classes ************************************************/
+
+#define UNKNOWN 0
+#define TERM 1
+#define NONTERM 2
+
+
+/******* the undefined value *******************************************/
+
+#define UNDEFINED (-1)
+
+
+/******* action codes **************************************************/
+
+#define SHIFT 1
+#define REDUCE 2
+
+
+/******* character macros **********************************************/
+
+#define IS_IDENT(c) (zubr_is_alnum(c) || (c) == '_' || (c) == '.' || (c) == '$')
+#define IS_OCTAL(c) ((c) >= '0' && (c) <= '7')
+
+#define NUMERIC_VALUE(c) ((c) - '0')
+
+
+/******* symbol macros *************************************************/
+
+#define ISTOKEN(s) ((s) < start_symbol)
+#define ISVAR(s) ((s) >= start_symbol)
+
+
+/******* the structure of a symbol table entry *************************/
+
+typedef struct bucket bucket;
+struct bucket
+{
+ struct bucket *link;
+ struct bucket *next;
+ __mpu_char16_t *name;
+ __mpu_char16_t *tag;
+
+ int value; /* old: short */
+ int index; /* old: short */
+ int prec; /* old: short */
+
+ char class;
+ char assoc;
+};
+
+
+/******* the structure of the LR(0) state machine **********************/
+
+typedef struct core core;
+struct core
+{
+ struct core *next;
+ struct core *link;
+
+ int number;
+ int accessing_symbol;
+ int nitems;
+ int items[1];
+};
+
+
+/******* the structure used to record shifts ***************************/
+
+typedef struct shifts shifts;
+struct shifts
+{
+ struct shifts *next;
+
+ int number;
+ int nshifts;
+ int shift[1];
+};
+
+
+/******* the structure used to store reductions ************************/
+
+typedef struct reductions reductions;
+struct reductions
+{
+ struct reductions *next;
+
+ int number;
+ int nreds;
+ int rules[1];
+};
+
+
+/******* the structure used to represent parser actions ****************/
+
+typedef struct action action;
+struct action
+{
+ struct action *next;
+
+ int symbol;
+ int number;
+ int prec;
+ char action_code;
+ char assoc;
+ char suppressed;
+};
+
+
+/*************************************************************************
+ global variables
+ *************************************************************************/
+
+/******* lalr.c ********************************************************/
+
+extern int *lookaheads;
+extern int *LAruleno;
+extern unsigned *LA;
+extern int *accessing_symbol;
+extern core **state_table;
+extern shifts **shift_table;
+extern reductions **reduction_table;
+extern int *goto_map;
+extern int *from_state;
+extern int *to_state;
+
+
+/******* lr0.c *********************************************************/
+
+extern int nstates;
+extern core *first_state;
+extern shifts *first_shift;
+extern reductions *first_reduction;
+
+
+/******* main.c ********************************************************/
+
+extern char bflag;
+extern char p_name_flag;
+extern char l_name_flag;
+extern char iflag;
+
+extern char dflag;
+extern char lflag;
+extern char pflag;
+extern char rflag;
+extern char sflag;
+extern char tflag;
+extern char vflag;
+
+
+
+extern __mpu_char16_t *myname;
+extern int lineno;
+extern int outline;
+
+extern __mpu_char16_t *parse_func_name;
+extern __mpu_char16_t *lex_func_name;
+extern __mpu_char16_t *inc_token_filename;
+extern __mpu_char16_t *name_prefix;
+extern __mpu_char16_t *name_prefix_upper;
+
+extern __mpu_char16_t *parse_header_file_name;
+extern __mpu_char16_t *action_file_name;
+extern __mpu_char16_t *text_file_name;
+extern __mpu_char16_t *union_file_name;
+extern __mpu_char16_t *input_file_name;
+extern __mpu_char16_t *output_file_name;
+extern __mpu_char16_t *defines_file_name;
+extern __mpu_char16_t *code_file_name;
+extern __mpu_char16_t *verbose_file_name;
+
+
+extern mpu_FILE *parse_header_file;
+extern mpu_FILE *action_file;
+extern mpu_FILE *text_file;
+extern mpu_FILE *union_file;
+extern mpu_FILE *input_file;
+extern mpu_FILE *output_file;
+extern mpu_FILE *defines_file;
+extern mpu_FILE *code_file;
+extern mpu_FILE *verbose_file;
+
+extern int nitems;
+extern int nrules;
+extern int nsyms;
+extern int ntokens;
+extern int nvars;
+
+extern int start_symbol;
+extern __mpu_char16_t **symbol_name;
+extern int *symbol_value;
+extern int *symbol_prec;
+extern char *symbol_assoc;
+
+extern int *ritem;
+extern int *rlhs;
+extern int *rrhs;
+extern int *rprec;
+extern char *rassoc;
+
+extern int **derives;
+extern char *nullable;
+
+
+/******* mkpar.c *******************************************************/
+
+extern action **parser;
+extern int SRtotal;
+extern int RRtotal;
+extern int *SRconflicts;
+extern int *RRconflicts;
+extern int *defred;
+extern int *rules_used;
+extern int nunused;
+extern int final_state;
+
+
+/******* reader.c ******************************************************/
+
+extern __mpu_char16_t *cptr;
+extern __mpu_char16_t *line;
+extern int ntags;
+extern char unionized;
+extern __mpu_char16_t line_format[];
+
+
+/******* skeleton.c ****************************************************/
+
+
+/******* symtab.c ******************************************************/
+
+extern bucket *first_symbol;
+extern bucket *last_symbol;
+
+
+/*************************************************************************
+ global functions
+ *************************************************************************/
+
+/******* error.c *******************************************************/
+
+extern void fatal( __mpu_char16_t *message );
+extern void fatal_reorder( __mpu_char16_t *fname );
+extern void no_space( void );
+extern void bad_fileprefix( __mpu_char16_t *s, int l );
+extern void bad_filename( __mpu_char16_t *s, int l );
+extern void bad_funcname( __mpu_char16_t *s, int l );
+extern void open_error( __mpu_char16_t *filename );
+extern void input_error( void );
+extern void unexpected_EOF( void );
+extern void print_pos( __mpu_char16_t *st_line, __mpu_char16_t *st_cptr );
+extern void syntax_error( int st_lineno, __mpu_char16_t *st_line, __mpu_char16_t *st_cptr );
+extern void unterminated_comment( int c_lineno, __mpu_char16_t *c_line, __mpu_char16_t *c_cptr );
+extern void unterminated_string( int s_lineno, __mpu_char16_t *s_line, __mpu_char16_t *s_cptr );
+extern void unterminated_text( int t_lineno, __mpu_char16_t *t_line, __mpu_char16_t *t_cptr ) __attribute__((noreturn));
+extern void unterminated_union( int u_lineno, __mpu_char16_t *u_line, __mpu_char16_t *u_cptr );
+extern void over_unionized( __mpu_char16_t *u_cptr );
+extern void illegal_character( __mpu_char16_t *c_cptr );
+extern void used_reserved( __mpu_char16_t *s );
+extern void illegal_tag( int t_lineno, __mpu_char16_t *t_line, __mpu_char16_t *t_cptr );
+extern void tokenized_start( __mpu_char16_t *s );
+extern void terminal_start( __mpu_char16_t *s );
+extern void no_grammar( void ) __attribute__((noreturn));
+extern void terminal_lhs( int s_lineno );
+extern void unterminated_action( int a_lineno, __mpu_char16_t *a_line, __mpu_char16_t *a_cptr ) __attribute__((noreturn));
+extern void untyped_lhs( void );
+extern void untyped_rhs( int i, __mpu_char16_t *s );
+extern void unknown_rhs( int i );
+extern void undefined_goal( __mpu_char16_t *s );
+extern void dollar_error( int a_lineno, __mpu_char16_t *a_line, __mpu_char16_t *a_cptr );
+
+extern void bad_option( __mpu_char16_t *s ) __attribute__((noreturn));
+extern void bad_code_page( __mpu_char16_t *s, __mpu_char16_t *p );
+
+
+/********** warnings **********/
+extern void dollar_warning( int a_lineno, int i );
+extern void retyped_warning( __mpu_char16_t *s );
+extern void reprec_warning( __mpu_char16_t *s );
+extern void revalued_warning( __mpu_char16_t *s );
+extern void restarted_warning( void );
+extern void default_action_warning( void );
+extern void undefined_symbol_warning( __mpu_char16_t *s );
+extern void prec_redeclared( void );
+
+/******* closure.c ****************************************************/
+
+extern void set_first_derives( void ); /* use in LR0.C */
+extern void closure( int *nucleus, int n ); /* use in LR0.C */
+extern void finalize_closure( void ); /* use in LR0.C */
+
+/******* lalr.c ********************************************************/
+
+extern void lalr( void );
+
+/******* lr0.c *********************************************************/
+
+extern void lr0( void );
+extern void free_nullable( void );
+extern void free_derives( void );
+
+/******* main.c ********************************************************/
+
+extern void done( int k ) __attribute__((noreturn));
+extern void onintr( int sig_number );
+extern void set_signals( void );
+extern void usage( void );
+extern void getargs( int argc, __mpu_char16_t *argv[] );
+extern char *allocate( unsigned n );
+extern void create_file_names( void );
+extern void open_files( void );
+
+/******* mkpar.c *******************************************************/
+
+extern void make_parser( void );
+extern void free_parser( void ); /* use in OUTPUT.C */
+
+/******* output.c ******************************************************/
+
+extern void output( void );
+
+/******* reader.c ******************************************************/
+
+extern void reader( void );
+
+/******* skeleton.c ****************************************************/
+
+extern void write_parse_name_definition( void );
+extern void write_parse_name_declaration( void );
+
+extern void write_banner( void );
+extern void write_extern_tables( void );
+extern void write_header( void );
+extern void write_header_definitions( void );
+extern void write_begin_body( void );
+extern void write_end_body( void );
+extern void write_trailer( void );
+
+/******* symtab.c ******************************************************/
+
+extern int hash( __mpu_char16_t *name );
+extern bucket * make_bucket( __mpu_char16_t *name );
+extern bucket * lookup( __mpu_char16_t *name ); /* use in READER.C */
+extern void create_symbol_table( void ); /* use in READER.C */
+extern void free_symbol_table( void ); /* use in READER.C */
+extern void free_symbols( void ); /* use in READER.C */
+
+/******* verbose.c *****************************************************/
+
+extern void verbose( void );
+
+/******* warshall.c ****************************************************/
+
+extern void reflexive_transitive_closure( unsigned *R, int n );
+ /* use in CLOSURE.C */
+
+/******* zubr-port.c ***************************************************/
+
+extern int zubr_is_alpha( __mpu_char16_t c );
+extern int zubr_is_alnum( __mpu_char16_t c );
+extern int zubr_is_digit( __mpu_char16_t c );
+extern int zubr_is_upper( __mpu_char16_t c );
+extern int zubr_is_print( __mpu_char16_t c );
+extern __mpu_char16_t zubr_to_lower( __mpu_char16_t c );
+extern __mpu_char16_t zubr_to_upper( __mpu_char16_t c );
+extern mpu_FILE *zubr_fopen( const __mpu_char16_t *filename, const char *mode );
+extern int zubr_unlink( const __mpu_char16_t *filename );
+extern __mpu_char16_t *zubr_getenv( const char *name );
+extern __mpu_char16_t *zubr_utf8_to_ucs2_dup( const char *s );
+
+
+/******* storage allocation macros *************************************/
+
+#define MALLOC(n) (malloc((size_t)(n)))
+#define CALLOC(k,n) (calloc((size_t)(k),(size_t)(n)))
+#define REALLOC(p,n) (realloc((void *)(p),(size_t)(n)))
+#define FREE(x) (free((void *)(x)))
+#define NEW(t) ((t*)allocate(sizeof(t)))
+#define NEW2(n,t) ((t*)allocate((unsigned)((n)*sizeof(t))))
+
+
+#endif /* __NO_COMPILE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DEFS_H */
+
+/************************* END OF FILE DEFS.H **************************/
diff --git a/src/error.c b/src/error.c
new file mode 100644
index 0000000..3a5703f
--- /dev/null
+++ b/src/error.c
@@ -0,0 +1,550 @@
+
+/***************************************************************
+ ERROR.C
+
+ This file containts routines for printing
+ error messages.
+
+ PART OF : ZUBR - Parsers generator for multiple syntax
+ language compilers .
+
+ COMPILE : .
+
+ NOTE : NONE .
+
+ Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+/*
+ This file contant RUSSIAN letters( code-page: UTF-8 )
+ ***************************************************************/
+
+#include <defs.h>
+
+#ifndef __NO_COMPILE
+
+
+void fatal( __mpu_char16_t *message )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "FATAL ERROR:" );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s %s\n" ), msg, message );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+ done( 2 );
+}
+
+void fatal_reorder( __mpu_char16_t *fname )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "FATAL ERROR:" );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s Can't reorder bytes in file \"%s\"\n" ), msg, fname );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+ done( 2 );
+}
+
+
+void no_space( void )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0001 Cannot allocated memory" ); /* out of space */
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s\n" ), msg );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+ done( 2 );
+}
+
+
+void bad_filename( __mpu_char16_t *s, int l )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0002 Inadmissible file_name:" );
+ register int i;
+ register int n;
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s %s\n" ), msg, s );
+ n = mpu_str16len( msg );
+ n += l + 1;
+ for( i = 0; i < n; ++i ) mpu_putc( ' ', mpu_stderr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "^ illegal character\n" ) );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+ done( 1 );
+}
+
+
+void bad_fileprefix( __mpu_char16_t *s, int l )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0003 Inadmissible file_prefix:" );
+ register int i;
+ register int n;
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s %s\n" ), msg, s );
+ n = mpu_str16len( msg );
+ n += l + 1;
+ for( i = 0; i < n; ++i ) mpu_putc( ' ', mpu_stderr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "^ illegal character\n" ) );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+ done( 1 );
+}
+
+
+void bad_funcname( __mpu_char16_t *s, int l )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0004 Inadmissible fuction name or prefix:" );
+ register int i;
+ register int n;
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s %s\n" ), msg, s );
+ n = mpu_str16len( msg );
+ n += l + 1;
+ for( i = 0; i < n; ++i ) mpu_putc( ' ', mpu_stderr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "^ illegal character\n" ) );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname);
+ done( 1 );
+}
+
+
+
+
+void open_error( __mpu_char16_t *filename )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0005 Cannot open file:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, filename );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+ done( 2 );
+}
+
+
+void input_error( void )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0006 Cannot read UTF-8 input file:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void unexpected_EOF( void )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0006 Unexpected end-of-file:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void print_pos( __mpu_char16_t *st_line, __mpu_char16_t *st_cptr )
+{
+ register __mpu_char16_t *s;
+
+ if( st_line == 0 ) return;
+ for( s = st_line; *s != '\n'; ++s )
+ {
+ if( zubr_is_print(*s) || *s == '\t' ) mpu_putc( *s, mpu_stderr );
+ else mpu_putc( '?', mpu_stderr );
+ }
+ mpu_putc( '\n', mpu_stderr );
+ for( s = st_line; s < st_cptr; ++s )
+ {
+ if( *s == '\t' ) mpu_putc( '\t', mpu_stderr );
+ else mpu_putc( ' ', mpu_stderr );
+ }
+ mpu_putc( '^', mpu_stderr );
+ mpu_putc( '\n', mpu_stderr );
+
+}
+
+
+void syntax_error( int st_lineno, __mpu_char16_t *st_line, __mpu_char16_t *st_cptr )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0007 Syntax error:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), st_lineno );
+ print_pos( st_line, st_cptr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+
+}
+
+
+void unterminated_comment( int c_lineno,
+ __mpu_char16_t *c_line, __mpu_char16_t *c_cptr )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0008 Unterminated comment:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), c_lineno );
+ print_pos( c_line, c_cptr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void unterminated_string( int s_lineno,
+ __mpu_char16_t *s_line, __mpu_char16_t *s_cptr )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0009 Unterminated string:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), s_lineno );
+ print_pos( s_line, s_cptr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void unterminated_text( int t_lineno,
+ __mpu_char16_t *t_line, __mpu_char16_t *t_cptr )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0010 Unmatched %%{ :" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), t_lineno );
+ print_pos( t_line, t_cptr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void unterminated_union( int u_lineno,
+ __mpu_char16_t *u_line, __mpu_char16_t *u_cptr )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0011 Unterminated %%union declaration:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), u_lineno );
+ print_pos( u_line, u_cptr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void over_unionized( __mpu_char16_t *u_cptr )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0012 Too many %%union declarations:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ print_pos( line, u_cptr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void illegal_character( __mpu_char16_t *c_cptr )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0013 Illegal character:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ print_pos( line, c_cptr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void used_reserved( __mpu_char16_t *s )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0014 Illegal use of reserved symbol:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " Symbol %s is reserved\n" ), s );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void illegal_tag( int t_lineno, __mpu_char16_t *t_line, __mpu_char16_t *t_cptr )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0015 Illegal tag:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), t_lineno );
+ print_pos( t_line, t_cptr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void tokenized_start( __mpu_char16_t *s )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0016 Start symbol cannot be declared:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr,
+ MPU_UCS2( " The start symbol %s cannot be declared to be a token\n" ), s );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void terminal_start( __mpu_char16_t *s )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0017 Start symbol cannot be declared:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " The start symbol %s is a token\n" ), s );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void no_grammar( void )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0018 No grammar has been specified:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void terminal_lhs( int s_lineno )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0019 Terminal lhs:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), s_lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " A token appears on the lhs of a production\n" ) );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void unterminated_action( int a_lineno,
+ __mpu_char16_t *a_line, __mpu_char16_t *a_cptr )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0020 Unterminated_action:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), a_lineno );
+ print_pos( a_line, a_cptr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void untyped_lhs( void )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0021 Untyped lhs:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " $$ is untyped\n" ) );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void untyped_rhs( int i, __mpu_char16_t *s )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0022 Untyped rhs:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " $%d (%s) is untyped\n" ), i, s );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void unknown_rhs( int i )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0023 Unknown rhs:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " $%d is untyped\n" ), i );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void undefined_goal( __mpu_char16_t *s )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0024 Undefined start:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " The start symbol %s is undefined\n" ), s );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void dollar_error( int a_lineno, __mpu_char16_t *a_line, __mpu_char16_t *a_cptr )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0025 Dollar error:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), a_lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " Illegal $-name\n" ) );
+ print_pos( a_line, a_cptr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+
+ done( 1 );
+}
+
+
+void bad_option( __mpu_char16_t *s )
+{ /* можно потом поставить на № 0005 */
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0026 Invalid option:" );
+ register int i;
+ register int n;
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s %s\n" ), msg, s );
+ n = mpu_str16len( msg );
+ n += 1;
+ for( i = 0; i < n; ++i ) mpu_putc( ' ', mpu_stderr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "^ illegal option\n" ) );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+ done( 1 );
+}
+
+
+void bad_code_page( __mpu_char16_t *s, __mpu_char16_t *p )
+{ /* можно потом поставить на № 0006 */
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "ERROR 0027 Invalid parameter in option:" );
+ register int i;
+ register int n;
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s %s %s\n" ), msg, s, p );
+ n = mpu_str16len( msg ) + mpu_str16len( s );
+ n += 2;
+ for( i = 0; i < n; ++i ) mpu_putc( ' ', mpu_stderr );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "^ illegal code page\n" ) );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: return bad status\n" ), myname );
+ done( 1 );
+}
+
+
+/******* warnings ******************************************************/
+
+
+void dollar_warning( int a_lineno, int i )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "WARNING 0001 Dollar warning:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), a_lineno );
+ mpu_fprintf( mpu_stderr,
+ MPU_UCS2( " $%d references beyond the end of the current rule\n" ), i );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: inform of warning status\n" ), myname );
+
+}
+
+
+void retyped_warning( __mpu_char16_t *s )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "WARNING 0002 Redeclared type:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " The type of %s has been redeclared\n" ), s );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: inform of warning status\n" ), myname );
+
+}
+
+
+void reprec_warning( __mpu_char16_t *s )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "WARNING 0003 Redeclared precedence:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " The precedence of %s has been redeclared\n" ), s );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: inform of warning status\n" ), myname );
+
+}
+
+
+void revalued_warning( __mpu_char16_t *s )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "WARNING 0004 Redeclared value:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " The value of %s has been redeclared\n" ), s );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: inform of warning status\n" ), myname );
+
+}
+
+
+void restarted_warning( void )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "WARNING 0005 Redeclared start symbol:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " The start symbol has been redeclared\n" ) );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: inform of warning status\n" ), myname );
+
+}
+
+
+void default_action_warning( void )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "WARNING 0006 Default action:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr,
+ MPU_UCS2( " The default action assigns an undefined value to $$\n" ) );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: inform of warning status\n" ), myname );
+
+}
+
+
+void undefined_symbol_warning( __mpu_char16_t *s )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "WARNING 0007 Undefined_symbol:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " The symbol %s is undefined\n" ), s );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: inform of warning status\n" ), myname );
+
+}
+
+
+void prec_redeclared( void )
+{
+ __mpu_char16_t *msg = (__mpu_char16_t *)MPU_UCS2( "WARNING 0008 Conflicting %%prec:" );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s \"%s\"\n" ), msg, input_file_name );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " #line %d\n" ), lineno );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( " Conflicting %%prec specifiers\n" ) );
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: inform of warning status\n" ), myname );
+
+}
+
+#endif /* __NO_COMPILE */
+
+/************************* END OF FILE ERROR.H *************************/
diff --git a/src/lalr.c b/src/lalr.c
new file mode 100644
index 0000000..74bea60
--- /dev/null
+++ b/src/lalr.c
@@ -0,0 +1,956 @@
+
+/***************************************************************
+ LALR.C
+
+ This file containts LALR routines of ZUBR.
+
+ PART OF : ZUBR - Parsers generator for multiple syntax
+ language compilers .
+
+ COMPILE : .
+
+ NOTE : NONE .
+
+ Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+/*
+ This file contant RUSSIAN letters( code-page: UTF-8 )
+ ***************************************************************/
+
+#include <defs.h>
+
+#ifndef __NO_COMPILE
+
+
+typedef struct ints
+{
+ struct ints *next;
+ int value;/*short*/
+} ints;
+
+int tokensetsize;
+int *lookaheads;
+int *LAruleno;
+unsigned *LA;
+int *accessing_symbol;
+core **state_table;
+shifts **shift_table;
+reductions **reduction_table;
+int *goto_map;
+int *from_state;
+int *to_state;
+
+static int infinity;
+static int maxrhs;
+static int ngotos;
+static unsigned *F;
+static int **includes;
+static ints **lookback;
+static int **R;
+static int *INDEX;
+static int *VERTICES;
+static int top;
+
+
+void traverse( int i )
+/***************************************************************
+
+ Description : traverse
+
+ Concepts :
+
+ Use Global Variable: int tokensetsize; | this file
+ static int infinity; | this file
+ static unsigned *F; | this file
+ static int **R; | this file
+ static int *INDEX; | this file
+ static int *VERTICES; | this file
+ static int top; | this file
+
+ Use Functions : void traverse( int ); | this file
+
+ Parameters : int i
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register unsigned *fp1, *fp2, *fp3;
+ register int j;
+ register int *rp;
+
+ int height;
+ unsigned *base;
+
+ VERTICES[++top] = i;
+ INDEX[i] = height = top;
+
+ base = F + i * tokensetsize;
+ fp3 = base + tokensetsize;
+
+ rp = R[i];
+ if( rp )
+ {
+ while( (j = *rp++) >= 0 )
+ {
+ if( INDEX[j] == 0 ) traverse( j ); /* recursive call */
+
+ if( INDEX[i] > INDEX[j] ) INDEX[i] = INDEX[j];
+
+ fp1 = base;
+ fp2 = F + j * tokensetsize;
+
+ while( fp1 < fp3 ) *fp1++ |= *fp2++;
+ }
+ }
+
+ if( INDEX[i] == height )
+ {
+ for( ;; )
+ {
+ j = VERTICES[top--];
+ INDEX[j] = infinity;
+
+ if( i == j ) break;
+
+ fp1 = base;
+ fp2 = F + j * tokensetsize;
+
+ while( fp1 < fp3 ) *fp2++ = *fp1++;
+ }
+ }
+
+} /******* End of traverse( int i ) **************************/
+
+
+void digraph( int **relation )
+/***************************************************************
+
+ Description : digraph
+
+ Concepts :
+
+ Use Global Variable: static int infinity; | this file
+ static int ngotos; | this file
+ static int **R; | this file
+ static int *INDEX; | this file
+ static int *VERTICES; | this file
+ static int top; | this file
+
+ Use Functions : void traverse( int ); | this file
+
+ Parameters : int **relation
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+
+ infinity = ngotos + 2;
+ INDEX = NEW2 (ngotos + 1, int );
+ VERTICES = NEW2 (ngotos + 1, int );
+ top = 0;
+
+ R = relation;
+
+ for( i = 0; i < ngotos; i++ ) INDEX[i] = 0;
+
+ for( i = 0; i < ngotos; i++ )
+ {
+ if( INDEX[i] == 0 && R[i] ) traverse( i );
+ }
+
+ FREE( INDEX );
+ FREE( VERTICES );
+
+} /******* End of digraph( int **relation ) ******************/
+
+
+
+int ** transpose( int **R, int n )
+/***************************************************************
+
+ Description : transpose
+
+ Concepts :
+
+ Use Global Variable:
+
+ Use Functions :
+
+ Parameters : int **R, int n
+
+ Return : int **
+
+ ***************************************************************/
+{
+ register int **new_R;
+ register int **temp_R;
+ register int *nedges;
+ register int *sp;
+ register int i;
+ register int k;
+
+ nedges = NEW2( n, int );
+
+ for( i = 0; i < n; i++ )
+ {
+ sp = R[i];
+ if( sp )
+ {
+ while( *sp >= 0 ) nedges[*sp++]++;
+ }
+ }
+
+ new_R = NEW2 (n, int *);
+ temp_R = NEW2 (n, int *);
+
+ for( i = 0; i < n; i++ )
+ {
+ k = nedges[i];
+ if( k > 0 )
+ {
+ sp = NEW2( k + 1, int );
+ new_R[i] = sp;
+ temp_R[i] = sp;
+ sp[k] = -1;
+ }
+ }
+
+ FREE( nedges );
+
+ for( i = 0; i < n; i++ )
+ {
+ sp = R[i];
+ if( sp )
+ {
+ while( *sp >= 0 ) *temp_R[*sp++]++ = i;
+ }
+ }
+
+ FREE( temp_R );
+
+ return( new_R );
+
+} /******* End of transpose( int **R, int n ) ****************/
+
+
+int map_goto( int state, int symbol )
+/***************************************************************
+
+ Description : map_goto
+
+ Concepts : Map_goto maps a state/symbol pair into its numeric
+ representation.
+
+ Use Global Variable: int *goto_map; | this file
+ int *from_state; | this file
+
+ Use Functions :
+
+ Parameters : int state, int symbol
+
+ Return : int
+
+ ***************************************************************/
+{
+ register int high, low, middle;
+ register int s;
+
+ low = goto_map[symbol];
+ high = goto_map[symbol+1];
+
+ for( ;; )
+ {
+ if( low > high )
+ {
+ done( 2 );
+ }
+
+ middle = ( low + high ) >> 1;
+ s = from_state[middle];
+ if( s == state ) return( middle );
+ else if( s < state ) low = middle + 1;
+ else high = middle - 1;
+ }
+
+} /******* End of map_goto( int state, int symbol ) **********/
+
+
+void add_lookback_edge( int stateno, int ruleno, int gotono )
+/***************************************************************
+
+ Description : add_lookback_edge
+
+ Concepts :
+
+ Use Global Variable: int *lookaheads; | this file
+ int *LAruleno; | this file
+ static ints **lookback; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i, k;
+ register int found = 0;
+ register ints *sp;
+
+ i = lookaheads[stateno];
+ k = lookaheads[stateno + 1];
+
+ found = 0;
+
+ while( !found && i < k )
+ {
+ if( LAruleno[i] == ruleno ) found = 1;
+ else ++i;
+ }
+
+ if( found == 0 )
+ {
+ done( 2 );
+ }
+
+ sp = NEW( ints );
+ sp->next = lookback[i];
+ sp->value = gotono;
+ lookback[i] = sp;
+
+} /******* End of add_lookback_edge( int, int, int ) *********/
+
+
+void compute_lookaheads( void )
+/***************************************************************
+
+ Description : compute_lookaheads
+
+ Concepts :
+
+ Use Global Variable: int tokensetsize; | this file
+ int *lookaheads; | this file
+ unsigned *LA; | this file
+ static unsigned *F; | this file
+ static ints **lookback; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i, n;
+ register unsigned *fp1, *fp2, *fp3;
+ register ints *sp, *next;
+ register unsigned *rowp;
+
+ rowp = LA;
+ n = lookaheads[nstates];
+ for( i = 0; i < n; i++ )
+ {
+ fp3 = rowp + tokensetsize;
+ for( sp = lookback[i]; sp; sp = sp->next )
+ {
+ fp1 = rowp;
+ fp2 = F + tokensetsize * sp->value;
+ while( fp1 < fp3 ) *fp1++ |= *fp2++;
+ }
+ rowp = fp3;
+ }
+
+ for( i = 0; i < n; i++ )
+ for( sp = lookback[i]; sp; sp = next )
+ {
+ next = sp->next;
+ FREE( sp );
+ }
+
+ FREE( lookback );
+ FREE( F );
+
+} /******* End of compute_lookaheads( void ) *****************/
+
+
+void compute_FOLLOWS( void )
+/***************************************************************
+
+ Description : compute_FOLLOWS
+
+ Concepts :
+
+ Use Global Variable: static short **includes; | this file
+
+ Use Functions : void digraph( int ** ); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ digraph( includes );
+
+} /******* End of compute_FOLLOWS( void ) ********************/
+
+
+void build_relations( void )
+/***************************************************************
+
+ Description : build_relations
+
+ Concepts :
+
+ Use Global Variable: int *accessing_symbol; | this file
+ shifts **shift_table; | this file
+ int *from_state; | this file
+ int *to_state; | this file
+ static int maxrhs; | this file
+ static int ngotos; | this file
+ static int **includes; | this file
+ char *nullable; | main.c
+ int **derives; | main.c
+ int *ritem; | main.c
+ int *rrhs; | main.c
+
+ Use Functions : void add_lookback_edge( int, int, int );
+ int map_goto( int, int ); | this file
+ int ** transpose( int **, int ); | this file
+
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+ register int j;
+ register int k;
+ register int *rulep;
+ register int *rp;
+ register shifts *sp;
+ register int length;
+ register int nedges;
+ register int done;
+ register int state1;
+ register int stateno;
+ register int symbol1;
+ register int symbol2;
+ register int *intp;
+ register int *edge;
+ register int *states;
+ register int **new_includes;
+
+ includes = NEW2( ngotos, int * );
+ edge = NEW2( ngotos + 1, int );
+ states = NEW2( maxrhs + 1, int );
+
+ for( i = 0; i < ngotos; i++ )
+ {
+ nedges = 0;
+ state1 = from_state[i];
+ symbol1 = accessing_symbol[to_state[i]];
+
+ for( rulep = derives[symbol1]; *rulep >= 0; rulep++ )
+ {
+ length = 1;
+ states[0] = state1;
+ stateno = state1;
+
+ for( rp = ritem + rrhs[*rulep]; *rp >= 0; rp++ )
+ {
+ symbol2 = *rp;
+ sp = shift_table[stateno];
+ k = sp->nshifts;
+
+ for( j = 0; j < k; j++ )
+ {
+ stateno = sp->shift[j];
+ if( accessing_symbol[stateno] == symbol2 ) break;
+ }
+ states[length++] = stateno;
+
+ } /* End of for (rp = ritem + rrhs[*rulep]; *rp >= 0; rp++) */
+ add_lookback_edge( stateno, *rulep, i );
+
+ length--;
+ done = 0;
+ while( !done )
+ {
+ done = 1;
+ rp--;
+ if( ISVAR( *rp ) )
+ {
+ stateno = states[--length];
+ edge[nedges++] = map_goto( stateno, *rp );
+ if( nullable[*rp] && length > 0 ) done = 0;
+ }
+ } /* End of while (!done) */
+ } /* End of for( rulep = derives[symbol1]; *rulep >= 0; rulep++ ) */
+
+ if( nedges )
+ {
+ includes[i] = intp = NEW2( nedges + 1, int );
+ for( j = 0; j < nedges; j++ ) intp[j] = edge[j];
+ intp[nedges] = -1;
+ }
+ } /* End of for( i = 0; i < ngotos; i++ ) */
+
+ new_includes = transpose( includes, ngotos );
+
+ for( i = 0; i < ngotos; i++ )
+ if( includes[i] )
+ FREE( includes[i] );
+
+ FREE( includes );
+
+ includes = new_includes;
+
+ FREE( edge );
+ FREE( states );
+
+} /******* End of build_relations( void ) ********************/
+
+
+void initialize_F( void )
+/***************************************************************
+
+ Description : initialize_F
+
+ Concepts :
+
+ Use Global Variable: int tokensetsize; | this file
+ int *accessing_symbol; | this file
+ shifts **shift_table; | this file
+ int *to_state; | this file
+ static int ngotos; | this file
+ static unsigned *F; | this file
+ char *nullable; | main.c
+
+ Use Functions : int map_goto( int, int ); | this file
+ void digraph( int ** ); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+ register int j;
+ register int k;
+ register shifts *sp;
+ register int *edge;
+ register unsigned *rowp;
+ register int *rp;
+ register int **reads;
+ register int nedges;
+ register int stateno;
+ register int symbol;
+ register int nwords;
+
+ nwords = ngotos * tokensetsize;
+ F = NEW2( nwords, unsigned );
+ reads = NEW2( ngotos, int * );
+ edge = NEW2( ngotos + 1, int );
+ nedges = 0;
+
+ rowp = F;
+ for( i = 0; i < ngotos; i++ )
+ {
+ stateno = to_state[i];
+ sp = shift_table[stateno];
+ if( sp )
+ {
+ k = sp->nshifts;
+
+ for( j = 0; j < k; j++ )
+ {
+ symbol = accessing_symbol[sp->shift[j]];
+ if( ISVAR(symbol) ) break;
+ SETBIT( rowp, symbol );
+ }
+ for( ; j < k; j++ )
+ {
+ symbol = accessing_symbol[sp->shift[j]];
+ if( nullable[symbol] )
+ edge[nedges++] = map_goto( stateno, symbol );
+ }
+ if( nedges )
+ {
+ reads[i] = rp = NEW2( nedges + 1, int );
+ for( j = 0; j < nedges; j++ ) rp[j] = edge[j];
+ rp[nedges] = -1;
+ nedges = 0;
+ }
+ }
+ rowp += tokensetsize;
+ } /* End of for( i = 0; i < ngotos; i++ ) */
+
+ SETBIT( F, 0 );
+ digraph( reads );
+ for( i = 0; i < ngotos; i++ )
+ {
+ if( reads[i] ) FREE( reads[i] );
+ }
+ FREE( reads );
+ FREE( edge );
+
+} /******* End of initialize_F( void ) ***********************/
+
+
+void set_goto_map( void )
+/***************************************************************
+
+ Description : set_goto_map
+
+ Concepts :
+
+ Use Global Variable: int *goto_map; | this file
+ int *accessing_symbol; | this file
+ static int ngotos; | this file
+ int *from_state; | this file
+ int *to_state; | this file
+ shifts *first_shift; | lr0.c
+ int nsyms; | main.c
+ int nvars; | main.c
+ int ntokens; | main.c
+
+ Use Functions : void fatal( char * ); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register shifts *sp;
+ register int i;
+ register int symbol;
+ register int k;
+ register int *temp_map;
+ register int state2;
+ register int state1;
+
+ goto_map = NEW2( nvars + 1, int ) - ntokens;
+ temp_map = NEW2( nvars + 1, int ) - ntokens;
+
+ ngotos = 0;
+ for( sp = first_shift; sp; sp = sp->next )
+ {
+ for( i = sp->nshifts - 1; i >= 0; i-- )
+ {
+ symbol = accessing_symbol[sp->shift[i]];
+ if( ISTOKEN(symbol) ) break;
+ if( ngotos == MAXWORD ) fatal( (__mpu_char16_t *)MPU_UCS2( "Too many gotos" ) );
+ ngotos++;
+ goto_map[symbol]++;
+ }
+ }
+
+ k = 0;
+ for( i = ntokens; i < nsyms; i++ )
+ {
+ temp_map[i] = k;
+ k += goto_map[i];
+ }
+
+ for( i = ntokens; i < nsyms; i++ ) goto_map[i] = temp_map[i];
+
+ goto_map[nsyms] = ngotos;
+ temp_map[nsyms] = ngotos;
+
+ from_state = NEW2( ngotos, int );
+ to_state = NEW2( ngotos, int );
+
+ for( sp = first_shift; sp; sp = sp->next )
+ {
+ state1 = sp->number;
+ for( i = sp->nshifts - 1; i >= 0; i-- )
+ {
+ state2 = sp->shift[i];
+ symbol = accessing_symbol[state2];
+
+ if( ISTOKEN(symbol) ) break;
+
+ k = temp_map[symbol]++;
+ from_state[k] = state1;
+ to_state[k] = state2;
+ }
+ }
+ FREE( temp_map + ntokens );
+
+} /******* End of set_goto_map( void ) ***********************/
+
+
+void initialize_LA( void )
+/***************************************************************
+
+ Description : initialize_LA
+
+ Concepts :
+
+ Use Global Variable: int tokensetsize; | this file
+ int *lookaheads; | this file
+ reductions **reduction_table; | this file
+ int *LAruleno; | this file
+ unsigned *LA; | this file
+ static ints **lookback; | this file
+ int nstates; | lr0.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i, j, k;
+ register reductions *rp;
+
+ lookaheads = NEW2( nstates + 1, int );
+
+ k = 0;
+ for( i = 0; i < nstates; i++ )
+ {
+ lookaheads[i] = k;
+ rp = reduction_table[i];
+ if( rp ) k += rp->nreds;
+ }
+ lookaheads[nstates] = k;
+
+ LA = NEW2 (k * tokensetsize, unsigned);
+ LAruleno = NEW2 (k, int);
+ lookback = NEW2 (k, ints *);
+
+ k = 0;
+ for( i = 0; i < nstates; i++ )
+ {
+ rp = reduction_table[i];
+
+ if( rp )
+ {
+ for( j = 0; j < rp->nreds; j++ )
+ {
+ LAruleno[k] = rp->rules[j];
+ k++;
+ }
+ }
+ }
+
+} /******* End of initialize_LA( void ) **********************/
+
+
+
+void set_maxrhs( void )
+/***************************************************************
+
+ Description : set_maxrhs
+
+ Concepts :
+
+ Use Global Variable: static int maxrhs; | this file
+ int nitems; | main.c
+ int *ritem; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int *itemp;
+ register int *item_end;
+ register int length;
+ register int max;
+
+ length = 0;
+ max = 0;
+ item_end = ritem + nitems;
+ for( itemp = ritem; itemp < item_end; itemp++ )
+ {
+ if( *itemp >= 0 )
+ {
+ length++;
+ }
+ else
+ {
+ if( length > max ) max = length;
+ length = 0;
+ }
+ }
+ maxrhs = max;
+
+} /******* End of set_maxrhs( void ) *************************/
+
+
+void set_reduction_table( void )
+/***************************************************************
+
+ Description : set_reduction_table
+
+ Concepts :
+
+ Use Global Variable: reductions **reduction_table; | this file
+ int nstates; | lr0.c
+ reductions *first_reduction; | lr0.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register reductions *rp;
+
+ reduction_table = NEW2( nstates, reductions * );
+ for( rp = first_reduction; rp; rp = rp->next )
+ reduction_table[rp->number] = rp;
+
+} /******* End of set_reduction_table( void ) ****************/
+
+
+void set_shift_table( void )
+/***************************************************************
+
+ Description : set_shift_table
+
+ Concepts :
+
+ Use Global Variable: shifts **shift_table; | this file
+ int nstates; | lr0.c
+ shifts *first_shift; | lr0.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register shifts *sp;
+
+ shift_table = NEW2( nstates, shifts * );
+ for( sp = first_shift; sp; sp = sp->next )
+ shift_table[sp->number] = sp;
+
+} /******* End of set_shift_table( void ) ********************/
+
+
+void set_accessing_symbol( void )
+/***************************************************************
+
+ Description : set_accessing_symbol
+
+ Concepts :
+
+ Use Global Variable: short *accessing_symbol; | this file
+ int nstates; | lr0.c
+ core *first_state; | lr0.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register core *sp;
+
+ accessing_symbol = NEW2( nstates, int );
+ for( sp = first_state; sp; sp = sp->next )
+ accessing_symbol[sp->number] = sp->accessing_symbol;
+
+} /******* End of set_accessing_symbol( void ) ***************/
+
+
+void set_state_table( void )
+/***************************************************************
+
+ Description : set_state_table
+
+ Concepts :
+
+ Use Global Variable: core **state_table; | this file
+ int nstates; | lr0.c
+ core *first_state; | lr0.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register core *sp;
+
+ state_table = NEW2( nstates, core * );
+ for( sp = first_state; sp; sp = sp->next )
+ state_table[sp->number] = sp;
+
+} /******* End of set_state_table( void ) ********************/
+
+
+void lalr( void )
+/***************************************************************
+
+ Description : lalr
+
+ Concepts : use in main.c
+
+ Use Global Variable: int tokensetsize; | this file
+ int ntokens; | main.c
+
+ Use Functions : void set_state_table (void); | this file
+ void set_accessing_symbol (void); | this file
+ void set_shift_table (void); | this file
+ void set_reduction_table (void); | this file
+ void set_maxrhs (void); | this file
+ void initialize_LA (void); | this file
+ void set_goto_map (void); | this file
+ void initialize_F (void); | this file
+ void build_relations (void); | this file
+ void compute_FOLLOWS (void); | this file
+ void compute_lookaheads (void); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ tokensetsize = SIZE_IN_INT( ntokens );
+
+ set_state_table();
+ set_accessing_symbol();
+ set_shift_table();
+ set_reduction_table();
+ set_maxrhs();
+ initialize_LA();
+ set_goto_map();
+ initialize_F();
+ build_relations();
+ compute_FOLLOWS();
+ compute_lookaheads();
+
+} /******* End of lalr( void ) *******************************/
+
+#endif /* __NO_COMPILE */
+
+/******************** ENF OF FILE LALR.C *********************/
diff --git a/src/lr0.c b/src/lr0.c
new file mode 100644
index 0000000..d99ae9f
--- /dev/null
+++ b/src/lr0.c
@@ -0,0 +1,1035 @@
+
+/***************************************************************
+ LR0.C
+
+ This file containts LR0 routines of ZUBR.
+
+ PART OF : ZUBR - Parsers generator for multiple syntax
+ language compilers .
+
+ COMPILE : .
+
+ NOTE : Use macro _DEBUG, TRACE for out additional
+ info into mpu_stdout, mpu_stderr.
+
+ Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+/*
+ This file contant RUSSIAN letters( code-page: UTF-8 )
+ ***************************************************************/
+
+#include <defs.h>
+
+#ifndef __NO_COMPILE
+
+
+extern int *itemset; /* define in CLOSURE.C */
+extern int *itemsetend; /* define in CLOSURE.C */
+extern unsigned *ruleset; /* define in CLOSURE.C */
+
+int nstates;
+core *first_state;
+shifts *first_shift;
+reductions *first_reduction;
+
+static core **state_set;
+static core *this_state;
+static core *last_state;
+static shifts *last_shift;
+static reductions *last_reduction;
+
+static int nshifts;
+static int *shift_symbol;
+
+static int *redset;
+static int *shiftset;
+
+static int **kernel_base;
+static int **kernel_end;
+static int *kernel_items;
+
+
+/************* Start of functions for debuging ***************/
+#ifdef _DEBUG
+
+void show_cores( void )
+/***************************************************************
+
+ Description : show cores
+
+ Concepts : show_cores() is used for debugging
+
+ Use Global Variable: char **symbol_name; | main.c
+ int *ritem; | main.c
+ int *rrhs; | main.c
+ int *rlhs; | main.c
+ core *first_state; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ core *p;
+ int i, j, k, n;
+ int itemno;
+
+ k = 0;
+ for( p = first_state; p; ++k, p = p->next )
+ {
+ if( k ) mpu_fprintf( mpu_stdout, MPU_UCS2( "\n" ) );
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( "state %d, number = %d, accessing symbol = %s\n" ),
+ k, p->number, symbol_name[p->accessing_symbol] );
+ n = p->nitems;
+ for( i = 0; i < n; ++i )
+ {
+ itemno = p->items[i];
+ mpu_fprintf( mpu_stdout, MPU_UCS2( "%4d " ), itemno );
+ j = itemno;
+ while( ritem[j] >= 0 ) ++j;
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( "%s :" ), symbol_name[rlhs[-ritem[j]]] );
+ j = rrhs[-ritem[j]];
+ while( j < itemno ) mpu_fprintf( mpu_stdout,
+ MPU_UCS2( " %s" ),
+ symbol_name[ritem[j++]] );
+ mpu_fprintf( mpu_stdout, MPU_UCS2( " ." ) );
+ while( ritem[j] >= 0 )
+ mpu_fprintf( mpu_stdout, MPU_UCS2( " %s" ),
+ symbol_name[ritem[j++]] );
+ mpu_fprintf( mpu_stdout, MPU_UCS2( "\n" ) );
+ mpu_fflush( mpu_stdout ); /* stdio.h */
+
+ } /* End of for( i = 0; i < n; ++i ) */
+ } /* End of for( p = first_state; p; ++k, p = p->next ) */
+
+} /******* End of show_cores( void ) **************************/
+
+
+void show_ritems( void )
+/***************************************************************
+
+ Description : show ritems
+
+ Concepts : show_ritems() is used for debugging
+
+ Use Global Variable: int nitems; | main.c
+ int *ritem; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ int i;
+
+ for( i = 0; i < nitems; ++i )
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( "ritem[%d] = %d\n" ), i, ritem[i] );
+
+} /******* End of show_ritems( void ) ************************/
+
+
+void show_rrhs( void )
+/***************************************************************
+
+ Description : show rrhs
+
+ Concepts : show_rrhs() is used for debugging
+
+ Use Global Variable: int nrules; | main.c
+ int *rrhs; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ int i;
+
+ for( i = 0; i < nrules; ++i )
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( "rrhs[%d] = %d\n" ), i, rrhs[i] );
+
+} /******* End of show_rrhs( void ) **************************/
+
+
+void show_shifts( void )
+/***************************************************************
+
+ Description : show shifts
+
+ Concepts : show_shifts() is used for debugging
+
+ Use Global Variable: shifts *first_shift; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ shifts *p;
+ int i, j, k;
+
+ k = 0;
+ for( p = first_shift; p; ++k, p = p->next )
+ {
+ if( k ) mpu_fprintf( mpu_stdout, MPU_UCS2( "\n" ) );
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( "shift %d, number = %d, nshifts = %d\n" ),
+ k, p->number, p->nshifts );
+ j = p->nshifts;
+ for( i = 0; i < j; ++i )
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( "\t%d\n" ), p->shift[i] );
+ }
+
+} /******* End of show_shifts( void ) ************************/
+
+
+void print_derives( void )
+/***************************************************************
+
+ Description : print derives
+
+ Concepts : print_derives() is used for debugging
+
+ Use Global Variable: int nsyms; | main.c
+ int start_symbol; | main.c
+ char **symbol_name; | main.c
+ int **derives; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+ register int *sp;
+
+ mpu_fprintf( mpu_stdout, MPU_UCS2( "\nDERIVES\n\n" ) );
+
+ for( i = start_symbol; i < nsyms; i++ )
+ {
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( "%s derives " ), symbol_name[i] );
+ for( sp = derives[i]; *sp >= 0; sp++ )
+ {
+ mpu_fprintf( mpu_stdout, MPU_UCS2( " %d" ), *sp );
+ }
+ mpu_putc( '\n', mpu_stdout );
+ }
+ mpu_putc( '\n', mpu_stdout );
+
+} /******* End of print_derives( void ) **********************/
+
+#endif
+/***************** End of functions for debuging ***************/
+
+
+
+void allocate_itemsets( void )
+/***************************************************************
+
+ Description : allocate itemsets
+
+ Concepts :
+
+ Use Global Variable: int nsyms; | main.c
+ int nitems; | main.c
+ int *ritem; | main.c
+ static int *shift_symbol; | this file
+ static int **kernel_base; | this file
+ static int **kernel_end; | this file
+ static int *kernel_items; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int *itemp;
+ register int *item_end;
+ register int symbol;
+ register int i;
+ register int count;
+ register int max;
+ register int *symbol_count;
+
+ count = 0;
+ symbol_count = NEW2( nsyms, int );
+
+ item_end = ritem + nitems;
+ for( itemp = ritem; itemp < item_end; itemp++ )
+ {
+ symbol = *itemp;
+ if( symbol >= 0 )
+ {
+ count++;
+ symbol_count[symbol]++;
+ }
+ }
+
+ kernel_base = NEW2( nsyms, int * );
+ kernel_items = NEW2( count, int );
+
+ count = 0;
+ max = 0;
+ for( i = 0; i < nsyms; i++ )
+ {
+ kernel_base[i] = kernel_items + count;
+ count += symbol_count[i];
+ if( max < symbol_count[i] ) max = symbol_count[i];
+ }
+
+ shift_symbol = symbol_count;
+ kernel_end = NEW2( nsyms, int * );
+
+} /******* End of allocate_itemsets( void ) ******************/
+
+
+void allocate_storage( void )
+/***************************************************************
+
+ Description : allocate storage
+
+ Concepts :
+
+ Use Global Variable: int nsyms; | main.c
+ int nitems; | main.c
+ int nrules; | main.c
+ static core **state_set; | this file
+ static int *redset; | this file
+ static int *shiftset; | this file
+
+ Use Functions : void allocate_itemsets (void); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ allocate_itemsets();
+
+ shiftset = NEW2( nsyms, int );
+ redset = NEW2( nrules + 1, int );
+ state_set = NEW2( nitems, core * );
+
+} /******* End of allocate_storage( void ) *******************/
+
+
+void free_storage( void )
+/***************************************************************
+
+ Description : free storage
+
+ Concepts :
+
+ Use Global Variable: static core **state_set; | this file
+ static int *redset; | this file
+ static int *shiftset; | this file
+ static int *shift_symbol; | this file
+ static int **kernel_base; | this file
+ static int **kernel_end; | this file
+ static int *kernel_items; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ FREE( shift_symbol );
+ FREE( redset );
+ FREE( shiftset );
+ FREE( kernel_base );
+ FREE( kernel_end );
+ FREE( kernel_items );
+ FREE( state_set );
+
+} /******* End of free_storage( void ) ***********************/
+
+
+core * new_state( int symbol )
+/***************************************************************
+
+ Description : new state
+
+ Concepts :
+
+ Use Global Variable: int nstates; | this file
+ static core *last_state; | this file
+ static int **kernel_base; | this file
+ static int **kernel_end; | this file
+
+ Use Functions : char *allocate (unsigned n); | main.c
+ void fatal (char *); | error.c
+
+ Parameters : int symbol
+
+ Return : core *p
+
+ ***************************************************************/
+{
+ register int n;
+ register core *p;
+ register int *isp1, *isp2;
+ register int *iend;
+
+#ifdef TRACE
+ mpu_fprintf( mpu_stderr,
+ MPU_UCS2( "Entering new_state(%d)\n" ), symbol);
+#endif
+
+ if( nstates >= MAXWORD ) fatal( (__mpu_char16_t *)MPU_UCS2( "Too many states" ) );
+
+ isp1 = kernel_base[symbol];
+ iend = kernel_end[symbol];
+ n = iend - isp1;
+
+ p = (core *)
+ allocate( (unsigned)(sizeof(core) + (n - 1) * sizeof(int)) );
+ p->accessing_symbol = symbol;
+ p->number = nstates;
+ p->nitems = n;
+
+ isp2 = p->items;
+ while( isp1 < iend ) *isp2++ = *isp1++;
+
+ last_state->next = p;
+ last_state = p;
+
+ nstates++;
+
+ return( p );
+
+} /******* End of new_state( int symbol ) ********************/
+
+
+int get_state( int symbol )
+/***************************************************************
+
+ Description : get state
+
+ Concepts :
+
+ Use Global Variable: static core **state_set; | this file
+ static int **kernel_base; | this file
+ static int **kernel_end; | this file
+
+ Use Functions : core * new_state (int symbol); | this file
+
+ Parameters : int
+
+ Return : int
+
+ ***************************************************************/
+{
+ register int key;
+ register int *isp1;
+ register int *isp2;
+ register int *iend;
+ register core *sp;
+ register int found;
+ register int n;
+
+#ifdef TRACE
+ mpu_fprintf( mpu_stderr,
+ MPU_UCS2( "Entering get_state(%d)\n" ), symbol );
+#endif
+
+ isp1 = kernel_base[symbol];
+ iend = kernel_end[symbol];
+ n = iend - isp1;
+ key = *isp1;
+
+ if( 0 > key || key >= nitems )
+ {
+ done( 2 );
+ }
+ sp = state_set[key];
+ if( sp )
+ {
+ found = 0;
+ while( !found )
+ {
+ if( sp->nitems == n )
+ {
+ found = 1;
+ isp1 = kernel_base[symbol];
+ isp2 = sp->items;
+
+ while( found && isp1 < iend )
+ {
+ if( *isp1++ != *isp2++ ) found = 0;
+ }
+ }
+
+ if( !found )
+ {
+ if( sp->link )
+ {
+ sp = sp->link;
+ }
+ else
+ {
+ sp = sp->link = new_state( symbol );
+ found = 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ state_set[key] = sp = new_state( symbol );
+ }
+ return( sp->number );
+
+} /******* End of get_state( int symbol ) ********************/
+
+
+void append_states( void )
+/***************************************************************
+
+ Description : append states
+
+ Concepts :
+
+ Use Global Variable: static int nshifts; | this file
+ static int *shiftset; | this file
+ static int *shift_symbol; | this file
+
+ Use Functions : int get_state (int symbol); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+ register int j;
+ register int symbol;
+
+#ifdef TRACE
+ mpu_fprintf( mpu_stderr,
+ MPU_UCS2( "Entering append_states()\n" ) );
+#endif
+ for( i = 1; i < nshifts; i++ )
+ {
+ symbol = shift_symbol[i];
+ j = i;
+ while( j > 0 && shift_symbol[j - 1] > symbol )
+ {
+ shift_symbol[j] = shift_symbol[j - 1];
+ j--;
+ }
+ shift_symbol[j] = symbol;
+ }
+
+ for( i = 0; i < nshifts; i++ )
+ {
+ symbol = shift_symbol[i];
+ shiftset[i] = get_state (symbol);
+ }
+
+} /******* End of append_states( void ) **********************/
+
+
+void initialize_states( void )
+/***************************************************************
+
+ Description : initialize states
+
+ Concepts :
+
+ Use Global Variable: int start_symbol; | main.c
+ int **derives; | main.c
+ int *rrhs; | main.c
+ core *first_state; | this file
+ static core *this_state; | this file
+ static core *last_state; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+ register int *start_derives;
+ register core *p;
+
+ start_derives = derives[start_symbol];
+ for( i = 0; start_derives[i] >= 0; ++i ) continue;
+
+ p = (core *)MALLOC( sizeof(core) + i*sizeof(int) );
+ if( p == 0 ) no_space();
+
+ p->next = 0;
+ p->link = 0;
+ p->number = 0;
+ p->accessing_symbol = 0;
+ p->nitems = i;
+
+ for( i = 0; start_derives[i] >= 0; ++i )
+ p->items[i] = rrhs[start_derives[i]];
+
+ first_state = last_state = this_state = p;
+ nstates = 1;
+
+} /******* End of initialize_states( void ) ******************/
+
+
+void new_itemsets( void )
+/***************************************************************
+
+ Description : new itensets
+
+ Concepts :
+
+ Use Global Variable: int nsyms; | main.c
+ int *ritem; | main.c
+ int *itemset; | closure.c
+ int *itemsetend; | closure.c
+ static int nshifts; | this file
+ static int *shift_symbol; | this file
+ static int **kernel_base; | this file
+ static int **kernel_end; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+ register int shiftcount;
+ register int *isp;
+ register int *ksp;
+ register int symbol;
+
+ for( i = 0; i < nsyms; i++ ) kernel_end[i] = 0;
+
+ shiftcount = 0;
+ isp = itemset;
+ while( isp < itemsetend )
+ {
+ i = *isp++;
+ symbol = ritem[i];
+ if( symbol > 0 )
+ {
+ ksp = kernel_end[symbol];
+ if( !ksp )
+ {
+ shift_symbol[shiftcount++] = symbol;
+ ksp = kernel_base[symbol];
+ }
+ *ksp++ = i + 1;
+ kernel_end[symbol] = ksp;
+ }
+ }
+ nshifts = shiftcount;
+
+} /******* End of new_itemsets( void ) ***********************/
+
+
+void save_shifts( void )
+/***************************************************************
+
+ Description : save shifts
+
+ Concepts :
+
+ Use Global Variable: static int nshifts; | this file
+ static core *this_state; | this file
+ static int *shiftset; | this file
+
+ Use Functions : char * allocate (unsigned u); | main.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register shifts *p;
+ register int *sp1;
+ register int *sp2;
+ register int *send;
+
+ p = (shifts *)allocate( (unsigned)(sizeof (shifts) +
+ (nshifts - 1) * sizeof(int)) );
+
+ p->number = this_state->number;
+ p->nshifts = nshifts;
+
+ sp1 = shiftset;
+ sp2 = p->shift;
+ send = shiftset + nshifts;
+
+ while( sp1 < send ) *sp2++ = *sp1++;
+
+ if( last_shift )
+ {
+ last_shift->next = p;
+ last_shift = p;
+ }
+ else
+ {
+ first_shift = p;
+ last_shift = p;
+ }
+
+} /******* End of save_shifts( void ) ************************/
+
+
+void save_reductions( void )
+/***************************************************************
+
+ Description : save reduction
+
+ Concepts :
+
+ Use Global Variable: int *ritem; | main.c
+ int *itemset; | closure.c
+ int *itemsetend; | closure.c
+ static core *this_state; | this file
+ reductions *first_reduction; | this file
+ static reductions *last_reduction; | this file
+ static int *redset; | this file
+
+ Use Functions : char * allocate (unsigned u); | main.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int *isp;
+ register int *rp1;
+ register int *rp2;
+ register int item;
+ register int count;
+ register reductions *p;
+ register int *rend;
+
+ count = 0;
+ for( isp = itemset; isp < itemsetend; isp++ )
+ {
+ item = ritem[*isp];
+ if( item < 0 )
+ {
+ redset[count++] = -item;
+ }
+ }
+
+ if( count )
+ {
+ p = (reductions *)allocate( (unsigned)(sizeof (reductions) +
+ (count - 1) * sizeof(int)) );
+
+ p->number = this_state->number;
+ p->nreds = count;
+ rp1 = redset;
+ rp2 = p->rules;
+ rend = rp1 + count;
+
+ while( rp1 < rend ) *rp2++ = *rp1++;
+
+ if( last_reduction )
+ {
+ last_reduction->next = p;
+ last_reduction = p;
+ }
+ else
+ {
+ first_reduction = p;
+ last_reduction = p;
+ }
+ }
+
+} /******* End of save_reductions( void ) ********************/
+
+
+void set_derives( void )
+/***************************************************************
+
+ Description : set derives
+
+ Concepts :
+
+ Use Global Variable: int nsyms; | main.c
+ int nvars; | main.c
+ int nrules; | main.c
+ int start_symbol; | main.c
+ int **derives; | main.c
+ int *rlhs; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i, k;
+ register int lhs;
+ register int *rules;
+
+ derives = NEW2( nsyms, int * );
+ rules = NEW2( nvars + nrules, int );
+
+ k = 0;
+ for( lhs = start_symbol; lhs < nsyms; lhs++ )
+ {
+ derives[lhs] = rules + k;
+ for( i = 0; i < nrules; i++ )
+ {
+ if( rlhs[i] == lhs )
+ {
+ rules[k] = i;
+ k++;
+ }
+ }
+ rules[k] = -1;
+ k++;
+ }
+
+#ifdef _DEBUG
+ print_derives();
+#endif
+
+} /******* End of set_derives( void ) ************************/
+
+
+void set_nullable( void )
+/***************************************************************
+
+ Description : set nullable
+
+ Concepts :
+
+ Use Global Variable: int nsyms; | main.c
+ int nitems; | main.c
+ char **symbol_name; | main.c
+ int *ritem; | main.c
+ int *rlhs; | main.c
+
+ Use Functions : void no_space (void); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i, j;
+ register int empty;
+ int done;
+
+ nullable = (char *)MALLOC( nsyms );
+ if( nullable == 0 ) no_space();
+
+ for( i = 0; i < nsyms; ++i ) nullable[i] = 0;
+
+ done = 0;
+ while( !done )
+ {
+ done = 1;
+ for( i = 1; i < nitems; i++ )
+ {
+ empty = 1;
+ while( (j = ritem[i]) >= 0 )
+ {
+ if( !nullable[j] ) empty = 0;
+ ++i;
+ }
+ if( empty )
+ {
+ j = rlhs[-j];
+ if( !nullable[j] )
+ {
+ nullable[j] = 1;
+ done = 0;
+ }
+ }
+ }
+ }
+
+
+#ifdef _DEBUG
+ for( i = 0; i < nsyms; i++ )
+ {
+ if( nullable[i] )
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( "%s is nullable\n" ), symbol_name[i] );
+ else
+ mpu_fprintf( mpu_stdout,
+ MPU_UCS2( "%s is not nullable\n" ), symbol_name[i] );
+ }
+#endif
+
+} /******* End of set_nullable (void) ************************/
+
+
+void generate_states( void )
+/***************************************************************
+
+ Description : generate states
+
+ Concepts :
+
+ Use Global Variable: int nitems; | main.c
+ int *itemset; | closure.c
+ unsigned *ruleset; | closure.c
+ static core *this_state; | this file
+
+ Use Functions : void allocate_storage (void); | this file
+ void free_storage (void); | this file
+ void save_reductions (void); | this file
+ void new_itemsets (void); | this file
+ void append_states (void); | this file
+ void save_shifts (void); | this file
+ void initialize_states (void); | this file
+ void set_first_derives (void); | closure.c
+ void closure (int *, int); | closure.c
+ void finalize_closure (void); | closure.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ allocate_storage();
+ itemset = NEW2( nitems, int );
+ ruleset = NEW2( SIZE_IN_INT( nrules ), unsigned );
+ set_first_derives();
+ initialize_states();
+
+ while( this_state )
+ {
+ closure( this_state->items, this_state->nitems );
+ save_reductions();
+ new_itemsets();
+ append_states();
+
+ if( nshifts > 0 ) save_shifts();
+
+ this_state = this_state->next;
+ }
+
+ finalize_closure();
+ free_storage();
+
+} /******* Enf of generate_states( void ) ********************/
+
+
+void lr0( void )
+/***************************************************************
+
+ Description : lr0
+
+ Concepts :
+
+ Use Global Variable:
+
+ Use Functions : void set_derives (void); | this file
+ void set_nullable (void); | this file
+ void generate_states (void); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ set_derives();
+ set_nullable();
+ generate_states();
+
+} /******* End of lr0( void ) ********************************/
+
+
+
+/********** this functions is not use of this file **********/
+/********** this functions is use in main.c: done() **********/
+
+void free_nullable( void )
+/***************************************************************
+
+ Description : free nullable
+
+ Concepts :
+
+ Use Global Variable: char *nullable; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ FREE( nullable );
+
+} /******* End of free_nullable( void ) **********************/
+
+
+void free_derives( void )
+/***************************************************************
+
+ Description : free derives
+
+ Concepts :
+
+ Use Global Variable: int start_symbol; | main.c
+ int **derives; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ FREE( derives[start_symbol] );
+ FREE( derives );
+
+} /******* Enf of free_derives( void ) ***********************/
+
+#endif /* __NO_COMPILE */
+
+/******************** END OF FILE LR0.C **********************/
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..2882216
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,1372 @@
+
+/***************************************************************
+ MAIN.C
+
+ This file containts main routine of ZUBR.
+
+ PART OF : ZUBR - Parsers generator for multiple syntax
+ language compilers .
+
+ COMPILE : .
+
+ NOTE : NONE .
+
+ Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+/*
+ This file contant RUSSIAN letters( code-page: UTF-8 )
+ ***************************************************************/
+
+#include <defs.h>
+
+#ifndef __NO_COMPILE
+
+
+
+/***************************************************************
+
+ Name : IS_ADMISSIBLE(c) ( macros )
+
+ Description : the folloving symbol is illegal in file_name
+ and file_prefix (compilers pass of space)
+
+ all systems: u" / * ? | < >
+ += FAT : + = ; [ ] space
+ += HPFS : &
+
+ Concepts : - the folloving symbols | < > &
+ include in file name if its begin of symbol
+ '\"'
+ - symbol '\"' may by include in file name if -b
+ option use without space
+
+ Value : if( c is legal character ) return TRUE;
+ if( c is illegal character ) return FALSE;
+
+ ***************************************************************/
+#define IS_ADMISSIBLE(c) ((c) != '\"' && \
+ (c) != '*' && \
+ (c) != '?' && \
+ (c) != '|' && \
+ (c) != '>' && \
+ (c) != '<' && \
+ (c) != '+' && \
+ (c) != '=' && \
+ (c) != ';' && \
+ (c) != '[' && \
+ (c) != ']' && \
+ (c) != '&')
+/* (c) != '/' && \ */
+/* (c) != ' ') */
+/*************************************************************************/
+
+
+/* flags of command line is global variables: */
+/* in defs.h its define as extern */
+
+char bflag; /* use prefix for variables and zubr_lex, zubr_parse */
+char p_name_flag; /* name for zubr_parse() and header file */
+char l_name_flag; /* name for zubr_lex() */
+char iflag; /* include extern tokens definitions */
+
+char dflag;
+char lflag;
+char pflag; /* .cpp extention */
+char rflag;
+char sflag; /* static option */
+char tflag; /* trase option */
+char vflag;
+
+char C_mem; /* signal for done() / memory allocate ? */
+char D_mem;
+char R_mem;
+char V_mem;
+
+
+__mpu_char16_t *file_prefix = (__mpu_char16_t *)MPU_UCS2( "z" ); /* only this file */
+__mpu_char16_t *myname = (__mpu_char16_t *)MPU_UCS2( "zubr" ); /* in defs.h define as extern */
+__mpu_char16_t temp_form[256]; /* only this file */
+
+/* global: in defs.h define as extern */
+int lineno;
+int outline;
+
+/* global: in defs.h define as extern */
+__mpu_char16_t *parse_func_name;
+__mpu_char16_t *lex_func_name;
+__mpu_char16_t *inc_token_filename;
+__mpu_char16_t *name_prefix;
+__mpu_char16_t *name_prefix_upper;
+
+__mpu_char16_t *parse_header_file_name; /* header for zubr_parse() function */
+__mpu_char16_t *action_file_name;
+__mpu_char16_t *text_file_name;
+__mpu_char16_t *union_file_name;
+__mpu_char16_t *input_file_name;
+__mpu_char16_t *output_file_name;
+__mpu_char16_t *defines_file_name;
+__mpu_char16_t *code_file_name;
+__mpu_char16_t *verbose_file_name;
+
+/* global: in defs.h define as extern */
+mpu_FILE *parse_header_file; /* header for zubr_parse() function */
+mpu_FILE *action_file; /* a temp file, used to save actions associated */
+ /* with rules until the parser is written */
+mpu_FILE *text_file; /* a temp file, used to save text until all */
+ /* symbols have been defined */
+mpu_FILE *union_file; /* a temp file, used to save the union */
+ /* definition until all symbol have been */
+ /* defined */
+mpu_FILE *input_file; /* the input file */
+mpu_FILE *output_file; /* z_tab.c */
+mpu_FILE *defines_file; /* z_tab.h */
+mpu_FILE *code_file; /* z_code.c (used when the -r option is specified) */
+mpu_FILE *verbose_file; /* z.output */
+
+
+/* global: in defs.h define as extern */
+int nitems;
+int nrules;
+int nsyms;
+int ntokens;
+int nvars;
+
+/* global: in defs.h define as extern */
+int start_symbol;
+__mpu_char16_t **symbol_name;
+int *symbol_value;
+int *symbol_prec;
+char *symbol_assoc;
+
+/* global: in defs.h define as extern */
+int *ritem;
+int *rlhs;
+int *rrhs;
+int *rprec;
+char *rassoc;
+
+/* global: in defs.h define as extern */
+int **derives;
+char *nullable;
+
+
+/* static int out_unix_mode = 1; */
+/* static int out_msg_lang; */
+
+
+static void welcome( void )
+{
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "\
+zubr (ZUBR) %s\n\
+Copyright (C) 1995 - 2026 Andrey V.Kosteltsev.\n\
+This is free software. There is NO warranty; not even\n\
+for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" ),
+ ZUBR_VERSION );
+}
+
+
+
+
+
+int main( int argc, char *argv[] )
+/*************************************************************************
+
+ Description : ZUBR
+
+ Concepts : - LALR(1)
+
+ Use Global Variable:
+
+ Use Functions : void set_signals (void); | this file
+ void getargs (int argc, char *argv[]); | --/--
+ void open_files (void); | this file
+ void reader (void); | reader.c
+ lr0 (); | lr0.c
+ lalr (); | lalr.c
+ make_parser (); | mkpar.c
+ verbose (); | verbose.c
+ output (); | output.c
+ void done (int exit_code); | this file
+
+ Parameters : Command Line
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ welcome();
+
+ set_signals();
+
+ {
+ int i;
+ __mpu_char16_t **uargv = calloc( argc + 1, sizeof(*uargv) );
+ if( !uargv ) no_space();
+ for( i = 0; i < argc; ++i )
+ {
+ uargv[i] = zubr_utf8_to_ucs2_dup( argv[i] );
+ if( !uargv[i] ) fatal( MPU_UCS2( "Invalid UTF-8 command line argument" ) );
+ }
+ getargs( argc, uargv );
+ }
+ open_files();
+ reader();
+ lr0();
+ lalr();
+ make_parser();
+ verbose();
+ output();
+ done( 0 );
+
+ /*NOTREACHED*/
+ return( 0 );
+
+} /******* End of main( int argc, char *argv[] ) ***********************/
+
+
+void done( int exit_code )
+/*************************************************************************
+
+ Description : delete the .tmp files befor all exit.
+
+ Concepts :
+
+ Use Global Variable: mpu_FILE *action_file; | this file
+ mpu_FILE *text_file; | this file
+ mpu_FILE *union_file; | this file
+ mpu_FILE *input_file; | this file
+ mpu_FILE *output_file; | this file
+ mpu_FILE *defines_file; | this file
+ mpu_FILE *code_file; | this file
+ mpu_FILE *verbose_file; | this file
+ char *action_file_name; | this file
+ char *text_file_name; | this file
+ char *union_file_name; | this file
+ char *input_file_name; | this file
+ char *output_file_name; | this file
+ char *defines_file_name; | this file
+ char *code_file_name; | this file
+ char *verbose_file_name; | this file
+
+ Use Functions :
+
+ Parameters : int exit_code
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ if( action_file ) { mpu_fclose( action_file ); zubr_unlink( action_file_name ); }
+ if( action_file_name ) FREE( action_file_name );
+
+ if( text_file ) { mpu_fclose( text_file ); zubr_unlink( text_file_name ); }
+ if( text_file_name ) FREE( text_file_name );
+
+ if( union_file ) { mpu_fclose( union_file ); zubr_unlink( union_file_name ); }
+ if( union_file_name ) FREE( union_file_name );
+
+ if( input_file ) mpu_fclose( input_file );
+
+ if( output_file ) mpu_fclose( output_file );
+ if( output_file_name && C_mem ) FREE( output_file_name );
+
+ if( defines_file ) mpu_fclose( defines_file );
+ if( defines_file_name && D_mem ) FREE( defines_file_name );
+
+ if( code_file && rflag ) mpu_fclose( code_file );
+ if( code_file_name && R_mem ) FREE( code_file_name );
+
+ if( verbose_file ) mpu_fclose( verbose_file );
+ if( verbose_file_name && V_mem ) FREE( verbose_file_name );
+
+ if( parse_header_file ) mpu_fclose( parse_header_file );
+ if( parse_header_file_name ) FREE( parse_header_file_name );
+ if( parse_func_name ) FREE( parse_func_name );
+
+ if( lex_func_name ) FREE( lex_func_name );
+ if( inc_token_filename ) FREE( inc_token_filename );
+ if( name_prefix ) FREE( name_prefix );
+ if( name_prefix_upper ) FREE( name_prefix_upper );
+
+
+ /*******************************
+ this functions declare in file
+ lr0.c and not used in all files
+ of this project
+ *******************************/
+ if( nullable ) free_nullable();
+ if( derives ) free_derives();
+ /*******************************/
+
+
+ exit( exit_code );
+
+} /******* End of done( int exit_code ) ********************************/
+
+
+void onintr( int sig_number )
+/*************************************************************************
+
+ Description : call done() and exit
+
+ Concepts : - only for Set_signals()
+
+ Use Global Variable:
+
+ Use Functions : void done (int exit_code); | this file
+
+ Parameters : int sig_number // for signal() system function
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ sig_number = sig_number; /* no warning */
+
+ done( 1 );
+
+} /******* End of onintr( int sig_number ) *****************************/
+
+
+void set_signals( void )
+/*************************************************************************
+
+ Description : Если родительский процесс не запрещал прерывания,
+ то их надо обрабатывать и уходить.
+
+ Concepts : - не изменять родительским установкам (see UNIX)
+
+ Use Global Variable:
+
+ Use Functions : void onintr (int sig_number); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+
+#ifdef SIGINT
+ if( signal(SIGINT, SIG_IGN) != SIG_IGN ) signal( SIGINT, onintr );
+#endif
+
+#ifdef SIGTERM
+ if( signal(SIGTERM, SIG_IGN) != SIG_IGN ) signal( SIGTERM, onintr );
+#endif
+
+#ifdef SIGBREAK
+ if( signal(SIGBREAK, SIG_IGN) != SIG_IGN ) signal( SIGBREAK, onintr );
+#else
+#ifdef SIGHUP /* for UNIX-clone operating systems */
+ if( signal(SIGHUP, SIG_IGN ) != SIG_IGN ) signal( SIGHUP, onintr );
+#endif
+#endif
+
+} /******* End of set_signals( void ) **********************************/
+
+
+void usage( void ) __attribute__((noreturn));
+
+void usage( void )
+{
+ mpu_fprintf( mpu_stderr,
+ MPU_UCS2( "ZUBR %s\n" )
+ MPU_UCS2( "Usage: %s [-dlprstv] [other options] [-bFilePrefix] InputFile\n\n" )
+ MPU_UCS2( "Options:\n" )
+ MPU_UCS2( " -b[FilePrefix] set output file prefix\n" )
+ MPU_UCS2( " -d produce FilePrefix_tab.h\n" )
+ MPU_UCS2( " -l omit #line directives\n" )
+ MPU_UCS2( " -r split tables and parser code\n" )
+ MPU_UCS2( " -t include parser debugging code\n" )
+ MPU_UCS2( " -v produce FilePrefix.output\n" )
+ MPU_UCS2( " -p use .cpp extension\n" )
+ MPU_UCS2( " -s use static storage where applicable\n" )
+ MPU_UCS2( " -B[name] prefix global parser names\n" )
+ MPU_UCS2( " -C[FileName] set output code file\n" )
+ MPU_UCS2( " -D[FileName] set output header file\n" )
+ MPU_UCS2( " -I[filename] include external token definitions\n" )
+ MPU_UCS2( " -Lfuncname set lexer function name\n" )
+ MPU_UCS2( " -Pfuncname set parser function name\n" )
+ MPU_UCS2( " -R[FileName] split tables and code with code filename\n" )
+ MPU_UCS2( " -V[FileName] set verbose output filename\n" )
+ MPU_UCS2( " -o[FileName] set output code filename\n" )
+ MPU_UCS2( " --help display this help\n" )
+ MPU_UCS2( " --version display version\n\n" )
+ MPU_UCS2( "Input and output text files use UTF-8; ZUBR text is UCS-2 internally.\n" ),
+ ZUBR_VERSION, myname );
+ exit( 1 );
+}
+
+void is_admissible_name( __mpu_char16_t *s, int prefix_flag )
+/*************************************************************************
+
+ Description : is admissible file_name or file_prefix
+
+ Concepts : call bad_filename() if prefix_flag = 0
+ call bad_fileprefix() if prefix_flag = 1
+
+ Use Global Variable:
+
+ Use Functions : IS_ADMISSIBLE(char c) ( macros ) | this file
+ void bad_filename (char *s, int l); | error.c
+ void bad_fileprefix(char *s,int l); | error.c
+
+ Parameters : char *s;
+ int prefix_flag;
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int l, len;
+ register __mpu_char16_t *ptr;
+
+ ptr = s;
+
+ len = mpu_str16len( ptr );
+ for( l = 0; l < len; ++l )
+ {
+ if( IS_ADMISSIBLE( *ptr ) ) ptr++;
+ else
+ {
+ if( prefix_flag ) bad_fileprefix( s, l );
+ else bad_filename( s, l );
+ }
+ } /* End for( l < len ) */
+
+} /*********** End of is_admissible_name( char *, int ) ****************/
+
+
+void is_admissible_func_name( __mpu_char16_t *s )
+/*************************************************************************
+
+ Description : is admissible func_name for zubr_lex(), zubr_parse()
+
+ Concepts : call bad_funcname()
+
+ Use Global Variable:
+
+ Use Functions : void bad_funcname (char *s, int l); | error.c
+
+ Parameters : char *s;
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int l = 0, c;
+ register __mpu_char16_t *ptr;
+
+ ptr = s;
+ c = *ptr;
+
+ if( !zubr_is_alpha(c) && c != '_' ) bad_funcname( s, l );
+
+ while( (c = *++ptr) )
+ {
+ ++l;
+ if( !zubr_is_alnum(c) && c != '_' ) bad_funcname( s, l );
+ }
+
+} /******* End of is_admissible_func_name( char *, int ) ***************/
+
+
+
+void cut_off_extention( __mpu_char16_t *s )
+/*************************************************************************
+
+ Description : cut off the extention of file_name if it exist
+
+ Concepts : add '\0'
+
+ Use Global Variable:
+
+ Use Functions :
+
+ Parameters : char *s;
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int l, len;
+ register __mpu_char16_t *ptr;
+
+ len = mpu_str16len( s ) - 1;
+ ptr = s + len;
+
+ for( l = len; l > 0 &&
+ !IS_DIR_SEPARATOR(*ptr) &&
+ *ptr != '.'; --l ) --ptr;
+ if( *ptr == '.' )
+ {
+ for( l = l; l < len+1; l++ ) s[l] = NUL;
+ }
+
+} /*************** End of cut_off_extention( char * ) ******************/
+
+
+
+void cut_off_filename( __mpu_char16_t *s )
+/*************************************************************************
+
+ Description : cut off the file_name of full_file_name
+ (stay only the current dir of source file_name)
+
+ Concepts : add '\0'
+
+ Use Global Variable:
+
+ Use Functions :
+
+ Parameters : char *s;
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int l, len;
+ register __mpu_char16_t *ptr;
+
+ len = mpu_str16len( s ) - 1;
+ ptr = s + len;
+
+ for( l = len; l > 0 &&
+ !IS_DIR_SEPARATOR(*ptr); --l ) --ptr;
+ if( IS_DIR_SEPARATOR(*ptr) || l == 0 )
+ {
+ if( IS_DIR_SEPARATOR(*ptr) ) l++;
+ for( l = l; l < len+1; l++ ) s[l] = NUL;
+ }
+
+} /************** End of cut_off_filename( char * ) ********************/
+
+
+void getargs( int argc, __mpu_char16_t *argv[] )
+/*************************************************************************
+
+ Description : read of command line
+
+ Concepts :
+
+ Use Global Variable: mpu_FILE *input_file; | this file
+ mpu_FILE *code_file; | this file
+ mpu_FILE *defines_file; | this file
+ mpu_FILE *output_file; | this file
+ mpu_FILE *verbose_file; | this file
+ char *input_file_name; | this file
+ char *code_file_name; | this file
+ char *defines_file_name; | this file
+ char *output_file_name; | this file
+ char *verbose_file_name; | this file
+ char *file_prefix; | this file
+ char *myname; | this file
+
+ Use Functions : void usage (void); | this file
+ void no_space (void); | error.c
+ is_admissible_name (char *s, int l); | this file
+ is_admissible_func_name ( *s, l ); | this file
+ void cut_off_extention (char *s); | this file
+
+ Parameters : int argc;
+ char *argv[];
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i, c;
+ register __mpu_char16_t *s;
+
+ register int len;
+
+ register char C_flag = 0;
+ register char D_flag = 0;
+ register char R_flag = 0;
+ register char V_flag = 0;
+
+ register char B_flag = 0;
+ register char I_flag = 0;
+ register char L_flag = 0;
+ register char P_flag = 0;
+
+ __mpu_char16_t *prefix_name_tmp = (__mpu_char16_t *)MPU_UCS2( "" );
+ __mpu_char16_t *inc_name_tmp = (__mpu_char16_t *)MPU_UCS2( "" );
+ __mpu_char16_t *lex_name_tmp = (__mpu_char16_t *)MPU_UCS2( "" );
+ __mpu_char16_t *parse_name_tmp = (__mpu_char16_t *)MPU_UCS2( "" );
+
+
+ if( argc > 0 ) myname = argv[0];
+ for( i = 1; i < argc; ++i )
+ {
+ s = argv[i];
+ if( *s != '-' ) break;
+
+ switch( *++s )
+ {
+ case '\0':
+ usage();
+
+ case 'B':
+ if( B_flag ) usage();
+ B_flag = 1;
+ bflag = 1;
+ if( *++s )
+ {
+ prefix_name_tmp = s;
+ is_admissible_func_name( prefix_name_tmp );
+ continue;
+ }
+ else
+ continue;
+
+ case 'C':
+ if( C_flag ) usage();
+ C_flag = 1;
+ if( *++s )
+ {
+ output_file_name = s;
+ is_admissible_name( output_file_name, 0 );
+ continue;
+ }
+ else
+ continue;
+
+ case '-':
+ ++s;
+ if( !mpu_str16cmp( s, MPU_UCS2( "help" ) ) ) usage();
+ if( !mpu_str16cmp( s, MPU_UCS2( "version" ) ) ) done( 0 );
+ bad_option( argv[i] );
+
+ case 'd':
+ dflag = 1;
+ break;
+
+ case 'D':
+ if( D_flag ) usage();
+ D_flag = 1;
+ if( *++s )
+ {
+ defines_file_name = s;
+ is_admissible_name( defines_file_name, 0 );
+ continue;
+ }
+ else
+ continue;
+
+ case 'I':
+ if( I_flag ) usage();
+ I_flag = 1;
+ iflag = 1;
+ if( *++s )
+ {
+ inc_name_tmp = s;
+ is_admissible_name( inc_name_tmp, 0 );
+ continue;
+ }
+ else
+ continue;
+
+ case 'L':
+ if( L_flag ) usage();
+ L_flag = 1;
+ l_name_flag = 1;
+ if( *++s )
+ {
+ lex_name_tmp = s;
+ is_admissible_func_name( lex_name_tmp );
+ continue;
+ }
+ else
+ continue;
+
+ case 'l':
+ lflag = 1;
+ break;
+
+ case 'o':
+ if( C_flag ) usage();
+ C_flag = 1;
+ if( *++s )
+ {
+ output_file_name = s;
+ is_admissible_name( output_file_name, 0 );
+ continue;
+ }
+ else
+ {
+ if( ++i < argc )
+ {
+ output_file_name = argv[i];
+ is_admissible_name( output_file_name, 0 );
+ continue;
+ }
+ else
+ usage();
+ }
+ continue;
+
+ case 'P':
+ if( P_flag ) usage();
+ P_flag = 1;
+ p_name_flag = 1;
+ if( *++s )
+ {
+ parse_name_tmp = s;
+ is_admissible_func_name( parse_name_tmp );
+ continue;
+ }
+ else
+ continue;
+
+ case 'p':
+ pflag = 1;
+ break;
+
+ case 'r':
+ rflag = 1;
+ break;
+
+ case 'R':
+ if( R_flag ) usage();
+ R_flag = 1;
+ if( *++s )
+ {
+ code_file_name = s;
+ is_admissible_name( code_file_name, 0 );
+ continue;
+ }
+ else
+ continue;
+
+ case 's':
+ sflag = 1;
+ break;
+
+ case 't':
+ tflag = 1;
+ break;
+
+ case 'v':
+ vflag = 1;
+ break;
+
+ case 'V':
+ if( V_flag ) usage();
+ V_flag = 1;
+ if( *++s )
+ {
+ verbose_file_name = s;
+ is_admissible_name( verbose_file_name, 0 );
+ continue;
+ }
+ else
+ continue;
+
+ case 'b':
+ if( *++s )
+ {
+ file_prefix = s;
+ is_admissible_name( file_prefix, 1 );
+ continue;
+ }
+ else
+ {
+ if( ++i < argc )
+ {
+ file_prefix = argv[i];
+ is_admissible_name( file_prefix, 1 );
+ continue;
+ }
+ else
+ usage();
+ }
+ continue;
+
+ default:
+ usage();
+ } /* End switch( *++s ) */
+
+
+ for( ;; )
+ {
+ switch( *++s )
+ {
+ case '\0':
+ goto end_of_option;
+
+ case 'd':
+ dflag = 1;
+ break;
+
+ case 'l':
+ lflag = 1;
+ break;
+
+ case 'p':
+ pflag = 1;
+ break;
+
+ case 'r':
+ rflag = 1;
+ break;
+
+ case 's':
+ sflag = 1;
+ break;
+
+ case 't':
+ tflag = 1;
+ break;
+
+ case 'v':
+ vflag = 1;
+ break;
+
+ default:
+ usage();
+ } /* End switch( *++s ) */
+ } /* End for( ;; ) */
+
+end_of_option: ;
+
+ } /* End for( i < argc ) */
+
+
+ if( i + 1 != argc ) usage();
+
+ /* read input_file_name and check-up IS_ADMISSIBLE(c) */
+ input_file_name = argv[i];
+ is_admissible_name( input_file_name, 0 );
+
+ if( C_flag )
+ {
+ if( !output_file_name && !rflag && !R_flag )
+ {
+ if( pflag )
+ len = mpu_str16len( input_file_name )+1+
+ mpu_str16len( PROC_CPP_SUFFIX );
+ else
+ len = mpu_str16len(input_file_name)+1+
+ mpu_str16len( PROC_C_SUFFIX );
+ output_file_name = (__mpu_char16_t *)MALLOC( len * sizeof(__mpu_char16_t) );
+ if( output_file_name == 0 ) no_space();
+ memset( output_file_name, NUL, len * sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( output_file_name, input_file_name );
+ cut_off_extention( output_file_name );
+
+ if( pflag ) mpu_str16cat( output_file_name, PROC_CPP_SUFFIX );
+ else mpu_str16cat( output_file_name, PROC_C_SUFFIX );
+
+ C_mem = 1; /* memory for output_file_name is allocate */
+ }
+ else if( rflag || R_flag ) output_file_name = NULL;
+ else C_mem = 0; /* memory for output_file_name not allocate */
+
+ } /* Enf if( C_flag ) */
+
+ if( D_flag )
+ {
+ if( !defines_file_name && !dflag )
+ {
+ len = mpu_str16len( input_file_name )+1+
+ mpu_str16len( HEADER_SUFFIX );
+ defines_file_name = (__mpu_char16_t *)MALLOC( len * sizeof(__mpu_char16_t) );
+ if( defines_file_name == 0 ) no_space();
+ memset( defines_file_name, NUL, len * sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( defines_file_name, input_file_name );
+ cut_off_extention( defines_file_name );
+
+ mpu_str16cat( defines_file_name, HEADER_SUFFIX );
+
+ D_mem = 1; /* memory for defines_file_name is allocate */
+ }
+ else if( dflag ) defines_file_name = NULL;
+ else D_mem = 0; /* memory for defines_file_name not allocate */
+
+ } /* Enf if( D_flag ) */
+
+
+ if( R_flag )
+ {
+ if( !code_file_name && !rflag )
+ {
+ /* code_file_name */
+ if( pflag )
+ len = mpu_str16len( input_file_name )+1+
+ mpu_str16len( PROC_CPP_SUFFIX );
+ else
+ len = mpu_str16len( input_file_name )+1+
+ mpu_str16len( PROC_C_SUFFIX );
+ code_file_name = (__mpu_char16_t *)MALLOC( len * sizeof(__mpu_char16_t) );
+ if( code_file_name == 0 ) no_space();
+ memset( code_file_name, NUL, len * sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( code_file_name, input_file_name );
+ cut_off_extention( code_file_name );
+
+ if( pflag ) mpu_str16cat( code_file_name, PROC_CPP_SUFFIX );
+ else mpu_str16cat( code_file_name, PROC_C_SUFFIX );
+
+ R_mem = 1; /* memory for code_file_name is allocate */
+ }
+ else if( rflag ) code_file_name = NULL;
+ else R_mem = 0; /* memory for code_file_name not allocate */
+
+ } /* Enf if( R_flag ) */
+
+ if( V_flag )
+ {
+ if( !verbose_file_name && !vflag )
+ {
+ len = mpu_str16len( input_file_name )+1+
+ mpu_str16len( VERBOSE_SUFFIX );
+ verbose_file_name = (__mpu_char16_t *)MALLOC( len * sizeof(__mpu_char16_t) );
+ if( verbose_file_name == 0 ) no_space();
+ memset( verbose_file_name, NUL, len * sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( verbose_file_name, input_file_name );
+ cut_off_extention( verbose_file_name );
+
+ mpu_str16cat( verbose_file_name, VERBOSE_SUFFIX );
+
+ V_mem = 1; /* memory for verbose_file_name is allocate */
+ }
+ else if( vflag ) verbose_file_name = NULL;
+ else V_mem = 0; /* memory for verbose_file_name not allocate */
+
+ } /* Enf if( V_flag ) */
+
+
+ if( B_flag )
+ {
+ if( prefix_name_tmp )
+ {
+ len = mpu_str16len( prefix_name_tmp ) + 1;
+
+ name_prefix = (__mpu_char16_t *)MALLOC( len * sizeof(__mpu_char16_t) );
+ if( name_prefix == 0 ) no_space();
+ memset( name_prefix, NUL, len * sizeof(__mpu_char16_t) );
+
+ name_prefix_upper = (__mpu_char16_t *)MALLOC( len *
+ sizeof(__mpu_char16_t) );
+ if( name_prefix_upper == 0 ) no_space();
+ memset( name_prefix_upper, NUL, len * sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( name_prefix, prefix_name_tmp );
+
+ s = name_prefix;
+ i = 0;
+
+ while( (c = *s++) )
+ {
+ if( zubr_is_alpha(c) )
+ {
+ name_prefix_upper[i] = zubr_to_upper( name_prefix[i] );
+ ++i;
+ }
+ else
+ {
+ name_prefix_upper[i] = name_prefix[i];
+ ++i;
+ }
+ } /* End of while( c = *s++ ) */
+ }
+
+ } /* Enf if( B_flag ) */
+
+ if( I_flag )
+ {
+ if( inc_name_tmp )
+ {
+ len = mpu_str16len( inc_name_tmp ) + 1;
+ inc_token_filename = (__mpu_char16_t *)MALLOC( len *
+ sizeof(__mpu_char16_t) );
+ if( inc_token_filename == 0 ) no_space();
+ memset( inc_token_filename, NUL, len * sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( inc_token_filename, inc_name_tmp );
+ }
+
+ } /* Enf if( I_flag ) */
+
+ if( L_flag )
+ {
+ if( lex_name_tmp )
+ {
+ len = mpu_str16len( lex_name_tmp ) + 1;
+ lex_func_name = (__mpu_char16_t *)MALLOC( len *
+ sizeof(__mpu_char16_t) );
+ if( lex_func_name == 0 ) no_space();
+ memset( lex_func_name, NUL, len * sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( lex_func_name, lex_name_tmp );
+ }
+
+ } /* Enf if( L_flag ) */
+
+ if( P_flag )
+ {
+ if( parse_name_tmp )
+ {
+ len = mpu_str16len( parse_name_tmp ) + 1;
+ parse_func_name = (__mpu_char16_t *)MALLOC( len *
+ sizeof(__mpu_char16_t) );
+ if( parse_func_name == 0 ) no_space();
+ memset( parse_func_name, NUL, len * sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( parse_func_name, parse_name_tmp );
+ }
+
+ } /* Enf if( P_flag ) */
+
+
+ /*****************************************************
+ reset option -s if create code_file or defines_file
+ or define name_prefix (B_flag)
+ *****************************************************/
+ if( rflag || dflag || R_flag || D_flag /*|| B_flag*/ ) sflag = 0;
+
+} /************** End of getargs( int argc, char *argv[] ) *************/
+
+
+char *allocate( unsigned n )
+/*************************************************************************
+
+ Description : allocate n byte of memory and return pointer
+
+ Concepts :
+
+ Use Global Variable:
+
+ Use Functions : CALLOC(k,n) // macros | defs.h
+
+ Parameters : unsigned n;
+
+ Return : char *p;
+
+ *************************************************************************/
+{
+ register char *p;
+
+ p = NULL;
+ if( n )
+ {
+ p = CALLOC( 1, n );
+ if( !p ) no_space();
+ }
+ return( p );
+
+} /******* End of allocate( unsigned n ) *******************************/
+
+
+void create_file_names( void )
+/*************************************************************************
+
+ Description : create mames of .tmp files
+ UNIX-compatible options
+
+ Concepts : getenv (u"TMP") else getenv (u"TEMP")
+ else use current directory
+
+ Use Global Variable: char *file_prefix = u"z"; | this file
+ char dflag; | this file
+ char pflag; | this file
+ char rflag; | this file
+ char vflag; | this file
+ char *action_file_name; | this file
+ char *text_file_name; | this file
+ char *union_file_name; | this file
+ char *output_file_name; | this file
+ char *defines_file_name; | this file
+ char *code_file_name; | this file
+ char *verbose_file_name; | this file
+
+ Use Functions : void no_space (void); | error.c
+ void cut_off_filename (char *s); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ int i, len, nLength;
+ __mpu_char16_t *tmpdir;
+
+ tmpdir = zubr_getenv( "TMPDIR" );
+ if( tmpdir == NULL ) tmpdir = zubr_getenv( "TEMP" );
+ if( tmpdir == NULL ) tmpdir = zubr_getenv( "TMP" );
+ if( tmpdir == NULL ) /* current working directory */
+ {
+ tmpdir = (__mpu_char16_t *)MALLOC( 1 * sizeof(__mpu_char16_t) );
+ *tmpdir = NUL;
+ }
+
+#define L_pid 8
+#define L_prefix 7 /* see below: u"zubr_%u." */
+ len = mpu_str16len( tmpdir );
+ i = len + L_pid + L_prefix + 4; /* L_pid defined for %u <= pid */
+ /* + 4 for u"_a_", u"_t_", u"_u_" and '\0' */
+ if( len && !IS_DIR_SEPARATOR(tmpdir[len-1]) ) ++i;
+
+ action_file_name = MALLOC( i * sizeof(__mpu_char16_t) );
+ if( action_file_name == 0 ) no_space();
+ memset( action_file_name, NUL,
+ i * sizeof(__mpu_char16_t) ); /* incinerator */
+
+ text_file_name = MALLOC( i * sizeof(__mpu_char16_t) );
+ if( text_file_name == 0 ) no_space();
+ memset( text_file_name, NUL,
+ i * sizeof(__mpu_char16_t) ); /* incinerator */
+
+ union_file_name = MALLOC( i * sizeof(__mpu_char16_t) );
+ if( union_file_name == 0 ) no_space();
+ memset( union_file_name, NUL,
+ i * sizeof(__mpu_char16_t) ); /* incinerator */
+
+ mpu_str16cpy( action_file_name, tmpdir );
+ mpu_str16cpy( text_file_name, tmpdir );
+ mpu_str16cpy( union_file_name, tmpdir );
+
+ if( len && !IS_DIR_SEPARATOR(tmpdir[len-1]) )
+ {
+ action_file_name[len] = DIR_SEPARATOR;
+ text_file_name[len] = DIR_SEPARATOR;
+ union_file_name[len] = DIR_SEPARATOR;
+ }
+
+ mpu_sprintf( temp_form, MPU_UCS2( "zubr_%u." ), getpid() );
+
+ mpu_str16cat( action_file_name, temp_form );
+ mpu_str16cat( text_file_name, temp_form );
+ mpu_str16cat( union_file_name, temp_form );
+
+ mpu_str16cat( action_file_name, (__mpu_char16_t *)MPU_UCS2( "_a_" ) );
+ mpu_str16cat( text_file_name, (__mpu_char16_t *)MPU_UCS2( "_t_" ) );
+ mpu_str16cat( union_file_name, (__mpu_char16_t *)MPU_UCS2( "_u_" ) );
+
+ FREE( tmpdir );
+
+ len = mpu_str16len( file_prefix );
+
+ if( !output_file_name )
+ {
+ nLength = mpu_str16len( input_file_name );
+
+ output_file_name = (__mpu_char16_t *)
+ MALLOC( (nLength+len+2*MAX_SUFFIX_LEN) *
+ sizeof(__mpu_char16_t) );
+ /* 2*MAX_SUFFIX_LEN == 2*strlen( MAX_SUFFIX_LEN ) == 2*7 */
+ /* see defs.h */
+ if( output_file_name == 0 ) no_space();
+ memset( output_file_name, NUL, (nLength+len+2*MAX_SUFFIX_LEN) *
+ sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( output_file_name, input_file_name );
+ cut_off_filename( output_file_name );
+
+ mpu_str16cat( output_file_name, file_prefix );
+
+ mpu_str16cat( output_file_name, OUTPUT_SUFFIX );
+
+ if( pflag ) mpu_str16cat( output_file_name, PROC_CPP_SUFFIX );
+ else mpu_str16cat( output_file_name, PROC_C_SUFFIX );
+
+ C_mem = 1; /* memory for output_file_name is allocate */
+ }
+
+
+ if( dflag )
+ {
+ nLength = mpu_str16len( input_file_name );
+
+ defines_file_name = (__mpu_char16_t *)
+ MALLOC( (nLength+len+2*MAX_SUFFIX_LEN) *
+ sizeof(__mpu_char16_t) );
+ if( defines_file_name == 0 ) no_space();
+ memset( defines_file_name, NUL, (nLength+len+2*MAX_SUFFIX_LEN) *
+ sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( defines_file_name, input_file_name );
+ cut_off_filename( defines_file_name );
+
+ mpu_str16cat( defines_file_name, file_prefix );
+
+ mpu_str16cat( defines_file_name, DEFINES_SUFFIX );
+
+ D_mem = 1; /* memory for defines_file_name is allocate */
+ }
+
+
+ if( rflag )
+ {
+ nLength = mpu_str16len( input_file_name );
+
+ code_file_name = (__mpu_char16_t *)
+ MALLOC( (nLength+len+2*MAX_SUFFIX_LEN) *
+ sizeof(__mpu_char16_t) );
+ if( code_file_name == 0 ) no_space();
+ memset( code_file_name, NUL, (nLength+len+2*MAX_SUFFIX_LEN) *
+ sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( code_file_name, input_file_name );
+ cut_off_filename( code_file_name );
+
+ mpu_str16cat( code_file_name, file_prefix );
+
+ mpu_str16cat( code_file_name, CODE_SUFFIX );
+
+ if( pflag ) mpu_str16cat( code_file_name, PROC_CPP_SUFFIX );
+ else mpu_str16cat( code_file_name, PROC_C_SUFFIX );
+
+ R_mem = 1; /* memory for code_file_name is allocate */
+ }
+ else if( !code_file_name )
+ {
+ code_file_name = output_file_name;
+ R_mem = NUL;/*NULL*/ /* not repeat free memory in done() */
+ }
+ else rflag = 1; /* rflag for use open_files() */
+
+
+ if( vflag )
+ {
+ nLength = mpu_str16len( input_file_name );
+
+ verbose_file_name = (__mpu_char16_t *)
+ MALLOC( (nLength+len+2*MAX_SUFFIX_LEN) *
+ sizeof(__mpu_char16_t) );
+ if( verbose_file_name == 0 ) no_space();
+ memset( verbose_file_name, NUL, (nLength+len+2*MAX_SUFFIX_LEN) *
+ sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( verbose_file_name, input_file_name );
+ cut_off_filename( verbose_file_name );
+
+ mpu_str16cat( verbose_file_name, file_prefix );
+
+ mpu_str16cat( verbose_file_name, VERBOSE_SUFFIX );
+
+ V_mem = 1; /* memory for verbose_file_name is allocate */
+ }
+
+
+ if( p_name_flag )
+ {
+ if( parse_func_name )
+ {
+ len = mpu_str16len( parse_func_name );
+ nLength = mpu_str16len( input_file_name );
+
+ parse_header_file_name =
+ (__mpu_char16_t *)MALLOC( (nLength+len+mpu_str16len(HEADER_SUFFIX)) *
+ sizeof(__mpu_char16_t) );
+ if( parse_header_file_name == 0 ) no_space();
+ memset( parse_header_file_name,
+ NUL, (nLength+len+mpu_str16len(HEADER_SUFFIX)) *
+ sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( parse_header_file_name, input_file_name );
+ cut_off_filename( parse_header_file_name );
+ mpu_str16cpy( parse_header_file_name, parse_func_name );
+ mpu_str16cat( parse_header_file_name, HEADER_SUFFIX );
+ }
+
+ }
+
+} /******* End of create_file_names( void ) ****************************/
+
+
+void open_files( void )
+/*************************************************************************
+
+ Description : open files
+
+ Concepts :
+
+ Use Global Variable: char dflag; | this file
+ char rflag; | this file
+ char vflag; | this file
+ char *action_file_name; | this file
+ char *text_file_name; | this file
+ char *union_file_name; | this file
+ char *input_file_name; | this file
+ char *output_file_name; | this file
+ char *defines_file_name; | this file
+ char *code_file_name; | this file
+ char *verbose_file_name; | this file
+ mpu_FILE *action_file; | this file
+ mpu_FILE *text_file; | this file
+ mpu_FILE *union_file; | this file
+ mpu_FILE *input_file; | this file
+ mpu_FILE *output_file; | this file
+ mpu_FILE *defines_file; | this file
+ mpu_FILE *code_file; | this file
+ mpu_FILE *verbose_file; | this file
+
+ Use Functions : void open_error (char *filename); | error.c
+ int reorder_bytes( char *filename); | twinio.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+
+ create_file_names();
+
+ input_file = zubr_fopen( input_file_name, "r" );
+ if( input_file == 0 ) open_error( input_file_name );
+
+ action_file = zubr_fopen( action_file_name, "w" );
+ if( action_file == 0 ) open_error( action_file_name );
+
+ text_file = zubr_fopen( text_file_name, "w" );
+ if( text_file == 0 ) open_error( text_file_name );
+
+ if( vflag || verbose_file_name ) /* vflag or V_flag */
+ {
+ verbose_file = zubr_fopen( verbose_file_name, "w" );
+ if( verbose_file == 0 ) open_error( verbose_file_name );
+ vflag = 1; /* if( !vflag ) vflag = 1; // for use oter functions */
+ }
+
+ if( dflag || defines_file_name ) /* dflag or D_flag */
+ {
+ defines_file = zubr_fopen( defines_file_name, "w" );
+ if( defines_file == 0 ) open_error( defines_file_name );
+
+ union_file = zubr_fopen( union_file_name, "w" );
+ if( union_file == 0 ) open_error( union_file_name );
+ dflag = 1; /* if( !dflag ) dflag = 1; // for use oter functions */
+ }
+
+ output_file = zubr_fopen( output_file_name, "w" );
+ if( output_file == 0 ) open_error( output_file_name );
+
+ if( rflag ) /* rflag or R_flag */
+ {
+ code_file = zubr_fopen( code_file_name, "w" );
+ if( code_file == 0 ) open_error( code_file_name );
+ }
+ else code_file = output_file;
+
+ if( p_name_flag )
+ {
+ parse_header_file = zubr_fopen( parse_header_file_name, "w" );
+ if( parse_header_file == 0 )
+ open_error( parse_header_file_name );
+ }
+
+
+} /******* End of open_files( void ) *************************/
+
+#endif /* __NO_COMPILE */
+
+/****************** END OF FILE MAIN.C ***********************/
diff --git a/src/mkpar.c b/src/mkpar.c
new file mode 100644
index 0000000..bfa2fe2
--- /dev/null
+++ b/src/mkpar.c
@@ -0,0 +1,619 @@
+
+/***************************************************************
+ MKPAR.C
+
+ This file containts MAKE PARSER routines of ZUBR.
+
+ PART OF : ZUBR - Parsers generator for multiple syntax
+ language compilers .
+
+ COMPILE : .
+
+ Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+/*
+ This file contant RUSSIAN letters( code-page: UTF-8 )
+ ***************************************************************/
+
+#include <defs.h>
+
+#ifndef __NO_COMPILE
+
+
+action **parser;
+int SRtotal;
+int RRtotal;
+int *SRconflicts;
+int *RRconflicts;
+int *defred;
+int *rules_used;
+int nunused;
+int final_state;
+
+static int SRcount;
+static int RRcount;
+
+
+action *add_reduce( action *actions, int ruleno, int symbol )
+/***************************************************************
+
+ Description : add_reduce
+
+ Concepts :
+
+ Use Global Variable: int *rprec; | main.c
+ char *rassoc; | main.c
+
+ Use Functions :
+
+ Parameters : action *actions, int ruleno, int symbol
+
+ Return : action *
+
+ ***************************************************************/
+{
+ register action *temp, *prev, *next;
+
+ prev = 0;
+ for( next = actions;
+ next && next->symbol < symbol;
+ next = next->next )
+ prev = next;
+
+ while( next && next->symbol == symbol && next->action_code == SHIFT )
+ {
+ prev = next;
+ next = next->next;
+ }
+
+ while( next &&
+ next->symbol == symbol &&
+ next->action_code == REDUCE && next->number < ruleno )
+ {
+ prev = next;
+ next = next->next;
+ }
+
+ temp = NEW( action );
+ temp->next = next;
+ temp->symbol = symbol;
+ temp->number = ruleno;
+ temp->prec = rprec[ruleno];
+ temp->action_code = REDUCE;
+ temp->assoc = rassoc[ruleno];
+
+ if( prev ) prev->next = temp;
+ else actions = temp;
+
+ return( actions );
+
+} /******* End of add_reduce( action *, int, int ) ***********/
+
+
+int sole_reduction( int stateno )
+/***************************************************************
+
+ Description : sole_reduction
+
+ Concepts :
+
+ Use Global Variable: action **parser; | this file
+
+ Use Functions :
+
+ Parameters : int stateno
+
+ Return : int
+
+ ***************************************************************/
+{
+ register int count, ruleno;
+ register action *p;
+
+ count = 0;
+ ruleno = 0;
+ for( p = parser[stateno]; p; p = p->next )
+ {
+ if( p->action_code == SHIFT && p->suppressed == 0 ) return( 0 );
+ else if( p->action_code == REDUCE && p->suppressed == 0 )
+ {
+ if( ruleno > 0 && p->number != ruleno ) return( 0 );
+ if( p->symbol != 1 ) ++count;
+ ruleno = p->number;
+ }
+ }
+
+ if( count == 0 ) return( 0 );
+ return( ruleno );
+
+} /******* End of sole_reduction( int stateno ) **************/
+
+
+action *add_reductions( int stateno, action *actions )
+/***************************************************************
+
+ Description : add_reductions
+
+ Concepts :
+
+ Use Global Variable: int *lookaheads; | lalr.c
+ int *LAruleno; | lalr.c
+ int ntokens; | main.c
+
+ Use Functions : action * add_reduce (action *, int, int);
+ | this file
+
+ Parameters : int stateno, action *actions
+
+ Return : action *
+
+ ***************************************************************/
+{
+ register int i, j, m, n;
+ register int ruleno, tokensetsize;
+ register unsigned *rowp;
+
+ tokensetsize = SIZE_IN_INT( ntokens );
+ m = lookaheads[stateno];
+ n = lookaheads[stateno + 1];
+ for( i = m; i < n; i++ )
+ {
+ ruleno = LAruleno[i];
+ rowp = LA + i * tokensetsize;
+ for( j = ntokens - 1; j >= 0; j-- )
+ {
+ if( BIT(rowp, j) )
+ actions = add_reduce( actions, ruleno, j );
+ }
+ }
+ return( actions );
+
+} /******* End of add_reductions( int, action * ) ************/
+
+
+action *get_shifts (int stateno)
+/***************************************************************
+
+ Description : get_shifts
+
+ Concepts :
+
+ Use Global Variable: int *accessing_symbol; | lalr.c
+ shifts **shift_table; | lalr.c
+ int *symbol_prec; | main.c
+ char *symbol_assoc; | main.c
+
+ Use Functions :
+
+ Parameters : int stateno
+
+ Return : action *
+
+ ***************************************************************/
+{
+ register action *actions, *temp;
+ register shifts *sp;
+ register int *to_state;
+ register int i, k;
+ register int symbol;
+
+ actions = 0;
+ sp = shift_table[stateno];
+ if( sp )
+ {
+ to_state = sp->shift;
+ for( i = sp->nshifts - 1; i >= 0; i-- )
+ {
+ k = to_state[i];
+ symbol = accessing_symbol[k];
+ if( ISTOKEN(symbol) )
+ {
+ temp = NEW( action );
+ temp->next = actions;
+ temp->symbol = symbol;
+ temp->number = k;
+ temp->prec = symbol_prec[symbol];
+ temp->action_code = SHIFT;
+ temp->assoc = symbol_assoc[symbol];
+ actions = temp;
+ }
+ }
+ }
+ return( actions );
+
+} /******* End of get_shifts( int stateno ) ******************/
+
+
+void defreds( void )
+/***************************************************************
+
+ Description : defreds
+
+ Concepts :
+
+ Use Global Variable: int *defred; | this file
+ int nstates; | lr0.c
+
+ Use Functions : int sole_reduction (int); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+
+ defred = NEW2( nstates, int );
+ for( i = 0; i < nstates; i++ ) defred[i] = sole_reduction( i );
+
+} /******* End of defreds( void ) ****************************/
+
+
+void total_conflicts( void )
+/***************************************************************
+
+ Description : total_conflicts
+
+ Concepts :
+
+ Use Global Variable: int SRtotal; | this file
+ int RRtotal; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ mpu_fprintf( mpu_stderr, MPU_UCS2( "%s: " ), myname );
+
+ if( SRtotal == 1 )
+ mpu_fprintf( mpu_stderr,
+ MPU_UCS2( "1 shift/reduce conflict" ) );
+ else if( SRtotal > 1 )
+ mpu_fprintf( mpu_stderr,
+ MPU_UCS2( "%d shift/reduce conflicts" ),
+ SRtotal );
+
+ if( SRtotal && RRtotal )
+ mpu_fprintf( mpu_stderr, MPU_UCS2( ", u" ) );
+
+ if( RRtotal == 1 )
+ mpu_fprintf( mpu_stderr,
+ MPU_UCS2( "1 reduce/reduce conflict" ) );
+ else if( RRtotal > 1 )
+ mpu_fprintf( mpu_stderr,
+ MPU_UCS2( "%d reduce/reduce conflicts" ),
+ RRtotal );
+
+ mpu_fprintf( mpu_stderr, MPU_UCS2( ".\n" ) );
+
+} /******* End of total_conflicts( void ) ********************/
+
+
+void unused_rules( void )
+/***************************************************************
+
+ Description : unused_rules
+
+ Concepts :
+
+ Use Global Variable: action **parser; | this file
+ int *rules_used; | this file
+ int nunused; | this file
+ char *myname; | main.c
+ int nrules; | main.c
+ int nstates; | lr0.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+ register action *p;
+
+ rules_used = (int *)MALLOC( nrules*sizeof(int) );
+ if( rules_used == 0 ) no_space();
+
+ for( i = 0; i < nrules; ++i ) rules_used[i] = 0;
+
+ for( i = 0; i < nstates; ++i )
+ {
+ for( p = parser[i]; p; p = p->next )
+ {
+ if( p->action_code == REDUCE && p->suppressed == 0 )
+ rules_used[p->number] = 1;
+ }
+ }
+
+ nunused = 0;
+ for( i = 3; i < nrules; ++i )
+ if( !rules_used[i] ) ++nunused;
+
+ if( nunused )
+ {
+ if( nunused == 1 )
+ mpu_fprintf( mpu_stderr,
+ MPU_UCS2( "%s: 1 rule never reduced\n" ),
+ myname );
+ else
+ mpu_fprintf( mpu_stderr,
+ MPU_UCS2( "%s: %d rules never reduced\n" ),
+ myname, nunused );
+ }
+
+} /******* End of unused_rules( void ) ***********************/
+
+
+void remove_conflicts( void )
+/***************************************************************
+
+ Description : remove_conflicts
+
+ Concepts :
+
+ Use Global Variable: action **parser; | this file
+ int SRtotal; | this file
+ int RRtotal; | this file
+ int *SRconflicts; | this file
+ int *RRconflicts; | this file
+ int final_state; | this file
+ static int SRcount; | this file
+ static int RRcount; | this file
+ int nstates; | lr0.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+ register int symbol;
+ register action *p, *pref = NULL;
+
+ SRtotal = 0;
+ RRtotal = 0;
+ SRconflicts = NEW2( nstates, int );
+ RRconflicts = NEW2( nstates, int );
+ for( i = 0; i < nstates; i++ )
+ {
+ SRcount = 0;
+ RRcount = 0;
+ symbol = -1;
+
+ for( p = parser[i]; p; p = p->next )
+ {
+ if( p->symbol != symbol )
+ {
+ pref = p;
+ symbol = p->symbol;
+ }
+ else if( i == final_state && symbol == 0 )
+ {
+ SRcount++;
+ p->suppressed = 1;
+ }
+ else if( pref->action_code == SHIFT )
+ {
+ if( pref->prec > 0 && p->prec > 0 )
+ {
+ if( pref->prec < p->prec )
+ {
+ pref->suppressed = 2;
+ pref = p;
+ }
+ else if( pref->prec > p->prec )
+ {
+ p->suppressed = 2;
+ }
+ else if( pref->assoc == LEFT )
+ {
+ pref->suppressed = 2;
+ pref = p;
+ }
+ else if( pref->assoc == RIGHT )
+ {
+ p->suppressed = 2;
+ }
+ else
+ {
+ pref->suppressed = 2;
+ p->suppressed = 2;
+ }
+ } /* End if( pref->prec > 0 && p->prec > 0 ) */
+ else
+ {
+ SRcount++;
+ p->suppressed = 1;
+ }
+ } /* End if( pref->action_code == SHIFT ) */
+ else
+ {
+ RRcount++;
+ p->suppressed = 1;
+ }
+ } /* End of for( p = parser[i]; p; p = p->next ) */
+
+ SRtotal += SRcount;
+ RRtotal += RRcount;
+ SRconflicts[i] = SRcount;
+ RRconflicts[i] = RRcount;
+ } /* End of for( i = 0; i < nstates; i++ ) */
+
+} /******* End of remove_conflicts( void ) *******************/
+
+
+void find_final_state( void )
+/***************************************************************
+
+ Description : find_final_state
+
+ Concepts :
+
+ Use Global Variable: int final_state; | this file
+ int *ritem; | main.c
+ int *accessing_symbol; | lalr.c
+ shifts **shift_table; | lalr.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int goal, i;
+ register int *to_state;
+ register shifts *p;
+
+ p = shift_table[0];
+ to_state = p->shift;
+ goal = ritem[1];
+ for( i = p->nshifts - 1; i >= 0; --i )
+ {
+ final_state = to_state[i];
+ if( accessing_symbol[final_state] == goal ) break;
+ }
+
+} /******* End of find_final_state( void ) *******************/
+
+
+action *parse_actions( int stateno )
+/***************************************************************
+
+ Description : parse_actions
+
+ Concepts :
+
+ Use Global Variable:
+
+ Use Functions : action * add_reductions (int, action *);
+ action * get_shifts (int); | this file
+
+ Parameters : int stateno
+
+ Return : action *
+
+ ***************************************************************/
+{
+ register action *actions;
+
+ actions = get_shifts( stateno );
+ actions = add_reductions( stateno, actions );
+
+ return( actions );
+
+} /******* End of parse_actions( int stateno ) ***************/
+
+
+void make_parser( void )
+/***************************************************************
+
+ Description : make_parser
+
+ Concepts :
+
+ Use Global Variable: action **parser; | this file
+ int SRtotal; | this file
+ int RRtotal; | this file
+ int nstates; | lr0.c
+
+ Use Functions : void defreds (void); | this file
+ void total_conflicts (void); | this file
+ void remove_conflicts (void); | this file
+ void unused_rules (void); | this file
+ void find_final_state (void); | this file
+ action * parse_actions (int); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+
+ parser = NEW2( nstates, action * );
+ for( i = 0; i < nstates; i++ ) parser[i] = parse_actions( i );
+
+ find_final_state();
+ remove_conflicts();
+ unused_rules();
+ if( SRtotal + RRtotal > 0 ) total_conflicts();
+ defreds();
+
+} /******* End of make_parser( void ) ************************/
+
+
+/****************** this functions use in output.c ***********/
+
+void free_action_row( action *p )
+/***************************************************************
+
+ Description : free_action_row
+
+ Concepts :
+
+ Use Global Variable:
+
+ Use Functions :
+
+ Parameters : action *p
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register action *q;
+
+ while( p )
+ {
+ q = p->next;
+ FREE (p);
+ p = q;
+ }
+
+} /******* End of free_action_row( action *p ) ***************/
+
+
+void free_parser( void )
+/***************************************************************
+
+ Description : free_parser
+
+ Concepts :
+
+ Use Global Variable: action **parser; | this file
+ int nstates; | lr0.c
+
+ Use Functions : void free_action_row (action *); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+
+ for( i = 0; i < nstates; i++ ) free_action_row( parser[i] );
+
+ FREE( parser );
+
+} /******* End of free_parser( void ) ************************/
+
+#endif /* __NO_COMPILE */
+
+/************************ END OF FILE MKPAR.C ****************/
diff --git a/src/output.c b/src/output.c
new file mode 100644
index 0000000..d67c6bd
--- /dev/null
+++ b/src/output.c
@@ -0,0 +1,2071 @@
+
+/***************************************************************
+ OUTPUT.C
+
+ This file containts OUTPUT files writer of ZUBR.
+
+ PART OF : ZUBR - Parsers generator for multiple syntax
+ language compilers .
+
+ COMPILE : .
+
+ NOTE : .
+
+ Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+/*
+ This file contant RUSSIAN letters( code-page: UTF-8 )
+ ***************************************************************/
+
+#include <defs.h>
+
+#ifndef __NO_COMPILE
+
+static int nvectors;
+static int nentries;
+static int **froms;
+static int **tos;
+static int *tally;
+static int *width;
+static int *state_count;
+static int *order;
+static int *base;
+static int *pos;
+static int maxtable;
+static int *table;
+static int *check;
+static int lowzero;
+static int high;
+
+
+/*************************************************************************
+
+ The function matching_vector determines if the vector specified by the
+ input parameter matches a previously considered vector. The test at
+ the start of the function checks if the vector represents a row of
+ shifts over terminal symbols or a row of reductions, or a column of
+ shifts over a nonterminal symbol. ZUBR //and Berkeley Yacc // does not
+ check if a column of shifts over a nonterminal symbols matches
+ a previously considered vector. Because of the nature of LR parsing
+ tables, no two columns can match. Therefore, the only possible match
+ would be between a row and a column. Such matches are unlikely.
+ Therefore, to save time, no attempt is made to see if a column matches
+ a previously considered vector.
+
+ Matching_vector is poorly designed. The test could easily be made
+ faster. Also, it depends on the vectors being in a specific order.
+
+ *************************************************************************/
+
+
+int matching_vector( int vector )
+/*************************************************************************
+
+ Description : matching_vector
+
+ Concepts :
+
+ Use Global Variable: static int **froms; | this file
+ static int **tos; | this file
+ static int *tally; | this file
+ static int *width; | this file
+ static int *order; | this file
+ int nstates; | lr0.c
+
+ Use Functions :
+
+ Parameters : int vector
+
+ Return : int
+
+ *************************************************************************/
+{
+ register int i;
+ register int j;
+ register int k;
+ register int t;
+ register int w;
+ register int match;
+ register int prev;
+
+ i = order[vector];
+ if( i >= 2*nstates ) return( -1 );
+
+ t = tally[i];
+ w = width[i];
+
+ for( prev = vector - 1; prev >= 0; prev-- )
+ {
+ j = order[prev];
+ if( width[j] != w || tally[j] != t ) return( -1 );
+
+ match = 1;
+ for( k = 0; match && k < t; k++ )
+ {
+ if( tos[j][k] != tos[i][k] || froms[j][k] != froms[i][k] )
+ match = 0;
+ }
+
+ if( match ) return( j );
+ }
+ return( -1 );
+
+} /******* End of matching_vector( int vector ) ************************/
+
+
+int pack_vector( int vector )
+/*************************************************************************
+
+ Description : pack_vector
+
+ Concepts :
+
+ Use Global Variable: static int **froms; | this file
+ static int **tos; | this file
+ static int *tally; | this file
+ static int *order; | this file
+ static int *pos; | this file
+ static int maxtable; | this file
+ static int *table; | this file
+ static int *check; | this file
+ static int lowzero; | this file
+ static int high; | this file
+
+ Use Functions : void fatal( char * ); | error.c
+ void no_space( void ); | error.c
+
+ Parameters : int vector
+
+ Return : int
+
+ *************************************************************************/
+{
+ register int i, j, k, l;
+ register int t;
+ register int loc;
+ register int ok;
+ register int *from;
+ register int *to;
+
+ int newmax;
+
+ i = order[vector];
+ t = tally[i];
+
+ if( !t )
+ {
+ done( 2 );
+ }
+
+ from = froms[i];
+ to = tos[i];
+
+ j = lowzero - from[0];
+ for( k = 1; k < t; ++k )
+ if( lowzero - from[k] > j ) j = lowzero - from[k];
+
+ for( ;; ++j )
+ {
+ if( j == 0 ) continue;
+ ok = 1;
+
+ for( k = 0; ok && k < t; k++ )
+ {
+ loc = j + from[k];
+ if( loc >= maxtable )
+ {
+ if( loc >= MAXTABLE )
+ fatal( (__mpu_char16_t *)MPU_UCS2( "Maximum table size exceeded" ) );
+
+ newmax = maxtable;
+ do { newmax += 200; } while( newmax <= loc );
+ table = (int *)REALLOC( table, newmax*sizeof( int ) );
+ if (table == 0) no_space ();
+ check = (int *)REALLOC( check, newmax*sizeof( int ) );
+ if( check == 0 ) no_space();
+ for( l = maxtable; l < newmax; ++l )
+ {
+ table[l] = 0;
+ check[l] = -1;
+ }
+ maxtable = newmax;
+ }
+
+ if( check[loc] != -1 ) ok = 0;
+
+ } /* End of for( k = 0; ok && k < t; k++ ) */
+
+ for( k = 0; ok && k < vector; k++ )
+ {
+ if( pos[k] == j ) ok = 0;
+ }
+
+ if( ok )
+ {
+ for( k = 0; k < t; k++ )
+ {
+ loc = j + from[k];
+ table[loc] = to[k];
+ check[loc] = from[k];
+ if( loc > high ) high = loc;
+ }
+
+ while( check[lowzero] != -1 ) ++lowzero;
+
+ return( j );
+ }
+ } /* End of for( ;; ++j ) */
+
+} /******* End of pack_vector( int vector ) ****************************/
+
+
+int default_goto( int symbol )
+/*************************************************************************
+
+ Description : default_goto
+
+ Concepts :
+
+ Use Global Variable: static int *state_count; | this file
+ int *goto_map; | lalr.c
+ int *to_state; | lalr.c
+ int nstates; | lr0.c
+
+ Use Functions :
+
+ Parameters : int symbol
+
+ Return : int
+
+ *************************************************************************/
+{
+ register int i;
+ register int m;
+ register int n;
+ register int default_state;
+ register int max;
+
+ m = goto_map[symbol];
+ n = goto_map[symbol + 1];
+
+ if( m == n ) return( 0 );
+
+ for( i = 0; i < nstates; i++ ) state_count[i] = 0;
+
+ for( i = m; i < n; i++ ) state_count[to_state[i]]++;
+
+ max = 0;
+ default_state = 0;
+ for( i = 0; i < nstates; i++ )
+ {
+ if( state_count[i] > max )
+ {
+ max = state_count[i];
+ default_state = i;
+ }
+ }
+
+ return( default_state );
+
+} /******* Emd of default_goto( int symbol ) ***************************/
+
+
+void save_column( int symbol, int default_state )
+/*************************************************************************
+
+ Description : save_column
+
+ Concepts :
+
+ Use Global Variable: static int **froms; | this file
+ static int **tos; | this file
+ static int *tally; | this file
+ static int *width; | this file
+ int *goto_map; | lalr.c
+ int *from_state; | lalr.c
+ int *to_state; | lalr.c
+ int *symbol_value; | main.c
+
+ Use Functions :
+
+ Parameters : int symbol, int default_state
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i;
+ register int m;
+ register int n;
+ register int *sp;
+ register int *sp1;
+ register int *sp2;
+ register int count;
+ register int symno;
+
+ m = goto_map[symbol];
+ n = goto_map[symbol + 1];
+
+ count = 0;
+ for( i = m; i < n; i++ )
+ {
+ if( to_state[i] != default_state ) ++count;
+ }
+ if( count == 0 ) return;
+
+ symno = symbol_value[symbol] + 2*nstates;
+
+ froms[symno] = sp1 = sp = NEW2( count, int );
+ tos[symno] = sp2 = NEW2( count, int );
+
+ for( i = m; i < n; i++ )
+ {
+ if( to_state[i] != default_state )
+ {
+ *sp1++ = from_state[i];
+ *sp2++ = to_state[i];
+ }
+ }
+
+ tally[symno] = count;
+ width[symno] = sp1[-1] - sp[0] + 1;
+
+} /******* End of save_column( int symbol, int default_state ) *********/
+
+
+void output_check( void )
+/*************************************************************************
+
+ Description : output_check
+
+ Concepts :
+
+ Use Global Variable: static int *check; | this file
+ char rflag; | main.c
+ mpu_FILE *output_file; | main.c
+ int outline; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i;
+ register int j;
+
+ if( sflag )
+ {
+ /* это условие факт. не нужно, т.к. -B сбрасывает -s
+ но тут надо подумать стоит ли сбрасывать -s */
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int %szubr_check[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int zubr_check[] =" ) );
+ }
+ else
+ {
+ if( bflag )
+ mpu_fprintf( output_file, MPU_UCS2( "int %szubr_check[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file, MPU_UCS2( "int zubr_check[] =" ) );
+ }
+
+ if( !rflag ) outline += 2;
+ mpu_fprintf( output_file, MPU_UCS2( "\n{\n" ) );
+
+ j = 0;
+ for( i = 0; i <= high; i++ )
+ {
+ if( j >= 10 )
+ {
+ if( !rflag ) ++outline;
+ mpu_putc( '\n', output_file );
+ j = 1;
+ }
+ else ++j;
+
+ mpu_fprintf( output_file, MPU_UCS2( "%6d," ), check[i] );
+ }
+ if( !rflag ) outline += 3;
+ mpu_fprintf( output_file, MPU_UCS2( "\n};\n\n" ) );
+ FREE( check );
+
+
+} /******* End of output_check( void ) *********************************/
+
+
+void output_table( void )
+/*************************************************************************
+
+ Description : output_table
+
+ Concepts :
+
+ Use Global Variable: static int *table; | this file
+ static int high; | this file
+ char rflag; | main.c
+ mpu_FILE *code_file; | main.c
+ mpu_FILE *output_file; | main.c
+ int outline; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i;
+ register int j;
+
+ ++outline;
+ if( bflag )
+ mpu_fprintf( code_file, MPU_UCS2( "#define %sZUBR_TABLESIZE %d\n" ),
+ name_prefix_upper, high);
+ else
+ mpu_fprintf( code_file, MPU_UCS2( "#define ZUBR_TABLESIZE %d\n" ),
+ high );
+
+ if( sflag )
+ {
+ /* это условие факт. не нужно, т.к. -B сбрасывает -s
+ но тут надо подумать стоит ли сбрасывать -s */
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int %szubr_table[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int zubr_table[] =" ) );
+ }
+ else
+ {
+ if( bflag )
+ mpu_fprintf( output_file, MPU_UCS2( "int %szubr_table[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file, MPU_UCS2( "int zubr_table[] =" ) );
+ }
+
+ if( !rflag ) outline += 2;
+ mpu_fprintf( output_file, MPU_UCS2( "\n{\n" ) );
+
+ j = 0;
+ for( i = 0; i <= high; i++ )
+ {
+ if( j >= 10 )
+ {
+ if( !rflag ) ++outline;
+ mpu_putc( '\n', output_file );
+ j = 1;
+ }
+ else ++j;
+
+ mpu_fprintf( output_file, MPU_UCS2( "%6d," ), table[i] );
+
+ }
+ if( !rflag ) outline += 3;
+ mpu_fprintf( output_file, MPU_UCS2( "\n};\n\n" ) );
+ FREE( table );
+
+} /******* End of output_table( void ) *********************************/
+
+
+void output_base( void )
+/*************************************************************************
+
+ Description : output_base
+
+ Concepts :
+
+ Use Global Variable: static int nvectors; | this file
+ static int *base; | this file
+ int nstates; | lr0.c
+ char rflag; | main.c
+ mpu_FILE *output_file; | main.c
+ int outline; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i, j;
+
+ if( sflag )
+ {
+ /* это условие факт. не нужно, т.к. -B сбрасывает -s
+ но тут надо подумать стоит ли сбрасывать -s */
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int %szubr_sindex[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int zubr_sindex[] =" ) );
+ }
+ else
+ {
+ if( bflag )
+ mpu_fprintf( output_file, MPU_UCS2( "int %szubr_sindex[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file, MPU_UCS2( "int zubr_sindex[] =" ) );
+ }
+
+ if( !rflag ) outline += 2;
+ mpu_fprintf( output_file, MPU_UCS2( "\n{\n" ) );
+
+ j = 0;
+ for( i = 0; i < nstates; i++ )
+ {
+ if( j >= 10 )
+ {
+ if( !rflag ) ++outline;
+ mpu_putc( '\n', output_file );
+ j = 1;
+ }
+ else ++j;
+
+ mpu_fprintf( output_file, MPU_UCS2( "%6d," ), base[i] );
+
+ }
+
+ if( !rflag ) outline += 3;
+ if( sflag )
+ {
+ /* это условие факт. не нужно, т.к. -B сбрасывает -s
+ но тут надо подумать стоит ли сбрасывать -s */
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "\n};\n\nstatic int %szubr_rindex[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "\n};\n\nstatic int zubr_rindex[] =" ) );
+ }
+ else
+ {
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "\n};\n\nint %szubr_rindex[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "\n};\n\nint zubr_rindex[] =" ) );
+ }
+
+ if( !rflag ) outline += 2;
+ mpu_fprintf( output_file, MPU_UCS2( "\n{\n" ) );
+
+ j = 0;
+ for( i = nstates; i < 2*nstates; i++ )
+ {
+ if( j >= 10 )
+ {
+ if( !rflag ) ++outline;
+ mpu_putc( '\n', output_file );
+ j = 1;
+ }
+ else ++j;
+
+ mpu_fprintf( output_file, MPU_UCS2( "%6d," ), base[i] );
+
+ }
+
+ if( !rflag ) outline += 3;
+ if( sflag )
+ {
+ /* это условие факт. не нужно, т.к. -B сбрасывает -s
+ но тут надо подумать стоит ли сбрасывать -s */
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "\n};\n\nstatic int %szubr_gindex[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "\n};\n\nstatic int zubr_gindex[] =" ) );
+ }
+ else
+ {
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "\n};\n\nint %szubr_gindex[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "\n};\n\nint zubr_gindex[] =" ) );
+ }
+
+ if( !rflag ) outline += 2;
+ mpu_fprintf( output_file, MPU_UCS2( "\n{\n" ) );
+
+ j = 0;
+ for( i = 2*nstates; i < nvectors - 1; i++ )
+ {
+ if( j >= 10 )
+ {
+ if( !rflag ) ++outline;
+ mpu_putc( '\n', output_file );
+ j = 1;
+ }
+ else ++j;
+
+ mpu_fprintf( output_file, MPU_UCS2( "%6d," ), base[i] );
+
+ }
+ if( !rflag ) outline += 3;
+ mpu_fprintf( output_file, MPU_UCS2( "\n};\n\n" ) );
+ FREE( base );
+
+} /******* End of output_base( void ) **********************************/
+
+
+void pack_table( void )
+/*************************************************************************
+
+ Description : pack_table
+
+ Concepts :
+
+ Use Global Variable: static int nvectors; | this file
+ static int nentries; | this file
+ static int **froms; | this file
+ static int **tos; | this file
+ static int *base; | this file
+ static int *pos; | this file
+ static int maxtable; | this file
+ static int *table; | this file
+ static int *check; | this file
+ static int lowzero; | this file
+ static int high; | this file
+
+ Use Functions : int pack_vector( int ); | this file
+ int matching_vector( int ); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i;
+ register int place;
+ register int state;
+
+ base = NEW2( nvectors, int );
+ pos = NEW2( nentries, int );
+
+ maxtable = 1024; /* 0x400 */
+
+ table = NEW2( maxtable, int );
+ check = NEW2( maxtable, int );
+
+ lowzero = 0;
+ high = 0;
+
+ for( i = 0; i < maxtable; i++ ) check[i] = -1;
+
+ for( i = 0; i < nentries; i++ )
+ {
+ state = matching_vector( i );
+
+ if( state < 0 ) place = pack_vector( i );
+ else place = base[state];
+
+ pos[i] = place;
+ base[order[i]] = place;
+ }
+
+ for( i = 0; i < nvectors; i++ )
+ {
+ if( froms[i] ) FREE( froms[i] );
+ if( tos[i] ) FREE( tos[i] );
+ }
+
+ FREE( froms );
+ FREE( tos );
+ FREE( pos );
+
+} /******* End of pack_table( void ) ***********************************/
+
+
+void sort_actions( void )
+/*************************************************************************
+
+ Description : sort_actions
+
+ Concepts :
+
+ Use Global Variable: static int nvectors; | this file
+ static int nentries; | this file
+ static int *tally; | this file
+ static int *width; | this file
+ static int *order; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i;
+ register int j;
+ register int k;
+ register int t;
+ register int w;
+
+ order = NEW2( nvectors, int );
+ nentries = 0;
+
+ for( i = 0; i < nvectors; i++ )
+ {
+ if( tally[i] > 0 )
+ {
+ t = tally[i];
+ w = width[i];
+ j = nentries - 1;
+
+ while( j >= 0 && (width[order[j]] < w) )
+ j--;
+
+ while( j >= 0 && (width[order[j]] == w) &&
+ (tally[order[j]] < t) )
+ j--;
+
+ for( k = nentries - 1; k > j; k-- ) order[k + 1] = order[k];
+
+ order[j + 1] = i;
+ nentries++;
+ }
+ }
+
+} /******* End of sort_actions( void ) *********************************/
+
+
+void goto_actions( void )
+/*************************************************************************
+
+ Description : goto_actions
+
+ Concepts :
+
+ Use Global Variable: static int *state_count; | this file
+ int nsyms; | main.c
+ int start_symbol; | main.c
+ mpu_FILE *output_file; | main.c
+ int outline; | main.c
+ int nstates; | lr0.c
+
+ Use Functions : void save_column(int, int ); | this file
+ int default_goto( int ); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i, j, k;
+
+ state_count = NEW2( nstates, int );
+
+ if( sflag )
+ {
+ /* это условие факт. не нужно, т.к. -B сбрасывает -s
+ но тут надо подумать стоит ли сбрасывать -s */
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int %szubr_dgoto[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int zubr_dgoto[] =" ) );
+ }
+ else
+ {
+ if( bflag )
+ mpu_fprintf( output_file, MPU_UCS2( "int %szubr_dgoto[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file, MPU_UCS2( "int zubr_dgoto[] =" ) );
+ }
+
+ if( !rflag ) outline += 2;
+ mpu_fprintf( output_file, MPU_UCS2( "\n{\n" ) );
+
+ j = 0;
+ for( i = start_symbol + 1; i < nsyms; i++ )
+ {
+ if( j >= 10 )
+ {
+ if( !rflag ) ++outline;
+ mpu_putc( '\n', output_file );
+ j = 1;
+ }
+ else ++j;
+
+ k = default_goto( i );
+ mpu_fprintf( output_file, MPU_UCS2( "%6d," ), k );
+ save_column( i, k );
+ }
+
+ if( !rflag ) outline += 3;
+ mpu_fprintf( output_file, MPU_UCS2( "\n};\n\n" ) );
+ FREE( state_count );
+
+
+} /******* End of goto_actions( void ) *********************************/
+
+
+void token_actions( void )
+/*************************************************************************
+
+ Description : token_actions
+
+ Concepts :
+
+ Use Global Variable: static int **froms; | this file
+ static int **tos; | this file
+ static int *tally; | this file
+ static int *width; | this file
+ int nstates; | lr0.c
+ int ntokens; | main.c
+ int *symbol_value; | main.c
+ action **parser; | mkpar.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i, j;
+ register int shiftcount, reducecount;
+ register int max, min;
+ register int *actionrow, *r, *s;/*short*/
+ register action *p;
+
+ actionrow = NEW2( 2*ntokens, int );
+ for( i = 0; i < nstates; ++i )
+ {
+ if( parser[i] )
+ {
+ for( j = 0; j < 2*ntokens; ++j ) actionrow[j] = 0;
+
+ shiftcount = 0;
+ reducecount = 0;
+ for( p = parser[i]; p; p = p->next )
+ {
+ if( p->suppressed == 0 )
+ {
+ if( p->action_code == SHIFT )
+ {
+ ++shiftcount;
+ actionrow[p->symbol] = p->number;
+ }
+ else if( p->action_code == REDUCE &&
+ p->number != defred[i] )
+ {
+ ++reducecount;
+ actionrow[p->symbol + ntokens] = p->number;
+ }
+
+ } /* End if( p->suppressed == 0 ) */
+ } /* End of for( p = parser[i]; p; p = p->next ) */
+
+ tally[i] = shiftcount;
+ tally[nstates+i] = reducecount;
+ width[i] = 0;
+ width[nstates+i] = 0;
+
+ if( shiftcount > 0 )
+ {
+ froms[i] = r = NEW2( shiftcount, int );
+ tos[i] = s = NEW2( shiftcount, int );
+ min = MAXWORD;
+ max = 0;
+ for( j = 0; j < ntokens; ++j )
+ {
+ if( actionrow[j] )
+ {
+ if( min > symbol_value[j] ) min = symbol_value[j];
+ if( max < symbol_value[j] ) max = symbol_value[j];
+ *r++ = symbol_value[j];
+ *s++ = actionrow[j];
+ }
+ }
+ width[i] = max - min + 1;
+ } /* End if( shiftcount > 0 ) */
+
+ if( reducecount > 0 )
+ {
+ froms[nstates+i] = r = NEW2( reducecount, int );
+ tos[nstates+i] = s = NEW2( reducecount, int );
+ min = MAXWORD;
+ max = 0;
+ for( j = 0; j < ntokens; ++j )
+ {
+ if( actionrow[ntokens+j] )
+ {
+ if( min > symbol_value[j] ) min = symbol_value[j];
+ if( max < symbol_value[j] ) max = symbol_value[j];
+ *r++ = symbol_value[j];
+ *s++ = actionrow[ntokens+j] - 2;
+ }
+ }
+ width[nstates+i] = max - min + 1;
+ } /* End if( reducecount > 0 ) */
+ } /* End if( parser[i] ) */
+ } /* End of for( i = 0; i < nstates; ++i ) */
+ FREE( actionrow );
+
+} /******* End of token_actions( void ) ********************************/
+
+
+int is_C_identifier( __mpu_char16_t *name )
+/*************************************************************************
+
+ Description : is_C_identifier
+
+ Concepts :
+
+ Use Global Variable:
+
+ Use Functions :
+
+ Parameters : char *name
+
+ Return : int
+
+ *************************************************************************/
+{
+ register __mpu_char16_t *s;
+ register int c;
+
+ s = name;
+ c = *s;
+ if( c == '"' )
+ {
+ c = *++s;
+ if( !zubr_is_alpha(c) && c != '_' && c != '$' ) return( 0 );
+
+ while( (c = *++s) != '"' )
+ {
+ if( !zubr_is_alnum(c) && c != '_' && c != '$' )
+ return( 0 );
+ }
+ return( 1 );
+ }
+
+ if( !zubr_is_alpha(c) && c != '_' && c != '$' ) return( 0 );
+
+ while( (c = *++s) )
+ {
+ if( !zubr_is_alnum(c) && c != '_' && c != '$' ) return( 0 );
+ }
+ return( 1 );
+
+} /******* End of is_C_identifier( char *name ) ************************/
+
+
+void output_semantic_actions( void )
+/*************************************************************************
+
+ Description : output_semantic_actions
+
+ Concepts :
+
+ Use Global Variable: mpu_FILE *action_file; | main.c
+ char *action_file_name; | main.c
+ mpu_FILE *code_file; | main.c
+ char *code_file_name; | main.c
+ int outline; | main.c
+ char line_format[]; | reader.c
+
+ Use Functions : void open_error( char * ); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c, last;
+ register mpu_FILE *out;
+
+ mpu_fclose( action_file );
+ action_file = zubr_fopen( action_file_name, "r" );
+ if( action_file == NULL ) open_error( action_file_name );
+
+ if( (c = mpu_getc( action_file )) == mpu_EOF ) return;
+
+ out = code_file;
+ last = c;
+ if( c == '\n' ) ++outline;
+ mpu_putc( c, out );
+ while( (c = mpu_getc( action_file )) != mpu_EOF )
+ {
+ if( c == '\n' ) ++outline;
+ mpu_putc( c, out );
+ last = c;
+ }
+
+ if( last != '\n' )
+ {
+ ++outline;
+ mpu_putc( '\n', out );
+ }
+
+ if( !lflag )
+ mpu_fprintf( out, line_format, ++outline + 1, code_file_name);
+
+} /******* End of output_semantic_actions( void ) **********************/
+
+
+void output_trailing_text( void )
+/*************************************************************************
+
+ Description : output_trailing_text
+
+ Concepts :
+
+ Use Global Variable: char lflag; | main.c
+ mpu_FILE *input_file; | main.c
+ char *input_file_name; | main.c
+ mpu_FILE *code_file; | main.c
+ char *code_file_name; | main.c
+ int lineno; | main.c
+ int outline; | main.c
+ char *cptr; | reader.c
+ char *line; | reader.c
+ char line_format[]; | reader.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c, last;
+ register mpu_FILE *in, *out;
+
+ if( line == 0 ) return;
+
+ in = input_file;
+ out = code_file;
+
+ c = *cptr;
+ if( c == '\n' )
+ {
+ ++lineno;
+ if( (c = mpu_getc( in )) == mpu_EOF ) return;
+ if( !lflag )
+ {
+ ++outline;
+ mpu_fprintf( out, line_format, lineno, input_file_name );
+ }
+ if( c == '\n' ) ++outline;
+ mpu_putc( c, out );
+ last = c;
+ }
+ else
+ {
+ if( !lflag )
+ {
+ ++outline;
+ mpu_fprintf( out, line_format, lineno, input_file_name );
+ }
+ do { mpu_putc( c, out ); } while( (c = *++cptr) != '\n' );
+ ++outline;
+ mpu_putc( '\n', out );
+ last = '\n';
+ }
+
+ while( (c = mpu_getc( in )) != mpu_EOF )
+ {
+ if( c == '\n' ) ++outline;
+ mpu_putc( c, out );
+ last = c;
+ }
+ if( mpu_ferror( in ) ) input_error();
+
+ if( last != '\n' )
+ {
+ ++outline;
+ mpu_putc( '\n', out );
+ }
+ if( !lflag )
+ mpu_fprintf( out, line_format, ++outline + 1, code_file_name );
+
+} /******* End of output_trailing_text( void ) *************************/
+
+
+void output_stype( void )
+/*************************************************************************
+
+ Description : output_stype
+
+ Concepts :
+
+ Use Global Variable: int ntags; | main.c
+ mpu_FILE *code_file; | main.c
+ int outline; | main.c
+ char unionized; | reader.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ if( !unionized && ntags == 0 )
+ {
+ outline += 4;
+ if( bflag )
+ mpu_fprintf( code_file,
+ MPU_UCS2( "#ifndef %sZUBR_STYPE\ntypedef int %sZUBR_STYPE;\n#endif\n\n" ),
+ name_prefix_upper, name_prefix_upper );
+ else
+ mpu_fprintf( code_file,
+ MPU_UCS2( "#ifndef ZUBR_STYPE\ntypedef int ZUBR_STYPE;\n#endif\n\n" ) );
+ }
+
+} /******* End of output_stype( void ) *********************************/
+
+
+void output_debug( void )
+/*************************************************************************
+
+ Description : output_debug
+
+ Concepts :
+
+ Use Global Variable: int final_state; | mkpar.c
+ char rflag; | main.c
+ char tflag; | main.c
+ int ntokens; | main.c
+ int nrules; | main.c
+ char **symbol_name; | main.c
+ int *symbol_value; | main.c
+ int *ritem; | main.c
+ int *rrhs; | main.c
+ int *rlhs; | main.c
+ mpu_FILE *code_file; | main.c
+ mpu_FILE *output_file; | main.c
+ int outline; | main.c
+
+ Use Functions : void no_space( void ); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i, j, k, max;
+ __mpu_char16_t **symnam, *s;
+ __mpu_char16_t *_char_type = (__mpu_char16_t *)MPU_UCS2( "__mpu_char16_t" );
+
+ ++outline;
+ if( bflag )
+ mpu_fprintf( code_file, MPU_UCS2( "#define %sZUBR_FINAL %d\n" ),
+ name_prefix_upper, final_state );
+ else
+ mpu_fprintf( code_file, MPU_UCS2( "#define ZUBR_FINAL %d\n" ),
+ final_state );
+
+ outline += 3;
+ if( bflag )
+ mpu_fprintf( code_file,
+ MPU_UCS2( "#ifndef %sZUBR_DEBUG\n#define %sZUBR_DEBUG %d\n#endif\n" ),
+ name_prefix_upper, name_prefix_upper, tflag );
+ else
+ mpu_fprintf( code_file,
+ MPU_UCS2( "#ifndef ZUBR_DEBUG\n#define ZUBR_DEBUG %d\n#endif\n" ),
+ tflag );
+
+ if( rflag )
+ {
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "#ifndef %sZUBR_DEBUG\n#define %sZUBR_DEBUG %d\n#endif\n" ),
+ name_prefix_upper, name_prefix_upper, tflag );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "#ifndef ZUBR_DEBUG\n#define ZUBR_DEBUG %d\n#endif\n" ),
+ tflag );
+ }
+ max = 0;
+ for( i = 2; i < ntokens; ++i )
+ if( symbol_value[i] > max )
+ max = symbol_value[i];
+
+ ++outline;
+ if( bflag )
+ mpu_fprintf( code_file, MPU_UCS2( "#define %sZUBR_MAXTOKEN %d\n" ),
+ name_prefix_upper, max );
+ else
+ mpu_fprintf( code_file, MPU_UCS2( "#define ZUBR_MAXTOKEN %d\n" ), max );
+
+ symnam = (__mpu_char16_t **)MALLOC( (max+1)*sizeof(__mpu_char16_t *) );
+ if( symnam == 0 ) no_space();
+
+ /* Note that it is not necessary to initialize the element */
+ /* symnam[max]. */
+ for( i = 0; i < max; ++i ) symnam[i] = 0;
+ for( i = ntokens - 1; i >= 2; --i )
+ symnam[symbol_value[i]] = symbol_name[i];
+ symnam[0] = (__mpu_char16_t *)MPU_UCS2( "end-of-file" );
+
+ if( !rflag ) ++outline;
+ if( sflag )
+ {
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "#if %sZUBR_DEBUG\nstatic %s *%szubr_name[] =" ),
+ name_prefix_upper, _char_type, name_prefix );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "#if ZUBR_DEBUG\nstatic %s *zubr_name[] =" ), _char_type );
+ }
+ else
+ {
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "#if %sZUBR_DEBUG\n%s *%szubr_name[] =" ),
+ name_prefix_upper, _char_type, name_prefix );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "#if ZUBR_DEBUG\n%s *zubr_name[] =" ), _char_type );
+ }
+
+ if( !rflag ) ++outline;
+ mpu_fprintf( output_file, MPU_UCS2( "\n{" ) );
+
+ j = 80;
+ for( i = 0; i <= max; ++i )
+ {
+ if( (s = symnam[i]) )
+ {
+ if( s[0] == '"' )
+ {
+ k = 7;
+ while( *++s != '"' )
+ {
+ ++k;
+ if( *s == '\\' )
+ {
+ k += 2;
+ if( *++s == '\\' ) ++k;
+ }
+ }
+ j += k;
+ if( j > 80 )
+ {
+ if( !rflag ) ++outline;
+ mpu_fprintf( output_file, MPU_UCS2( "\n " ) );
+ j = k;
+ }
+ mpu_fprintf( output_file, MPU_UCS2( "u\"\\\"" ) );
+ s = symnam[i];
+ while( *++s != '"' )
+ {
+ if( *s == '\\' )
+ {
+ mpu_fprintf( output_file, MPU_UCS2( "\\\\" ) );
+ if( *++s == '\\' )
+ mpu_fprintf( output_file, MPU_UCS2( "\\\\" ) );
+ else
+ mpu_putc( *s, output_file );
+ }
+ else
+ mpu_putc( *s, output_file );
+ }
+ mpu_fprintf( output_file, MPU_UCS2( "\\\"\"," ) );
+ } /* End if( s[0] == '"' ) */
+
+ else if( s[0] == '\'' )
+ {
+ if( s[1] == '"' )
+ {
+ j += 7;
+ if( j > 80 )
+ {
+ if( !rflag ) ++outline;
+ mpu_putc( '\n', output_file );
+ j = 7;
+ }
+ mpu_fprintf( output_file, MPU_UCS2( "u\"'\\\"'\"," ) );
+ }
+ else
+ {
+ k = 5;
+ while( *++s != '\'' )
+ {
+ ++k;
+ if( *s == '\\' )
+ {
+ k += 2;
+ if ( *++s == '\\' ) ++k;
+ }
+ }
+ j += k;
+ if( j > 80 )
+ {
+ if( !rflag ) ++outline;
+ mpu_fprintf( output_file, MPU_UCS2( "\n " ) );
+ j = k;
+ }
+ mpu_fprintf( output_file, MPU_UCS2( "u\"'" ) );
+ s = symnam[i];
+ while( *++s != '\'' )
+ {
+ if( *s == '\\' )
+ {
+ mpu_fprintf( output_file, MPU_UCS2( "\\\\" ) );
+ if( *++s == '\\' )
+ mpu_fprintf( output_file, MPU_UCS2( "\\\\" ) );
+ else
+ mpu_putc( *s, output_file );
+ }
+ else
+ mpu_putc( *s, output_file );
+ }
+ mpu_fprintf( output_file, MPU_UCS2( "'\"," ) );
+ }
+ } /* End if( s[0] == '\'' ) */
+
+ else
+ {
+ k = mpu_str16len( s ) + 3;
+ j += k;
+ if( j > 80 )
+ {
+ if( !rflag ) ++outline;
+ mpu_fprintf( output_file, MPU_UCS2( "\n " ) );
+ j = k;
+ }
+ mpu_fprintf( output_file, MPU_UCS2( "u\"" ) );
+ do
+ {
+ mpu_putc( *s, output_file );
+
+ } while( *++s );
+ mpu_fprintf( output_file, MPU_UCS2( "\"," ) );
+ }
+
+ } /* End if( s = symnam[i] ) */
+ else
+ {
+ j += 2;
+ if( j > 80 )
+ {
+ if( !rflag ) ++outline;
+ mpu_fprintf( output_file, MPU_UCS2( "\n " ) );
+ j = 2;
+ }
+ mpu_fprintf( output_file, MPU_UCS2( "0," ) );
+ }
+
+ } /* End of for (i = 0; i <= max; ++i) */
+ if( !rflag ) outline += 3;
+ mpu_fprintf( output_file, MPU_UCS2( "\n};\n\n" ) );
+ FREE( symnam );
+
+ if( !rflag ) ++outline;
+ if( sflag )
+ {
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static %s *%szubr_rule[] =\n" ),
+ _char_type, name_prefix );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static %s *zubr_rule[] =\n" ), _char_type );
+ }
+ else
+ {
+ if( bflag )
+ mpu_fprintf( output_file, MPU_UCS2( "%s *%szubr_rule[] =\n" ),
+ _char_type, name_prefix );
+ else
+ mpu_fprintf( output_file, MPU_UCS2( "%s *zubr_rule[] =\n" ), _char_type );
+ }
+
+ if( !rflag ) ++outline;
+ mpu_fprintf( output_file, MPU_UCS2( "{\n" ) );
+
+ for( i = 2; i < nrules; ++i )
+ {
+ mpu_fprintf( output_file, MPU_UCS2( " MPU_UCS2(\"" ) );
+ mpu_fprintf( output_file,
+ MPU_UCS2( "%s :" ), symbol_name[rlhs[i]] );
+
+ for( j = rrhs[i]; ritem[j] > 0; ++j )
+ {
+ s = symbol_name[ritem[j]];
+ if( s[0] == '"' )
+ {
+ mpu_fprintf( output_file, MPU_UCS2( " \\\"" ) );
+ while( *++s != '"' )
+ {
+ if( *s == '\\' )
+ {
+ if( s[1] == '\\' )
+ mpu_fprintf( output_file, MPU_UCS2( "\\\\\\\\" ) );
+ else
+ {
+ mpu_fprintf( output_file, MPU_UCS2( "\\\\" ) );
+ mpu_putc( s[1], output_file );
+ }
+ ++s;
+ }
+ else
+ mpu_putc( *s, output_file );
+ }
+ mpu_fprintf( output_file, MPU_UCS2( "\\\"" ) );
+ }
+ else if( s[0] == '\'' )
+ {
+ if( s[1] == '"' )
+ mpu_fprintf( output_file, MPU_UCS2( " '\\\"'" ) );
+ else if( s[1] == '\\' )
+ {
+ if( s[2] == '\\' )
+ mpu_fprintf( output_file, MPU_UCS2( " '\\\\\\\\" ) );
+ else
+ {
+ mpu_fprintf( output_file, MPU_UCS2( " '\\\\" ) );
+ mpu_putc( s[2], output_file );
+ }
+ s += 2;
+ while( *++s != '\'' )
+ mpu_putc( *s, output_file );
+ mpu_putc( '\'', output_file );
+ }
+ else
+ {
+ mpu_fprintf( output_file, MPU_UCS2( " '" ) );
+ mpu_putc( s[1], output_file );
+ mpu_fprintf( output_file, MPU_UCS2( "'" ) );
+ }
+ }
+ else
+ mpu_fprintf( output_file, MPU_UCS2( " %s" ), s );
+
+ } /* End of for (j = rrhs[i]; ritem[j] > 0; ++j) */
+ if( !rflag ) ++outline;
+ mpu_fprintf( output_file, MPU_UCS2( "\"),\n" ) );
+
+ } /* End of for (i = 2; i < nrules; ++i) */
+ if( !rflag ) outline += 3;
+ mpu_fprintf( output_file, MPU_UCS2( "};\n#endif\n\n" ) );
+
+ if( rflag )
+ {
+ /* Print 'End of FILE' into z_tab.c */
+ mpu_fprintf( output_file, MPU_UCS2( "\
+/************************ End of File **************************/\n" )
+ );
+ }
+
+} /******* End of output_debug( void ) *********************************/
+
+
+void output_actions( void )
+/*************************************************************************
+
+ Description : output_actions
+
+ Concepts :
+
+ Use Global Variable: static int nvectors; | this file
+ static int **froms; | this file
+ static int **tos; | this file
+ static int *tally; | this file
+ static int *width; | this file
+ int *lookaheads; | lalr.c
+ int *LAruleno; | lalr.c
+ unsigned *LA; | lalr.c
+ int *accessing_symbol; | lalr.c
+ int *goto_map; | lalr.c
+ int *from_state; | lalr.c
+ int *to_state; | lalr.c
+ int nstates; | lr0.c
+ int ntokens; | main.c
+ int nvars; | main.c
+
+ Use Functions : void output_check( void ); | this file
+ void output_table( void ); | this file
+ void output_base( void ); | this file
+ void pack_table( void ); | this file
+ void sort_actions( void ); | this file
+ void goto_actions( void ); | this file
+ void token_actions( void ); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ nvectors = 2*nstates + nvars;
+
+ froms = NEW2( nvectors, int * );
+ tos = NEW2( nvectors, int * );
+ tally = NEW2( nvectors, int );
+ width = NEW2( nvectors, int );
+
+ token_actions();
+ FREE( lookaheads );
+ FREE( LA );
+ FREE( LAruleno );
+ FREE( accessing_symbol );
+
+ goto_actions();
+ FREE( goto_map + ntokens );
+ FREE( from_state );
+ FREE( to_state );
+
+ sort_actions();
+ pack_table();
+ output_base();
+ output_table();
+ output_check();
+
+} /******* End of output_actions( void ) *******************************/
+
+
+void output_zubr_defred( void )
+/*************************************************************************
+
+ Description : output_zubr_defred
+
+ Concepts :
+
+ Use Global Variable: int nstates; | lr0.c
+ char rflag; | main.c
+ mpu_FILE *output_file; | main.c
+ int outline; | main.c
+ int *defred; | mkpar.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i, j;
+
+ if( sflag )
+ {
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int %szubr_defred[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int zubr_defred[] =" ) );
+ }
+ else
+ {
+ if( bflag )
+ mpu_fprintf( output_file, MPU_UCS2( "int %szubr_defred[] =" ),
+ name_prefix );
+ else
+ mpu_fprintf( output_file, MPU_UCS2( "int zubr_defred[] =" ) );
+ }
+
+ if( !rflag ) outline += 2;
+ mpu_fprintf( output_file, MPU_UCS2( "\n{\n" ) );
+
+ j = 0;
+ for( i = 0; i < nstates; i++ )
+ {
+ if( j < 10 ) ++j;
+ else
+ {
+ if( !rflag ) ++outline;
+ mpu_putc( '\n', output_file );
+ j = 1;
+ }
+
+ mpu_fprintf( output_file,
+ MPU_UCS2( "%6d," ), (defred[i] ? defred[i] - 2 : 0) );
+ }
+
+ if( !rflag ) outline += 3;
+ mpu_fprintf( output_file, MPU_UCS2( "\n};\n\n" ) );
+
+} /******* End of output_zubr_defred( void ) ***************************/
+
+
+void output_rule_data( void )
+/*************************************************************************
+
+ Description : output_rule_data
+
+ Concepts :
+
+ Use Global Variable: char rflag; | main.c
+ int nrules; | main.c
+ int start_symbol; | main.c
+ int *symbol_value; | main.c
+ int *rrhs; | main.c
+ int *rlhs; | main.c
+ mpu_FILE *output_file; | main.c
+ int outline; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i;
+ register int j;
+
+ if( !rflag ) outline +=2;
+ else
+ {
+ /* Print 'HEADER' into file z_tab.c */
+ mpu_fprintf( output_file, MPU_UCS2( "\n\
+/***************************************************************\n\
+ This file prodused by ZUBR for save the read-only tables.\n\
+ ***************************************************************/\n\n\n" ) );
+ }
+
+ if( sflag )
+ {
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int %szubr_lhs[] =\n{\n%6d," ),
+ name_prefix, symbol_value[start_symbol] );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int zubr_lhs[] =\n{\n%6d," ),
+ symbol_value[start_symbol] );
+ }
+ else
+ {
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "int %szubr_lhs[] =\n{\n%6d," ),
+ name_prefix, symbol_value[start_symbol] );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "int zubr_lhs[] =\n{\n%6d," ),
+ symbol_value[start_symbol] );
+ }
+
+ j = 1;
+ for( i = 3; i < nrules; i++ )
+ {
+ if( j >= 10 )
+ {
+ if( !rflag) ++outline;
+ mpu_putc( '\n', output_file );
+ j = 1;
+ }
+ else ++j;
+
+ mpu_fprintf( output_file, MPU_UCS2( "%6d," ), symbol_value[rlhs[i]] );
+
+ }
+ if( !rflag ) outline += 3;
+ mpu_fprintf( output_file, MPU_UCS2( "\n};\n\n" ) );
+
+
+ if( !rflag ) outline +=2;
+ if( sflag )
+ {
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int %szubr_len[] =\n{\n%6d," ),
+ name_prefix, 2 );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "static int zubr_len[] =\n{\n%6d," ), 2 );
+ }
+ else
+ {
+ if( bflag )
+ mpu_fprintf( output_file,
+ MPU_UCS2( "int %szubr_len[] =\n{\n%6d," ),
+ name_prefix, 2 );
+ else
+ mpu_fprintf( output_file,
+ MPU_UCS2( "int zubr_len[] =\n{\n%6d," ), 2 );
+ }
+
+ j = 1;
+ for( i = 3; i < nrules; i++ )
+ {
+ if( j >= 10 )
+ {
+ if( !rflag ) ++outline;
+ mpu_putc( '\n', output_file );
+ j = 1;
+ }
+ else j++;
+
+ mpu_fprintf( output_file, MPU_UCS2( "%6d," ),
+ rrhs[i + 1] - rrhs[i] - 1 );
+
+ }
+ if( !rflag ) outline += 3;
+ mpu_fprintf( output_file, MPU_UCS2( "\n};\n\n" ) );
+
+} /******* End of output_rule_data( void ) *****************************/
+
+
+void output_defines( void )
+/*************************************************************************
+
+ Description : output_defines
+
+ Concepts :
+
+ Use Global Variable: char dflag; | main.c
+ int ntokens; | main.c
+ char **symbol_name; | main.c
+ int *symbol_value; | main.c
+ mpu_FILE *union_file; | main.c
+ char *union_file_name; | main.c
+ mpu_FILE *code_file; | main.c
+ mpu_FILE *defines_file; | main.c
+ int outline; | main.c
+ char unionized; | reader.c
+
+ Use Functions : int is_C_identifier( char * ); | this file
+ void open_error( char * ); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c, i;
+ register __mpu_char16_t *s;
+
+ if( dflag )
+ {
+ mpu_fprintf( defines_file, MPU_UCS2( "\n\
+/***************************************************************\n\
+ This file prodused by ZUBR for used token definitions and\n\
+ union declaration.\n\
+ ***************************************************************/\n" ) );
+ }
+
+ ++outline;
+ mpu_putc( '\n', code_file );
+ if( dflag ) mpu_putc( '\n', defines_file );
+
+
+ if( !iflag )
+ {
+
+ for( i = 2; i < ntokens; ++i )
+ {
+ s = symbol_name[i];
+ if( is_C_identifier( s ) )
+ {
+ mpu_fprintf( code_file, MPU_UCS2( "#define " ) );
+ if( dflag ) mpu_fprintf( defines_file, MPU_UCS2( "#define " ) );
+
+ c = *s;
+ if( c == '"' )
+ {
+ while( (c = *++s) != '"' )
+ {
+ mpu_putc( c, code_file );
+ if( dflag ) mpu_putc( c, defines_file );
+ }
+ }
+ else
+ {
+ do
+ {
+ mpu_putc( c, code_file );
+ if( dflag ) mpu_putc( c, defines_file );
+ }
+ while( (c = *++s) );
+ }
+ ++outline;
+ mpu_fprintf( code_file, MPU_UCS2( " %d\n" ), symbol_value[i] );
+ if( dflag )
+ mpu_fprintf( defines_file, MPU_UCS2( " %d\n" ),
+ symbol_value[i] );
+ }
+ } /* End of for( i = 2; i < ntokens; ++i ) */
+ } /* End if( !iflag ) */
+ else
+ {
+ ++outline;
+ mpu_fprintf( code_file,
+ MPU_UCS2( "#include \"%s\"\n" ), inc_token_filename );
+ if( dflag )
+ mpu_fprintf( defines_file,
+ MPU_UCS2( "#include \"%s\"\n" ), inc_token_filename );
+ }
+
+
+ ++outline;
+ mpu_putc( '\n', code_file );
+ if( dflag ) mpu_putc( '\n', defines_file );
+
+ outline += 2;
+ if( bflag )
+ mpu_fprintf( code_file, MPU_UCS2( "#define %sZUBR_ERRCODE %d\n\n" ),
+ name_prefix_upper, symbol_value[1] );
+ else
+ mpu_fprintf( code_file, MPU_UCS2( "#define ZUBR_ERRCODE %d\n\n" ),
+ symbol_value[1] );
+
+
+ if( dflag && unionized )
+ {
+ mpu_fclose( union_file );
+ union_file = zubr_fopen( union_file_name, "r" );
+ if( union_file == NULL ) open_error( union_file_name );
+ while( (c = mpu_getc( union_file )) != mpu_EOF )
+ mpu_putc( c, defines_file );
+ if( bflag )
+ mpu_fprintf( defines_file,
+ MPU_UCS2( " %sZUBR_STYPE;\n\nextern %sZUBR_STYPE %szubr_lval;\n\n" ),
+ name_prefix_upper, name_prefix_upper, name_prefix );
+ else
+ mpu_fprintf( defines_file,
+ MPU_UCS2( " ZUBR_STYPE;\n\nextern ZUBR_STYPE zubr_lval;\n\n" ) );
+ }
+
+
+ if( dflag )
+ {
+ mpu_fprintf( defines_file, MPU_UCS2( "\
+/************************ End of File **************************/\n" )
+ );
+ }
+
+} /******* End of output_defines( void ) *******************************/
+
+
+void output_stored_text( void )
+/*************************************************************************
+
+ Description : output_stored_text
+
+ Concepts :
+
+ Use Global Variable: mpu_FILE *text_file; | main.c
+ char *text_file_name; | main.c
+ mpu_FILE *code_file; | main.c
+ char *code_file_name; | main.c
+ int outline; | main.c
+ char line_format[]; | reader.c
+
+ Use Functions : void open_error( char * ); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c;
+ register mpu_FILE *in, *out;
+
+ mpu_fclose( text_file );
+ text_file = zubr_fopen( text_file_name, "r" );
+ if( text_file == NULL ) open_error( text_file_name );
+ in = text_file;
+ if( (c = mpu_getc( in )) == mpu_EOF ) return;
+ out = code_file;
+ if( c == '\n' ) ++outline;
+ mpu_putc( c, out );
+ while( (c = mpu_getc( in )) != mpu_EOF )
+ {
+ if( c == '\n' ) ++outline;
+ mpu_putc( c, out );
+ }
+ if( !lflag )
+ mpu_fprintf( out, line_format, ++outline + 1, code_file_name );
+
+} /******* End of output_stored_text( void ) ***************************/
+
+
+void free_reductions( void )
+/*************************************************************************
+
+ Description : free_reductions
+
+ Concepts :
+
+ Use Global Variable: reductions **reduction_table; | lalr.c
+ reductions *first_reduction; | lr0.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register reductions *rp, *next;
+
+ FREE( reduction_table );
+ for( rp = first_reduction; rp; rp = next )
+ {
+ next = rp->next;
+ FREE( rp );
+ }
+
+} /******* End of free_reductions( void ) ******************************/
+
+
+void free_shifts( void )
+/*************************************************************************
+
+ Description : free_shifts
+
+ Concepts :
+
+ Use Global Variable: shifts **shift_table; | lalr.c
+ shifts *first_shift; | lr0.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register shifts *sp, *next;
+
+ FREE( shift_table );
+ for( sp = first_shift; sp; sp = next )
+ {
+ next = sp->next;
+ FREE( sp );
+ }
+
+} /******* End of free_shifts( void ) **********************************/
+
+
+void free_itemsets( void )
+/*************************************************************************
+
+ Description : free_itemsets
+
+ Concepts :
+
+ Use Global Variable: core **state_table; | lalr.c
+ core *first_state; | lr0.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register core *cp, *next;
+
+ FREE( state_table );
+ for( cp = first_state; cp; cp = next )
+ {
+ next = cp->next;
+ FREE( cp );
+ }
+
+} /******* End of free_itemsets( void ) ********************************/
+
+
+void output( void )
+/*************************************************************************
+
+ Description : output
+
+ Concepts :
+
+ Use Global Variable: char rflag; | main.c
+
+ Use Functions : void free_reductions( void ); | this file
+ void free_shifts( void ); | this file
+ void free_itemsets( void ); | this file
+ void output_semantic_actions(void); | this file
+ void output_trailing_text( void ); | this file
+ void output_stype( void ); | this file
+ void output_debug( void ); | this file
+ void output_stored_text( void ); | this file
+ void output_defines( void ); | this file
+ void output_actions( void ); | this file
+ void output_zubr_defred( void ); | this file
+ void output_rule_data( void ); | this file
+ void free_parser( void ); | mkpar.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ free_itemsets();
+ free_shifts();
+ free_reductions();
+ output_stored_text();
+ output_defines();
+ output_rule_data();
+ output_zubr_defred();
+ output_actions();
+ free_parser();
+ output_debug();
+ output_stype ();
+ if( rflag ) write_extern_tables();
+
+ write_header();
+ write_header_definitions();
+
+ output_trailing_text();
+
+ write_begin_body();
+ write_parse_name_definition();
+
+ write_end_body();
+ output_semantic_actions();
+ write_trailer();
+
+} /******* End of output( void ) *****************************/
+
+#endif /* __NO_COMPILE */
+
+/******************* END OF FILE OUTPUT.C ********************/
diff --git a/src/port.c b/src/port.c
new file mode 100644
index 0000000..38999b0
--- /dev/null
+++ b/src/port.c
@@ -0,0 +1,109 @@
+
+#include <defs.h>
+
+#ifndef __NO_COMPILE
+
+int zubr_is_alpha( __mpu_char16_t c )
+{
+ return (c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') || c >= 0x80;
+}
+
+int zubr_is_alnum( __mpu_char16_t c )
+{
+ return zubr_is_alpha( c ) || (c >= '0' && c <= '9');
+}
+
+int zubr_is_digit( __mpu_char16_t c )
+{
+ return c >= '0' && c <= '9';
+}
+
+int zubr_is_upper( __mpu_char16_t c )
+{
+ return c >= 'A' && c <= 'Z';
+}
+
+int zubr_is_print( __mpu_char16_t c )
+{
+ return c >= 0x20 && c != 0x7f;
+}
+
+__mpu_char16_t zubr_to_lower( __mpu_char16_t c )
+{
+ if( c >= 'A' && c <= 'Z' ) return c - 'A' + 'a';
+ return c;
+}
+
+__mpu_char16_t zubr_to_upper( __mpu_char16_t c )
+{
+ if( c >= 'a' && c <= 'z' ) return c - 'a' + 'A';
+ return c;
+}
+
+static char *zubr_ucs2_to_utf8_dup( const __mpu_char16_t *s )
+{
+ size_t n = mpu_str16len( s );
+ size_t cap = n * 3 + 1;
+ char *p = malloc( cap );
+
+ if( !p ) return NULL;
+
+ if( mpu_ucs2_to_utf8( (__mpu_char8_t *)p, s, cap ) == (__mpu_size_t)-1 )
+ {
+ free( p );
+ return NULL;
+ }
+
+ return p;
+}
+
+__mpu_char16_t *zubr_utf8_to_ucs2_dup( const char *s )
+{
+ size_t n = strlen( s );
+ __mpu_char16_t *p = malloc( (n + 1) * sizeof(*p) );
+
+ if( !p ) return NULL;
+
+ if( mpu_utf8_to_ucs2( p, (const __mpu_char8_t *)s, n + 1 ) == (__mpu_size_t)-1 )
+ {
+ free( p );
+ return NULL;
+ }
+
+ return p;
+}
+
+mpu_FILE *zubr_fopen( const __mpu_char16_t *filename, const char *mode )
+{
+ char *name = zubr_ucs2_to_utf8_dup( filename );
+ mpu_FILE *fp;
+
+ if( !name ) return NULL;
+ fp = mpu_fopen( name, mode );
+ free( name );
+
+ return fp;
+}
+
+int zubr_unlink( const __mpu_char16_t *filename )
+{
+ char *name = zubr_ucs2_to_utf8_dup( filename );
+ int rc;
+
+ if( !name ) return -1;
+ rc = unlink( name );
+ free( name );
+
+ return rc;
+}
+
+__mpu_char16_t *zubr_getenv( const char *name )
+{
+ char *value = getenv( name );
+
+ if( !value ) return NULL;
+ return zubr_utf8_to_ucs2_dup( value );
+}
+
+#endif
diff --git a/src/reader.c b/src/reader.c
new file mode 100644
index 0000000..d009daf
--- /dev/null
+++ b/src/reader.c
@@ -0,0 +1,2769 @@
+
+/***************************************************************
+ READER.C
+
+ This file containts INPUT file reader of ZUBR.
+
+ PART OF : ZUBR - Parsers generator for multiple syntax
+ language compilers .
+
+ COMPILE : .
+
+ NOTE : .
+
+ Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+/*
+ This file contant RUSSIAN letters( code-page: UTF-8 )
+ ***************************************************************/
+
+#include <defs.h>
+
+#ifndef __NO_COMPILE
+
+
+
+/* The line size must be a positive integer. One hundred was chosen */
+/* because few lines in Yacc input grammars exceed 100 characters. */
+/* Note that if a line exceeds LINESIZE characters, the line buffer */
+/* will be expanded to accomodate it. */
+
+#define LINESIZE 100
+
+__mpu_char16_t *cache;
+int cinc, cache_size;
+
+int ntags, tagmax;
+__mpu_char16_t **tag_table;
+
+char saw_eof, unionized;
+__mpu_char16_t *cptr, *line;
+int linesize;
+
+bucket *goal;
+int prec;
+int gensym;
+char last_was_action;
+
+int maxitems;
+bucket **pitem;
+
+int maxrules;
+bucket **plhs;
+
+int name_pool_size;
+__mpu_char16_t *name_pool;
+
+__mpu_char16_t line_format[] = MPU_UCS2( "#line %d \"%s\"\n" );
+
+
+void cachec( int c )
+/*************************************************************************
+
+ Description : запись в кэш нового символа
+
+ Concepts : для новой записи обнулить cinc = 0;
+ затем в цикле можно записывать символы
+
+ Use Global Variable:
+
+ Use Functions : void no_space (void); | error.c
+
+ Parameters : int c
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ if( cinc < 0 )
+ {
+ done( 2 );
+ }
+ if( cinc >= cache_size )
+ {
+ cache_size += 256;
+ cache = REALLOC( cache, cache_size * sizeof(__mpu_char16_t) );
+ if( cache == 0 ) no_space();
+ }
+ cache[cinc] = c;
+ ++cinc;
+
+} /******* End of cachec( int c ) **************************************/
+
+
+void get_line( void )
+/*************************************************************************
+
+ Description : чтение строки input_file в char *line
+
+ Concepts : cptr устанавливается в начало line (cptr = line)
+
+ Use Global Variable: char *cptr; | this file
+ char *line; | this file
+ int lineno; | main.c
+ mpu_FILE *input_file; | main.c
+
+ Use Functions : void no_space (void); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register mpu_FILE *f = input_file;
+ register int c;
+ register int i;
+
+ if( saw_eof || (c = mpu_getc(f)) == mpu_EOF )
+ {
+ if( !saw_eof && mpu_ferror( f ) ) input_error();
+ if( line ) { FREE( line ); line = 0; }
+ cptr = 0;
+ saw_eof = 1;
+ return;
+ }
+
+ if( line == 0 || linesize != (LINESIZE + 1) )
+ {
+ if( line ) FREE( line );
+ linesize = LINESIZE + 1;
+ line = (__mpu_char16_t *)MALLOC( linesize * sizeof(__mpu_char16_t) );
+ if( line == 0 ) no_space();
+ memset( line, NUL, linesize * sizeof(__mpu_char16_t) );
+ }
+
+ i = 0;
+ ++lineno;
+ for( ;; )
+ {
+ line[i] = c;
+ if( c == '\n' ) { cptr = line; return; }
+ if( ++i >= linesize )
+ {
+ linesize += LINESIZE;
+ line = REALLOC( line, linesize * sizeof(__mpu_char16_t) );
+ if( line == 0 ) no_space();
+ }
+ c = mpu_getc( f );
+ if( c == mpu_EOF )
+ {
+ line[i] = '\n';
+ saw_eof = 1;
+ cptr = line;
+ return;
+ }
+ }
+
+} /******* End of get_line( void ) *************************************/
+
+
+__mpu_char16_t *dup_line( void )
+/*************************************************************************
+
+ Description : копирование строки из char *line в выделяемую
+ память и возврат указателя
+
+ Concepts : длина строки вычисляется до '\n'
+
+ Use Global Variable: char *line; | this file
+
+ Use Functions : void no_space (void); | error.c
+
+ Parameters : [void]
+
+ Return : char *p
+
+ *************************************************************************/
+{
+ register int len;
+ register __mpu_char16_t *p, *s, *t;
+
+ if( line == 0 ) return( 0 );
+ s = line;
+ while( *s != '\n' ) ++s;
+ len = s - line + 1;
+ p = (__mpu_char16_t *)MALLOC( len * sizeof(__mpu_char16_t) );
+ if( p == 0 ) no_space ();
+ memset( p, NUL, len * sizeof(__mpu_char16_t) );
+
+ s = line;
+ t = p;
+ while( (*t++ = *s++) != '\n' ) continue;
+ return( p );
+
+} /******* End of dup_line( void ) *************************************/
+
+
+void skip_comment( void )
+/*************************************************************************
+
+ Description : пропуск коментариев
+
+ Concepts :
+
+ Use Global Variable: char *line; | this file
+ char *cptr; | this file
+ int lineno; | main.c
+
+ Use Functions : char * dup_line (void); | this file
+ void unterminated_comment (int, char *, char *);
+ | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register __mpu_char16_t *s;
+
+ int st_lineno = lineno;
+ __mpu_char16_t *st_line = dup_line ();
+ __mpu_char16_t *st_cptr = st_line + (cptr - line);
+
+ s = cptr + 2;
+ for( ;; )
+ {
+ if( *s == '*' && s[1] == '/' )
+ {
+ cptr = s + 2;
+ FREE( st_line );
+ return;
+ }
+ if( *s == '\n' )
+ {
+ get_line();
+ if( line == 0 )
+ unterminated_comment( st_lineno, st_line, st_cptr );
+ s = cptr;
+ }
+ else
+ ++s;
+ }
+
+} /******* End of skip_comment( void ) *********************************/
+
+
+int nextc( void )
+/*************************************************************************
+
+ Description : чтение символа из char *line
+
+ Concepts : если '\n' get_line()
+
+ Use Global Variable: char *line; | this file
+ char *cptr; | this file
+
+ Use Functions : void get_line (void); | this file
+ void skip_comment (void); | this file
+
+ Parameters : [void]
+
+ Return : int // *s
+
+ *************************************************************************/
+{
+ register __mpu_char16_t *s;
+
+ if( line == 0 )
+ {
+ get_line();
+ if( line == 0 ) return( mpu_EOF );
+ }
+
+ s = cptr;
+ for( ;; )
+ {
+ switch( *s )
+ {
+ case '\n':
+ get_line();
+ if( line == 0 ) return( mpu_EOF );
+ s = cptr;
+ break;
+
+ case ' ':
+ case '\t':
+ case '\f':
+ case '\r':
+ case '\v':
+ case ',':
+ case ';':
+ ++s;
+ break;
+
+ case '\\':
+ cptr = s;
+ return( '%' );
+
+ case '/':
+ if( s[1] == '*' )
+ {
+ cptr = s;
+ skip_comment();
+ s = cptr;
+ break;
+ }
+ else if( s[1] == '/' )
+ {
+ get_line();
+ if( line == 0 ) return( mpu_EOF );
+ s = cptr;
+ break;
+ }
+ /* fall through */
+
+ default:
+ cptr = s;
+ return( *s );
+ } /* End of switch (*s) */
+ } /* End of for (;;) */
+
+} /******* End of nextc( void ) ****************************************/
+
+
+int keyword( void )
+/*************************************************************************
+
+ Description : use in read_declarations()
+
+ Concepts :
+
+ Use Global Variable: char *cptr; | this file
+ char *line; | this file
+ int lineno; | main.c
+
+ Use Functions : void cachec (int c); | this file
+ void syntax_error(int, char *, char *);
+ | error.c
+
+ Parameters : [void]
+
+ Return : int c
+
+ *************************************************************************/
+{
+ register int c;
+ __mpu_char16_t *t_cptr = cptr;
+
+ c = *++cptr;
+ if( zubr_is_alpha( c ) )
+ {
+ cinc = 0;
+ for( ;; )
+ {
+ if( zubr_is_alpha( c ) )
+ {
+ if( zubr_is_upper( c ) ) c = zubr_to_lower( c );
+ cachec( c );
+ }
+ else if( zubr_is_digit( c ) || c == '_' ||
+ c == '.' || c == '$' )
+ cachec( c );
+ else
+ break;
+ c = *++cptr;
+ }
+ cachec( NUL );
+
+
+ if( mpu_str16cmp( cache, (__mpu_char16_t *)MPU_UCS2( "token" ) ) == 0 ||
+ mpu_str16cmp( cache, (__mpu_char16_t *)MPU_UCS2( "term" ) ) == 0 )
+ return( TOKEN );
+ if( mpu_str16cmp( cache, (__mpu_char16_t *)MPU_UCS2( "type" ) ) == 0 )
+ return( TYPE );
+ if( mpu_str16cmp( cache, (__mpu_char16_t *)MPU_UCS2( "left" ) ) == 0 )
+ return( LEFT );
+ if( mpu_str16cmp( cache, (__mpu_char16_t *)MPU_UCS2( "right" ) ) == 0 )
+ return( RIGHT );
+ if( mpu_str16cmp( cache, (__mpu_char16_t *)MPU_UCS2( "nonassoc" ) ) == 0 ||
+ mpu_str16cmp( cache, (__mpu_char16_t *)MPU_UCS2( "binary" ) ) == 0 )
+ return( NONASSOC );
+ if( mpu_str16cmp( cache, (__mpu_char16_t *)MPU_UCS2( "start" ) ) == 0 )
+ return( START );
+ if( mpu_str16cmp( cache, (__mpu_char16_t *)MPU_UCS2( "union" ) ) == 0 )
+ return( UNION );
+ if( mpu_str16cmp( cache, (__mpu_char16_t *)MPU_UCS2( "ident" ) ) == 0 )
+ return( IDENT );
+ }
+ else
+ {
+ ++cptr;
+ if( c == '{' ) return( TEXT );
+ if( c == '%' || c == '\\' ) return( MARK );
+ if( c == '<' ) return( LEFT );
+ if( c == '>' ) return( RIGHT );
+ if( c == '0' ) return( TOKEN );
+ if( c == '2' ) return( NONASSOC );
+ }
+ syntax_error( lineno, line, t_cptr );
+
+ /*NOTREACHED*/
+ return( -1 );
+
+} /******* End of keyword( void ) **************************************/
+
+
+void copy_ident( void )
+/*************************************************************************
+
+ Description :
+
+ Concepts : ZUBR встречая? %ident u"string"
+ записывает на выход #ident u"string".
+
+ Use Global Variable: char *cptr; | this file
+ char *line; | this file
+ int lineno; | main.c
+ int outline; | main.c
+ mpu_FILE *output_file; | main.c
+
+ Use Functions : void unexpected_EOF (void); | error.c
+ void syntax_error (int, char *, char *);
+ | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c;
+ register mpu_FILE *f = output_file;
+
+ c = nextc();
+ if( c == mpu_EOF ) unexpected_EOF();
+ if( c != '\"' ) syntax_error( lineno, line, cptr );
+ ++outline;
+ mpu_fprintf( f, MPU_UCS2( "#ident \"" ) );
+ for( ;; )
+ {
+ c = *++cptr;
+ if( c == '\n' )
+ {
+ mpu_fprintf( f, MPU_UCS2( "\"\n" ) );
+ return;
+ }
+
+ mpu_putc( c, f );
+
+ if( c == '\"' )
+ {
+ mpu_putc( '\n', f );
+ ++cptr;
+ return;
+ }
+ } /* End of for( ;; ) */
+
+} /******* End of copy_ident( void ) ***********************************/
+
+
+void copy_text( void )
+/*************************************************************************
+
+ Description : запись во временный файл text_file
+ строк заключенных между %{ и %}
+
+ Concepts : в этих строках соментарии // заменяются на ANSI
+
+ Use Global Variable: char *cptr; | this file
+ char *line; | this file
+ char *line_format; | this file
+ int lineno; | main.c
+ mpu_FILE *text_file; | main.c
+ char *input_file_name; | main.c
+ char lflag; | main.c
+
+ Use Functions : void get_line (void); | this file
+ char * dup_line (void); | this file
+ void unterminated_text (int, char *, char *);
+ void unterminated_string (int, char *, char *);
+ void unterminated_comment (int, char *, char *);
+ | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c;
+ int quote;
+ register mpu_FILE *f = text_file;
+ /* в text_file пишем с помощью системных функций */
+ int need_newline = 0;
+ int t_lineno = lineno;
+ __mpu_char16_t *t_line = dup_line ();
+ __mpu_char16_t *t_cptr = t_line + (cptr - line - 2);
+
+ if( *cptr == '\n' )
+ {
+ get_line();
+ if( line == 0 ) unterminated_text( t_lineno, t_line, t_cptr );
+ }
+ if( !lflag ) mpu_fprintf( f, line_format, lineno, input_file_name );
+
+loop:
+
+
+ c = *cptr++;
+ switch( c )
+ {
+ case '\n':
+next_line:
+ mpu_putc( '\n', f );
+ need_newline = 0;
+ get_line();
+ if( line ) goto loop;
+ unterminated_text( t_lineno, t_line, t_cptr );
+
+ case '\'':
+ case '\"':
+ {
+ int s_lineno = lineno;
+ __mpu_char16_t *s_line = dup_line ();
+ __mpu_char16_t *s_cptr = s_line + (cptr - line - 1);
+
+ quote = c;
+ mpu_putc( c, f );
+ for( ;; )
+ {
+ c = *cptr++;
+ mpu_putc( c, f );
+ if( c == quote )
+ {
+ need_newline = 1;
+ FREE( s_line );
+ goto loop;
+ }
+ if( c == '\n' )
+ unterminated_string( s_lineno, s_line, s_cptr );
+ if( c == '\\' )
+ {
+ c = *cptr++;
+ mpu_putc( c, f );
+ if( c == '\n' )
+ {
+ get_line();
+ if( line == 0 )
+ unterminated_string( s_lineno, s_line, s_cptr );
+ }
+ }
+ } /* End of for (;;) */
+ }
+
+ case '/':
+ mpu_putc( c, f );
+ need_newline = 1;
+ c = *cptr;
+ if( c == '/' )
+ {
+ mpu_putc ( '*', f );
+ while( (c = *++cptr) != '\n' )
+ {
+ if( c == '*' && cptr[1] == '/' )
+ mpu_fprintf( f, MPU_UCS2( "* " ) );
+ else mpu_putc( c, f );
+ }
+ mpu_fprintf( f, MPU_UCS2( "*/" ) );
+ goto next_line;
+ }
+ if( c == '*' )
+ {
+ int c_lineno = lineno;
+ __mpu_char16_t *c_line = dup_line();
+ __mpu_char16_t *c_cptr = c_line + (cptr - line - 1);
+
+ mpu_putc( '*', f );
+ ++cptr;
+ for( ;; )
+ {
+ c = *cptr++;
+ mpu_putc( c, f );
+ if( c == '*' && *cptr == '/' )
+ {
+ mpu_putc( '/', f );
+ ++cptr;
+ FREE( c_line );
+ goto loop;
+ }
+ if( c == '\n' )
+ {
+ get_line();
+ if( line == 0 )
+ unterminated_comment( c_lineno, c_line, c_cptr );
+ }
+ } /* End of for (;;) */
+ }
+ need_newline = 1;
+ goto loop;
+
+
+ case '%':
+ case '\\':
+ if( *cptr == '}' )
+ {
+ if( need_newline ) mpu_putc( '\n', f );
+ ++cptr;
+ FREE( t_line );
+ return;
+ }
+ /* fall through */
+
+ default:
+ mpu_putc( c, f );
+ need_newline = 1;
+ goto loop;
+
+ } /* End of switch (c) */
+
+} /******* End of copy_text( void ) ************************************/
+
+
+void copy_union( void )
+/*************************************************************************
+
+ Description : запись во временный файл text_file
+ и if (dflag) в union_file директивы %union
+
+ ПРИМЕР:
+
+ %union {
+ int nVal;
+ double dVal;
+ }
+
+ запишется в text_file следующим образом
+
+ typedef union {
+ int nVal;
+ double dVal;
+ } ZUBR_STYPE;
+ при использовании префикса -B с параметром my_,
+ вывод будет таким
+ typedef union {
+ int nVal;
+ double dVal;
+ } MY_ZUBR_STYPE;
+
+
+ Concepts : comments // заменяются на ANSI
+
+ Use Global Variable: char *cptr; | this file
+ char *line; | this file
+ char *line_format; | this file
+ int lineno; | main.c
+ mpu_FILE *text_file; | main.c
+ mpu_FILE *union_file; | main.c
+ char *input_file_name; | main.c
+ char lflag; | main.c
+ char dflag; | main.c
+
+ Use Functions : void get_line (void); | this file
+ char * dup_line (void); | this file
+ void unterminated_text (int, char *, char *);
+ void over_unionized (char *);
+ void unterminated_union (int, char *, char *);
+ void unterminated_string (int, char *, char *);
+ void unterminated_comment (int, char *, char *);
+ | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c;
+ int quote;
+ int depth;
+ int u_lineno = lineno;
+ __mpu_char16_t *u_line = dup_line();
+ __mpu_char16_t *u_cptr = u_line + (cptr - line - 6);
+
+ if( unionized ) over_unionized( cptr - 6 );
+ unionized = 1;
+
+ if( !lflag ) mpu_fprintf( text_file,
+ line_format, lineno, input_file_name );
+
+ mpu_fprintf( text_file, MPU_UCS2( "typedef union" ) );
+ if( dflag ) mpu_fprintf( union_file, MPU_UCS2( "typedef union" ) );
+
+ depth = 0;
+
+loop:
+
+ c = *cptr++;
+ mpu_putc( c, text_file );
+ if( dflag ) mpu_putc( c, union_file );
+ switch( c )
+ {
+ case '\n':
+next_line:
+ get_line();
+ if( line == 0 ) unterminated_union( u_lineno, u_line, u_cptr );
+ goto loop;
+
+ case '{':
+ ++depth;
+ goto loop;
+
+ case '}':
+ if (--depth == 0)
+ {
+ if( bflag )
+ mpu_fprintf( text_file,
+ MPU_UCS2( " %sZUBR_STYPE;\n" ), name_prefix_upper );
+ else
+ mpu_fprintf( text_file, MPU_UCS2( " ZUBR_STYPE;\n" ) );
+
+ FREE( u_line );
+ return;
+ }
+ goto loop;
+
+ case '\'':
+ case '\"':
+ {
+ int s_lineno = lineno;
+ __mpu_char16_t *s_line = dup_line ();
+ __mpu_char16_t *s_cptr = s_line + (cptr - line - 1);
+
+ quote = c;
+ for( ;; )
+ {
+ c = *cptr++;
+ mpu_putc( c, text_file );
+ if( dflag ) mpu_putc( c, union_file );
+
+ if( c == quote )
+ {
+ FREE( s_line );
+ goto loop;
+ }
+ if( c == '\n' )
+ unterminated_string( s_lineno, s_line, s_cptr );
+ if( c == '\\' )
+ {
+ c = *cptr++;
+ mpu_putc( c, text_file );
+ if( dflag ) mpu_putc( c, union_file );
+ if( c == '\n' )
+ {
+ get_line();
+ if( line == 0 )
+ unterminated_string( s_lineno, s_line, s_cptr );
+ }
+ }
+ } /* End of for (;;) */
+ }
+
+ case '/':
+ c = *cptr;
+ if( c == '/' )
+ {
+ mpu_putc( '*', text_file );
+ if( dflag ) mpu_putc( '*', union_file );
+ while( (c = *++cptr) != '\n' )
+ {
+ if( c == '*' && cptr[1] == '/' )
+ {
+ mpu_fprintf( text_file, MPU_UCS2( "* " ) );
+ if( dflag ) mpu_fprintf( union_file, MPU_UCS2( "* " ) );
+ }
+ else
+ {
+ mpu_putc( c, text_file );
+ if( dflag ) mpu_putc( c, union_file );
+ }
+ } /* End of while ((c = *++cptr) != '\n') */
+ mpu_fprintf( text_file, MPU_UCS2( "*/\n" ) );
+ if( dflag ) mpu_fprintf( union_file, MPU_UCS2( "*/\n" ) );
+ goto next_line;
+ }
+ if( c == '*' )
+ {
+ int c_lineno = lineno;
+ __mpu_char16_t *c_line = dup_line();
+ __mpu_char16_t *c_cptr = c_line + (cptr - line - 1);
+
+ mpu_putc( '*', text_file );
+ if( dflag ) mpu_putc( '*', union_file );
+
+ ++cptr;
+ for( ;; )
+ {
+ c = *cptr++;
+ mpu_putc( c, text_file );
+ if( dflag ) mpu_putc( c, union_file );
+ if( c == '*' && *cptr == '/' )
+ {
+ mpu_putc( '/', text_file );
+ if( dflag ) mpu_putc( '/', union_file );
+ ++cptr;
+ FREE( c_line );
+ goto loop;
+ }
+ if( c == '\n' )
+ {
+ get_line();
+ if( line == 0 )
+ unterminated_comment( c_lineno, c_line, c_cptr );
+ }
+ } /* End of for (;;) */
+ }
+ goto loop;
+
+ default:
+ goto loop;
+
+ } /* End of switch (c) */
+
+} /******* End of copy_union( void ) ***********************************/
+
+
+int hexval( int c )
+/*************************************************************************
+
+ Description : return the digit value of the hex value
+
+ Concepts :
+
+ Use Global Variable:
+
+ Use Functions :
+
+ Parameters : int c
+
+ Return : int rc; if( rc = - 1 ) - error of parameter
+
+ *************************************************************************/
+{
+ if( c >= '0' && c <= '9' ) return( c - '0' );
+ if( c >= 'A' && c <= 'F' ) return( c - 'A' + 10 );
+ if( c >= 'a' && c <= 'f' ) return( c - 'a' + 10 );
+
+ return (-1);
+
+} /******* End of hexval( int c ) **************************************/
+
+
+bucket * get_literal( void )
+/*************************************************************************
+
+ Description : чтение литерала и запись его в symbol_table
+
+ Concepts : литерал окружен одинарными или двойными кавычками
+
+ Use Global Variable: char *cptr; | this file
+ char *line; | this file
+ int lineno; | main.c
+
+ Use Functions : void get_line (void); | this file
+ char * dup_line (void); | this file
+ void cachec (int c); | this file
+ bucket * lookup (char *name) | symtab.c
+ void no_space (void);
+ void illegal_character (char *);
+ void unterminated_string (int, char *, char *);
+ | error.c
+
+ Parameters : [void]
+
+ Return : bucket *bp
+
+ *************************************************************************/
+{
+ register int c, quote;
+ register int i;
+ register int n;
+ register __mpu_char16_t *s;
+ register bucket *bp;
+ int s_lineno = lineno;
+ __mpu_char16_t *s_line = dup_line ();
+ __mpu_char16_t *s_cptr = s_line + (cptr - line);
+
+ quote = *cptr++;
+ cinc = 0;
+ for( ;; )
+ {
+ c = *cptr++;
+ if( c == quote ) break;
+ if( c == '\n' )
+ unterminated_string( s_lineno, s_line, s_cptr );
+ if( c == '\\' )
+ {
+ __mpu_char16_t *c_cptr = cptr - 1;
+
+ c = *cptr++;
+ switch( c )
+ {
+ case '\n':
+ get_line();
+ if( line == 0 )
+ unterminated_string( s_lineno, s_line, s_cptr );
+ continue;
+
+ case '0': case '1': case '2':
+ case '3': case '4': case '5':
+ case '6': case '7':
+ n = c - '0';
+ for( i = 1; i < 6; ++i )
+ {
+ c = *cptr;
+ if( !IS_OCTAL(c) ) break;
+ n = (n << 3) + (c - '0');
+ ++cptr;
+ }
+ if( n == 0 || n > MAXCHAR || (n >= 0xd800 && n <= 0xdfff) )
+ illegal_character( c_cptr );
+ c = n;
+ break;
+
+ case 'x':
+ case 'X':
+ n = 0;
+ for( i = 0; i < 4; ++i )
+ {
+ c = *cptr++;
+ c = hexval( c );
+ if( c < 0 ) illegal_character( c_cptr );
+ n = (n << 4) + c;
+ }
+ if( n == 0 || n > MAXCHAR || (n >= 0xd800 && n <= 0xdfff) )
+ illegal_character( c_cptr );
+ c = n;
+ break;
+
+
+ case 'a': c = 7; break;
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'v': c = '\v'; break;
+ } /* End of switch (c) */
+ } /* End of if (c == '\\') */
+ cachec( c );
+
+ } /* End of for (;;) */
+ FREE( s_line );
+
+ n = cinc;
+ s = (__mpu_char16_t *)MALLOC( n * sizeof(__mpu_char16_t) );
+ if( s == 0 ) no_space();
+ memset( s, NUL, n * sizeof(__mpu_char16_t) );
+
+ for( i = 0; i < n; ++i ) s[i] = cache[i];
+
+ cinc = 0;
+ if( n == 1 ) cachec( '\'' );
+ else cachec( '\"' );
+
+ for( i = 0; i < n; ++i )
+ {
+ c = ((__mpu_char16_t *)s)[i];
+ if( c == '\\' || c == cache[0] )
+ {
+ cachec( '\\' );
+ cachec( c );
+ }
+ else if( zubr_is_print(c) ) cachec(c);
+ else
+ {
+ cachec( '\\' );
+ switch( c )
+ {
+ case 7: cachec( 'a' ); break;
+ case '\b': cachec( 'b' ); break;
+ case '\f': cachec( 'f' ); break;
+ case '\n': cachec( 'n' ); break;
+ case '\r': cachec( 'r' ); break;
+ case '\t': cachec( 't' ); break;
+ case '\v': cachec( 'v' ); break;
+ default:
+ cachec( ((c >> 15) & 7) + '0' );
+ cachec( ((c >> 12) & 7) + '0' );
+ cachec( ((c >> 9) & 7) + '0' );
+ cachec( ((c >> 6) & 7) + '0' );
+ cachec( ((c >> 3) & 7) + '0' );
+ cachec( ( c & 7) + '0' );
+ break;
+ } /* End of switch (c) */
+ } /* End if () */
+ } /* End of for (i = 0; i < n; ++i) */
+
+ if( n == 1 ) cachec( '\'' );
+ else cachec( '\"' );
+
+ cachec( NUL );
+ bp = lookup( cache );
+ bp->class = TERM;
+ if( n == 1 && bp->value == UNDEFINED )
+ bp->value = *(__mpu_char16_t *)s; /* or unsigned char */
+ FREE( s );
+
+ return( bp );
+
+} /* End of get_literal( void ) ****************************************/
+
+
+int is_reserved( __mpu_char16_t *name )
+/*************************************************************************
+
+ Description : это зарезервированное имя ? или нет
+
+ Concepts :
+
+ Use Global Variable:
+
+ Use Functions :
+
+ Parameters : char *name
+
+ Return : int rc // rc = 1; if its reserved name
+
+ *************************************************************************/
+{
+ __mpu_char16_t *s;
+
+ if( mpu_str16cmp( name, (__mpu_char16_t *)MPU_UCS2( "." ) ) == 0 ||
+ mpu_str16cmp( name, (__mpu_char16_t *)MPU_UCS2( "$accept" ) ) == 0 ||
+ mpu_str16cmp( name, (__mpu_char16_t *)MPU_UCS2( "$end" ) ) == 0 ) return( 1 );
+
+ if( name[0] == '$' && name[1] == '$' && zubr_is_digit(name[2]) )
+ {
+ s = name + 3;
+ while( zubr_is_digit(*s) ) ++s;
+ if( *s == NUL ) return( 1 );
+ }
+
+ return( 0 );
+
+} /******* End of is_reserved( char *name ) ****************************/
+
+
+bucket *get_name( void )
+/*************************************************************************
+
+ Description : чтение имени и запись его в symbol_table
+
+ Concepts :
+
+ Use Global Variable: char *cptr; | this file
+
+ Use Functions : void cachec (int c); | this file
+ int is_reserved (char *name); | this file
+ bucket * lookup (char *name) | symtab.c
+ void used_reserved (char *); | error.c
+
+ Parameters : [void]
+
+ Return : bucket *bp
+
+ *************************************************************************/
+{
+ register int c;
+
+ cinc = 0;
+ for( c = *cptr; IS_IDENT (c); c = *++cptr ) cachec( c );
+ cachec( NUL );
+
+ if( is_reserved( cache ) ) used_reserved( cache );
+
+ return( lookup( cache ) );
+
+} /******* End of get_name( void ) *************************************/
+
+
+int get_number( void )
+/*************************************************************************
+
+ Description : get number
+
+ Concepts :
+
+ Use Global Variable: char *cptr; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : int n
+
+ *************************************************************************/
+{
+ register int c;
+ register int n;
+
+ n = 0;
+ for( c = *cptr; zubr_is_digit(c); c = *++cptr )
+ n = 10*n + (c - '0' );
+
+ return( n );
+
+} /******* End of get_number( void ) ***********************************/
+
+
+__mpu_char16_t *get_tag( void )
+/*************************************************************************
+
+ Description : чтение тега (слова заключенного между '<' и '>')
+ и запись его в таблицу тегов (tag_table)
+
+ Concepts :
+
+ Use Global Variable: char *cptr; | this file
+ char *line; | this file
+ char **tag_table; | this file
+ int ntags; | this file
+ int tagmax; | this file
+ int lineno; | main.c
+
+ Use Functions : void get_line (void); | this file
+ char * dup_line (void); | this file
+ void cachec (int c); | this file
+ int nextc (void); | this file
+ void no_space (void);
+ void illegal_tag (int, char *, char *);
+ void unexpected_EOF (void); | error.c
+
+ Parameters : [void]
+
+ Return : char *s
+
+ *************************************************************************/
+{
+ register int c;
+ register int i;
+ register __mpu_char16_t *s;
+ int t_lineno = lineno;
+ __mpu_char16_t *t_line = dup_line();
+ __mpu_char16_t *t_cptr = t_line + (cptr - line);
+
+ ++cptr;
+ c = nextc();
+ if( c == mpu_EOF) unexpected_EOF();
+ if( !zubr_is_alpha(c) && c != '_' && c != '$' )
+ illegal_tag( t_lineno, t_line, t_cptr );
+
+ cinc = 0;
+ do { cachec(c); c = *++cptr; } while( IS_IDENT(c) );
+ cachec( NUL );
+
+ c = nextc();
+ if( c == mpu_EOF ) unexpected_EOF ();
+ if( c != '>' ) illegal_tag( t_lineno, t_line, t_cptr );
+ ++cptr;
+
+ for( i = 0; i < ntags; ++i )
+ {
+ if( mpu_str16cmp( cache, tag_table[i] ) == 0 )
+ {
+ FREE( t_line );
+ return( tag_table[i] );
+ }
+ }
+
+ if( ntags >= tagmax )
+ {
+ tagmax += 16;
+ tag_table = (__mpu_char16_t **)
+ (tag_table ? REALLOC( tag_table, tagmax*sizeof(__mpu_char16_t *))
+ : MALLOC( tagmax*sizeof(__mpu_char16_t *)));
+ if( tag_table == 0 ) no_space();
+ }
+
+ s = (__mpu_char16_t *) MALLOC( cinc * sizeof(__mpu_char16_t) );
+ if( s == 0 ) no_space();
+ memset( s, NUL, cinc * sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( s, cache );
+ tag_table[ntags] = s;
+ ++ntags;
+ FREE( t_line );
+ return( s );
+
+} /******* End of get_tag( void ) **************************************/
+
+
+void declare_tokens( int assoc )
+/*************************************************************************
+
+ Description : declare tokens
+
+ Concepts : функции get_name() и get_literal() заносят
+ прочитанные имена и литералы в symbol_table
+
+ Use Global Variable: bucked *goal; | this file
+ int prec; | this file
+
+ Use Functions : int nextc (void); | this file
+ char * get_tag (void); | this file
+ bucked * get_name (void); | this file
+ bucked * get_literal (void); | this file
+ int get_number (void); | this file
+ void no_space (void);
+ void tokenized_start (char *);
+ void retyped_warning (char *);
+ void reprec_warning (char *);
+ void revalued_warning (char *);
+ void unexpected_EOF (void); | error.c
+
+ Parameters : int assoc
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c;
+ register bucket *bp;
+ int value;
+ __mpu_char16_t *tag = 0;
+
+ if( assoc != TOKEN ) ++prec;
+
+ c = nextc();
+ if( c == mpu_EOF ) unexpected_EOF();
+ if( c == '<' )
+ {
+ tag = get_tag();
+ c = nextc();
+ if( c == mpu_EOF ) unexpected_EOF();
+ }
+
+ for( ;; )
+ {
+ if( zubr_is_alpha(c) ||
+ c == '_' || c == '.' || c == '$' )
+ bp = get_name();
+ else if (c == '\'' || c == '\"' ) bp = get_literal();
+ else
+ return;
+
+ if( bp == goal ) tokenized_start( bp->name );
+ bp->class = TERM;
+
+ if( tag )
+ {
+ if( bp->tag && tag != bp->tag ) retyped_warning( bp->name );
+ bp->tag = tag;
+ }
+
+ if( assoc != TOKEN )
+ {
+ if( bp->prec && prec != bp->prec ) reprec_warning( bp->name );
+ bp->assoc = assoc;
+ bp->prec = prec;
+ }
+
+ c = nextc();
+ if( c == mpu_EOF ) unexpected_EOF();
+ value = UNDEFINED;
+ if( zubr_is_digit(c) )
+ {
+ value = get_number();
+ if( bp->value != UNDEFINED && value != bp->value )
+ revalued_warning( bp->name );
+ bp->value = value;
+ c = nextc();
+ if( c == mpu_EOF ) unexpected_EOF();
+ }
+ } /* End of for( ;; ) */
+
+} /******* End of declare_tokens( int assoc ) **************************/
+
+
+void declare_types( void )
+/*************************************************************************
+
+ Description : declare types
+
+ Concepts : функция get_tag() заносит прочитанные теги
+ в tag_table
+ функции get_name() и get_literal() заносят
+ прочитанные имена и литералы в symbol_table
+
+ Use Global Variable: char *cptr; | this file
+ char *line; | this file
+ int lineno; | main.c
+
+ Use Functions : int nextc (void); | this file
+ char * get_tag (void); | this file
+ bucked * get_name (void); | this file
+ bucked * get_literal (void); | this file
+ void syntax_error (int, char *, char *);
+ void retyped_warning (char *);
+ void unexpected_EOF (void); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c;
+ register bucket *bp;
+ __mpu_char16_t *tag;
+
+ c = nextc();
+ if( c == mpu_EOF ) unexpected_EOF();
+ if( c != '<' ) syntax_error( lineno, line, cptr );
+ tag = get_tag();
+
+ for( ;; )
+ {
+ c = nextc();
+ if( zubr_is_alpha(c) || c == '_' ||
+ c == '.' || c == '$' ) bp = get_name();
+ else if( c == '\'' || c == '\"' ) bp = get_literal();
+ else
+ return;
+
+ if( bp->tag && tag != bp->tag ) retyped_warning( bp->name );
+ bp->tag = tag;
+ }
+
+} /******* End of declare_types( void ) ********************************/
+
+
+void declare_start( void )
+/*************************************************************************
+
+ Description : declare start
+
+ Concepts : функция get_name() заносит прочитанные имена
+ в symbol_table
+
+ Use Global Variable: bucked * goal; | this file
+ char *cptr; | this file
+ char *line; | this file
+ int lineno; | main.c
+
+ Use Functions : int nextc (void); | this file
+ bucked * get_name (void); | this file
+ void syntax_error (int, char *, char *);
+ void terminal_start (char *);
+ void restarted_warning (void);
+ void unexpected_EOF (void); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c;
+ register bucket *bp;
+
+ c = nextc();
+ if( c == mpu_EOF ) unexpected_EOF();
+ if( !zubr_is_alpha(c) &&
+ c != '_' && c != '.' && c != '$' )
+ syntax_error( lineno, line, cptr );
+
+ bp = get_name();
+ if( bp->class == TERM ) terminal_start( bp->name );
+ if( goal && goal != bp ) restarted_warning();
+ goal = bp;
+
+} /******* End of declare_start( void ) ********************************/
+
+
+void read_declarations( void )
+/*************************************************************************
+
+ Description :
+
+ Concepts :
+
+ Use Global Variable: char *cptr; | this file
+ char *line; | this file
+ int lineno; | main.c
+
+ Use Functions : int nextc (void); | this file
+ int keyword (void); | this file
+ void copy_ident (void); | this file
+ void copy_text (void); | this file
+ void copy_union (void); | this file
+ void declare_tokens (int k); | this file
+ void declare_types (void); | this file
+ void declare_start (void); | this file
+ void syntax_error (int, char *, char *);
+ void no_space (void);
+ void unexpected_EOF (void); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c, k;
+
+ cache_size = 256;
+ cache = (__mpu_char16_t *)MALLOC( cache_size * sizeof(__mpu_char16_t) );
+ if( cache == 0 ) no_space();
+
+ for( ;; )
+ {
+ c = nextc();
+ if( c == mpu_EOF ) unexpected_EOF();
+ if( c != '%' ) syntax_error( lineno, line, cptr );
+ switch( k = keyword() )
+ {
+ case MARK:
+ return;
+
+ case IDENT:
+ copy_ident();
+ break;
+
+ case TEXT:
+ copy_text();
+ break;
+
+ case UNION:
+ copy_union();
+ break;
+
+ case TOKEN:
+ case LEFT:
+ case RIGHT:
+ case NONASSOC:
+ declare_tokens( k );
+ break;
+
+ case TYPE:
+ declare_types();
+ break;
+
+ case START:
+ declare_start();
+ break;
+ } /* End of switch( k ) */
+ } /* End of for( ;; ) */
+
+} /******* End of read_declarations( void ) ****************************/
+
+
+void initialize_grammar( void )
+/*************************************************************************
+
+ Description : initialize grammar
+
+ Concepts :
+
+ Use Global Variable: int maxitems; | this file
+ int maxrules; | this file
+ bucket **pitem; | this file
+ bucket **plhs; | this file
+ int nitems; | main.c
+ int nrules; | main.c
+ int *rprec; | main.c
+ char *rassoc; | main.c
+
+ Use Functions : void no_space (void); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ nitems = 4;
+ maxitems = 300;
+ pitem = (bucket **)MALLOC( maxitems*sizeof(bucket *) );
+ if( pitem == 0 ) no_space();
+ pitem[0] = 0;
+ pitem[1] = 0;
+ pitem[2] = 0;
+ pitem[3] = 0;
+
+ nrules = 3;
+ maxrules = 100;
+ plhs = (bucket **)MALLOC( maxrules*sizeof(bucket *) );
+ if( plhs == 0 ) no_space();
+ plhs[0] = 0;
+ plhs[1] = 0;
+ plhs[2] = 0;
+ rprec = (int *)MALLOC( maxrules*sizeof(int) );
+ if( rprec == 0 ) no_space();
+ rprec[0] = 0;
+ rprec[1] = 0;
+ rprec[2] = 0;
+ rassoc = (char *)MALLOC( maxrules*sizeof(char) );
+ if( rassoc == 0 ) no_space();
+ rassoc[0] = TOKEN;
+ rassoc[1] = TOKEN;
+ rassoc[2] = TOKEN;
+
+} /******* End of initialize_grammar( void ) ***************************/
+
+
+void expand_items( void )
+/*************************************************************************
+
+ Description : expand items
+
+ Concepts :
+
+ Use Global Variable: int maxitems; | this file
+ bucket **pitem; | this file
+
+ Use Functions : void no_space (void); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ maxitems += 300;
+
+ pitem = (bucket **)REALLOC( pitem, maxitems*sizeof(bucket *) );
+ if( pitem == 0 ) no_space();
+
+} /******* End of expand_items( void ) *********************************/
+
+
+void expand_rules( void )
+/*************************************************************************
+
+ Description : expand rules
+
+ Concepts :
+
+ Use Global Variable: int maxrules; | this file
+ bucket **plhs; | this file
+ int *rprec; | main.c
+ char *rassoc; | main.c
+
+ Use Functions : void no_space (void); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ maxrules += 100;
+
+ plhs = (bucket **)REALLOC( plhs, maxrules*sizeof(bucket *) );
+ if( plhs == 0 ) no_space();
+
+ rprec = (int *)REALLOC( rprec, maxrules*sizeof(int) );
+ if( rprec == 0 ) no_space();
+
+ rassoc = (char *)REALLOC( rassoc, maxrules*sizeof(char) );
+ if( rassoc == 0 ) no_space();
+
+} /******* End of expand_rules( void ) *********************************/
+
+
+void start_rule( bucket *bp, int s_lineno )
+/*************************************************************************
+
+ Description : start rule
+
+ Concepts :
+
+ Use Global Variable: int maxrules; | this file
+ bucket **plhs; | this file
+ int nrules; | main.c
+ int *rprec; | main.c
+ char *rassoc; | main.c
+
+ Use Functions : void expand_rules (void); | this file
+ void terminal_lhs (int s_lineno); | error.c
+
+ Parameters : bucked *bp, int s_lineno
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ if( bp->class == TERM ) terminal_lhs( s_lineno );
+ bp->class = NONTERM;
+ if( nrules >= maxrules ) expand_rules();
+ plhs[nrules] = bp;
+ rprec[nrules] = UNDEFINED;
+ rassoc[nrules] = TOKEN;
+
+} /******* End of start_rule( bucket *bp, int s_lineno ) ***************/
+
+
+void end_rule( void )
+/*************************************************************************
+
+ Description : end rule
+
+ Concepts :
+
+ Use Global Variable: int maxitems; | this file
+ char last_was_action; | this file
+ bucket **plhs; | this file
+ bucket **pitem; | this file
+ int nitems; | main.c
+ int nrules; | main.c
+
+ Use Functions : void expand_items (void); | this file
+ void default_action_warning (void); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i;
+
+ if( !last_was_action && plhs[nrules]->tag )
+ {
+ for( i = nitems - 1; pitem[i]; --i ) continue;
+ if( pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag )
+ default_action_warning();
+ }
+
+ last_was_action = 0;
+ if( nitems >= maxitems ) expand_items();
+ pitem[nitems] = 0;
+ ++nitems;
+ ++nrules;
+
+} /******* End of end_rule( void ) *************************************/
+
+
+void advance_to_start( void )
+/*************************************************************************
+
+ Description : advance to start
+
+ Concepts :
+
+ Use Global Variable: char *cptr; | this file
+ char *line; | this file
+ bucked * goal; | this file
+ int lineno; | main.c
+
+ Use Functions : int nextc (void); | this file
+ int keyword (void); | this file
+ bucked * get_name (void); | this file
+ void copy_text (void); | this file
+ void declare_start (void); | this file
+ void start_rule (bucket *, int); | this file
+ void syntax_error (int, char *, char *);
+ void no_grammar (void); | error.c
+ void terminal_start (char *); | error.c
+ void unexpected_EOF (void); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c;
+ register bucket *bp;
+ __mpu_char16_t *s_cptr;
+ int s_lineno;
+
+ for( ;; )
+ {
+ c = nextc();
+ if( c != '%' ) break;
+ s_cptr = cptr;
+ switch( keyword() )
+ {
+ case MARK:
+ no_grammar();
+
+ case TEXT:
+ copy_text();
+ break;
+
+ case START:
+ declare_start();
+ break;
+
+ default:
+ syntax_error( lineno, line, s_cptr );
+ } /* End of swith (keyword ()) */
+ } /* End of for (;;) */
+
+ c = nextc();
+ if( !zubr_is_alpha(c) &&
+ c != '_' && c != '.' && c != '_' )
+ syntax_error( lineno, line, cptr );
+ bp = get_name();
+ if( goal == 0 )
+ {
+ if( bp->class == TERM )
+ terminal_start( bp->name );
+ goal = bp;
+ }
+
+ s_lineno = lineno;
+ c = nextc();
+ if( c == mpu_EOF) unexpected_EOF();
+ if( c != ':') syntax_error( lineno, line, cptr );
+ start_rule( bp, s_lineno );
+ ++cptr;
+
+} /******* End of advance_to_start( void ) *****************************/
+
+
+void insert_empty_rule( void )
+/*************************************************************************
+
+ Description : insert empty rule
+
+ Concepts :
+
+ Use Global Variable: int gensym; | this file
+ char *cache; | this file
+ int maxitems; | this file
+ int maxrules; | this file
+ bucket **pitem; | this file
+ bucket **plhs; | this file
+ int nitems; | main.c
+ int nrules; | main.c
+ int *rprec; | main.c
+ char *rassoc; | main.c
+ bucked *last_symbol; | symtab.c
+
+ Use Functions : void expand_rules (void); | this file
+ void expand_items (void); | this file
+ bucket * make_bucket (char *name); | symtab.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register bucket *bp, **bpp;
+
+ if( !cache )
+ {
+ done( 2 );
+ }
+ mpu_sprintf( cache, MPU_UCS2( "$$%d" ), ++gensym );
+ bp = make_bucket( cache );
+ last_symbol->next = bp;
+ last_symbol = bp;
+ bp->tag = plhs[nrules]->tag;
+ bp->class = NONTERM;
+
+ if( (nitems += 2) > maxitems ) expand_items();
+ bpp = pitem + nitems - 1;
+ *bpp-- = bp;
+ while( (bpp[0] = bpp[-1]) ) --bpp;
+
+ if( ++nrules >= maxrules ) expand_rules();
+ plhs[nrules] = plhs[nrules-1];
+ plhs[nrules-1] = bp;
+ rprec[nrules] = rprec[nrules-1];
+ rprec[nrules-1] = 0;
+ rassoc[nrules] = rassoc[nrules-1];
+ rassoc[nrules-1] = TOKEN;
+
+} /******* End of insert_empty_rule( void ) ****************************/
+
+
+void add_symbol( void )
+/*************************************************************************
+
+ Description : add symbol
+
+ Concepts :
+
+ Use Global Variable: char last_was_action; | this file
+ int maxitems; | this file
+ bucket **pitem; | this file
+ char *cptr; | this file
+ int lineno; | main.c
+ int nitems; | main.c
+
+ Use Functions : int nextc (void); | this file
+ bucket * get_literal (void); | this file
+ bucket * get_name (void); | this file
+ void start_rule (bucket *, int); | this file
+ void end_rule (void); | this file
+ void insert_empty_rule (void); | this file
+ void expand_items (void); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c;
+ register bucket *bp;
+ int s_lineno = lineno;
+
+ c = *cptr;
+ if( c == '\'' || c == '\"' ) bp = get_literal();
+ else bp = get_name();
+
+ c = nextc();
+ if( c == ':' )
+ {
+ end_rule();
+ start_rule( bp, s_lineno );
+ ++cptr;
+ return;
+ }
+
+ if( last_was_action ) insert_empty_rule();
+ last_was_action = 0;
+
+ if( ++nitems > maxitems ) expand_items();
+ pitem[nitems-1] = bp;
+
+} /******* End of add_symbol( void ) ***********************************/
+
+
+void copy_action( void )
+/*************************************************************************
+
+ Description : copy action
+
+ Concepts :
+
+ Use Global Variable: char *lile_format; | this file
+ char last_was_action; | this file
+ bucked **pitem; | this file
+ bucked **plhs; | this file
+ int ntags; | this file
+ char *cptr; | this file
+ char *line; | this file
+ int lineno; | main.c
+ int nitems; | main.c
+ int nrules; | main.c
+ mpu_FILE *action_file; | main.c
+ char *input_file_name; | main.c
+ char lflag; | main.c
+
+ Use Functions : char *dup_line (void); | this file
+ void get_line (void); | this file
+ char * get_tag (void); | this file
+ int get_number (void); | this file
+ void insert_empty_rule (void); | this file
+
+ void dollar_warning (int, int);
+ void dollar_error (int, char *, char *);
+ void untyped_lhs (void);
+ void untyped_rhs (int, char *);
+ void unknown_rhs (int);
+ void unterminated_action (int, char *, char *);
+ void unterminated_string (int, char *, char *);
+ void unterminated_comment (int, char *, char *);
+ | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c;
+ register int i, n;
+ int depth;
+ int quote;
+ __mpu_char16_t *tag;
+ register mpu_FILE *f = action_file;
+ int a_lineno = lineno;
+ __mpu_char16_t *a_line = dup_line ();
+ __mpu_char16_t *a_cptr = a_line + (cptr - line);
+
+ if( last_was_action ) insert_empty_rule();
+ last_was_action = 1;
+
+ mpu_fprintf( f, MPU_UCS2( " case %d:\n" ), nrules - 2 );
+ if( !lflag ) mpu_fprintf( f, line_format, lineno, input_file_name );
+ mpu_fprintf( f, MPU_UCS2( " " ) ); /* на уровне case */
+
+ if( *cptr == '=' ) ++cptr;
+
+ n = 0;
+ for( i = nitems - 1; pitem[i]; --i ) ++n;
+
+ depth = 0;
+
+loop:
+
+ c = *cptr;
+ if( c == '$' )
+ {
+ if( cptr[1] == '<' )
+ {
+ int d_lineno = lineno;
+ __mpu_char16_t *d_line = dup_line();
+ __mpu_char16_t *d_cptr = d_line + (cptr - line);
+
+ ++cptr;
+ tag = get_tag();
+ c = *cptr;
+ if( c == '$' )
+ {
+ if( bflag )
+ mpu_fprintf( f, MPU_UCS2( "%szubr_val.%s" ), name_prefix, tag );
+ else
+ mpu_fprintf( f, MPU_UCS2( "zubr_val.%s" ), tag );
+
+ ++cptr;
+ FREE( d_line );
+ goto loop;
+ }
+ else if( zubr_is_digit(c) )
+ {
+ i = get_number();
+ if( i > n ) dollar_warning( d_lineno, i );
+
+ if( bflag )
+ mpu_fprintf( f, MPU_UCS2( "%szubr_vsp[%d].%s" ),
+ name_prefix, i - n, tag );
+ else
+ mpu_fprintf( f, MPU_UCS2( "zubr_vsp[%d].%s" ), i - n, tag );
+
+ FREE( d_line );
+ goto loop;
+ }
+
+ else if( c == '-' && zubr_is_digit(cptr[1]) )
+ {
+ ++cptr;
+ i = -get_number() - n;
+
+ if( bflag )
+ mpu_fprintf( f, MPU_UCS2( "%szubr_vsp[%d].%s" ),
+ name_prefix, i, tag);
+ else
+ mpu_fprintf( f, MPU_UCS2( "zubr_vsp[%d].%s" ),
+ i, tag );
+
+ FREE( d_line );
+ goto loop;
+ }
+ else dollar_error( d_lineno, d_line, d_cptr );
+ }
+
+ else if( cptr[1] == '$' )
+ {
+ if( ntags )
+ {
+ tag = plhs[nrules]->tag;
+ if( tag == 0 ) untyped_lhs();
+
+ if( bflag )
+ mpu_fprintf( f, MPU_UCS2( "%szubr_val.%s" ),
+ name_prefix, tag );
+ else
+ mpu_fprintf( f, MPU_UCS2( "zubr_val.%s" ), tag );
+ }
+ else
+ {
+ if( bflag )
+ mpu_fprintf( f, MPU_UCS2( "%szubr_val" ), name_prefix );
+ else
+ mpu_fprintf( f, MPU_UCS2( "zubr_val" ) );
+ }
+
+ cptr += 2;
+ goto loop;
+ }
+ else if( zubr_is_digit(cptr[1]) )
+ {
+ ++cptr;
+ i = get_number();
+ if( ntags )
+ {
+ if( i <= 0 || i > n ) unknown_rhs( i );
+ tag = pitem[nitems + i - n - 1]->tag;
+ if( tag == 0 )
+ untyped_rhs( i,
+ pitem[nitems + i - n - 1]->name );
+
+ if( bflag )
+ mpu_fprintf( f, MPU_UCS2( "%szubr_vsp[%d].%s" ),
+ name_prefix, i - n, tag );
+ else
+ mpu_fprintf( f, MPU_UCS2( "zubr_vsp[%d].%s" ),
+ i - n, tag );
+ }
+ else
+ {
+ if( i > n ) dollar_warning( lineno, i );
+
+ if( bflag )
+ mpu_fprintf( f, MPU_UCS2( "%szubr_vsp[%d]" ),
+ name_prefix, i - n );
+ else
+ mpu_fprintf( f, MPU_UCS2( "zubr_vsp[%d]" ), i - n );
+ }
+ goto loop;
+ }
+ else if( cptr[1] == '-' )
+ {
+ cptr += 2;
+ i = get_number();
+ if( ntags ) unknown_rhs( -i );
+
+ if( bflag )
+ mpu_fprintf( f, MPU_UCS2( "%szubr_vsp[%d]" ),
+ name_prefix, -i - n );
+ else
+ mpu_fprintf( f, MPU_UCS2( "zubr_vsp[%d]" ),
+ -i - n );
+
+ goto loop;
+ }
+ } /* End if( c == '$' ) */
+
+ if( zubr_is_alpha(c) || c == '_' || c == '$' )
+ {
+ do
+ {
+ mpu_putc( c, f );
+ c = *++cptr;
+ } while( zubr_is_alnum(c) || c == '_' || c == '$' );
+ goto loop;
+ }
+ mpu_putc( c, f );
+
+ ++cptr;
+ switch( c )
+ {
+ case '\n':
+next_line:
+ get_line();
+ if( line ) goto loop;
+ unterminated_action( a_lineno, a_line, a_cptr );
+
+ case ';':
+ if( depth > 0 ) goto loop;
+ mpu_fprintf( f, MPU_UCS2( "\n break;\n" ) );
+ FREE( a_line );
+ return;
+
+ case '{':
+ ++depth;
+ goto loop;
+
+ case '}':
+ if( --depth > 0 ) goto loop;
+ mpu_fprintf( f, MPU_UCS2( "\n break;\n" ) );
+ FREE( a_line );
+ return;
+
+ case '\'':
+ case '\"':
+ {
+ int s_lineno = lineno;
+ __mpu_char16_t *s_line = dup_line();
+ __mpu_char16_t *s_cptr = s_line + (cptr - line - 1);
+ quote = c;
+ for( ;; )
+ {
+ c = *cptr++;
+ mpu_putc( c, f );
+ if( c == quote )
+ {
+ FREE( s_line );
+ goto loop;
+ }
+ if( c == '\n' )
+ unterminated_string( s_lineno, s_line, s_cptr );
+ if( c == '\\' )
+ {
+ c = *cptr++;
+ mpu_putc( c, f );
+ if( c == '\n' )
+ {
+ get_line();
+ if( line == 0 )
+ unterminated_string( s_lineno, s_line, s_cptr );
+ }
+ }
+ } /* End of for( ;; ) */
+ }
+
+ case '/':
+ c = *cptr;
+ if( c == '/' )
+ {
+ mpu_putc( '*', f );
+ while( (c = *++cptr) != '\n' )
+ {
+ if( c == '*' && cptr[1] == '/' )
+ mpu_fprintf( f, MPU_UCS2( "* " ) );
+ else mpu_putc( c, f );
+ }
+ mpu_fprintf( f, MPU_UCS2( "*/\n" ) );
+ goto next_line;
+ }
+ if( c == '*' )
+ {
+ int c_lineno = lineno;
+ __mpu_char16_t *c_line = dup_line();
+ __mpu_char16_t *c_cptr = c_line + (cptr - line - 1);
+
+ mpu_putc( '*', f );
+ ++cptr;
+ for( ;; )
+ {
+ c = *cptr++;
+ mpu_putc( c, f );
+ if( c == '*' && *cptr == '/' )
+ {
+ mpu_putc( '/', f );
+ ++cptr;
+ FREE( c_line );
+ goto loop;
+ }
+ if( c == '\n' )
+ {
+ get_line();
+ if( line == 0 )
+ unterminated_comment( c_lineno, c_line, c_cptr );
+ }
+ } /* End of for( ;; ) */
+ } /* End if( c == '*' ) */
+ goto loop;
+
+ default:
+ goto loop;
+ } /* End of switch( c ) */
+
+} /****** End of copy_action( void ) ***********************************/
+
+
+int mark_symbol( void )
+/*************************************************************************
+
+ Description : mark symbol
+
+ Concepts :
+
+ Use Global Variable: char *cptr; | this file
+ char *line; | this file
+ int lineno; | main.c
+ int *rprec; | main.c
+ char *rassoc; | main.c
+ int nrules; | main.c
+
+ Use Functions : int nextc (void); | this file
+ bucket * get_literal (void); | this file
+ bucket * get_name (void); | this file
+
+ void syntax_error (int, char *, char *);
+ void prec_redeclared (void); | error.c
+
+ Parameters : [void]
+
+ Return : int
+
+ *************************************************************************/
+{
+ register int c;
+ register bucket *bp = NULL;
+
+ c = cptr[1];
+ if( c == '%' || c == '\\' )
+ {
+ cptr += 2;
+ return( 1 );
+ }
+
+ if( c == '=' ) cptr += 2;
+ else if( (c == 'p' || c == 'P') &&
+ ((c = cptr[2]) == 'r' || c == 'R') &&
+ ((c = cptr[3]) == 'e' || c == 'E') &&
+ ((c = cptr[4]) == 'c' || c == 'C') &&
+ ((c = cptr[5], !IS_IDENT(c) ))) cptr += 5;
+ else syntax_error( lineno, line, cptr );
+
+ c = nextc();
+ if( zubr_is_alpha(c) || c == '_' ||
+ c == '.' || c == '$' ) bp = get_name();
+ else if( c == '\'' || c == '\"' ) bp = get_literal();
+ else
+ {
+ syntax_error( lineno, line, cptr );
+ /*NOTREACHED*/
+ }
+
+ if( rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules] )
+ prec_redeclared();
+
+ rprec[nrules] = bp->prec;
+ rassoc[nrules] = bp->assoc;
+
+ return( 0 );
+
+} /******* End of mark_symbol( void ) **********************************/
+
+
+void read_grammar( void )
+/*************************************************************************
+
+ Description : read grammar
+
+ Concepts :
+
+ Use Global Variable: char *cptr; | this file
+ char *line; | this file
+ int lineno; | main.c
+
+ Use Functions : int nextc (void); | this file
+ void initialize_grammar (void); | this file
+ void advance_to_start (void); | this file
+ void add_symbol (void); | this file
+ void copy_action (void); | this file
+ void end_rule (void); | this file
+ void start_rule (bucket *, int); | this file
+ int mark_symbol (void); | this file
+
+ void syntax_error (int, char *, char *);
+ | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int c;
+
+ initialize_grammar();
+ advance_to_start();
+ for( ;; )
+ {
+ c = nextc();
+ if (c == mpu_EOF) break;
+ if( zubr_is_alpha(c) || c == '_' ||
+ c == '.' || c == '$' ||
+ c == '\'' || c == '\"' ) add_symbol();
+ else if( c == '{' || c == '=' ) copy_action();
+ else if( c == '|' )
+ {
+ end_rule();
+ start_rule( plhs[nrules-1], 0 );
+ ++cptr;
+ }
+ else if( c == '%' )
+ { if( mark_symbol() ) break; }
+ else syntax_error( lineno, line, cptr );
+ } /* End of for( ;; ) */
+ end_rule();
+
+} /******* End of read_grammar( void ) *********************************/
+
+
+void free_tags( void )
+/*************************************************************************
+
+ Description : free tags
+
+ Concepts :
+
+ Use Global Variable: int ntags; | this file
+ char **tag_table; | this file
+ int lineno; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i;
+
+ if( tag_table == 0 ) return;
+
+ for( i = 0; i < ntags; ++i )
+ {
+ if( !tag_table[i] )
+ {
+ done( 2 );
+ }
+ FREE( tag_table[i] );
+ }
+ FREE( tag_table );
+
+} /******* End of free_tags( void ) ************************************/
+
+
+void pack_names( void )
+/*************************************************************************
+
+ Description : pack names
+
+ Concepts :
+
+ Use Global Variable: int name_pool_size; | this file
+ char *name_pool; | this file
+ bucket *first_symbol; | symtab.c
+
+ Use Functions : void no_space (void); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register bucket *bp;
+ register __mpu_char16_t *p, *s, *t;
+
+ name_pool_size = 13; /* 13 == sizeof(u"$end") + sizeof(u"$accept") */
+
+ for( bp = first_symbol; bp; bp = bp->next )
+ name_pool_size += mpu_str16len( bp->name ) + 1;
+
+ name_pool = (__mpu_char16_t *)MALLOC( name_pool_size *
+ sizeof(__mpu_char16_t) );
+ if( name_pool == 0 ) no_space();
+ memset( name_pool, NUL, name_pool_size *
+ sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( name_pool, (__mpu_char16_t *)MPU_UCS2( "$accept" ) );
+ mpu_str16cpy( name_pool+8, (__mpu_char16_t *)MPU_UCS2( "$end" ) );
+ t = name_pool + 13;
+ for( bp = first_symbol; bp; bp = bp->next )
+ {
+ p = t;
+ s = bp->name;
+ while( (*t++ = *s++) ) continue;
+ FREE( bp->name );
+ bp->name = p;
+ }
+
+} /******* End of pack_names( void ) ***********************************/
+
+
+void check_symbols( void )
+/*************************************************************************
+
+ Description : check symbols
+
+ Concepts :
+
+ Use Global Variable: bucket *goal; | this file
+ bucket *first_symbol; | symtab.c
+
+ Use Functions : void undefined_symbol_warning (char *);
+ void undefined_goal (char *); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register bucket *bp;
+
+ if( goal->class == UNKNOWN ) undefined_goal( goal->name );
+
+ for( bp = first_symbol; bp; bp = bp->next )
+ {
+ if( bp->class == UNKNOWN )
+ {
+ undefined_symbol_warning( bp->name );
+ bp->class = TERM;
+ }
+ }
+
+} /******* End of check_symbols( void ) ********************************/
+
+
+void pack_symbols( void )
+/*************************************************************************
+
+ Description : pack symbols
+
+ Concepts :
+
+ Use Global Variable: bucket *goal; | this file
+ char *name_pool; | this file
+ bucket *first_symbol; | symtab.c
+ int nvars; | main.c
+ int nsyms; | main.c
+ int ntokens; | main.c
+ int start_symbol; | main.c
+ char **symbol_name; | main.c
+ int *symbol_value; | main.c
+ int *symbol_prec; | main.c
+ char *symbol_assoc; | main.c
+
+ Use Functions : void no_space (void); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register bucket *bp;
+ register bucket **v;
+ register int i, j, k, n;
+
+ nsyms = 2;
+ ntokens = 1;
+ for( bp = first_symbol; bp; bp = bp->next )
+ {
+ ++nsyms;
+ if( bp->class == TERM ) ++ntokens;
+ }
+ start_symbol = ntokens;
+ nvars = nsyms - ntokens;
+
+ symbol_name = (__mpu_char16_t **) MALLOC( nsyms*sizeof(__mpu_char16_t *) );
+ if( symbol_name == 0 ) no_space();
+ symbol_value = (int *)MALLOC( nsyms*sizeof(int) );
+ if( symbol_value == 0 ) no_space();
+ symbol_prec = (int *)MALLOC( nsyms*sizeof(int) );
+ if( symbol_prec == 0 ) no_space();
+ symbol_assoc = (char *)MALLOC( nsyms );
+ if( symbol_assoc == 0 ) no_space();
+
+ v = (bucket **)MALLOC( nsyms*sizeof(bucket *) );
+ if( v == 0 ) no_space();
+
+
+ v[0] = 0;
+ v[start_symbol] = 0;
+
+ i = 1;
+ j = start_symbol + 1;
+ for( bp = first_symbol; bp; bp = bp->next )
+ {
+ if( bp->class == TERM ) v[i++] = bp;
+ else v[j++] = bp;
+ }
+ if( i != ntokens || j != nsyms )
+ {
+ done( 2 );
+ }
+
+ for( i = 1; i < ntokens; ++i ) v[i]->index = i;
+
+ goal->index = start_symbol + 1;
+ k = start_symbol + 2;
+ while( ++i < nsyms )
+ if( v[i] != goal )
+ {
+ v[i]->index = k;
+ ++k;
+ }
+
+ goal->value = 0;
+ k = 1;
+ for( i = start_symbol + 1; i < nsyms; ++i )
+ {
+ if( v[i] != goal )
+ {
+ v[i]->value = k;
+ ++k;
+ }
+ }
+
+ k = 0;
+ for( i = 1; i < ntokens; ++i )
+ {
+ n = v[i]->value;
+
+ if( n > 256 )
+ {
+ for( j = k++; j > 0 && symbol_value[j-1] > n; --j )
+ symbol_value[j] = symbol_value[j-1];
+ symbol_value[j] = n;
+ }
+ }
+
+ if( v[1]->value == UNDEFINED )
+ v[1]->value = 256;
+
+ j = 0;
+ n = 257;
+ for( i = 2; i < ntokens; ++i )
+ {
+ if( v[i]->value == UNDEFINED )
+ {
+ while( j < k && n == symbol_value[j] )
+ {
+ while( ++j < k && n == symbol_value[j] ) continue;
+ ++n;
+ }
+ v[i]->value = n;
+ ++n;
+ }
+ }
+
+ symbol_name[0] = name_pool + 8;
+ symbol_value[0] = 0;
+ symbol_prec[0] = 0;
+ symbol_assoc[0] = TOKEN;
+
+ for( i = 1; i < ntokens; ++i )
+ {
+ symbol_name[i] = v[i]->name;
+ symbol_value[i] = v[i]->value;
+ symbol_prec[i] = v[i]->prec;
+ symbol_assoc[i] = v[i]->assoc;
+ }
+
+ symbol_name[start_symbol] = name_pool;
+ symbol_value[start_symbol] = -1;
+ symbol_prec[start_symbol] = 0;
+ symbol_assoc[start_symbol] = TOKEN;
+
+ for( ++i; i < nsyms; ++i )
+ {
+ k = v[i]->index;
+ symbol_name[k] = v[i]->name;
+ symbol_value[k] = v[i]->value;
+ symbol_prec[k] = v[i]->prec;
+ symbol_assoc[k] = v[i]->assoc;
+ }
+
+ FREE( v );
+
+} /******* End of pack_symbols( void ) *********************************/
+
+
+void pack_grammar( void )
+/*************************************************************************
+
+ Description : pack grammar
+
+ Concepts :
+
+ Use Global Variable: bucked **pitem; | this file
+ bucked **plhs; | this file
+ bucket *goal; | this file
+ int *ritem; | main.c
+ int *rlhs; | main.c
+ int *rrhs; | main.c
+ int *rprec; | main.c
+ char *rassoc; | main.c
+ int nrules; | main.c
+ int nitems; | main.c
+ int start_symbol; | main.c
+
+ Use Functions : void no_space (void); | error.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i, j;
+ int assoc, prec;
+
+ ritem = (int *)MALLOC( nitems*sizeof( int ) );
+ if( ritem == 0 ) no_space();
+ rlhs = (int *)MALLOC( nrules*sizeof( int ) );
+ if( rlhs == 0 ) no_space();
+ rrhs = (int *)MALLOC( (nrules+1)*sizeof( int ) );
+ if( rrhs == 0 ) no_space();
+ rprec = (int *)REALLOC( rprec, nrules*sizeof( int ) );
+ if( rprec == 0 ) no_space();
+ rassoc = (char *)REALLOC( rassoc, nrules );
+ if( rassoc == 0 ) no_space();
+
+ ritem[0] = -1;
+ ritem[1] = goal->index;
+ ritem[2] = 0;
+ ritem[3] = -2;
+
+ rlhs[0] = 0;
+ rlhs[1] = 0;
+ rlhs[2] = start_symbol;
+
+ rrhs[0] = 0;
+ rrhs[1] = 0;
+ rrhs[2] = 1;
+
+ j = 4;
+ for( i = 3; i < nrules; ++i )
+ {
+ rlhs[i] = plhs[i]->index;
+ rrhs[i] = j;
+ assoc = TOKEN;
+ prec = 0;
+ while( pitem[j] )
+ {
+ ritem[j] = pitem[j]->index;
+ if( pitem[j]->class == TERM )
+ {
+ prec = pitem[j]->prec;
+ assoc = pitem[j]->assoc;
+ }
+ ++j;
+ }
+ ritem[j] = -i;
+ ++j;
+ if( rprec[i] == UNDEFINED )
+ {
+ rprec[i] = prec;
+ rassoc[i] = assoc;
+ }
+ } /* End of for (i = 3; i < nrules; ++i) */
+ rrhs[i] = j;
+
+ FREE( plhs );
+ FREE( pitem );
+
+} /******* End of pack_grammar( void ) *********************************/
+
+
+void print_grammar( void )
+/*************************************************************************
+
+ Description : print grammar
+
+ Concepts :
+
+ Use Global Variable: int *ritem; | main.c
+ int *rlhs; | main.c
+ int nrules; | main.c
+ char **symbol_name; | main.c
+ mpu_FILE *verbose_file; | main.c
+ char vflag; | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ register int i, j, k;
+ int spacing = 0;
+ register mpu_FILE *f = verbose_file;
+
+ if( !vflag ) return;
+ mpu_fprintf( f, MPU_UCS2( "\n\
+/***************************************************************\n\
+ This (verbose)file prodused by ZUBR for check grammar and\n\
+ working-out.\n\
+ ***************************************************************/\n\n" ) );
+
+ k = 1;
+ for( i = 2; i < nrules; ++i )
+ {
+ if( rlhs[i] != rlhs[i-1] )
+ {
+ if( i != 2 ) mpu_fprintf( f, MPU_UCS2( "\n" ) );
+ mpu_fprintf( f, MPU_UCS2( "%6d %s :" ),
+ i - 2, symbol_name[rlhs[i]] );
+ spacing = mpu_str16len( symbol_name[rlhs[i]] ) + 1;
+ }
+ else
+ {
+ mpu_fprintf( f, MPU_UCS2( "%6d " ), i - 2 );
+ j = spacing;
+ while( --j >= 0 ) mpu_putc( ' ', f );
+ mpu_putc( '|', f );
+ }
+
+ while( ritem[k] >= 0 )
+ {
+ mpu_fprintf( f, MPU_UCS2( " %s" ), symbol_name[ritem[k]] );
+ ++k;
+ }
+ ++k;
+ mpu_putc( '\n', f );
+
+ } /* End of for( i = 2; i < nrules; ++i ) */
+
+ mpu_fprintf( f, MPU_UCS2( "\n\
+/*********************** End of Grammar ************************/\n" )
+ );
+
+} /******* End of print_grammar( void ) **********************/
+
+
+void write_parse_header( void )
+{
+ register __mpu_char16_t *sf;
+ register mpu_FILE *fp;
+
+ fp = parse_header_file;
+ sf = parse_func_name;
+
+ mpu_fprintf( fp, MPU_UCS2( "\n\
+/***************************************************************\n\
+ This file prodused by ZUBR for used declaration\n\
+ zubr_parse() function name.\n\
+ ***************************************************************/\n" ) );
+
+ mpu_fprintf( fp, MPU_UCS2( "\nextern int %s();\n\n" ), sf );
+
+ mpu_fprintf( fp, MPU_UCS2( "\
+/************************ End of File **************************/\n" )
+ );
+
+}
+
+
+void reader( void )
+/*************************************************************************
+
+ Description : read declarations and grammar
+
+ Concepts :
+
+ Use Global Variable:
+
+ Use Functions : void read_declarations (void); | this file
+ void read_grammar (void); | this file
+ void free_tags (void); | this file
+ void pack_names (void); | this file
+ void check_symbols (void); | this file
+ void pack_symbols (void); | this file
+ void pack_grammar (void); | this file
+ void print_grammar (void); | this file
+ void create_symbol_table (void); | symtab.c
+ void free_symbol_table (void); | symtab.c
+ void free_symbols (void); | symtab.c
+ void write_section (char **section); | skeleton.c
+
+ Parameters : [void]
+
+ Return : [void]
+
+ *************************************************************************/
+{
+ if( p_name_flag ) write_parse_header();
+ write_banner();
+ write_parse_name_declaration();
+
+ create_symbol_table();
+ read_declarations();
+ read_grammar();
+ free_symbol_table();
+ free_tags();
+ pack_names();
+ check_symbols();
+ pack_symbols();
+ pack_grammar();
+ free_symbols();
+ print_grammar();
+
+} /******* End of reader( void ) *****************************/
+
+#endif /* __NO_COMPILE */
+
+/******************** END OF FILE READER.C *******************/
diff --git a/src/skeleton.c b/src/skeleton.c
new file mode 100644
index 0000000..c0b5765
--- /dev/null
+++ b/src/skeleton.c
@@ -0,0 +1,663 @@
+
+/***************************************************************
+ SKELETON.C
+
+ This file containts OUTPUT SKELETON routine of ZUBR.
+
+ PART OF : ZUBR - Parsers generator for multiple syntax
+ language compilers .
+
+ COMPILE : .
+
+ NOTE : NONE .
+
+ Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+/*
+ This file contant RUSSIAN letters( code-page: UTF-8 )
+ ***************************************************************/
+
+#include <defs.h>
+
+#ifndef __NO_COMPILE
+
+
+
+void write_parse_name_definition( void )
+{
+ register mpu_FILE *fp;
+ register __mpu_char16_t *s;
+
+ fp = code_file;
+ if( sflag ) s = (__mpu_char16_t *)MPU_UCS2( "static " );
+ else s = (__mpu_char16_t *)MPU_UCS2( "" );
+
+ outline += 3;
+ if( !p_name_flag )
+ {
+ if( bflag )
+ mpu_fprintf( fp, MPU_UCS2( "\n%sint %szubr_parse( void )\n{\n" ),
+ s, name_prefix );
+ else
+ mpu_fprintf( fp, MPU_UCS2( "\n%sint zubr_parse( void )\n{\n" ), s );
+ }
+ else
+ mpu_fprintf( fp, MPU_UCS2( "int %s( void )\n{\n" ), parse_func_name );
+}
+
+
+void write_parse_name_declaration( void )
+{
+ register mpu_FILE *fp;
+ register __mpu_char16_t *s;
+
+ fp = code_file;
+ if( sflag ) s = (__mpu_char16_t *)MPU_UCS2( "static " );
+ else s = (__mpu_char16_t *)MPU_UCS2( "" );
+
+ outline += 3;
+ if( !p_name_flag )
+ {
+ if( bflag )
+ mpu_fprintf( fp, MPU_UCS2( "\n%sint %szubr_parse( void );\n\n" ),
+ s, name_prefix );
+ else
+ mpu_fprintf( fp, MPU_UCS2( "\n%sint zubr_parse( void );\n\n" ), s );
+ }
+ else
+ mpu_fprintf( fp, MPU_UCS2( "\nint %s( void );\n\n" ), parse_func_name );
+}
+
+
+void write_extern_tables( void )
+/***************************************************************
+
+ Description : write section 'tables' into code file
+
+ Concepts :
+
+ Use Global Variable: mpu_FILE *code_file | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register mpu_FILE *fp;
+ register __mpu_char16_t *prefL, *prefU;
+ __mpu_char16_t *_char_type = (__mpu_char16_t *)MPU_UCS2( "__mpu_char16_t" );
+
+ fp = code_file;
+ if( bflag )
+ {
+ prefL = name_prefix;
+ prefU = name_prefix_upper;
+ }
+ else
+ {
+ prefL = (__mpu_char16_t *)MPU_UCS2( "" );
+ prefU = (__mpu_char16_t *)MPU_UCS2( "" );
+ }
+
+ outline += 14; /* number of lines in tables section */
+ mpu_fprintf( fp, MPU_UCS2( "extern int %szubr_lhs[];\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "extern int %szubr_len[];\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "extern int %szubr_defred[];\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "extern int %szubr_dgoto[];\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "extern int %szubr_sindex[];\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "extern int %szubr_rindex[];\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "extern int %szubr_gindex[];\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "extern int %szubr_table[];\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "extern int %szubr_check[];\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#if %sZUBR_DEBUG\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( "extern %s *%szubr_name[];\n" ),_char_type, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "extern %s *%szubr_rule[];\n" ),_char_type, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n\n" ) );
+
+} /******* End of write_extern_tables( void ) ****************/
+
+
+void write_header( void )
+/***************************************************************
+
+ Description : write section 'header' into code file
+
+ Concepts :
+
+ Use Global Variable: mpu_FILE *code_file | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register mpu_FILE *fp;
+ register __mpu_char16_t *prefL, *prefU;
+
+ fp = code_file;
+ if( bflag )
+ {
+ prefL = name_prefix;
+ prefU = name_prefix_upper;
+ }
+ else
+ {
+ prefL = (__mpu_char16_t *)MPU_UCS2( "" );
+ prefU = (__mpu_char16_t *)MPU_UCS2( "" );
+ }
+
+ outline += 15; /* number of lines in header section */
+ mpu_fprintf( fp, MPU_UCS2( "#define %szubr_clearin (%szubr_char=(-1))\n" ),
+ prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#define %szubr_errok (%szubr_errflag=0)\n" ),
+ prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#ifdef %sZUBR_STACKSIZE\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( "#ifndef %sZUBR_MAXDEPTH\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( "#define %sZUBR_MAXDEPTH %sZUBR_STACKSIZE\n" ),
+ prefU, prefU );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#else\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#ifdef %sZUBR_MAXDEPTH\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( "#define %sZUBR_STACKSIZE %sZUBR_MAXDEPTH\n" ),
+ prefU, prefU );
+ mpu_fprintf( fp, MPU_UCS2( "#else\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#define %sZUBR_STACKSIZE 500\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( "#define %sZUBR_MAXDEPTH 500\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n\n" ) );
+
+} /******* End of write_header( void ) ***********************/
+
+
+void write_header_definitions( void )
+/***************************************************************
+
+ Description : write section 'header_definitions'
+ or 'header_static_definitions'
+ into code file
+
+ Concepts :
+
+ Use Global Variable: mpu_FILE *code_file | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register mpu_FILE *fp;
+ register __mpu_char16_t *s, *prefL, *prefU;
+
+ fp = code_file;
+
+ if( sflag ) s = (__mpu_char16_t *)MPU_UCS2( "static " );
+ else s = (__mpu_char16_t *)MPU_UCS2( "" );
+
+ if( bflag )
+ {
+ prefL = name_prefix;
+ prefU = name_prefix_upper;
+ }
+ else
+ {
+ prefL = (__mpu_char16_t *)MPU_UCS2( "" );
+ prefU = (__mpu_char16_t *)MPU_UCS2( "" );
+ }
+
+ outline += 18; /* number of lines in header defs section */
+ mpu_fprintf( fp, MPU_UCS2( "#if %sZUBR_DEBUG\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( "%sint %szubr_debug;\n" ), s, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "%sint %szubr_nerrs;\n" ), s, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "%sint %szubr_errflag;\n" ), s, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "%sint %szubr_char;\n" ), s, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "%sint *%szubr_ssp;\n\n" ), s, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "%s%sZUBR_STYPE *%szubr_vsp;\n" ), s, prefU, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "%s%sZUBR_STYPE %szubr_val;\n" ), s, prefU, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "%s%sZUBR_STYPE %szubr_lval;\n\n" ), s, prefU, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "%sint %szubr_ss[%sZUBR_STACKSIZE];\n\n" ),
+ s, prefL, prefU );
+ mpu_fprintf( fp, MPU_UCS2( "%s%sZUBR_STYPE %szubr_vs[%sZUBR_STACKSIZE];\n\n" ),
+ s, prefU, prefL, prefU );
+ mpu_fprintf( fp, MPU_UCS2( "#define %szubr_stacksize %sZUBR_STACKSIZE\n\n" ),
+ prefL, prefU );
+
+} /******* End of write_header_definitions( void ) ***********/
+
+
+void write_begin_body( void )
+/***************************************************************
+
+ Description : write section 'begin_body' into code file
+
+ Concepts :
+
+ Use Global Variable: mpu_FILE *code_file | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register mpu_FILE *fp;
+ register __mpu_char16_t *prefL, *prefU;
+
+ fp = code_file;
+
+ if( bflag )
+ {
+ prefL = name_prefix;
+ prefU = name_prefix_upper;
+ }
+ else
+ {
+ prefL = (__mpu_char16_t *)MPU_UCS2( "" );
+ prefU = (__mpu_char16_t *)MPU_UCS2( "" );
+ }
+
+ outline += 6; /* number of lines in begin_body section */
+
+ mpu_fprintf( fp, MPU_UCS2( "\n#define %sZUBR_ABORT goto %szubr_abort\n" ), prefU, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#define %sZUBR_ACCEPT goto %szubr_accept\n" ),
+ prefU, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#define %sZUBR_NEWERROR goto %szubr_newerror\n" ),
+ prefU, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#define %sZUBR_ERROR goto %szubr_errlab\n\n" ),
+ prefU, prefL );
+
+} /******* End of write_begin_body( void ) *******************/
+
+
+
+/* The banner used here should be replaced with an #ident directive */
+/* if the target C compiler supports #ident directives. */
+/* */
+/* If the skeleton is changed, the banner should be changed so that */
+/* the altered version can easily be distinguished from the original. */
+
+void write_banner( void )
+/***************************************************************
+
+ Description : write section 'banner' into code file
+
+ Concepts :
+
+ Use Global Variable: mpu_FILE *code_file | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register mpu_FILE *fp;
+ register __mpu_char16_t *s;
+ __mpu_char16_t *_char_type = (__mpu_char16_t *)MPU_UCS2( "__mpu_char16_t" );
+
+ fp = code_file;
+ if( bflag ) s = name_prefix;
+ else s = (__mpu_char16_t *)MPU_UCS2( "" );
+
+ outline += 10; /* number of lines in banner section */
+ mpu_fprintf( fp, MPU_UCS2( "\n#include <ctype.h> /* character classification used by lexer */\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#include <libmpuio.h> /* UCS-2 parser diagnostics */\n\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#define %snot_defined_zubr_sccsid 1\n\n" ), s );
+ mpu_fprintf( fp, MPU_UCS2( "#define __ZUBR__ 1\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#ifndef %snot_defined_zubr_sccsid\n" ), s );
+ mpu_fprintf( fp, MPU_UCS2( "\
+static %s zubr_sccsid[] = MPU_UCS2(\"@(#)\
+zubr %s Andrey V.Kosteltsev 19/09/26\");\n" ), _char_type, ZUBR_VERSION );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+
+
+} /******* End of write_banner( void ) ***********************/
+
+
+void write_end_body( void )
+/***************************************************************
+
+ Description : write section 'end_body' into code file
+
+ Concepts :
+
+ Use Global Variable: mpu_FILE *code_file | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register mpu_FILE *fp;
+ register __mpu_char16_t *prefL, *prefU, *lex;
+ register __mpu_char16_t lex_mem_flag = 0;
+ __mpu_char16_t *_char_type = (__mpu_char16_t *)MPU_UCS2( "__mpu_char16_t" );
+ __mpu_char16_t *_getenv_name = (__mpu_char16_t *)MPU_UCS2( "getenv" );
+ __mpu_char16_t *_printf_name = (__mpu_char16_t *)MPU_UCS2( "mpu_printf" );
+
+ fp = code_file;
+ lex = (__mpu_char16_t *)0;
+
+ if( bflag )
+ {
+ prefL = name_prefix;
+ prefU = name_prefix_upper;
+
+ if( l_name_flag ) lex = lex_func_name;
+ else
+ {
+ lex = (__mpu_char16_t *)
+ MALLOC( (mpu_str16len( name_prefix ) +
+ mpu_str16len( (__mpu_char16_t *)MPU_UCS2( "zubr_lex" ) ) + 1) *
+ sizeof(__mpu_char16_t) );
+ if( lex == 0 ) no_space();
+ memset( lex, NUL, (mpu_str16len( name_prefix ) +
+ mpu_str16len( (__mpu_char16_t *)MPU_UCS2( "zubr_lex" ) )+1) *
+ sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( lex, name_prefix );
+ mpu_str16cat( lex, (__mpu_char16_t *)MPU_UCS2( "zubr_lex" ) );
+
+ lex_mem_flag = 1;
+ }
+ }
+ else
+ {
+ prefL = (__mpu_char16_t *)MPU_UCS2( "" );
+ prefU = (__mpu_char16_t *)MPU_UCS2( "" );
+
+ if( l_name_flag ) lex = lex_func_name;
+ else lex = (__mpu_char16_t *)MPU_UCS2( "zubr_lex" );
+ }
+
+ outline += 134; /* number of lines in end_body section */
+
+ mpu_fprintf( fp, MPU_UCS2( " register int %szubr_m, %szubr_n, %szubr_state;\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#if %sZUBR_DEBUG\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( " register %s *%szubr_s;\n" ), _char_type, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " register char *%szubr_dd;\n\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( (%szubr_dd = %s(\"ZUBR_DEBUG\")) )\n" ), prefL, _getenv_name );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_n = *%szubr_dd;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_n >= '0' && %szubr_n <= '9' ) %szubr_debug = %szubr_n - '0';\n" ), prefL, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " }\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_nerrs = 0;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_errflag = 0;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_char = (-1);\n\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_ssp = %szubr_ss;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_vsp = %szubr_vs;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " *%szubr_ssp = %szubr_state = 0;\n\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "%szubr_loop:\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( (%szubr_n = %szubr_defred[%szubr_state]) ) goto %szubr_reduce;\n" ), prefL, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_char < 0 )\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " if( (%szubr_char = %s()) < 0 ) %szubr_char = 0;\n" ), prefL, lex, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#if %sZUBR_DEBUG\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_debug )\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_s = 0;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_char <= %sZUBR_MAXTOKEN ) %szubr_s = %szubr_name[%szubr_char];\n" ), prefL, prefU, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( !%szubr_s ) %szubr_s = MPU_UCS2(\"illegal-symbol\");\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %s( MPU_UCS2(\"%szubr_debug: state %%d, reading %%d (%%s)\\n\"),\n" ), _printf_name, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_state, %szubr_char, %szubr_s );\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " }\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " } /* End if( %szubr_char < 0 ) */\n\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( (%szubr_n = %szubr_sindex[%szubr_state]) && (%szubr_n += %szubr_char) >= 0 &&\n" ), prefL, prefL, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_n <= %sZUBR_TABLESIZE && %szubr_check[%szubr_n] == %szubr_char )\n" ), prefL, prefU, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#if %sZUBR_DEBUG\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_debug )\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %s( MPU_UCS2(\"%szubr_debug: state %%d, shifting to state %%d\\n\"),\n" ), _printf_name, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_state, %szubr_table[%szubr_n] );\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_ssp >= %szubr_ss + %szubr_stacksize - 1 )\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " goto %szubr_overflow;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " }\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " *++%szubr_ssp = %szubr_state = %szubr_table[%szubr_n];\n" ), prefL, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " *++%szubr_vsp = %szubr_lval;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_char = (-1);\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_errflag > 0 ) --%szubr_errflag;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " goto %szubr_loop;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " }\n\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " if( (%szubr_n = %szubr_rindex[%szubr_state]) && (%szubr_n += %szubr_char) >= 0 &&\n" ), prefL, prefL, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_n <= %sZUBR_TABLESIZE && %szubr_check[%szubr_n] == %szubr_char )\n" ), prefL, prefU, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_n = %szubr_table[%szubr_n];\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " goto %szubr_reduce;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " }\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " if (%szubr_errflag) goto %szubr_inrecovery;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#ifdef %snot_defined_zubr_sccsid\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " goto %szubr_newerror;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "%szubr_newerror:\n" ), prefL );
+
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_error( \"syntax error\" );\n" ), prefL );
+
+ mpu_fprintf( fp, MPU_UCS2( "#ifdef %snot_defined_zubr_sccsid\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " goto %szubr_errlab;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "%szubr_errlab:\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " ++%szubr_nerrs;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "%szubr_inrecovery:\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_errflag < 3 )\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_errflag = 3;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " for( ;; )\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " if( (%szubr_n = %szubr_sindex[*%szubr_ssp]) && (%szubr_n += %sZUBR_ERRCODE) >= 0 &&\n" ), prefL, prefL, prefL, prefL, prefU );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_n <= %sZUBR_TABLESIZE && %szubr_check[%szubr_n] == %sZUBR_ERRCODE )\n" ), prefL, prefU, prefL, prefL, prefU );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#if %sZUBR_DEBUG\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_debug )\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %s( MPU_UCS2(\"%szubr_debug: state %%d, error recovery shifting\\\n" ), _printf_name, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " to state %%d\\n\")," ) );
+ mpu_fprintf( fp, MPU_UCS2( " *%szubr_ssp, %szubr_table[%szubr_n] );\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_ssp >= %szubr_ss + %szubr_stacksize - 1 )\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " goto %szubr_overflow;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " }\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " *++%szubr_ssp = %szubr_state = %szubr_table[%szubr_n];\n" ), prefL, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " *++%szubr_vsp = %szubr_lval;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " goto %szubr_loop;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " }\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " else\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#if %sZUBR_DEBUG\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_debug )\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %s( MPU_UCS2(\"%szubr_debug: error recovery discarding state %%d\\n\"),\n" ), _printf_name, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " *%szubr_ssp );\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_ssp <= %szubr_ss ) goto %szubr_abort;\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " --%szubr_ssp;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " --%szubr_vsp;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " }\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " } /* End of for( ;; ) */\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " } /* End if( %szubr_errflag < 3 ) */\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " else\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_char == 0 ) goto %szubr_abort;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#if %sZUBR_DEBUG\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_debug )\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_s = 0;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_char <= %sZUBR_MAXTOKEN ) %szubr_s = %szubr_name[%szubr_char];\n" ), prefL, prefU, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( !%szubr_s ) %szubr_s = MPU_UCS2(\"illegal-symbol\");\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %s( MPU_UCS2(\"%szubr_debug: state %%d, error recovery discards token %%d (%%s)\\n\"),\n" ), _printf_name, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_state, %szubr_char, %szubr_s );\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " }\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_char = (-1);\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " goto %szubr_loop;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " }\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "%szubr_reduce:\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#if %sZUBR_DEBUG\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_debug )\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %s( MPU_UCS2(\"%szubr_debug: state %%d, reducing by rule %%d (%%s)\\n\"),\n" ), _printf_name, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_state, %szubr_n, %szubr_rule[%szubr_n] );\n" ), prefL, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_m = %szubr_len[%szubr_n];\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_val = %szubr_vsp[1-%szubr_m];\n\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " switch( %szubr_n )\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+
+
+ if( lex_mem_flag )
+ {
+ if( lex ) FREE( lex );
+ }
+
+} /******* End of write_end_body( void ) *********************/
+
+
+void write_trailer( void )
+/***************************************************************
+
+ Description : write section 'trailer' into code file
+
+ Concepts :
+
+ Use Global Variable: mpu_FILE *code_file | main.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register mpu_FILE *fp;
+ register __mpu_char16_t *prefL, *prefU, *lex;
+ register __mpu_char16_t lex_mem_flag = 0;
+ __mpu_char16_t *_printf_name = (__mpu_char16_t *)MPU_UCS2( "mpu_printf" );
+
+ fp = code_file;
+ lex = (__mpu_char16_t *)0;
+
+ if( bflag )
+ {
+ prefL = name_prefix;
+ prefU = name_prefix_upper;
+
+ if( l_name_flag ) lex = lex_func_name;
+ else
+ {
+ lex = (__mpu_char16_t *)
+ MALLOC( (mpu_str16len( name_prefix ) +
+ mpu_str16len( (__mpu_char16_t *)MPU_UCS2( "zubr_lex" ) ) + 1) *
+ sizeof(__mpu_char16_t) );
+ if( lex == 0 ) no_space();
+ memset( lex, NUL, (mpu_str16len( name_prefix ) +
+ mpu_str16len( (__mpu_char16_t *)MPU_UCS2( "zubr_lex" ) ) + 1) *
+ sizeof(__mpu_char16_t) );
+
+ mpu_str16cpy( lex, name_prefix );
+ mpu_str16cat( lex, (__mpu_char16_t *)MPU_UCS2( "zubr_lex" ) );
+
+ lex_mem_flag = 1;
+ }
+ }
+ else
+ {
+ prefL = (__mpu_char16_t *)MPU_UCS2( "" );
+ prefU = (__mpu_char16_t *)MPU_UCS2( "" );
+
+ if( l_name_flag ) lex = lex_func_name;
+ else lex = (__mpu_char16_t *)MPU_UCS2( "zubr_lex" );
+ }
+
+ outline += 60; /* number of lines in trailer section */
+
+ mpu_fprintf( fp, MPU_UCS2( "\n } /* End of switch( %szubr_n ) */\n\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_ssp -= %szubr_m;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_state = *%szubr_ssp;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_vsp -= %szubr_m;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_m = %szubr_lhs[%szubr_n];\n\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_state == 0 && %szubr_m == 0 )\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#if %sZUBR_DEBUG\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_debug )\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %s( MPU_UCS2(\"%szubr_debug: after reduction, shifting from state 0 to\\\n" ), _printf_name, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " state %%d\\n\")," ) );
+ mpu_fprintf( fp, MPU_UCS2( " %sZUBR_FINAL );\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_state = %sZUBR_FINAL;\n" ), prefL, prefU );
+ mpu_fprintf( fp, MPU_UCS2( " *++%szubr_ssp = %sZUBR_FINAL;\n" ), prefL, prefU );
+ mpu_fprintf( fp, MPU_UCS2( " *++%szubr_vsp = %szubr_val;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_char < 0 )\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " if( (%szubr_char = %s()) < 0 ) %szubr_char = 0;\n" ), prefL, lex, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#if %sZUBR_DEBUG\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_debug )\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_s = 0;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_char <= %sZUBR_MAXTOKEN) %szubr_s = %szubr_name[%szubr_char];\n" ), prefL, prefU, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( !%szubr_s ) %szubr_s = MPU_UCS2(\"illegal-symbol\");\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %s( MPU_UCS2(\"%szubr_debug: state %%d, reading %%d (%%s)\\n\"),\n" ), _printf_name, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %sZUBR_FINAL, %szubr_char, %szubr_s);\n" ), prefU, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " }\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " }\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_char == 0 ) goto %szubr_accept;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " goto %szubr_loop;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " } /* End if( %szubr_state == 0 && %szubr_m == 0 ) */\n\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " if( (%szubr_n = %szubr_gindex[%szubr_m]) && (%szubr_n += %szubr_state) >= 0 &&\n" ), prefL, prefL, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_n <= %sZUBR_TABLESIZE && %szubr_check[%szubr_n] == %szubr_state )\n" ), prefL, prefU, prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_state = %szubr_table[%szubr_n];\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " else\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_state = %szubr_dgoto[%szubr_m];\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#if %sZUBR_DEBUG\n" ), prefU );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_debug )\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " %s( MPU_UCS2(\"%szubr_debug: after reduction, shifting from state %%d \\\n" ), _printf_name, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "to state %%d\\n\")," ) );
+ mpu_fprintf( fp, MPU_UCS2( " *%szubr_ssp, %szubr_state );\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( "#endif\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " if( %szubr_ssp >= %szubr_ss + %szubr_stacksize - 1 )\n" ), prefL, prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " {\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " goto %szubr_overflow;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " }\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( " *++%szubr_ssp = %szubr_state;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " *++%szubr_vsp = %szubr_val;\n" ), prefL, prefL );
+ mpu_fprintf( fp, MPU_UCS2( " goto %szubr_loop;\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( "%szubr_overflow:\n" ), prefL );
+
+ mpu_fprintf( fp, MPU_UCS2( " %szubr_error( \"zubr stack overflow\" );\n" ), prefL );
+
+ mpu_fprintf( fp, MPU_UCS2( "%szubr_abort:\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " return( 1 );\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "%szubr_accept:\n" ), prefL );
+ mpu_fprintf( fp, MPU_UCS2( " return( 0 );\n" ) );
+ mpu_fprintf( fp, MPU_UCS2( "}\n" ) );
+
+
+ if( lex_mem_flag )
+ {
+ if( lex ) FREE( lex );
+ }
+
+} /******* End of write_trailer( void ) **********************/
+
+#endif /* __NO_COMPILE */
+
+/****************** END OF FILE SKELETON.C *******************/
diff --git a/src/symtab.c b/src/symtab.c
new file mode 100644
index 0000000..9a8d0d6
--- /dev/null
+++ b/src/symtab.c
@@ -0,0 +1,260 @@
+
+/***************************************************************
+ SYMTAB.C
+
+ This file containts SYMBOL TABLE routines of ZUBR.
+
+ PART OF : ZUBR - Parsers generator for multiple syntax
+ language compilers .
+
+ COMPILE : .
+
+ NOTE : NONE .
+
+ Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+/*
+ This file contant RUSSIAN letters( code-page: UTF-8 )
+ ***************************************************************/
+
+#include <defs.h>
+
+#ifndef __NO_COMPILE
+
+
+/* TABLE_SIZE is the number of entries in the symbol table. */
+/* TABLE_SIZE must be a power of two. */
+
+#define TABLE_SIZE 2048
+
+bucket **symbol_table;
+bucket *first_symbol;
+bucket *last_symbol;
+
+int hash( __mpu_char16_t *name )
+/***************************************************************
+
+ Description : find unique number in symbol table
+
+ Concepts : excellent !
+
+ Use Global Variable:
+
+ Use Functions :
+
+ Parameters : char *name
+
+ Return : int k;
+
+ ***************************************************************/
+{
+ register __mpu_char16_t *s;
+ register int c, k;
+
+ if( !name || *name == 0 )
+ {
+ done( 2 );
+ }
+ s = name;
+ k = *s;
+ while( (c = *++s) ) k = (31*k + c) & (TABLE_SIZE - 1);
+
+ return( k );
+
+} /******* End of hash( char *name ) *************************/
+
+
+bucket * make_bucket( __mpu_char16_t *name )
+/***************************************************************
+
+ Description : allocate memory for symbol
+
+ Concepts :
+
+ Use Global Variable:
+
+ Use Functions :
+
+ Parameters : char *name
+
+ Return : bucket *bp
+
+ ***************************************************************/
+{
+ register bucket *bp;
+
+ if( !name )
+ {
+ done( 2 );
+ }
+ bp = (bucket *)MALLOC( sizeof( bucket ) );
+ if( bp == 0 ) no_space();
+
+ bp->link = 0;
+ bp->next = 0;
+
+ bp->name = (__mpu_char16_t *)MALLOC( (mpu_str16len( name ) + 1) *
+ sizeof(__mpu_char16_t) );
+ if( bp->name == 0 ) no_space();
+ mpu_str16cpy( bp->name, name );
+
+ bp->tag = 0;
+ bp->value = UNDEFINED;
+ bp->index = 0;
+ bp->prec = 0;
+ bp->class = UNKNOWN;
+ bp->assoc = TOKEN;
+
+ return( bp );
+
+} /******* End of make_bucket( char *name ) ******************/
+
+
+bucket * lookup( __mpu_char16_t *name )
+/***************************************************************
+
+ Description : find symbol in symbol table
+ if symbol not found,
+ then (for its) allocate memory (use make_bucket ())
+ and include in symbol table
+
+ Concepts :
+
+ Use Global Variable: bucket *last_symbol; | this file
+
+ Use Functions :
+
+ Parameters : char *name
+
+ Return : bucket *bp
+
+ ***************************************************************/
+{
+ register bucket *bp, **bpp;
+
+ bpp = symbol_table + hash( name );
+ bp = *bpp;
+
+ while( bp )
+ {
+ if( mpu_str16cmp( name, bp->name ) == 0 ) return( bp );
+ bpp = &bp->link; /* link для связи цепочки по
+ одному индексу в symbol_table[] */
+ bp = *bpp;
+ /*
+ См.:
+ David Gries, Compiler Construction
+ for Digital Computers,
+ Cornell University, 1971.
+
+ Д.Грис, Конструирование компиляторов для цифровых
+ вычислительных машин,
+ Пер. с англ., Е.Б.Докшитской и др.,
+ Под ред. Ю.М.Баяковского, М.: Мир, 1975.
+
+ п. 9.3.2. Метод цепочек, стр. 252.
+ */
+ }
+
+ *bpp = bp = make_bucket( name ); /* make and insert into symbol_table */
+ last_symbol->next = bp;
+ last_symbol = bp;
+
+ return( bp );
+
+} /******* End of lookup( char *name ) ***********************/
+
+
+void create_symbol_table( void )
+/***************************************************************
+
+ Description : allocate memory for symbol_table
+ and make symbol u"error"
+
+ Concepts :
+
+ Use Global Variable: bucket *first_symbol; | this file
+ bucket *last_symbol; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+ register bucket *bp;
+
+ symbol_table = (bucket **)MALLOC( TABLE_SIZE*sizeof( bucket * ) );
+ if( symbol_table == 0 ) no_space();
+ for( i = 0; i < TABLE_SIZE; i++ ) symbol_table[i] = 0;
+
+ bp = make_bucket( (__mpu_char16_t *)MPU_UCS2( "error" ) );
+ bp->index = 1;
+ bp->class = TERM;
+
+ first_symbol = bp;
+ last_symbol = bp;
+
+ symbol_table[hash( (__mpu_char16_t *)MPU_UCS2( "error" ) )] = bp;
+
+} /******* End of create_symbol_table( void ) ****************/
+
+
+void free_symbol_table( void )
+/***************************************************************
+
+ Description : free memory for symbol_table
+
+ Concepts :
+
+ Use Global Variable:
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ FREE( symbol_table );
+ symbol_table = 0;
+
+} /******* End of free_symbol_table( void ) ******************/
+
+
+void free_symbols( void )
+/***************************************************************
+
+ Description : free memory for all symbols in list
+
+ Concepts :
+
+ Use Global Variable: bucket *first_symbol; | this file
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register bucket *p, *q;
+
+ for( p = first_symbol; p; p = q )
+ {
+ q = p->next;
+ /* TODO ADD FREE(name) and other */
+ FREE( p );
+ }
+
+} /******* End of free_symbols( void ) ***********************/
+
+#endif /* __NO_COMPILE */
+
+/****************** END OF FILE SYMTAB.C *********************/
diff --git a/src/verbose.c b/src/verbose.c
new file mode 100644
index 0000000..3f3e318
--- /dev/null
+++ b/src/verbose.c
@@ -0,0 +1,584 @@
+
+/***************************************************************
+ VERBOSE.C
+
+ This file containts VERBOSE file writer of ZUBR.
+
+ PART OF : ZUBR - Parsers generator for multiple syntax
+ language compilers .
+
+ COMPILE : .
+
+ NOTE : .
+
+ Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+/*
+ This file contant RUSSIAN letters( code-page: UTF-8 )
+ ***************************************************************/
+
+#include <defs.h>
+
+#ifndef __NO_COMPILE
+
+
+static int *null_rules;
+
+/* NOTE *
+ In this file for output '\t'(tab) symbol use 12 space characters.
+ My be use the following string 'u" ' for find that symbols.
+ * END */
+
+void log_unused( void )
+/***************************************************************
+
+ Description : log unused
+
+ Concepts :
+
+ Use Global Variable: int nrules; | main.c
+ char **symbol_name; | main.c
+ int *ritem; | main.c
+ int *rrhs; | main.c
+ FILE *verbose_file; | main.c
+ int *rules_used; | mkpar.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+ register int *p;
+
+ mpu_fprintf( verbose_file, MPU_UCS2( "\n\nRules never reduced:\n" ) );
+ for( i = 3; i < nrules; ++i )
+ {
+ if( !rules_used[i] )
+ {
+ mpu_fprintf( verbose_file, MPU_UCS2( " %s :" ),
+ symbol_name[rlhs[i]]);
+ for( p = ritem + rrhs[i]; *p >= 0; ++p )
+ mpu_fprintf( verbose_file, MPU_UCS2( " %s" ), symbol_name[*p] );
+ mpu_fprintf( verbose_file, MPU_UCS2( " (%d)\n" ), i - 2 );
+ }
+ }
+
+} /******* End of log_unused( void ) *************************/
+
+
+void log_conflicts( void )
+/***************************************************************
+
+ Description : log conflicts
+
+ Concepts :
+
+ Use Global Variable: FILE *verbose_file; | main.c
+ int nstates; | lr0.c
+ int *SRconflicts; | mkpar.c
+ int *RRconflicts; | mkpar.c
+
+ Use Functions :
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+
+ mpu_fprintf( verbose_file, MPU_UCS2( "\n\n" ) );
+ for( i = 0; i < nstates; i++ )
+ {
+ if( SRconflicts[i] || RRconflicts[i] )
+ {
+ mpu_fprintf( verbose_file, MPU_UCS2( "State %d contains " ), i);
+ if( SRconflicts[i] == 1 )
+ mpu_fprintf( verbose_file, MPU_UCS2( "1 shift/reduce conflict" ) );
+ else if( SRconflicts[i] > 1 )
+ mpu_fprintf( verbose_file,
+ MPU_UCS2( "%d shift/reduce conflicts" ),
+ SRconflicts[i] );
+ if( SRconflicts[i] && RRconflicts[i] )
+ mpu_fprintf( verbose_file, MPU_UCS2( ", u" ) );
+ if( RRconflicts[i] == 1 )
+ mpu_fprintf( verbose_file, MPU_UCS2( "1 reduce/reduce conflict" ) );
+ else if( RRconflicts[i] > 1 )
+ mpu_fprintf( verbose_file,
+ MPU_UCS2( "%d reduce/reduce conflicts" ),
+ RRconflicts[i] );
+ mpu_fprintf( verbose_file, MPU_UCS2( ".\n" ) );
+
+ }
+ } /* End of for( i = 0; i < nstates; i++ ) */
+
+} /******* End of log_conflicts( void ) **********************/
+
+
+void print_conflicts( int state )
+/***************************************************************
+
+ Description : print conflicts
+
+ Concepts :
+
+ Use Global Variable: char **symbol_name; | main.c
+ FILE *verbose_file; | main.c
+ action **parser; | mkpar.c
+ int final_state; | mkpar.c
+
+ Use Functions :
+
+ Parameters : int state
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int symbol = 0, act = 0, number = 0;
+ register action *p;
+
+ symbol = -1;
+ for( p = parser[state]; p; p = p->next )
+ {
+ if( p->suppressed == 2 ) continue;
+
+ if( p->symbol != symbol )
+ {
+ symbol = p->symbol;
+ number = p->number;
+ if( p->action_code == SHIFT ) act = SHIFT;
+ else act = REDUCE;
+ }
+ else
+ if( p->suppressed == 1 )
+ {
+ if( state == final_state && symbol == 0 )
+ {
+ mpu_fprintf( verbose_file,
+ MPU_UCS2( "%d: shift/reduce conflict (accept, reduce %d) on $end\n" ),
+ state, p->number - 2 );
+ }
+ else
+ {
+ if( act == SHIFT )
+ {
+ mpu_fprintf( verbose_file,
+ MPU_UCS2( "%d: shift/reduce conflict (shift %d, reduce %d) on %s\n" ),
+ state, number, p->number - 2, symbol_name[symbol] );
+ }
+
+ else
+ {
+ mpu_fprintf( verbose_file,
+ MPU_UCS2( "%d: reduce/reduce conflict (reduce %d, reduce %d) on %s\n" ),
+ state, number - 2, p->number - 2, symbol_name[symbol] );
+ }
+ }
+ } /* End if( p->suppressed == 1 ) */
+ } /* End of for( p = parser[state]; p; p = p->next ) */
+
+} /******* End of print_conflicts( int state ) ***************/
+
+
+void print_core( int state )
+/***************************************************************
+
+ Description : print core
+
+ Concepts :
+
+ Use Global Variable: char **symbol_name; | main.c
+ int *ritem; | main.c
+ int *rrhs; | main.c
+ int *rlhs; | main.c
+ FILE *verbose_file; | main.c
+ core **state_table; | lalr.c
+
+ Use Functions :
+
+ Parameters : int state
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+ register int k;
+ register int rule;
+ register core *statep;
+ register int *sp;
+ register int *sp1;
+
+ statep = state_table[state];
+ k = statep->nitems;
+
+ for( i = 0; i < k; i++ )
+ {
+ sp1 = sp = ritem + statep->items[i];
+
+ while( *sp >= 0 ) ++sp;
+ rule = -(*sp);
+ mpu_fprintf( verbose_file,
+ MPU_UCS2( " %s : " ), symbol_name[rlhs[rule]] );
+
+ for( sp = ritem + rrhs[rule]; sp < sp1; sp++ )
+ mpu_fprintf( verbose_file, MPU_UCS2( "%s " ), symbol_name[*sp] );
+
+ mpu_putc( '.', verbose_file );
+
+ while( *sp >= 0 )
+ {
+ mpu_fprintf( verbose_file, MPU_UCS2( " %s" ), symbol_name[*sp] );
+ sp++;
+ }
+ mpu_fprintf( verbose_file, MPU_UCS2( " (%d)\n" ), -2 - *sp );
+
+ } /* End of for( i = 0; i < k; i++ ) */
+
+} /******* End of print_core( int state ) ********************/
+
+
+void print_nulls( int state )
+/***************************************************************
+
+ Description : print nulls
+
+ Concepts :
+
+ Use Global Variable: int *rrhs; | main.c
+ int *rlhs; | main.c
+ FILE *verbose_file; | main.c
+ action **parser; | mkpar.c
+ static int *null_rules; | this file
+
+ Use Functions :
+
+ Parameters : int state
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register action *p;
+ register int i, j, k, nnulls;
+
+ nnulls = 0;
+ for( p = parser[state]; p; p = p->next )
+ {
+ if( p->action_code == REDUCE &&
+ (p->suppressed == 0 || p->suppressed == 1) )
+ {
+ i = p->number;
+ if( rrhs[i] + 1 == rrhs[i+1] )
+ {
+ for( j = 0; j < nnulls && i > null_rules[j]; ++j )
+ continue;
+
+ if( j == nnulls )
+ {
+ ++nnulls;
+ null_rules[j] = i;
+ }
+ else if( i != null_rules[j] )
+ {
+ ++nnulls;
+ for( k = nnulls - 1; k > j; --k )
+ null_rules[k] = null_rules[k-1];
+ null_rules[j] = i;
+ }
+ } /* End if( rrhs[i] + 1 == rrhs[i+1] ) */
+ }
+ } /* End of for( p = parser[state]; p; p = p->next ) */
+
+ for( i = 0; i < nnulls; ++i )
+ {
+ j = null_rules[i];
+ mpu_fprintf( verbose_file, MPU_UCS2( " %s : . (%d)\n" ),
+ symbol_name[rlhs[j]], j - 2 );
+ }
+ mpu_fprintf( verbose_file, MPU_UCS2( "\n" ) );
+
+} /******* End of print_nulls( int state ) *******************/
+
+
+void print_shifts( action *p )
+/***************************************************************
+
+ Description : print shifts
+
+ Concepts :
+
+ Use Global Variable: char **symbol_name; | main.c
+ FILE *verbose_file; | main.c
+
+ Use Functions :
+
+ Parameters : action *p
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int count;
+ register action *q;
+
+ count = 0;
+ for( q = p; q; q = q->next )
+ {
+ if( q->suppressed < 2 && q->action_code == SHIFT ) ++count;
+ }
+
+ if( count > 0 )
+ {
+ for( ; p; p = p->next )
+ {
+ if( p->action_code == SHIFT && p->suppressed == 0 )
+ mpu_fprintf( verbose_file, MPU_UCS2( " %s shift %d\n" ),
+ symbol_name[p->symbol], p->number );
+ }
+ }
+
+} /******* End of print_shifts( action *p ) ******************/
+
+
+void print_reductions( action *p, int defred )
+/***************************************************************
+
+ Description : print reductions
+
+ Concepts :
+
+ Use Global Variable: char **symbol_name; | main.c
+ FILE *verbose_file; | main.c
+
+ Use Functions :
+
+ Parameters : action *p, int defred
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int k, anyreds;
+ register action *q;
+
+ anyreds = 0;
+ for( q = p; q ; q = q->next )
+ {
+ if( q->action_code == REDUCE && q->suppressed < 2 )
+ {
+ anyreds = 1;
+ break;
+ }
+ }
+
+ if( anyreds == 0 ) mpu_fprintf( verbose_file, MPU_UCS2( " . error\n" ) );
+ else
+ {
+ for( ; p; p = p->next )
+ {
+ if( p->action_code == REDUCE && p->number != defred )
+ {
+ k = p->number - 2;
+ if( p->suppressed == 0 )
+ mpu_fprintf( verbose_file, MPU_UCS2( " %s reduce %d\n" ),
+ symbol_name[p->symbol], k );
+ }
+ }
+
+ if( defred > 0 )
+ mpu_fprintf( verbose_file, MPU_UCS2( " . reduce %d\n" ),
+ defred - 2 );
+ }
+
+} /******* End of print_reductions( action *p, int defred ) **/
+
+
+void print_gotos( int stateno )
+/***************************************************************
+
+ Description : print gotos
+
+ Concepts :
+
+ Use Global Variable: char **symbol_name; | main.c
+ FILE *verbose_file; | main.c
+ shifts **shift_table; | lalr.c
+ int *accessing_symbol; | lalr.c
+
+ Use Functions :
+
+ Parameters : int stateno
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i, k;
+ register int as;
+ register int *to_state;
+ register shifts *sp;
+
+ mpu_putc( '\n', verbose_file );
+ sp = shift_table[stateno];
+ to_state = sp->shift;
+ for( i = 0; i < sp->nshifts; ++i )
+ {
+ k = to_state[i];
+ as = accessing_symbol[k];
+ if( ISVAR(as) )
+ mpu_fprintf( verbose_file, MPU_UCS2( " %s goto %d\n" ),
+ symbol_name[as], k );
+ }
+
+} /******* End of print_gotos( int stateno ) *****************/
+
+
+void print_actions( int stateno )
+/***************************************************************
+
+ Description : print actions
+
+ Concepts :
+
+ Use Global Variable: FILE *verbose_file; | main.c
+ shifts **shift_table; | lalr.c
+ int *accessing_symbol; | lalr.c
+ action **parser; | mkpar.c
+ int *defred; | mkpar.c
+ int final_state; | mkpar.c
+
+ Use Functions :
+ void print_shifts (action *p); | this file
+ void print_reductions (action *, int); | --/--
+ void print_gotos (int stateno); | this file
+
+ Parameters : int stateno
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register action *p;
+ register shifts *sp;
+ register int as;
+
+ if( stateno == final_state )
+ mpu_fprintf( verbose_file, MPU_UCS2( " $end accept\n" ) );
+
+ p = parser[stateno];
+ if( p )
+ {
+ print_shifts( p );
+ print_reductions( p, defred[stateno] );
+ }
+
+ sp = shift_table[stateno];
+ if( sp && sp->nshifts > 0 )
+ {
+ as = accessing_symbol[sp->shift[sp->nshifts - 1]];
+ if( ISVAR(as) ) print_gotos( stateno );
+ }
+
+} /******* End of print_actions( int stateno ) ***************/
+
+
+void print_state( int state )
+/***************************************************************
+
+ Description : print state
+
+ Concepts :
+
+ Use Global Variable: FILE *verbose_file; | main.c
+ int *SRconflicts; | mkpar.c
+ int *RRconflicts; | mkpar.c
+
+ Use Functions :
+ void print_conflicts (int state); | this file
+ void print_core (int state); | this file
+ void print_nulls (int state); | this file
+ void print_actions (int stateno); | this file
+
+ Parameters : int state
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ if( state ) mpu_fprintf( verbose_file, MPU_UCS2( "\n\n" ) );
+ if( SRconflicts[state] || RRconflicts[state] )
+ print_conflicts( state );
+ mpu_fprintf( verbose_file, MPU_UCS2( "state %d\n" ), state );
+ print_core( state );
+ print_nulls( state );
+ print_actions( state );
+
+} /******* End of print_state( int state ) *******************/
+
+
+void verbose( void )
+/***************************************************************
+
+ Description : verbose
+
+ Concepts :
+
+ Use Global Variable: int ntokens | main.c
+ int nrules; | main.c
+ int nvars; | main.c
+ char vflag; | main.c
+ FILE *verbose_file; | main.c
+ int nstates; | lr0.c
+ int nunused; | mkpar.c
+ int SRtotal; | mkpar.c
+ int RRtotal; | mkpar.c
+ static int *null_rules; | this file
+
+ Use Functions : void no_space (void); | error.c
+ void log_unused (void); | this file
+ void log_conflicts (void); | this file
+ void print_state (int state); | this file
+
+ Parameters : [void]
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int i;
+
+ if( !vflag ) return;
+
+ null_rules = (int *)MALLOC( nrules*sizeof(int) );
+ if( null_rules == 0 ) no_space();
+ mpu_fprintf( verbose_file, MPU_UCS2( "\n\n" ) );
+ for( i = 0; i < nstates; i++ ) print_state( i );
+ FREE( null_rules );
+
+ if( nunused ) log_unused();
+ if( SRtotal || RRtotal ) log_conflicts();
+
+ mpu_fprintf( verbose_file,
+ MPU_UCS2( "\n\n%d terminals, %d nonterminals\n" ),
+ ntokens, nvars );
+ mpu_fprintf( verbose_file,
+ MPU_UCS2( "%d grammar rules, %d states\n" ),
+ nrules - 2, nstates );
+
+ mpu_fprintf( verbose_file, MPU_UCS2( "\n\
+/************************ End of File **************************/\n" )
+ );
+
+} /******* End of verbose( void ) ****************************/
+
+#endif /* __NO_COMPILE */
+
+/******************* END OF FILE VERBOSE.C *******************/
diff --git a/src/warshall.c b/src/warshall.c
new file mode 100644
index 0000000..bfee572
--- /dev/null
+++ b/src/warshall.c
@@ -0,0 +1,140 @@
+
+/***************************************************************
+ WARSHALL.C
+
+ This file containts TRANSITIVE CLOSURE routines of ZUBR.
+
+ PART OF : ZUBR - Parsers generator for multiple syntax
+ language compilers .
+
+ COMPILE : .
+
+ NOTE : NONE .
+
+ Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev.
+ All Rights Reserved.
+ ***************************************************************/
+/*
+ This file contant RUSSIAN letters( code-page: UTF-8 )
+ ***************************************************************/
+
+#include <defs.h>
+
+#ifndef __NO_COMPILE
+
+
+void transitive_closure( unsigned *R, int n )
+/***************************************************************
+
+ Description : transitive_closure()
+
+ Concepts :
+
+ Use Global Variable:
+
+ Use Functions :
+
+ Parameters : unsigned *R, int n
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int rowsize;
+ register unsigned mask;
+ register unsigned *rowj;
+ register unsigned *rp;
+ register unsigned *rend;
+ register unsigned *ccol;
+ register unsigned *relend;
+ register unsigned *cword;
+ register unsigned *rowi;
+
+ rowsize = SIZE_IN_INT( n );
+ relend = R + n*rowsize;
+
+ cword = R;
+ mask = 1;
+ rowi = R;
+ while( rowi < relend )
+ {
+ ccol = cword;
+ rowj = R;
+
+ while( rowj < relend )
+ {
+ if( *ccol & mask )
+ {
+ rp = rowi;
+ rend = rowj + rowsize;
+ while( rowj < rend ) *rowj++ |= *rp++;
+ }
+ else
+ {
+ rowj += rowsize;
+ }
+ ccol += rowsize;
+
+ } /* End of while( rowj < relend ) */
+
+ mask <<= 1;
+ if( mask == 0 )
+ {
+ mask = 1;
+ cword++;
+ }
+ rowi += rowsize;
+
+ } /* End of while( rowi < relend ) */
+
+} /******* End of transitive_closure( unsigned *R, int n ) ***/
+
+
+void reflexive_transitive_closure( unsigned *R, int n )
+/***************************************************************
+
+ Description : transitive_closure()
+
+ Concepts :
+
+ Use Global Variable:
+
+ Use Functions : void transitive_closure( unsigned *R, int n );
+ | this file
+
+ Parameters : unsigned *R, int n
+
+ Return : [void]
+
+ ***************************************************************/
+{
+ register int rowsize;
+ register unsigned mask;
+ register unsigned *rp;
+ register unsigned *relend;
+
+ transitive_closure( R, n );
+
+ rowsize = SIZE_IN_INT( n );
+ relend = R + n*rowsize;
+
+ mask = 1;
+ rp = R;
+ while( rp < relend )
+ {
+ *rp |= mask;
+ mask <<= 1;
+ if( mask == 0 )
+ {
+ mask = 1;
+ rp++;
+ }
+ rp += rowsize;
+
+ } /* End of while( rp < relend ) */
+
+} /******* End of reflexive_transitive_closure( unsigned *R, int n ) ***/
+
+#endif /* __NO_COMPILE */
+
+/***************** END OF FILE WARSHALL.C ********************/