void read_region_name( struct parse* parse ) { p_test_tk( parse, TK_ID ); struct name* name = t_extend_name( parse->region->body, parse->tk_text ); // Regions must be opened once. This works like modules in other languages. if ( name->object ) { if ( p_peek( parse ) == TK_COLON_2 ) { // It is assumed the object will always be a region. parse->region = ( struct region* ) name->object; } else { p_diag( parse, DIAG_POS_ERR, &parse->tk_pos, "duplicate region" ); p_diag( parse, DIAG_POS, &name->object->pos, "region already found here" ); p_bail( parse ); } } else { struct region* region = t_alloc_region( parse->task, name, false ); region->object.pos = parse->tk_pos; name->object = ®ion->object; list_append( &parse->task->regions, region ); parse->region = region; } p_read_tk( parse ); }
void read_dirc( struct parse* parse, struct pos* pos ) { // Directives can only appear in the upmost region. if ( parse->region != parse->task->region_upmost ) { p_diag( parse, DIAG_POS_ERR, pos, "directive not in upmost region" ); p_bail( parse ); } if ( parse->tk == TK_IMPORT ) { p_read_tk( parse ); if ( parse->source->imported ) { p_test_tk( parse, TK_LIT_STRING ); p_read_tk( parse ); } else { read_include( parse, pos, true ); } } else if ( strcmp( parse->tk_text, "include" ) == 0 ) { p_read_tk( parse ); if ( parse->source->imported ) { p_test_tk( parse, TK_LIT_STRING ); p_read_tk( parse ); } else { read_include( parse, pos, false ); } } else if ( strcmp( parse->tk_text, "define" ) == 0 || strcmp( parse->tk_text, "libdefine" ) == 0 ) { read_define( parse ); } else if ( strcmp( parse->tk_text, "library" ) == 0 ) { p_read_tk( parse ); read_library( parse, pos ); } else if ( strcmp( parse->tk_text, "encryptstrings" ) == 0 ) { parse->task->library->encrypt_str = true; p_read_tk( parse ); } else if ( strcmp( parse->tk_text, "nocompact" ) == 0 ) { parse->task->library->format = FORMAT_BIG_E; p_read_tk( parse ); } else if ( // NOTE: Not sure what these two are. strcmp( parse->tk_text, "wadauthor" ) == 0 || strcmp( parse->tk_text, "nowadauthor" ) == 0 ) { p_diag( parse, DIAG_POS_ERR, pos, "directive `%s` not supported", parse->tk_text ); p_bail( parse ); } else { p_diag( parse, DIAG_POS_ERR, pos, "unknown directive '%s'", parse->tk_text ); p_bail( parse ); } }
void read_region_body( struct parse* parse ) { while ( true ) { if ( p_is_dec( parse ) ) { struct dec dec; p_init_dec( &dec ); dec.name_offset = parse->region->body; p_read_dec( parse, &dec ); } else if ( parse->tk == TK_SCRIPT ) { if ( ! parse->task->library->imported ) { p_read_script( parse ); } else { p_skip_block( parse ); } } else if ( parse->tk == TK_REGION ) { p_read_region( parse ); } else if ( parse->tk == TK_IMPORT ) { p_read_import( parse, NULL ); } else if ( parse->tk == TK_SEMICOLON ) { p_read_tk( parse ); } else if ( parse->tk == TK_BRACE_R ) { break; } else { p_diag( parse, DIAG_POS_ERR, &parse->tk_pos, "unexpected %s", p_get_token_name( parse->tk ) ); p_bail( parse ); } } }
void p_read_lib( struct parse* parse ) { while ( true ) { if ( p_is_dec( parse ) ) { struct dec dec; p_init_dec( &dec ); dec.name_offset = parse->task->region_upmost->body; p_read_dec( parse, &dec ); } else if ( parse->tk == TK_SCRIPT ) { if ( parse->task->library->imported ) { p_skip_block( parse ); } else { p_read_script( parse ); } } else if ( parse->tk == TK_REGION ) { p_read_region( parse ); } else if ( parse->tk == TK_IMPORT ) { p_read_import( parse, NULL ); } else if ( parse->tk == TK_SEMICOLON ) { p_read_tk( parse ); } else if ( parse->tk == TK_HASH ) { struct pos pos = parse->tk_pos; p_read_tk( parse ); read_dirc( parse, &pos ); } else if ( parse->tk == TK_END ) { break; } else { p_diag( parse, DIAG_POS_ERR, &parse->tk_pos, "unexpected %s", p_get_token_name( parse->tk ) ); p_bail( parse ); } } // Library must have the #library directive. if ( parse->task->library->imported && ! parse->task->library->name.length ) { p_diag( parse, DIAG_ERR | DIAG_FILE, &parse->tk_pos, "#imported file missing #library directive" ); p_bail( parse ); } }
void read_library( struct parse* parse, struct pos* pos ) { p_test_tk( parse, TK_LIT_STRING ); if ( ! parse->tk_length ) { p_diag( parse, DIAG_POS_ERR, &parse->tk_pos, "library name is blank" ); p_bail( parse ); } int length = parse->tk_length; if ( length > MAX_LIB_NAME_LENGTH ) { p_diag( parse, DIAG_WARN | DIAG_FILE | DIAG_LINE | DIAG_COLUMN, &parse->tk_pos, "library name too long" ); p_diag( parse, DIAG_FILE, &parse->tk_pos, "library name can be up to %d characters long", MAX_LIB_NAME_LENGTH ); length = MAX_LIB_NAME_LENGTH; } char name[ MAX_LIB_NAME_LENGTH + 1 ]; memcpy( name, parse->tk_text, length ); name[ length ] = 0; p_read_tk( parse ); // Different #library directives in the same library must have the same // name. if ( parse->task->library->name.length && strcmp( parse->task->library->name.value, name ) != 0 ) { p_diag( parse, DIAG_POS_ERR, pos, "library has multiple names" ); p_diag( parse, DIAG_FILE | DIAG_LINE | DIAG_COLUMN, &parse->task->library->name_pos, "first name given here" ); p_bail( parse ); } // Each library must have a unique name. list_iter_t i; list_iter_init( &i, &parse->task->libraries ); while ( ! list_end( &i ) ) { struct library* lib = list_data( &i ); if ( lib != parse->task->library && strcmp( name, lib->name.value ) == 0 ) { p_diag( parse, DIAG_POS_ERR, pos, "duplicate library name" ); p_diag( parse, DIAG_FILE | DIAG_LINE | DIAG_COLUMN, &lib->name_pos, "library name previously found here" ); p_bail( parse ); } list_next( &i ); } str_copy( &parse->task->library->name, name, length ); parse->task->library->importable = true; parse->task->library->name_pos = *pos; }
void p_unexpect_last_name( struct parse* parse, struct pos* pos, const char* subject ) { p_diag( parse, DIAG_POS, ( pos ? pos : &parse->tk_pos ), "expecting %s here", subject ); }
void p_unexpect_diag( struct parse* parse ) { p_diag( parse, DIAG_POS_ERR | DIAG_SYNTAX, &parse->tk_pos, "unexpected %s", p_get_token_name( parse->tk ) ); }
inline const DVectorSlice DMatrixSlice::diag(difference_type k) const { return p_diag(k); }
inline DVectorSlice DMatrix::diag(difference_type k) { return p_diag(k); }