int pn_scanner_symbol(pn_scanner_t *scanner, const char *str) { char c = str[1]; if (c == '"') { return pn_scanner_quoted(scanner, str, 2, PN_TOK_SYMBOL); } else { int n = pn_scanner_alpha_end(scanner, str, 1); pn_scanner_emit(scanner, PN_TOK_SYMBOL, str, n); return 0; } }
int pn_scanner_alpha(pn_scanner_t *scanner, const char *str) { int n = pn_scanner_alpha_end(scanner, str, 0); pn_token_type_t type; if (!strncmp(str, "true", n)) { type = PN_TOK_TRUE; } else if (!strncmp(str, "false", n)) { type = PN_TOK_FALSE; } else if (!strncmp(str, "null", n)) { type = PN_TOK_NULL; } else { type = PN_TOK_ID; } pn_scanner_emit(scanner, type, str, n); return type == PN_TOK_ERR ? pn_scanner_err(scanner, PN_ERR, "unrecognized keyword") : 0; }
int pn_scanner_quoted(pn_scanner_t *scanner, const char *str, int start, pn_token_type_t type) { bool escape = false; for (int i = start; true; i++) { char c = str[i]; if (escape) { escape = false; } else { switch (c) { case '\0': case '"': pn_scanner_emit(scanner, c ? type : PN_TOK_ERR, str, c ? i + 1 : i); return c ? 0 : pn_scanner_err(scanner, PN_ERR, "missmatched quote"); case '\\': escape = true; break; } } } }
int pn_scanner_scan(pn_scanner_t *scanner) { const char *str = scanner->position; char n; for (char c; true; str++) { c = *str; switch (c) { case '{': return pn_scanner_single(scanner, str, PN_TOK_LBRACE); case '}': return pn_scanner_single(scanner, str, PN_TOK_RBRACE); case'[': return pn_scanner_single(scanner, str, PN_TOK_LBRACKET); case ']': return pn_scanner_single(scanner, str, PN_TOK_RBRACKET); case '=': return pn_scanner_single(scanner, str, PN_TOK_EQUAL); case ',': return pn_scanner_single(scanner, str, PN_TOK_COMMA); case '.': n = *(str+1); if ((n >= '0' && n <= '9')) { return pn_scanner_number(scanner, str); } else { return pn_scanner_single(scanner, str, PN_TOK_DOT); } case '@': return pn_scanner_single(scanner, str, PN_TOK_AT); case '$': return pn_scanner_single(scanner, str, PN_TOK_DOLLAR); case '-': n = *(str+1); if ((n >= '0' && n <= '9') || n == '.') { return pn_scanner_number(scanner, str); } else { return pn_scanner_single(scanner, str, PN_TOK_NEG); } case '+': n = *(str+1); if ((n >= '0' && n <= '9') || n == '.') { return pn_scanner_number(scanner, str); } else { return pn_scanner_single(scanner, str, PN_TOK_POS); } case ' ': case '\t': case '\r': case '\v': case '\f': case '\n': break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return pn_scanner_number(scanner, str); case ':': return pn_scanner_symbol(scanner, str); case '"': return pn_scanner_string(scanner, str); case 'b': if (str[1] == '"') { return pn_scanner_binary(scanner, str); } case 'a': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': return pn_scanner_alpha(scanner, str); case '\0': pn_scanner_emit(scanner, PN_TOK_EOS, str, 0); return PN_EOS; default: pn_scanner_emit(scanner, PN_TOK_ERR, str, 1); return pn_scanner_err(scanner, PN_ERR, "illegal character"); } } }
int pn_scanner_single(pn_scanner_t *scanner, const char *str, pn_token_type_t type) { pn_scanner_emit(scanner, type, str, 1); return 0; }