/*Used to determine what type is coming next in the stream *Inputs: * in - the stream to read from * c - the first non-whitespace character to look at*/ object_type next_type(FILE *in, char c){ int next_char; if(c == EOF){ printf("Got EOF, exiting\n"); exit(0); } if(c == '#'){ /*a boolean or character*/ next_char = peek(in); switch(next_char){ case 't': case 'f': return BOOLEAN; case '\\': return CHARACTER; default: fprintf(stderr, "Unknown boolean or character literal\n"); exit(1); } }else if (isdigit(c) || (c == '-' && isdigit(peek(in)))){ ungetc(c, in); return FIXNUM; }else if(c == '('){ if(peek(in) == ')'){ return EMPTY_LIST; }else{ return PAIR; } }else if(c == '"'){ return STRING; /*if this is the start of a symbol*/ }else if(is_symbol_start(c) || /*or +/- by themselves*/ ((c == '+' || c == '-') && is_delimiter(peek(in)))){ //put this first character back ungetc(c, in); return SYMBOL; }else{ fprintf(stderr, "Bad input. Unexpected '%c'\n", c); exit(1); } fprintf(stderr, "No object type, no error... wtf?\n"); exit(1); }
static void pgn_read_token(pgn_t * pgn) { ASSERT(pgn!=NULL); // skip white-space characters pgn_skip_blanks(pgn); // init pgn->token_type = TOKEN_ERROR; strcpy(pgn->token_string,""); pgn->token_length = 0; pgn->token_line = pgn->char_line; pgn->token_column = pgn->char_column; // determine token type if (false) { } else if (pgn->char_hack == CHAR_EOF) { pgn->token_type = TOKEN_EOF; } else if (strchr(".[]()<>",pgn->char_hack) != NULL) { // single-character token pgn->token_type = pgn->char_hack; sprintf(pgn->token_string,"%c",pgn->char_hack); pgn->token_length = 1; } else if (pgn->char_hack == '*') { pgn->token_type = TOKEN_RESULT; sprintf(pgn->token_string,"%c",pgn->char_hack); pgn->token_length = 1; } else if (pgn->char_hack == '!') { pgn_char_read(pgn); if (false) { } else if (pgn->char_hack == '!') { // "!!" pgn->token_type = TOKEN_NAG; strcpy(pgn->token_string,"3"); pgn->token_length = 1; } else if (pgn->char_hack == '?') { // "!?" pgn->token_type = TOKEN_NAG; strcpy(pgn->token_string,"5"); pgn->token_length = 1; } else { // "!" pgn_char_unread(pgn); pgn->token_type = TOKEN_NAG; strcpy(pgn->token_string,"1"); pgn->token_length = 1; } } else if (pgn->char_hack == '?') { pgn_char_read(pgn); if (false) { } else if (pgn->char_hack == '?') { // "??" pgn->token_type = TOKEN_NAG; strcpy(pgn->token_string,"4"); pgn->token_length = 1; } else if (pgn->char_hack == '!') { // "?!" pgn->token_type = TOKEN_NAG; strcpy(pgn->token_string,"6"); pgn->token_length = 1; } else { // "?" pgn_char_unread(pgn); pgn->token_type = TOKEN_NAG; strcpy(pgn->token_string,"2"); pgn->token_length = 1; } } else if (is_symbol_start(pgn->char_hack)) { // symbol, integer, or result pgn->token_type = TOKEN_INTEGER; pgn->token_length = 0; do { if (pgn->token_length >= PGN_STRING_SIZE-1) { my_fatal("pgn_read_token(): symbol too long at line %d, column %d\n",pgn->char_line,pgn->char_column); } if (!isdigit(pgn->char_hack)) pgn->token_type = TOKEN_SYMBOL; pgn->token_string[pgn->token_length++] = pgn->char_hack; pgn_char_read(pgn); } while (is_symbol_next(pgn->char_hack)); pgn_char_unread(pgn); ASSERT(pgn->token_length>0&&pgn->token_length<PGN_STRING_SIZE); pgn->token_string[pgn->token_length] = '\0'; if (my_string_equal(pgn->token_string,"1-0") || my_string_equal(pgn->token_string,"0-1") || my_string_equal(pgn->token_string,"1/2-1/2")) { pgn->token_type = TOKEN_RESULT; } } else if (pgn->char_hack == '"') { // string pgn->token_type = TOKEN_STRING; pgn->token_length = 0; while (true) { pgn_char_read(pgn); if (pgn->char_hack == CHAR_EOF) { my_fatal("pgn_read_token(): EOF in string at line %d, column %d\n",pgn->char_line,pgn->char_column); } if (pgn->char_hack == '"') break; if (pgn->char_hack == '\\') { pgn_char_read(pgn); if (pgn->char_hack == CHAR_EOF) { my_fatal("pgn_read_token(): EOF in string at line %d, column %d\n",pgn->char_line,pgn->char_column); } if (pgn->char_hack != '"' && pgn->char_hack != '\\') { // bad escape, ignore if (pgn->token_length >= PGN_STRING_SIZE-1) { my_fatal("pgn_read_token(): string too long at line %d, column %d\n",pgn->char_line,pgn->char_column); } pgn->token_string[pgn->token_length++] = '\\'; } } if (pgn->token_length >= PGN_STRING_SIZE-1) { my_fatal("pgn_read_token(): string too long at line %d, column %d\n",pgn->char_line,pgn->char_column); } pgn->token_string[pgn->token_length++] = pgn->char_hack; } ASSERT(pgn->token_length>=0&&pgn->token_length<PGN_STRING_SIZE); pgn->token_string[pgn->token_length] = '\0'; } else if (pgn->char_hack == '$') { // NAG pgn->token_type = TOKEN_NAG; pgn->token_length = 0; while (true) { pgn_char_read(pgn); if (!isdigit(pgn->char_hack)) break; if (pgn->token_length >= 3) { my_fatal("pgn_read_token(): NAG too long at line %d, column %d\n",pgn->char_line,pgn->char_column); } pgn->token_string[pgn->token_length++] = pgn->char_hack; } pgn_char_unread(pgn); if (pgn->token_length == 0) { my_fatal("pgn_read_token(): malformed NAG at line %d, column %d\n",pgn->char_line,pgn->char_column); } ASSERT(pgn->token_length>0&&pgn->token_length<=3); pgn->token_string[pgn->token_length] = '\0'; } else { // unknown token // my_fatal("lexical error at line %d, column %d\n",pgn->char_line,pgn->char_column); } }