diff options
| author | kx <kx@radix-linux.su> | 2026-09-30 21:14:58 +0300 |
|---|---|---|
| committer | kx <kx@radix-linux.su> | 2026-09-30 21:14:58 +0300 |
| commit | 5b1c65152f77e03a4800fceae32d16efe2dadc9c (patch) | |
| tree | caffe4b2235503cccfedfb772dc266cb311840b3 /src | |
| parent | 8b354d2b9f2640d90705abd324a413a0d8fa3867 (diff) | |
| download | zubr-trunk.tar.xz | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 29 | ||||
| -rw-r--r-- | src/closure.c | 429 | ||||
| -rw-r--r-- | src/defs.h.in | 573 | ||||
| -rw-r--r-- | src/error.c | 550 | ||||
| -rw-r--r-- | src/lalr.c | 956 | ||||
| -rw-r--r-- | src/lr0.c | 1035 | ||||
| -rw-r--r-- | src/main.c | 1372 | ||||
| -rw-r--r-- | src/mkpar.c | 619 | ||||
| -rw-r--r-- | src/output.c | 2071 | ||||
| -rw-r--r-- | src/port.c | 109 | ||||
| -rw-r--r-- | src/reader.c | 2769 | ||||
| -rw-r--r-- | src/skeleton.c | 663 | ||||
| -rw-r--r-- | src/symtab.c | 260 | ||||
| -rw-r--r-- | src/verbose.c | 584 | ||||
| -rw-r--r-- | src/warshall.c | 140 |
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 ********************/ |
