/* Copyright 2009-2014 * Kaz Kylheku * Vancouver, Canada * All rights reserved. * * Redistribution of this software in source and binary forms, with or without * modification, is permitted provided that the following two conditions are met. * * Use of this software in any manner constitutes agreement with the disclaimer * which follows the two conditions. * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DAMAGES, HOWEVER CAUSED, * AND UNDER ANY THEORY OF LIABILITY, ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include "config.h" #include "lib.h" #include "signal.h" #include "unwind.h" #include "gc.h" #include "regex.h" #include "utf8.h" #include "match.h" #include "hash.h" #include "eval.h" #include "stream.h" #include "parser.h" val parser_s; static void parser_mark(val obj) { parser_t *p = coerce(parser_t *, obj->co.handle); gc_mark(p->stream); gc_mark(p->name); gc_mark(p->prepared_msg); gc_mark(p->syntax_tree); } static struct cobj_ops parser_ops = { eq, cobj_print_op, cobj_destroy_free_op, parser_mark, cobj_hash_op, }; val parser(val stream, val lineno) { parser_t *p = coerce(parser_t *, chk_malloc(sizeof *p)); val parser; p->lineno = 0; p->errors = 0; p->stream = nil; p->name = nil; p->prepared_msg = nil; p->syntax_tree = nil; p->scanner = 0; parser = cobj(coerce(mem_t *, p), parser_s, &parser_ops); p->lineno = c_num(default_arg(lineno, one)); p->stream = stream; return parser; } void open_txr_file(val spec_file, val *name, val *stream) { { FILE *in = w_fopen(c_str(spec_file), L"r"); if (in == 0) { spec_file = cat_str(list(spec_file, lit("txr"), nao), lit(".")); in = w_fopen(c_str(spec_file), L"r"); if (in == 0) uw_throwf(file_error_s, lit("unable to open ~a"), spec_file, nao); } *stream = make_stdio_stream(in, spec_file); *name = spec_file; } } val regex_parse(val string, val error_stream) { uses_or2; val parse_string = cat_str(list(lit("@\x01R"), string, nao), nil); val save_stream = std_error; val stream = make_string_byte_input_stream(parse_string); parser_t parser; error_stream = default_bool_arg(error_stream); std_error = if3(error_stream == t, std_output, or2(error_stream, std_null)); { int gc = gc_state(0); val name = if3(std_error != std_null, lit("regex"), lit("")); parse(stream, name, &parser); gc_state(gc); } std_error = save_stream; return parser.errors ? nil : parser.syntax_tree; } val lisp_parse(val source_in, val error_stream, val error_return_val) { uses_or2; val source = default_bool_arg(source_in); val input_stream = if3(stringp(source), make_string_byte_input_stream(source), or2(source, std_input)); val secret_token_stream = make_string_byte_input_stream(lit("@\x01" "E")); val name = if3(stringp(source), lit("string"), stream_get_prop(input_stream, name_k)); val stream = make_catenated_stream(list(secret_token_stream, input_stream, nao)); val saved_dyn = dyn_env; parser_t parser; dyn_env = make_env(nil, nil, dyn_env); error_stream = default_bool_arg(error_stream); error_stream = if3(error_stream == t, std_output, or2(error_stream, std_null)); class_check (error_stream, stream_s); env_vbind(dyn_env, stderr_s, error_stream); { int gc = gc_state(0); name = if3(std_error != std_null, name, lit("")); parse(stream, name, &parser); gc_state(gc); } dyn_env = saved_dyn; if (parser.errors) { if (missingp(error_return_val)) uw_throwf(syntax_error_s, lit("read: syntax error"), nao); return error_return_val; } return parser.syntax_tree; } void parse_init(void) { parser_s = intern(lit("parser"), user_package); parser_l_init(); }