struct jx *jx_copy( struct jx *j ) { if(!j) return 0; switch(j->type) { case JX_NULL: return jx_null(); case JX_DOUBLE: return jx_double(j->u.double_value); case JX_BOOLEAN: return jx_boolean(j->u.boolean_value); case JX_INTEGER: return jx_integer(j->u.integer_value); case JX_SYMBOL: return jx_symbol(j->u.symbol_name); case JX_STRING: return jx_string(j->u.string_value); case JX_ARRAY: return jx_array(jx_item_copy(j->u.items)); case JX_OBJECT: return jx_object(jx_pair_copy(j->u.pairs)); case JX_OPERATOR: return jx_operator(j->u.oper.type,jx_copy(j->u.oper.left),jx_copy(j->u.oper.right)); case JX_FUNCTION: return jx_function(j->u.func.function, jx_copy(j->u.func.arguments)); case JX_ERROR: return jx_error(jx_copy(j->u.err)); } /* not reachable, but some compilers complain. */ return 0; }
struct jx * jx_eval( struct jx *j, struct jx *context ) { if(!j) return 0; switch(j->type) { case JX_SYMBOL: if(context) { struct jx *result = jx_lookup(context,j->u.symbol_name); if(result) return jx_copy(result); } return jx_null(); case JX_DOUBLE: case JX_BOOLEAN: case JX_INTEGER: case JX_STRING: case JX_NULL: return jx_copy(j); case JX_ARRAY: return jx_array(jx_eval_item(j->u.items,context)); case JX_OBJECT: return jx_object(jx_eval_pair(j->u.pairs,context)); case JX_OPERATOR: return jx_eval_operator(&j->u.oper,context); } /* not reachable, but some compilers complain. */ return 0; }
struct jx * jx_arrayv( struct jx *value, ... ) { va_list args; va_start(args,value); struct jx *array = jx_array(0); while(value) { jx_array_append(array,value); value = va_arg(args,struct jx *); } va_end(args); return array; }
struct jx *jx_array_concat( struct jx *array, ...) { struct jx *result = jx_array(NULL); struct jx_item **tail = &result->u.items; va_list ap; va_start(ap, array); for(struct jx *a = array; a; a = va_arg(ap, struct jx *)) { if (!jx_istype(a, JX_ARRAY)) { break; } *tail = a->u.items; while(*tail) tail = &(*tail)->next; free(a); } va_end(ap); return result; }
struct jx * jx_parse( struct jx_parser *s ) { jx_token_t t = jx_scan(s); switch(t) { case JX_TOKEN_EOF: return 0; case JX_TOKEN_LBRACE: return jx_object(jx_parse_pair_list(s)); case JX_TOKEN_LBRACKET: return jx_array(jx_parse_item_list(s)); case JX_TOKEN_STRING: return jx_string(s->token); case JX_TOKEN_INTEGER: return jx_integer(s->integer_value); case JX_TOKEN_DOUBLE: return jx_double(s->double_value); case JX_TOKEN_TRUE: return jx_boolean(1); case JX_TOKEN_FALSE: return jx_boolean(0); case JX_TOKEN_NULL: return jx_null(); case JX_TOKEN_SYMBOL: if(s->strict_mode) { jx_parse_error(s,"symbols are not allowed in strict parsing mode"); return 0; } else { return jx_symbol(s->token); } case JX_TOKEN_RBRACE: case JX_TOKEN_RBRACKET: case JX_TOKEN_COMMA: case JX_TOKEN_COLON: case JX_TOKEN_ERROR: jx_parse_error(s,"unexpected token"); return 0; } /* We shouldn't get here, since all the token types should be handled above. But just in case... */ jx_parse_error(s,"parse error"); return 0; }