summaryrefslogtreecommitdiff
path: root/src/reader.c
diff options
context:
space:
mode:
authorkx <kx@radix-linux.su>2026-09-30 21:14:58 +0300
committerkx <kx@radix-linux.su>2026-09-30 21:14:58 +0300
commit5b1c65152f77e03a4800fceae32d16efe2dadc9c (patch)
treecaffe4b2235503cccfedfb772dc266cb311840b3 /src/reader.c
parent8b354d2b9f2640d90705abd324a413a0d8fa3867 (diff)
downloadzubr-trunk.tar.xz
Version 4.1.0HEAD4.1.0trunk
Diffstat (limited to 'src/reader.c')
-rw-r--r--src/reader.c2769
1 files changed, 2769 insertions, 0 deletions
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 *******************/