diff options
Diffstat (limited to 'src/reader.c')
| -rw-r--r-- | src/reader.c | 2769 |
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 *******************/ |
