Пример #1
0
/**
	@brief Collect characters into a number, and create a JSON_NUMBER for it.
	@param parser Pointer to a parser.
	@param firstc The first character in the number.
	@return Pointer to a newly created jsonObject of type JSON_NUMBER, or NULL upon error.

	Collect digits, signs, decimal points, and 'E' or 'e' (for scientific notation) into
	a buffer.  Make sure that the result is numeric.  If it's not numeric by strict JSON
	rules, try to make it numeric by some judicious massaging (we aren't quite as strict
	as the official JSON rules).

	If successful, construct a jsonObject of type JSON_NUMBER containing the resulting
	numeric string.  Otherwise log an error message and return NULL.
*/
static jsonObject* get_number( Parser* parser, char firstc ) {

	if( parser->str_buf )
		buffer_reset( parser->str_buf );
	else
		parser->str_buf = buffer_init( 64 );

	growing_buffer* gb = parser->str_buf;
	OSRF_BUFFER_ADD_CHAR( gb, firstc );

	char c;

	for( ;; ) {
		c = parser_nextc( parser );
		if( isdigit( (unsigned char) c ) ||
			'.' == c ||
			'-' == c ||
			'+' == c ||
			'e' == c ||
			'E' == c ) {
			OSRF_BUFFER_ADD_CHAR( gb, c );
		} else {
			if( ! isspace( (unsigned char) c ) )
				parser_ungetc( parser );
			break;
		}
	}

	char* s = buffer_data( gb );
	if( ! jsonIsNumeric( s ) ) {
		char* temp = jsonScrubNumber( s );
		free( s );
		s = temp;
		if( !s ) {
			report_error( parser, parser->buff[ parser->index - 1 ],
					"Invalid numeric format" );
			return NULL;
		}
	}

	jsonObject* obj = jsonNewObject( NULL );
	obj->type = JSON_NUMBER;
	obj->value.s = s;

	return obj;
}
Пример #2
0
/**
	@brief Parse the JSON keyword "true", and create a JSON_BOOL for it.
	@param parser Pointer to a Parser.
	@return Pointer to a newly created jsonObject of type JSON_BOOL, or NULL upon error.

	We already saw a 't', or we wouldn't be here.  Make sure that the next three characters
	are 'r', 'u', and 'e', and that the character after that is not a letter or a digit.

	If all goes well, create a jsonObject of type JSON_BOOL, and return a pointer to it.
	Otherwise log an error message and return NULL.
*/
static jsonObject* get_true( Parser* parser ) {

	if( parser_nextc( parser ) != 'r' ||
		parser_nextc( parser ) != 'u' ||
		parser_nextc( parser ) != 'e' ) {
		report_error( parser, parser->buff[ parser->index - 1 ],
					  "Expected \"rue\" to follow \"t\"; didn't find it" );
		return NULL;
	}

	// Peek at the next character to make sure that it's kosher
	char c = parser_nextc( parser );
	if( ! isspace( (unsigned char) c ) )
		parser_ungetc( parser );

	if( isalnum( (unsigned char) c ) ) {
		report_error( parser, c, "Found letter or number after \"true\"" );
		return NULL;
	}

	// Everything's okay.  Return a JSON_BOOL.
	return jsonNewBoolObject( 1 );
}
Пример #3
0
void lex (parser *p)
{
#if LDEBUG
    if (p->ch) fprintf(stderr, "lex: p->ch = '%c'\n", p->ch);
    else fprintf(stderr, "lex: p->ch = NUL\n");
#endif

    if (p->ch == 0) {
	p->sym = EOT;
	return;
    }

    while (p->ch != 0) {
	switch (p->ch) {
	case ' ':
	case '\t':
	case '\r':
        case '\n': 
	    parser_getc(p);
	    break;
        case '+': 
	    p->sym = B_ADD;
	    parser_getc(p);
	    return;
        case '-': 
	    p->sym = B_SUB;
	    parser_getc(p);
	    return;
        case '*': 
	    if (p->targ == LIST) {
		/* treat '*' as wildcard */
		getword(p);
		return;
	    }
	    parser_getc(p);
	    if (p->ch == '*') {
		p->sym = B_KRON;
		parser_getc(p);
	    } else {
		p->sym = B_MUL;
	    }
	    return;
	case '\'':
	    p->sym = B_TRMUL;
	    parser_getc(p);
	    return;
        case '/': 
	    p->sym = B_DIV;
	    parser_getc(p);
	    return;
        case '\\': 
	    p->sym = B_LDIV;
	    parser_getc(p);
	    return;
        case '%': 
	    p->sym = B_MOD;
	    parser_getc(p);
	    return;
        case '^': 
	    p->sym = B_POW;
	    parser_getc(p);
	    return;
        case '&': 
	    parser_getc(p);
	    if (p->ch == '&') {
		p->sym = B_AND;
		parser_getc(p);
	    } else {
		p->sym = U_ADDR;
	    }
	    return;
        case '|': 
	    parser_getc(p);
	    if (p->ch == '|') {
		p->sym = B_OR;
		parser_getc(p);
	    } else {
		p->sym = B_VCAT;
	    }
	    return;
        case '!': 
	    parser_getc(p);
	    if (p->ch == '=') {
		p->sym = B_NEQ;
		parser_getc(p);
	    } else {
		p->sym = U_NOT;
	    }
	    return;
        case '=': 
	    parser_getc(p);
	    if (p->ch == '=') {
		/* allow "==" as synonym for "=" */
		parser_getc(p);
	    }
	    p->sym = B_EQ;
	    return;
        case '>': 
	    parser_getc(p);
	    if (p->ch == '=') {
		p->sym = B_GTE;
		parser_getc(p);
	    } else {
		p->sym = B_GT;
	    }
	    return;
        case '<': 
	    parser_getc(p);
	    if (p->ch == '=') {
		p->sym = B_LTE;
		parser_getc(p);
	    } else if (p->ch == '>') {
		p->sym = B_NEQ;
		parser_getc(p);
	    } else {
		p->sym = B_LT;
	    }
	    return;
        case '(': 
	    p->sym = G_LPR;
	    parser_getc(p);
	    return;
        case ')': 
	    p->sym = G_RPR;
	    parser_getc(p);
	    return;
        case '[': 
	    p->sym = G_LBR;
	    parser_getc(p);
	    return;
        case '{': 
	    p->sym = G_LCB;
	    parser_getc(p);
	    return;
        case '}': 
	    p->sym = G_RCB;
	    parser_getc(p);
	    return;
        case ']': 
	    p->sym = G_RBR;
	    parser_getc(p);
	    return;
        case '~':
	    p->sym = B_HCAT;
	    parser_getc(p);
	    return;
        case ',': 
	    p->sym = P_COM;
	    parser_getc(p);
	    return;
        case ';': 
	    if (p->targ == LIST) {
		p->sym = B_JOIN;
	    } else {
		/* used in matrix definition */
		p->sym = P_SEMI;
	    }
	    parser_getc(p);
	    return;
        case ':': 
	    p->sym = P_COL;
	    parser_getc(p);
	    return;
        case '?': 
	    p->sym = QUERY;
	    parser_getc(p);
	    return;
	case '.':
	    if (*p->point == '$') {
		p->sym = P_DOT;
		parser_getc(p);
		return;
	    }
	    parser_getc(p);
	    if (p->ch == '*') {
		p->sym = B_DOTMULT;
		parser_getc(p);
		return;
	    } else if (p->ch == '/') {
		p->sym = B_DOTDIV;
		parser_getc(p);
		return;
	    } else if (p->ch == '^') {
		p->sym = B_DOTPOW;
		parser_getc(p);
		return;
	    } else if (p->ch == '+') {
		p->sym = B_DOTADD;
		parser_getc(p);
		return;
	    } else if (p->ch == '-') {
		p->sym = B_DOTSUB;
		parser_getc(p);
		return;
	    } else if (p->ch == '=') {
		p->sym = B_DOTEQ;
		parser_getc(p);
		return;
	    } else if (p->ch == '>') {
		p->sym = B_DOTGT;
		parser_getc(p);
		if (p->ch == '=') {
		    p->sym = B_DOTGTE;
		    parser_getc(p);
		}
		return;
	    } else if (p->ch == '<') {
		p->sym = B_DOTLT;
		parser_getc(p);
		if (p->ch == '=') {
		    p->sym = B_DOTLTE;
		    parser_getc(p);
		}
		return;
	    } else if (p->ch == '.') {
		p->sym = B_ELLIP;
		parser_getc(p);
		return;
	    } else {
		/* not a "dot operator", so back up */
		parser_ungetc(p);
	    }
        default: 
	    if (p->targ == LIST && lag_range_sym(p)) {
		p->sym = B_RANGE;
		parser_getc(p);
		parser_getc(p);
		return;
	    }
	    if (p->targ == LIST && *(p->point - 2) == ' ' && 
		(bare_data_type(p->sym) || closing_sym(p->sym) ||
		 (p->sym == LAG))) {
		/* may be forming a list, but only if there are 
		   spaces between the terms */
		p->sym = B_LCAT;
		return;
	    }
	    if (isdigit(p->ch) || (p->ch == '.' && isdigit(*p->point))) {
		parse_number(p);
		return;
	    } else if (islower(p->ch) || isupper(p->ch) || 
		       word_start_special(p->ch)) {
		getword(p);
		return;
	    } else if (p->ch == '"') {
		p->idstr = get_quoted_string(p);
		return;
	    } else {
		parser_print_input(p);
		pprintf(p->prn, _("Invalid character '%c'\n"), p->ch);
		p->err = E_PARSE;
		return;
	    }
	} /* end ch switch */
    } /* end while ch != 0 */
}