/*************************************************************** 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 #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 *******************/