/* * Read a keyword: * - the buffer must be empty * - current_char must be ':' * - add ':' + the sequence of simple_chars that follows to the buffer * * If ':' is not followed by a simple char, return SMT2_TK_INVALID_KEYWORD * Otherwise return SMT2_TK_KEYWORD. */ static smt2_token_t smt2_read_keyword(lexer_t *lex) { reader_t *rd; string_buffer_t *buffer; int c; smt2_token_t tk; rd = &lex->reader; buffer = lex->buffer; c = reader_current_char(rd); assert(string_buffer_length(buffer) == 0 && c == ':'); do { string_buffer_append_char(buffer, c); c = reader_next_char(rd); } while (issimple(c)); string_buffer_close(buffer); tk = SMT2_TK_KEYWORD; if (string_buffer_length(buffer) <= 1) { tk = SMT2_TK_INVALID_KEYWORD; } return tk; }
/* * Read an hexadecimal literal * - the buffer must contain '#' * - current_char must be 'x' * - add 'x' and the sequence of hexadecimal digits that * follows to the buffer * - stop on the first character that's not hexadecimal * * The resulting token is stored in buffer * - return code: * SMT2_TK_HEXADECIMAL if the sequence is non-empty * SMT2_TK_INVALID_HEXADECIMAL if the sequence is empty */ static smt2_token_t smt2_read_hexa(lexer_t *lex) { reader_t *rd; string_buffer_t *buffer; int c; smt2_token_t tk; rd = &lex->reader; buffer = lex->buffer; c = reader_current_char(rd); assert(string_buffer_length(buffer) == 1 && buffer->data[0] == '#' && c == 'x'); do { string_buffer_append_char(buffer, c); c = reader_next_char(rd); } while (isxdigit(c)); string_buffer_close(buffer); tk = SMT2_TK_HEXADECIMAL; if (string_buffer_length(buffer) <= 2) { tk = SMT2_TK_INVALID_HEXADECIMAL; } return tk; }
/* * Read a binary literal * - the buffer must contain '#' * - current char must be 'b' * - add 'b' and the sequence of '0' and '1' that follows * to the buffer * - stop on the first character that's not '0' or '1' * * The resulting token is stored in buffer * - return code: * SMT2_TK_BINARY if the sequence is non-empty * SMT2_TK_INVALID_BINARY if the sequence is empty */ static smt2_token_t smt2_read_binary(lexer_t *lex) { reader_t *rd; string_buffer_t *buffer; int c; smt2_token_t tk; rd = &lex->reader; buffer = lex->buffer; c = reader_current_char(rd); assert(string_buffer_length(buffer) == 1 && buffer->data[0] == '#' && c == 'b'); do { string_buffer_append_char(buffer, c); c = reader_next_char(rd); } while (c == '0' || c == '1'); string_buffer_close(buffer); tk = SMT2_TK_BINARY; if (string_buffer_length(buffer) <= 2) { tk = SMT2_TK_INVALID_BINARY; } return tk; }
/* * Numbers that start with '0' * - the buffer must be empty * - current char must be '0' */ static smt2_token_t smt2_read_number0(lexer_t *lex) { reader_t *rd; string_buffer_t *buffer; int c; smt2_token_t tk; rd = &lex->reader; buffer = lex->buffer; c = reader_current_char(rd); assert(string_buffer_length(buffer) == 0 && c == '0'); // add '0' string_buffer_append_char(buffer, c); c = reader_next_char(rd); tk = SMT2_TK_NUMERAL; if (c == '.') { // parse a decimal '0.<digits>' do { string_buffer_append_char(buffer, c); c = reader_next_char(rd); } while (isdigit(c)); tk = SMT2_TK_DECIMAL; if (string_buffer_length(buffer) <= 2) { tk = SMT2_TK_INVALID_DECIMAL; // '0.' but not digit after that } } else if (isdigit(c)) { /* * invalid numeral such as '00..' or '05...' * put all the digits that follow '0' in the buffer * to give a nicer error message */ do { string_buffer_append_char(buffer, c); c = reader_next_char(rd); } while (isdigit(c)); tk = SMT2_TK_INVALID_NUMERAL; } string_buffer_close(buffer); return tk; }
/* * Read a quoted symbol: any sequence of characters delimited by '|' * - exceptions: no '\' allowed in the symbol * - all characters between '|' must be printable * - the delimiting '|' are not part of the symbol * * - the buffer must be empty * - current char must be '|' * * Return SMT2_TK_INVALID_SYMBOL if a non-printable character * or '\' is found before the closing '|'. Return SMT2_TK_QSYMBOL * otherwise. */ static smt2_token_t smt2_read_quoted_symbol(lexer_t *lex) { reader_t *rd; string_buffer_t *buffer; int c; smt2_token_t tk; rd = &lex->reader; buffer = lex->buffer; assert(string_buffer_length(buffer) == 0 && reader_current_char(rd) == '|'); for (;;) { c = reader_next_char(rd); if (c == '|' || c == '\\' || !ok_char(c)) { // (!isprint(c) && !isspace(c))) { // HACK TO PARSE BENCHMARKS // either the terminator '|' or a character not allowed in quoted symbols break; } string_buffer_append_char(buffer, c); } string_buffer_close(buffer); tk = SMT2_TK_INVALID_SYMBOL; if (c == '|') { // consume the closing '|' reader_next_char(rd); tk = SMT2_TK_QSYMBOL; } return tk; }
/* * Read a simple symbol * - the buffer must be empty * - current_char must be simple * - read the sequence of simple chars and add it to the buffer * * If the symbol is a reserved word, return the corresponding * token id. Otherwise, return SMT2_TK_SYMBOL. */ static smt2_token_t smt2_read_symbol(lexer_t *lex) { reader_t *rd; string_buffer_t *buffer; const keyword_t *kw; int c; smt2_token_t tk; rd = &lex->reader; buffer = lex->buffer; c = reader_current_char(rd); assert(string_buffer_length(buffer) == 0 && issimple(c)); do { string_buffer_append_char(buffer, c); c = reader_next_char(rd); } while (issimple(c)); string_buffer_close(buffer); tk = SMT2_TK_SYMBOL; kw = in_smt2_tk(buffer->data, buffer->index); if (kw != NULL) { tk = kw->tk; } return tk; }
/* * Numbers that don't start with '0' * - the buffer must be empty * - current char must be a digit '1' to '9' * - read the sequence of digits that follows and add it to the buffer * - if the character after this sequence is '.' then read as a DECIMAL * otherwise the token is a NUMERAL. * * Return code: * - SMT2_INVALID_DECIMAL if the '.' is not followed by a digit */ static smt2_token_t smt2_read_number(lexer_t *lex) { reader_t *rd; string_buffer_t *buffer; int c; smt2_token_t tk; uint32_t i; rd = &lex->reader; buffer = lex->buffer; c = reader_current_char(rd); assert(string_buffer_length(buffer) == 0 && isdigit(c) && c != '0'); // first sequence of digits do { string_buffer_append_char(buffer, c); c = reader_next_char(rd); } while (isdigit(c)); tk = SMT2_TK_NUMERAL; if (c == '.') { i = string_buffer_length(buffer); // attempt to parse a DECIMAL do { string_buffer_append_char(buffer, c); c = reader_next_char(rd); } while (isdigit(c)); tk = SMT2_TK_DECIMAL; if (string_buffer_length(buffer) <= i+1) { tk = SMT2_TK_INVALID_DECIMAL; } } string_buffer_close(buffer); return tk; }
/* * Read a hexadecimal constant: * lex->current_char = 'x' and lex->buffer contains "0" */ static yices_token_t read_hex_constant(lexer_t *lex) { reader_t *rd; string_buffer_t *buffer; int c; rd = &lex->reader; c = reader_current_char(rd); buffer = lex->buffer; do { string_buffer_append_char(buffer, c); c = reader_next_char(rd); } while (isxdigit(c)); string_buffer_close(buffer); if (string_buffer_length(buffer) <= 2) { return TK_EMPTY_HEXCONST; // empty constant } else { return TK_HEX_CONSTANT; } }
bool string_buffer_append_string_buffer(StringBuffer* dst, const StringBuffer* src) { return string_buffer_append_bytes(dst, string_buffer_cstr(src), string_buffer_length(src)); }