Merge branch 'abandon-flex'
This commit is contained in:
		
						commit
						107a1dc339
					
				|  | @ -1,179 +0,0 @@ | ||||||
| # - Find flex executable and provides a macro to generate custom build rules |  | ||||||
| # |  | ||||||
| # The module defines the following variables: |  | ||||||
| #  FLEX_FOUND - true is flex executable is found |  | ||||||
| #  FLEX_EXECUTABLE - the path to the flex executable |  | ||||||
| #  FLEX_VERSION - the version of flex |  | ||||||
| #  FLEX_LIBRARIES - The flex libraries |  | ||||||
| # |  | ||||||
| # The minimum required version of flex can be specified using the |  | ||||||
| # standard syntax, e.g. FIND_PACKAGE(FLEX 2.5.13) |  | ||||||
| # |  | ||||||
| # |  | ||||||
| # If flex is found on the system, the module provides the macro: |  | ||||||
| #  FLEX_TARGET(Name FlexInput FlexOutput [COMPILE_FLAGS <string>]) |  | ||||||
| # which creates a custom command  to generate the <FlexOutput> file from |  | ||||||
| # the <FlexInput> file.  If  COMPILE_FLAGS option is specified, the next |  | ||||||
| # parameter is added to the flex  command line. Name is an alias used to |  | ||||||
| # get  details of  this custom  command.  Indeed the  macro defines  the |  | ||||||
| # following variables: |  | ||||||
| #  FLEX_${Name}_DEFINED - true is the macro ran successfully |  | ||||||
| #  FLEX_${Name}_OUTPUTS - the source file generated by the custom rule, an |  | ||||||
| #  alias for FlexOutput |  | ||||||
| #  FLEX_${Name}_INPUT - the flex source file, an alias for ${FlexInput} |  | ||||||
| # |  | ||||||
| # Flex scanners oftenly use tokens  defined by Bison: the code generated |  | ||||||
| # by Flex  depends of the header  generated by Bison.   This module also |  | ||||||
| # defines a macro: |  | ||||||
| #  ADD_FLEX_BISON_DEPENDENCY(FlexTarget BisonTarget) |  | ||||||
| # which  adds the  required dependency  between a  scanner and  a parser |  | ||||||
| # where  <FlexTarget>  and <BisonTarget>  are  the  first parameters  of |  | ||||||
| # respectively FLEX_TARGET and BISON_TARGET macros. |  | ||||||
| # |  | ||||||
| #  ==================================================================== |  | ||||||
| #  Example: |  | ||||||
| # |  | ||||||
| #   find_package(BISON) |  | ||||||
| #   find_package(FLEX) |  | ||||||
| # |  | ||||||
| #   BISON_TARGET(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp |  | ||||||
| #   FLEX_TARGET(MyScanner lexer.l  ${CMAKE_CURRENT_BIANRY_DIR}/lexer.cpp) |  | ||||||
| #   ADD_FLEX_BISON_DEPENDENCY(MyScanner MyParser) |  | ||||||
| # |  | ||||||
| #   include_directories(${CMAKE_CURRENT_BINARY_DIR}) |  | ||||||
| #   add_executable(Foo |  | ||||||
| #      Foo.cc |  | ||||||
| #      ${BISON_MyParser_OUTPUTS} |  | ||||||
| #      ${FLEX_MyScanner_OUTPUTS} |  | ||||||
| #   ) |  | ||||||
| #  ==================================================================== |  | ||||||
| 
 |  | ||||||
| #============================================================================= |  | ||||||
| # Copyright 2009 Kitware, Inc. |  | ||||||
| # Copyright 2006 Tristan Carel |  | ||||||
| # Modified 2010 by Jon Siwek, backporting for CMake 2.6 compat |  | ||||||
| # |  | ||||||
| # Distributed under the OSI-approved BSD License (the "License"): |  | ||||||
| # CMake - Cross Platform Makefile Generator |  | ||||||
| # Copyright 2000-2009 Kitware, Inc., Insight Software Consortium |  | ||||||
| # All rights reserved. |  | ||||||
| 
 |  | ||||||
| # Redistribution and use in source and binary forms, with or without |  | ||||||
| # modification, are permitted provided that the following conditions |  | ||||||
| # are met: |  | ||||||
| # |  | ||||||
| # * Redistributions of source code must retain the above copyright |  | ||||||
| #   notice, this list of conditions and the following disclaimer. |  | ||||||
| # |  | ||||||
| # * 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. |  | ||||||
| # |  | ||||||
| # * Neither the names of Kitware, Inc., the Insight Software Consortium, |  | ||||||
| #   nor the names of their contributors may be used to endorse or promote |  | ||||||
| #   products derived from this software without specific prior written |  | ||||||
| #   permission. |  | ||||||
| # |  | ||||||
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |  | ||||||
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |  | ||||||
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |  | ||||||
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |  | ||||||
| # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |  | ||||||
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |  | ||||||
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |  | ||||||
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |  | ||||||
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |  | ||||||
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |  | ||||||
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | ||||||
| # |  | ||||||
| # This software is distributed WITHOUT ANY WARRANTY; without even the |  | ||||||
| # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |  | ||||||
| # See the License for more information. |  | ||||||
| #============================================================================= |  | ||||||
| 
 |  | ||||||
| FIND_PROGRAM(FLEX_EXECUTABLE flex DOC "path to the flex executable") |  | ||||||
| MARK_AS_ADVANCED(FLEX_EXECUTABLE) |  | ||||||
| 
 |  | ||||||
| FIND_LIBRARY(FL_LIBRARY NAMES fl |  | ||||||
|   DOC "path to the fl library") |  | ||||||
| MARK_AS_ADVANCED(FL_LIBRARY) |  | ||||||
| SET(FLEX_LIBRARIES ${FL_LIBRARY}) |  | ||||||
| 
 |  | ||||||
| IF(FLEX_EXECUTABLE) |  | ||||||
| 
 |  | ||||||
|   EXECUTE_PROCESS(COMMAND ${FLEX_EXECUTABLE} --version |  | ||||||
|     OUTPUT_VARIABLE FLEX_version_output |  | ||||||
|     ERROR_VARIABLE FLEX_version_error |  | ||||||
|     RESULT_VARIABLE FLEX_version_result |  | ||||||
|     OUTPUT_STRIP_TRAILING_WHITESPACE) |  | ||||||
|   IF(NOT ${FLEX_version_result} EQUAL 0) |  | ||||||
|     IF(FLEX_FIND_REQUIRED) |  | ||||||
|       MESSAGE(SEND_ERROR "Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}") |  | ||||||
|     ELSE() |  | ||||||
|       MESSAGE("Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}\nFLEX_VERSION will not be available") |  | ||||||
|     ENDIF() |  | ||||||
|   ELSE() |  | ||||||
|     STRING(REGEX REPLACE "^flex (.*)$" "\\1" |  | ||||||
|       FLEX_VERSION "${FLEX_version_output}") |  | ||||||
|   ENDIF() |  | ||||||
| 
 |  | ||||||
|   #============================================================ |  | ||||||
|   # FLEX_TARGET (public macro) |  | ||||||
|   #============================================================ |  | ||||||
|   # |  | ||||||
|   MACRO(FLEX_TARGET Name Input Output) |  | ||||||
|     SET(FLEX_TARGET_usage "FLEX_TARGET(<Name> <Input> <Output> [COMPILE_FLAGS <string>]") |  | ||||||
|     IF(${ARGC} GREATER 3) |  | ||||||
|       IF(${ARGC} EQUAL 5) |  | ||||||
|         IF("${ARGV3}" STREQUAL "COMPILE_FLAGS") |  | ||||||
|           SET(FLEX_EXECUTABLE_opts  "${ARGV4}") |  | ||||||
|           SEPARATE_ARGUMENTS(FLEX_EXECUTABLE_opts) |  | ||||||
|         ELSE() |  | ||||||
|           MESSAGE(SEND_ERROR ${FLEX_TARGET_usage}) |  | ||||||
|         ENDIF() |  | ||||||
|       ELSE() |  | ||||||
|         MESSAGE(SEND_ERROR ${FLEX_TARGET_usage}) |  | ||||||
|       ENDIF() |  | ||||||
|     ENDIF() |  | ||||||
| 
 |  | ||||||
|     ADD_CUSTOM_COMMAND(OUTPUT ${Output} |  | ||||||
|       COMMAND ${FLEX_EXECUTABLE} |  | ||||||
|       ARGS ${FLEX_EXECUTABLE_opts} -o${Output} ${Input} |  | ||||||
|       DEPENDS ${Input} |  | ||||||
|       COMMENT "[FLEX][${Name}] Building scanner with flex ${FLEX_VERSION}" |  | ||||||
|       WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) |  | ||||||
| 
 |  | ||||||
|     SET(FLEX_${Name}_DEFINED TRUE) |  | ||||||
|     SET(FLEX_${Name}_OUTPUTS ${Output}) |  | ||||||
|     SET(FLEX_${Name}_INPUT ${Input}) |  | ||||||
|     SET(FLEX_${Name}_COMPILE_FLAGS ${FLEX_EXECUTABLE_opts}) |  | ||||||
|   ENDMACRO(FLEX_TARGET) |  | ||||||
|   #============================================================ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   #============================================================ |  | ||||||
|   # ADD_FLEX_BISON_DEPENDENCY (public macro) |  | ||||||
|   #============================================================ |  | ||||||
|   # |  | ||||||
|   MACRO(ADD_FLEX_BISON_DEPENDENCY FlexTarget BisonTarget) |  | ||||||
| 
 |  | ||||||
|     IF(NOT FLEX_${FlexTarget}_OUTPUTS) |  | ||||||
|       MESSAGE(SEND_ERROR "Flex target `${FlexTarget}' does not exists.") |  | ||||||
|     ENDIF() |  | ||||||
| 
 |  | ||||||
|     IF(NOT BISON_${BisonTarget}_OUTPUT_HEADER) |  | ||||||
|       MESSAGE(SEND_ERROR "Bison target `${BisonTarget}' does not exists.") |  | ||||||
|     ENDIF() |  | ||||||
| 
 |  | ||||||
|     SET_SOURCE_FILES_PROPERTIES(${FLEX_${FlexTarget}_OUTPUTS} |  | ||||||
|       PROPERTIES OBJECT_DEPENDS ${BISON_${BisonTarget}_OUTPUT_HEADER}) |  | ||||||
|   ENDMACRO(ADD_FLEX_BISON_DEPENDENCY) |  | ||||||
|   #============================================================ |  | ||||||
| 
 |  | ||||||
| ENDIF(FLEX_EXECUTABLE) |  | ||||||
| 
 |  | ||||||
| INCLUDE(FindPackageHandleStandardArgs) |  | ||||||
| FIND_PACKAGE_HANDLE_STANDARD_ARGS(FLEX FLEX_EXECUTABLE |  | ||||||
|                                        FLEX_VERSION) |  | ||||||
| 
 |  | ||||||
| # FindFLEX.cmake ends here |  | ||||||
|  | @ -1 +1 @@ | ||||||
| Subproject commit c7d08eb1abc829f3380991d3754a1ef6ce539c4d | Subproject commit 45cad164afcd0ad3f83286f39ae947c0e595c077 | ||||||
|  | @ -100,6 +100,8 @@ typedef struct { | ||||||
|   pic_value lib_tbl; |   pic_value lib_tbl; | ||||||
|   struct pic_lib *lib; |   struct pic_lib *lib; | ||||||
| 
 | 
 | ||||||
|  |   xhash rlabels; | ||||||
|  | 
 | ||||||
|   jmp_buf *jmp; |   jmp_buf *jmp; | ||||||
|   struct pic_error *err; |   struct pic_error *err; | ||||||
|   struct pic_jmpbuf *try_jmps; |   struct pic_jmpbuf *try_jmps; | ||||||
|  | @ -150,7 +152,8 @@ bool pic_interned_p(pic_state *, pic_sym); | ||||||
| char *pic_strdup(pic_state *, const char *); | char *pic_strdup(pic_state *, const char *); | ||||||
| char *pic_strndup(pic_state *, const char *, size_t); | char *pic_strndup(pic_state *, const char *, size_t); | ||||||
| 
 | 
 | ||||||
| pic_value pic_read(pic_state *, const char *); | pic_value pic_read(pic_state *, struct pic_port *); | ||||||
|  | pic_value pic_read_cstr(pic_state *, const char *); | ||||||
| pic_list pic_parse_file(pic_state *, FILE *); /* #f for incomplete input */ | pic_list pic_parse_file(pic_state *, FILE *); /* #f for incomplete input */ | ||||||
| pic_list pic_parse_cstr(pic_state *, const char *); | pic_list pic_parse_cstr(pic_state *, const char *); | ||||||
| 
 | 
 | ||||||
|  | @ -178,7 +181,7 @@ struct pic_lib *pic_find_library(pic_state *, pic_value); | ||||||
| #define pic_deflibrary_helper__(i, prev_lib, spec)                      \ | #define pic_deflibrary_helper__(i, prev_lib, spec)                      \ | ||||||
|   for (int i = 0; ! i; )                                                \ |   for (int i = 0; ! i; )                                                \ | ||||||
|     for (struct pic_lib *prev_lib; ! i; )                               \ |     for (struct pic_lib *prev_lib; ! i; )                               \ | ||||||
|       for ((prev_lib = pic->lib), pic_make_library(pic, pic_read(pic, spec)), pic_in_library(pic, pic_read(pic, spec)); ! i++; pic->lib = prev_lib) |       for ((prev_lib = pic->lib), pic_make_library(pic, pic_read_cstr(pic, spec)), pic_in_library(pic, pic_read_cstr(pic, spec)); ! i++; pic->lib = prev_lib) | ||||||
| 
 | 
 | ||||||
| void pic_import(pic_state *, pic_value); | void pic_import(pic_state *, pic_value); | ||||||
| void pic_export(pic_state *, pic_sym); | void pic_export(pic_state *, pic_sym); | ||||||
|  |  | ||||||
|  | @ -1,46 +0,0 @@ | ||||||
| /**
 |  | ||||||
|  * See Copyright Notice in picrin.h |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #ifndef PICRIN_PARSE_H__ |  | ||||||
| #define PICRIN_PARSE_H__ |  | ||||||
| 
 |  | ||||||
| #if defined(__cplusplus) |  | ||||||
| extern "C" { |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| enum { |  | ||||||
|   tEOF = 0, |  | ||||||
|   tLABEL_SET, tLABEL_REF, tDATUM_COMMENT, |  | ||||||
|   tLPAREN, tRPAREN, tLBRACKET, tRBRACKET, tDOT, tVPAREN, |  | ||||||
|   tQUOTE, tQUASIQUOTE, tUNQUOTE, tUNQUOTE_SPLICING, |  | ||||||
|   tINT, tBOOLEAN, |  | ||||||
|   tFLOAT, |  | ||||||
|   tSYMBOL, tSTRING, |  | ||||||
|   tCHAR, |  | ||||||
|   tBYTEVECTOR, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| typedef union YYSTYPE { |  | ||||||
|   int i; |  | ||||||
|   double f; |  | ||||||
|   struct { |  | ||||||
|     char *dat; |  | ||||||
|     size_t len; |  | ||||||
|   } buf; |  | ||||||
|   char c; |  | ||||||
| } YYSTYPE; |  | ||||||
| 
 |  | ||||||
| struct parser_control { |  | ||||||
|   pic_state *pic; |  | ||||||
|   YYSTYPE yylval; |  | ||||||
|   xhash labels; |  | ||||||
|   jmp_buf jmp; |  | ||||||
|   const char *msg; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| #if defined(__cplusplus) |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
|  | @ -37,6 +37,7 @@ struct pic_port *pic_stdin(pic_state *); | ||||||
| struct pic_port *pic_stdout(pic_state *); | struct pic_port *pic_stdout(pic_state *); | ||||||
| struct pic_port *pic_stderr(pic_state *); | struct pic_port *pic_stderr(pic_state *); | ||||||
| 
 | 
 | ||||||
|  | struct pic_port *pic_open_input_string(pic_state *, const char *); | ||||||
| struct pic_port *pic_open_output_string(pic_state *); | struct pic_port *pic_open_output_string(pic_state *); | ||||||
| struct pic_string *pic_get_output_string(pic_state *, struct pic_port *); | struct pic_string *pic_get_output_string(pic_state *, struct pic_port *); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -158,6 +158,7 @@ typedef struct pic_blob pic_blob; | ||||||
| #define pic_int_p(v) (pic_vtype(v) == PIC_VTYPE_INT) | #define pic_int_p(v) (pic_vtype(v) == PIC_VTYPE_INT) | ||||||
| #define pic_sym_p(v) (pic_vtype(v) == PIC_VTYPE_SYMBOL) | #define pic_sym_p(v) (pic_vtype(v) == PIC_VTYPE_SYMBOL) | ||||||
| #define pic_char_p(v) (pic_vtype(v) == PIC_VTYPE_CHAR) | #define pic_char_p(v) (pic_vtype(v) == PIC_VTYPE_CHAR) | ||||||
|  | #define pic_eof_p(v) (pic_vtype(v) == PIC_VTYPE_EOF) | ||||||
| 
 | 
 | ||||||
| #define pic_test(v) (! pic_false_p(v)) | #define pic_test(v) (! pic_false_p(v)) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,8 +1,3 @@ | ||||||
| # flex |  | ||||||
| find_package(FLEX REQUIRED) |  | ||||||
| flex_target(scan src/scan.l ${PROJECT_SOURCE_DIR}/src/lex.yy.c COMPILE_FLAGS --header-file="src/lex.yy.h") |  | ||||||
| set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${PROJECT_SOURCE_DIR}/src/lex.yy.h) |  | ||||||
| 
 |  | ||||||
| # xfile | # xfile | ||||||
| set(XFILE_SOURCES extlib/xfile/xfile.c) | set(XFILE_SOURCES extlib/xfile/xfile.c) | ||||||
| 
 | 
 | ||||||
|  | @ -18,7 +13,7 @@ add_custom_command( | ||||||
| 
 | 
 | ||||||
| # build! | # build! | ||||||
| file(GLOB PICRIN_SOURCES ${PROJECT_SOURCE_DIR}/src/*.c) | file(GLOB PICRIN_SOURCES ${PROJECT_SOURCE_DIR}/src/*.c) | ||||||
| add_library(picrin SHARED ${PICRIN_SOURCES} ${PICLIB_SOURCE} ${FLEX_scan_OUTPUTS} ${XFILE_SOURCES} ${PICRIN_CONTRIB_SOURCES}) | add_library(picrin SHARED ${PICRIN_SOURCES} ${PICLIB_SOURCE} ${XFILE_SOURCES} ${PICRIN_CONTRIB_SOURCES}) | ||||||
| target_link_libraries(picrin m ${PICRIN_CONTRIB_LIBRARIES}) | target_link_libraries(picrin m ${PICRIN_CONTRIB_LIBRARIES}) | ||||||
| 
 | 
 | ||||||
| # install | # install | ||||||
|  |  | ||||||
|  | @ -68,7 +68,7 @@ new_analyze_state(pic_state *pic) | ||||||
|   state->pic = pic; |   state->pic = pic; | ||||||
|   state->scope = NULL; |   state->scope = NULL; | ||||||
| 
 | 
 | ||||||
|   stdlib = pic_find_library(pic, pic_read(pic, "(scheme base)")); |   stdlib = pic_find_library(pic, pic_read_cstr(pic, "(scheme base)")); | ||||||
| 
 | 
 | ||||||
|   /* native VM procedures */ |   /* native VM procedures */ | ||||||
|   register_renamed_symbol(pic, state, rCONS, stdlib, "cons"); |   register_renamed_symbol(pic, state, rCONS, stdlib, "cons"); | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ pic_load_cstr(pic_state *pic, const char *src) | ||||||
| 
 | 
 | ||||||
|   exprs = pic_parse_cstr(pic, src); |   exprs = pic_parse_cstr(pic, src); | ||||||
|   if (pic_undef_p(exprs)) { |   if (pic_undef_p(exprs)) { | ||||||
|     pic_error(pic, "load: unexpected EOF"); |     pic_errorf(pic, "load: read failure (%s)", pic_errmsg(pic)); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   pic_for_each (v, exprs) { |   pic_for_each (v, exprs) { | ||||||
|  | @ -48,7 +48,7 @@ pic_load(pic_state *pic, const char *fn) | ||||||
| 
 | 
 | ||||||
|   exprs = pic_parse_file(pic, file); |   exprs = pic_parse_file(pic, file); | ||||||
|   if (pic_undef_p(exprs)) { |   if (pic_undef_p(exprs)) { | ||||||
|     pic_error(pic, "load: unexpected EOF"); |     pic_errorf(pic, "load: read failure (%s)", pic_errmsg(pic)); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   pic_for_each (v, exprs) { |   pic_for_each (v, exprs) { | ||||||
|  |  | ||||||
							
								
								
									
										37
									
								
								src/port.c
								
								
								
								
							
							
						
						
									
										37
									
								
								src/port.c
								
								
								
								
							|  | @ -54,6 +54,23 @@ port_new_stdport(pic_state *pic, xFILE *file, short dir) | ||||||
|   return pic_obj_value(port); |   return pic_obj_value(port); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | struct pic_port * | ||||||
|  | pic_open_input_string(pic_state *pic, const char *str) | ||||||
|  | { | ||||||
|  |   struct pic_port *port; | ||||||
|  | 
 | ||||||
|  |   port = (struct pic_port *)pic_obj_alloc(pic, sizeof(struct pic_port *), PIC_TT_PORT); | ||||||
|  |   port->file = xmopen(); | ||||||
|  |   port->flags = PIC_PORT_IN | PIC_PORT_TEXT; | ||||||
|  |   port->status = PIC_PORT_OPEN; | ||||||
|  | 
 | ||||||
|  |   xfputs(str, port->file); | ||||||
|  |   xfflush(port->file); | ||||||
|  |   xrewind(port->file); | ||||||
|  | 
 | ||||||
|  |   return port; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| struct pic_port * | struct pic_port * | ||||||
| pic_open_output_string(pic_state *pic) | pic_open_output_string(pic_state *pic) | ||||||
| { | { | ||||||
|  | @ -70,19 +87,20 @@ pic_open_output_string(pic_state *pic) | ||||||
| struct pic_string * | struct pic_string * | ||||||
| pic_get_output_string(pic_state *pic, struct pic_port *port) | pic_get_output_string(pic_state *pic, struct pic_port *port) | ||||||
| { | { | ||||||
|   long endpos; |   long size; | ||||||
|   char *buf; |   char *buf; | ||||||
| 
 | 
 | ||||||
|   /* get endpos */ |   /* get endpos */ | ||||||
|   xfflush(port->file); |   xfflush(port->file); | ||||||
|   endpos = xftell(port->file); |   size = xftell(port->file); | ||||||
|   xrewind(port->file); |   xrewind(port->file); | ||||||
| 
 | 
 | ||||||
|   /* copy to buf */ |   /* copy to buf */ | ||||||
|   buf = (char *)pic_alloc(pic, endpos); |   buf = (char *)pic_alloc(pic, size + 1); | ||||||
|   xfread(buf, 1, endpos, port->file); |   buf[size] = 0; | ||||||
|  |   xfread(buf, size, 1, port->file); | ||||||
| 
 | 
 | ||||||
|   return pic_str_new(pic, buf, endpos); |   return pic_str_new(pic, buf, size); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
|  | @ -268,14 +286,7 @@ pic_port_open_input_string(pic_state *pic) | ||||||
| 
 | 
 | ||||||
|   pic_get_args(pic, "z", &str); |   pic_get_args(pic, "z", &str); | ||||||
| 
 | 
 | ||||||
|   port = (struct pic_port *)pic_obj_alloc(pic, sizeof(struct pic_port *), PIC_TT_PORT); |   port = pic_open_input_string(pic, str); | ||||||
|   port->file = xmopen(); |  | ||||||
|   port->flags = PIC_PORT_IN | PIC_PORT_TEXT; |  | ||||||
|   port->status = PIC_PORT_OPEN; |  | ||||||
| 
 |  | ||||||
|   xfputs(str, port->file); |  | ||||||
|   xfflush(port->file); |  | ||||||
|   xrewind(port->file); |  | ||||||
| 
 | 
 | ||||||
|   return pic_obj_value(port); |   return pic_obj_value(port); | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										727
									
								
								src/read.c
								
								
								
								
							
							
						
						
									
										727
									
								
								src/read.c
								
								
								
								
							|  | @ -2,84 +2,428 @@ | ||||||
|  * See Copyright Notice in picrin.h |  * See Copyright Notice in picrin.h | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #include <ctype.h> | ||||||
|  | #include <math.h> | ||||||
| #include "picrin.h" | #include "picrin.h" | ||||||
| #include "picrin/parse.h" | #include "picrin/error.h" | ||||||
| #include "picrin/pair.h" | #include "picrin/pair.h" | ||||||
| #include "picrin/string.h" | #include "picrin/string.h" | ||||||
| #include "picrin/vector.h" | #include "picrin/vector.h" | ||||||
| #include "picrin/blob.h" | #include "picrin/blob.h" | ||||||
| #include "picrin/port.h" | #include "picrin/port.h" | ||||||
| 
 | 
 | ||||||
| #define YY_NO_UNISTD_H | typedef pic_value (*read_func_t)(pic_state *, struct pic_port *, char); | ||||||
| #include "lex.yy.h" |  | ||||||
| 
 | 
 | ||||||
| static pic_value read(int, yyscan_t); | static pic_value read(pic_state *pic, struct pic_port *port, char c); | ||||||
| 
 | 
 | ||||||
| #define pic (yyget_extra(scanner)->pic) | static noreturn void | ||||||
| #define yylval (yyget_extra(scanner)->yylval) | read_error(pic_state *pic, const char *msg) | ||||||
| #define yylabels (yyget_extra(scanner)->labels) |  | ||||||
| #define yymsg (yyget_extra(scanner)->msg) |  | ||||||
| #define yyjmp (yyget_extra(scanner)->jmp) |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| error(const char *msg, yyscan_t scanner) |  | ||||||
| { | { | ||||||
|   yymsg = msg; |   pic_error(pic, msg); | ||||||
|   longjmp(yyjmp, 1); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int | static char | ||||||
| gettok(yyscan_t scanner) | skip(struct pic_port *port, char c) | ||||||
| { | { | ||||||
|   int tok; |   while (isspace(c)) { | ||||||
| 
 |     c = xfgetc(port->file); | ||||||
|   while ((tok = yylex(scanner)) == tDATUM_COMMENT) { |  | ||||||
|     read(gettok(scanner), scanner); /* discard */ |  | ||||||
|   } |   } | ||||||
|   return tok; |   return c; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static char | ||||||
|  | next(struct pic_port *port) | ||||||
|  | { | ||||||
|  |   return xfgetc(port->file); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static char | ||||||
|  | peek(struct pic_port *port) | ||||||
|  | { | ||||||
|  |   char c; | ||||||
|  | 
 | ||||||
|  |   xungetc((c = xfgetc(port->file)), port->file); | ||||||
|  | 
 | ||||||
|  |   return c; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static pic_value | static pic_value | ||||||
| read_label_set(int i, yyscan_t scanner) | read_comment(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   UNUSED(pic); | ||||||
|  | 
 | ||||||
|  |   do { | ||||||
|  |     c = next(port); | ||||||
|  |   } while (! (c == EOF || c == '\n')); | ||||||
|  | 
 | ||||||
|  |   return pic_undef_value(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_block_comment(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   char x, y; | ||||||
|  |   int i; | ||||||
|  | 
 | ||||||
|  |   UNUSED(pic); | ||||||
|  |   UNUSED(c); | ||||||
|  | 
 | ||||||
|  |   x = next(port); | ||||||
|  |   y = next(port); | ||||||
|  | 
 | ||||||
|  |   i = 1; | ||||||
|  |   while (x != EOF && y != EOF && i > 0) { | ||||||
|  |     if (x == '|' && y == '#') { | ||||||
|  |       i--; | ||||||
|  |     } | ||||||
|  |     if (x == '#' && y == '|') { | ||||||
|  |       i++; | ||||||
|  |     } | ||||||
|  |     x = y; | ||||||
|  |     y = next(port); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return pic_undef_value(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_datum_comment(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   UNUSED(c); | ||||||
|  | 
 | ||||||
|  |   read(pic, port, next(port)); | ||||||
|  | 
 | ||||||
|  |   return pic_undef_value(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_quote(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   UNUSED(c); | ||||||
|  | 
 | ||||||
|  |   return pic_list2(pic, pic_sym_value(pic->sQUOTE), read(pic, port, next(port))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_quasiquote(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   UNUSED(c); | ||||||
|  | 
 | ||||||
|  |   return pic_list2(pic, pic_sym_value(pic->sQUASIQUOTE), read(pic, port, next(port))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_comma(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   c = next(port); | ||||||
|  | 
 | ||||||
|  |   if (c == '@') { | ||||||
|  |     return pic_list2(pic, pic_sym_value(pic->sUNQUOTE_SPLICING), read(pic, port, next(port))); | ||||||
|  |   } else { | ||||||
|  |     return pic_list2(pic, pic_sym_value(pic->sUNQUOTE), read(pic, port, c)); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_symbol(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   static const char TRAIL_SYMBOL[] = "+/*!$%&:@^~?<=>_.-"; | ||||||
|  |   size_t len; | ||||||
|  |   char *buf; | ||||||
|  |   pic_sym sym; | ||||||
|  | 
 | ||||||
|  |   len = 0; | ||||||
|  |   buf = NULL; | ||||||
|  | 
 | ||||||
|  |   do { | ||||||
|  |     if (len != 0) { | ||||||
|  |       c = next(port); | ||||||
|  |     } | ||||||
|  |     len += 1; | ||||||
|  |     buf = pic_realloc(pic, buf, len); | ||||||
|  |     buf[len - 1] = c; | ||||||
|  |   } while (isalnum(peek(port)) || strchr(TRAIL_SYMBOL, peek(port))); | ||||||
|  | 
 | ||||||
|  |   buf[len] = '\0'; | ||||||
|  |   sym = pic_intern_cstr(pic, buf); | ||||||
|  |   pic_free(pic, buf); | ||||||
|  | 
 | ||||||
|  |   return pic_sym_value(sym); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int64_t | ||||||
|  | read_uinteger(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   int64_t n; | ||||||
|  | 
 | ||||||
|  |   c = skip(port, c); | ||||||
|  | 
 | ||||||
|  |   if (! isdigit(c)) { | ||||||
|  |     read_error(pic, "expected one or more digits"); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   n = c - '0'; | ||||||
|  |   while (isdigit(c = peek(port))) { | ||||||
|  |     next(port); | ||||||
|  |     n = n * 10 + c - '0'; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return n; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_number(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   int64_t i, j; | ||||||
|  | 
 | ||||||
|  |   i = read_uinteger(pic, port, c); | ||||||
|  | 
 | ||||||
|  |   if (peek(port) == '.') { | ||||||
|  |     next(port); | ||||||
|  |     j = read_uinteger(pic, port, next(port)); | ||||||
|  |     return pic_float_value(i + (double)j * pow(10, -snprintf(NULL, 0, "%lld", j))); | ||||||
|  |   } | ||||||
|  |   else { | ||||||
|  |     return pic_int_value(i); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | negate(pic_value n) | ||||||
|  | { | ||||||
|  |   if (pic_int_p(n)) { | ||||||
|  |     return pic_int_value(-pic_int(n)); | ||||||
|  |   } else { | ||||||
|  |     return pic_float_value(-pic_float(n)); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_minus(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   static const char DIGITS[] = "0123456789"; | ||||||
|  | 
 | ||||||
|  |   /* TODO: -inf.0, -nan.0 */ | ||||||
|  | 
 | ||||||
|  |   if (strchr(DIGITS, peek(port))) { | ||||||
|  |     return negate(read_number(pic, port, c)); | ||||||
|  |   } | ||||||
|  |   else { | ||||||
|  |     return read_symbol(pic, port, c); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_plus(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   static const char DIGITS[] = "0123456789"; | ||||||
|  | 
 | ||||||
|  |   /* TODO: +inf.0, +nan.0 */ | ||||||
|  | 
 | ||||||
|  |   if (strchr(DIGITS, peek(port))) { | ||||||
|  |     return read_number(pic, port, c); | ||||||
|  |   } | ||||||
|  |   else { | ||||||
|  |     return read_symbol(pic, port, c); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_boolean(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   UNUSED(pic); | ||||||
|  |   UNUSED(port); | ||||||
|  | 
 | ||||||
|  |   /* TODO: support #true and #false */ | ||||||
|  | 
 | ||||||
|  |   if (c == 't') { | ||||||
|  |     return pic_true_value(); | ||||||
|  |   } else { | ||||||
|  |     return pic_false_value(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_char(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   UNUSED(pic); | ||||||
|  |   UNUSED(c); | ||||||
|  | 
 | ||||||
|  |   /* TODO: #\alart, #\space, so on and so on */ | ||||||
|  | 
 | ||||||
|  |   return pic_char_value(next(port)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_string(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   char *buf; | ||||||
|  |   size_t size, cnt; | ||||||
|  |   pic_str *str; | ||||||
|  | 
 | ||||||
|  |   size = 256; | ||||||
|  |   buf = pic_alloc(pic, size); | ||||||
|  |   cnt = 0; | ||||||
|  | 
 | ||||||
|  |   /* TODO: intraline whitespaces */ | ||||||
|  | 
 | ||||||
|  |   while ((c = next(port)) != '"') { | ||||||
|  |     if (c == '\\') { | ||||||
|  |       switch (c = next(port)) { | ||||||
|  |       case 'a': c = '\a'; break; | ||||||
|  |       case 'b': c = '\b'; break; | ||||||
|  |       case 't': c = '\t'; break; | ||||||
|  |       case 'n': c = '\n'; break; | ||||||
|  |       case 'r': c = '\r'; break; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     buf[cnt++] = c; | ||||||
|  |     if (cnt >= size) { | ||||||
|  |       buf = pic_realloc(pic, buf, size *= 2); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   buf[cnt] = '\0'; | ||||||
|  | 
 | ||||||
|  |   str = pic_str_new(pic, buf, size); | ||||||
|  |   pic_free(pic, buf); | ||||||
|  |   return pic_obj_value(str); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_unsigned_blob(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   int nbits, n; | ||||||
|  |   size_t len; | ||||||
|  |   char *buf; | ||||||
|  |   pic_blob *blob; | ||||||
|  | 
 | ||||||
|  |   nbits = 0; | ||||||
|  | 
 | ||||||
|  |   while (isdigit(c = next(port))) { | ||||||
|  |     nbits = 10 * nbits + c - '0'; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (nbits != 8) { | ||||||
|  |     read_error(pic, "unsupported bytevector bit width"); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (c != '(') { | ||||||
|  |     read_error(pic, "expected '(' character"); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   len = 0; | ||||||
|  |   buf = NULL; | ||||||
|  |   c = next(port); | ||||||
|  |   while ((c = skip(port, c)) != ')') { | ||||||
|  |     n = read_uinteger(pic, port, c); | ||||||
|  |     if (n < 0 || (1 << nbits) <= n) { | ||||||
|  |       read_error(pic, "invalid element in bytevector literal"); | ||||||
|  |     } | ||||||
|  |     len += 1; | ||||||
|  |     buf = pic_realloc(pic, buf, len); | ||||||
|  |     buf[len - 1] = n; | ||||||
|  |     c = next(port); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   blob = pic_blob_new(pic, buf, len); | ||||||
|  |   pic_free(pic, buf); | ||||||
|  |   return pic_obj_value(blob); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_pair(pic_state *pic, struct pic_port *port, char c) | ||||||
|  | { | ||||||
|  |   char tOPEN = c, tCLOSE = (tOPEN == '(') ? ')' : ']'; | ||||||
|  |   pic_value car, cdr; | ||||||
|  | 
 | ||||||
|  |   c = skip(port, ' '); | ||||||
|  | 
 | ||||||
|  |   if (c == tCLOSE) { | ||||||
|  |     return pic_nil_value(); | ||||||
|  |   } | ||||||
|  |   if (c == '.' && strchr("()#;,|'\" \t\n\r", peek(port)) != NULL) { | ||||||
|  |     cdr = read(pic, port, next(port)); | ||||||
|  | 
 | ||||||
|  |     if ((c = skip(port, ' ')) != tCLOSE) { | ||||||
|  |       read_error(pic, "unmatched parenthesis"); | ||||||
|  |     } | ||||||
|  |     return cdr; | ||||||
|  |   } | ||||||
|  |   else { | ||||||
|  |     car = read(pic, port, c); | ||||||
|  |     cdr = read_pair(pic, port, tOPEN); /* FIXME: don't use recursion */ | ||||||
|  |     return pic_cons(pic, car, cdr); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_vector(pic_state *pic, struct pic_port *port, char c) | ||||||
| { | { | ||||||
|   int tok; |  | ||||||
|   pic_value val; |   pic_value val; | ||||||
| 
 | 
 | ||||||
|   switch (tok = gettok(scanner)) { |   c = next(port); | ||||||
|   case tLPAREN: | 
 | ||||||
|   case tLBRACKET: |   val = pic_nil_value(); | ||||||
|  |   while ((c = skip(port, c)) != ')') { | ||||||
|  |     val = pic_cons(pic, read(pic, port, c), val); | ||||||
|  |     c = next(port); | ||||||
|  |   } | ||||||
|  |   return pic_obj_value(pic_vec_new_from_list(pic, pic_reverse(pic, val))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | read_label_set(pic_state *pic, struct pic_port *port, int i) | ||||||
|  | { | ||||||
|  |   pic_value val; | ||||||
|  |   char c; | ||||||
|  | 
 | ||||||
|  |   switch (c = skip(port, ' ')) { | ||||||
|  |   case '(': case '[': | ||||||
|     { |     { | ||||||
|       pic_value tmp; |       pic_value tmp; | ||||||
| 
 | 
 | ||||||
|       val = pic_cons(pic, pic_none_value(), pic_none_value()); |       val = pic_cons(pic, pic_none_value(), pic_none_value()); | ||||||
| 
 | 
 | ||||||
|       xh_put_int(&yylabels, i, &val); |       xh_put_int(&pic->rlabels, i, &val); | ||||||
| 
 | 
 | ||||||
|       tmp = read(tok, scanner); |       tmp = read(pic, port, c); | ||||||
|       pic_pair_ptr(val)->car = pic_car(pic, tmp); |       pic_pair_ptr(val)->car = pic_car(pic, tmp); | ||||||
|       pic_pair_ptr(val)->cdr = pic_cdr(pic, tmp); |       pic_pair_ptr(val)->cdr = pic_cdr(pic, tmp); | ||||||
| 
 | 
 | ||||||
|       return val; |       return val; | ||||||
|     } |     } | ||||||
|   case tVPAREN: |   case '#': | ||||||
|     { |     { | ||||||
|       pic_vec *tmp; |       bool vect; | ||||||
| 
 | 
 | ||||||
|       val = pic_obj_value(pic_vec_new(pic, 0)); |       if (peek(port) == '(') { | ||||||
|  |         vect = true; | ||||||
|  |       } else { | ||||||
|  |         vect = false; | ||||||
|  |       } | ||||||
| 
 | 
 | ||||||
|       xh_put_int(&yylabels, i, &val); |       if (vect) { | ||||||
|  |         pic_vec *tmp; | ||||||
| 
 | 
 | ||||||
|       tmp = pic_vec_ptr(read(tok, scanner)); |         val = pic_obj_value(pic_vec_new(pic, 0)); | ||||||
|       SWAP(pic_value *, tmp->data, pic_vec_ptr(val)->data); |  | ||||||
|       SWAP(size_t, tmp->len, pic_vec_ptr(val)->len); |  | ||||||
| 
 | 
 | ||||||
|       return val; |         xh_put_int(&pic->rlabels, i, &val); | ||||||
|  | 
 | ||||||
|  |         tmp = pic_vec_ptr(read(pic, port, c)); | ||||||
|  |         SWAP(pic_value *, tmp->data, pic_vec_ptr(val)->data); | ||||||
|  |         SWAP(size_t, tmp->len, pic_vec_ptr(val)->len); | ||||||
|  | 
 | ||||||
|  |         return val; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       FALLTHROUGH; | ||||||
|     } |     } | ||||||
|   default: |   default: | ||||||
|     { |     { | ||||||
|       val = read(tok, scanner); |       val = read(pic, port, c); | ||||||
| 
 | 
 | ||||||
|       xh_put_int(&yylabels, i, &val); |       xh_put_int(&pic->rlabels, i, &val); | ||||||
| 
 | 
 | ||||||
|       return val; |       return val; | ||||||
|     } |     } | ||||||
|  | @ -87,239 +431,188 @@ read_label_set(int i, yyscan_t scanner) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static pic_value | static pic_value | ||||||
| read_label_ref(int i, yyscan_t scanner) | read_label_ref(pic_state *pic, struct pic_port *port, int i) | ||||||
| { | { | ||||||
|   xh_entry *e; |   xh_entry *e; | ||||||
| 
 | 
 | ||||||
|   e = xh_get_int(&yylabels, i); |   UNUSED(port); | ||||||
|  | 
 | ||||||
|  |   e = xh_get_int(&pic->rlabels, i); | ||||||
|   if (! e) { |   if (! e) { | ||||||
|     error("label of given index not defined", scanner); |     read_error(pic, "label of given index not defined"); | ||||||
|   } |   } | ||||||
|   return xh_val(e, pic_value); |   return xh_val(e, pic_value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static pic_value | static pic_value | ||||||
| read_pair(int tOPEN, yyscan_t scanner) | read_label(pic_state *pic, struct pic_port *port, char c) | ||||||
| { | { | ||||||
|   int tok, tCLOSE = (tOPEN == tLPAREN) ? tRPAREN : tRBRACKET; |   int i; | ||||||
|   pic_value car, cdr; |  | ||||||
| 
 | 
 | ||||||
|   tok = gettok(scanner); |   i = 0; | ||||||
|   if (tok == tCLOSE) { |   do { | ||||||
|     return pic_nil_value(); |     i = i * 10 + c; | ||||||
|   } |   } while (isdigit(c = next(port))); | ||||||
|   if (tok == tDOT) { |  | ||||||
|     cdr = read(gettok(scanner), scanner); |  | ||||||
| 
 | 
 | ||||||
|     if (gettok(scanner) != tCLOSE) { |   if (c == '=') { | ||||||
|       error("unmatched parenthesis", scanner); |     return read_label_set(pic, port, i); | ||||||
|     } |  | ||||||
|     return cdr; |  | ||||||
|   } |   } | ||||||
|   else { |   if (c == '#') { | ||||||
|     car = read(tok, scanner); |     return read_label_ref(pic, port, i); | ||||||
|     cdr = read_pair(tOPEN, scanner); |  | ||||||
|     return pic_cons(pic, car, cdr); |  | ||||||
|   } |   } | ||||||
| } |   read_error(pic, "broken label expression"); | ||||||
| 
 |  | ||||||
| static pic_vec * |  | ||||||
| read_vect(yyscan_t scanner) |  | ||||||
| { |  | ||||||
|   int tok; |  | ||||||
|   pic_value val; |  | ||||||
| 
 |  | ||||||
|   val = pic_nil_value(); |  | ||||||
|   while ((tok = gettok(scanner)) != tRPAREN) { |  | ||||||
|     val = pic_cons(pic, read(tok, scanner), val); |  | ||||||
|   } |  | ||||||
|   return pic_vec_new_from_list(pic, pic_reverse(pic, val)); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static pic_value | static pic_value | ||||||
| read_abbrev(pic_sym sym, yyscan_t scanner) | read_dispatch(pic_state *pic, struct pic_port *port, char c) | ||||||
| { | { | ||||||
|   return pic_cons(pic, pic_sym_value(sym), pic_cons(pic, read(gettok(scanner), scanner), pic_nil_value())); |   c = next(port); | ||||||
|  | 
 | ||||||
|  |   switch (c) { | ||||||
|  |   case '!': | ||||||
|  |     return read_comment(pic, port, c); | ||||||
|  |   case '|': | ||||||
|  |     return read_block_comment(pic, port, c); | ||||||
|  |   case ';': | ||||||
|  |     return read_datum_comment(pic, port, c); | ||||||
|  |   case 't': case 'f': | ||||||
|  |     return read_boolean(pic, port, c); | ||||||
|  |   case '\\': | ||||||
|  |     return read_char(pic, port, c); | ||||||
|  |   case '(': | ||||||
|  |     return read_vector(pic, port, c); | ||||||
|  |   case '0': case '1': case '2': case '3': case '4': | ||||||
|  |   case '5': case '6': case '7': case '8': case '9': | ||||||
|  |     return read_label(pic, port, c); | ||||||
|  |   case 'u': | ||||||
|  |     return read_unsigned_blob(pic, port, c); | ||||||
|  |   default: | ||||||
|  |     read_error(pic, "unexpected dispatch character"); | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static pic_value | static pic_value | ||||||
| read_datum(int tok, yyscan_t scanner) | read_nullable(pic_state *pic, struct pic_port *port, char c) | ||||||
| { | { | ||||||
|   pic_value val; |   c = skip(port, c); | ||||||
| 
 | 
 | ||||||
|   switch (tok) { |   if (c == EOF) { | ||||||
|   case tLABEL_SET: |     read_error(pic, "unexpected EOF"); | ||||||
|     return read_label_set(yylval.i, scanner); |  | ||||||
| 
 |  | ||||||
|   case tLABEL_REF: |  | ||||||
|     return read_label_ref(yylval.i, scanner); |  | ||||||
| 
 |  | ||||||
|   case tSYMBOL: |  | ||||||
|     return pic_symbol_value(pic_intern(pic, yylval.buf.dat, yylval.buf.len)); |  | ||||||
| 
 |  | ||||||
|   case tINT: |  | ||||||
|     return pic_int_value(yylval.i); |  | ||||||
| 
 |  | ||||||
|   case tFLOAT: |  | ||||||
|     return pic_float_value(yylval.f); |  | ||||||
| 
 |  | ||||||
|   case tBOOLEAN: |  | ||||||
|     return pic_bool_value(yylval.i); |  | ||||||
| 
 |  | ||||||
|   case tCHAR: |  | ||||||
|     return pic_char_value(yylval.c); |  | ||||||
| 
 |  | ||||||
|   case tSTRING: |  | ||||||
|     val = pic_obj_value(pic_str_new(pic, yylval.buf.dat, yylval.buf.len)); |  | ||||||
|     pic_free(pic, yylval.buf.dat); |  | ||||||
|     return val; |  | ||||||
| 
 |  | ||||||
|   case tBYTEVECTOR: |  | ||||||
|     val = pic_obj_value(pic_blob_new(pic, yylval.buf.dat, yylval.buf.len)); |  | ||||||
|     pic_free(pic, yylval.buf.dat); |  | ||||||
|     return val; |  | ||||||
| 
 |  | ||||||
|   case tLPAREN: |  | ||||||
|   case tLBRACKET: |  | ||||||
|     return read_pair(tok, scanner); |  | ||||||
| 
 |  | ||||||
|   case tVPAREN: |  | ||||||
|     return pic_obj_value(read_vect(scanner)); |  | ||||||
| 
 |  | ||||||
|   case tQUOTE: |  | ||||||
|     return read_abbrev(pic->sQUOTE, scanner); |  | ||||||
| 
 |  | ||||||
|   case tQUASIQUOTE: |  | ||||||
|     return read_abbrev(pic->sQUASIQUOTE, scanner); |  | ||||||
| 
 |  | ||||||
|   case tUNQUOTE: |  | ||||||
|     return read_abbrev(pic->sUNQUOTE, scanner); |  | ||||||
| 
 |  | ||||||
|   case tUNQUOTE_SPLICING: |  | ||||||
|     return read_abbrev(pic->sUNQUOTE_SPLICING, scanner); |  | ||||||
| 
 |  | ||||||
|   case tRPAREN: |  | ||||||
|     error("unexpected close parenthesis", scanner); |  | ||||||
| 
 |  | ||||||
|   case tRBRACKET: |  | ||||||
|     error("unexpected close bracket", scanner); |  | ||||||
| 
 |  | ||||||
|   case tDOT: |  | ||||||
|     error("unexpected '.'", scanner); |  | ||||||
| 
 |  | ||||||
|   case tEOF: |  | ||||||
|     error(NULL, scanner); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   UNREACHABLE(); |   switch (c) { | ||||||
|  |   case ';': | ||||||
|  |     return read_comment(pic, port, c); | ||||||
|  |   case '#': | ||||||
|  |     return read_dispatch(pic, port, c); | ||||||
|  |   case '\'': | ||||||
|  |     return read_quote(pic, port, c); | ||||||
|  |   case '`': | ||||||
|  |     return read_quasiquote(pic, port, c); | ||||||
|  |   case ',': | ||||||
|  |     return read_comma(pic, port, c); | ||||||
|  |   case '"': | ||||||
|  |     return read_string(pic, port, c); | ||||||
|  |   case '0': case '1': case '2': case '3': case '4': | ||||||
|  |   case '5': case '6': case '7': case '8': case '9': | ||||||
|  |     return read_number(pic, port, c); | ||||||
|  |   case '+': | ||||||
|  |     return read_plus(pic, port, c); | ||||||
|  |   case '-': | ||||||
|  |     return read_minus(pic, port, c); | ||||||
|  |   case '(': case '[': | ||||||
|  |     return read_pair(pic, port, c); | ||||||
|  |   default: | ||||||
|  |     return read_symbol(pic, port, c); | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static pic_value | static pic_value | ||||||
| read(int tok, yyscan_t scanner) | read(pic_state *pic, struct pic_port *port, char c) | ||||||
| { | { | ||||||
|   size_t ai = pic_gc_arena_preserve(pic); |  | ||||||
|   pic_value val; |   pic_value val; | ||||||
| 
 | 
 | ||||||
|   val = read_datum(tok, scanner); |  retry: | ||||||
|  |   val = read_nullable(pic, port, c); | ||||||
|  | 
 | ||||||
|  |   if (pic_undef_p(val)) { | ||||||
|  |     c = next(port); | ||||||
|  |     goto retry; | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   pic_gc_arena_restore(pic, ai); |  | ||||||
|   pic_gc_protect(pic, val); |  | ||||||
|   return val; |   return val; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pic_value | pic_value | ||||||
| read_one(yyscan_t scanner) | pic_read(pic_state *pic, struct pic_port *port) | ||||||
| { | { | ||||||
|   int tok; |   pic_value val; | ||||||
|  |   char c = next(port); | ||||||
| 
 | 
 | ||||||
|   if (setjmp(yyjmp) != 0) { |  retry: | ||||||
|     pic_errorf(pic, "%s", yymsg ? yymsg : "unexpected EOF"); |   c = skip(port, c); | ||||||
|  | 
 | ||||||
|  |   if (c == EOF) { | ||||||
|  |     return pic_eof_object(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if ((tok = gettok(scanner)) == tEOF) { |   val = read_nullable(pic, port, c); | ||||||
|  | 
 | ||||||
|  |   if (pic_undef_p(val)) { | ||||||
|  |     c = next(port); | ||||||
|  |     goto retry; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return val; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pic_value | ||||||
|  | pic_read_cstr(pic_state *pic, const char *str) | ||||||
|  | { | ||||||
|  |   struct pic_port *port; | ||||||
|  | 
 | ||||||
|  |   port = pic_open_input_string(pic, str); | ||||||
|  | 
 | ||||||
|  |   return pic_read(pic, port); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static pic_value | ||||||
|  | pic_parse(pic_state *pic, struct pic_port *port) | ||||||
|  | { | ||||||
|  |   pic_value val, acc; | ||||||
|  | 
 | ||||||
|  |   pic_try { | ||||||
|  |     acc = pic_nil_value(); | ||||||
|  |     while (! pic_eof_p(val = pic_read(pic, port))) { | ||||||
|  |       pic_push(pic, val, acc); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   pic_catch { | ||||||
|     return pic_undef_value(); |     return pic_undef_value(); | ||||||
|   } |   } | ||||||
|   return read(tok, scanner); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| pic_list |   return pic_reverse(pic, acc); | ||||||
| read_many(yyscan_t scanner) |  | ||||||
| { |  | ||||||
|   int tok; |  | ||||||
|   pic_value vals; |  | ||||||
| 
 |  | ||||||
|   if (setjmp(yyjmp) != 0) { |  | ||||||
|     if (yymsg) { |  | ||||||
|       pic_errorf(pic, "%s", yymsg); |  | ||||||
|     } |  | ||||||
|     return pic_undef_value();   /* incomplete string */ |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   vals = pic_nil_value(); |  | ||||||
|   while ((tok = gettok(scanner)) != tEOF) { |  | ||||||
|     vals = pic_cons(pic, read(tok, scanner), vals); |  | ||||||
|   } |  | ||||||
|   return pic_reverse(pic, vals); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #undef pic |  | ||||||
| 
 |  | ||||||
| pic_value |  | ||||||
| pic_read(pic_state *pic, const char *cstr) |  | ||||||
| { |  | ||||||
|   yyscan_t scanner; |  | ||||||
|   struct parser_control ctrl; |  | ||||||
|   pic_value val; |  | ||||||
| 
 |  | ||||||
|   ctrl.pic = pic; |  | ||||||
|   xh_init_int(&ctrl.labels, sizeof(pic_value)); |  | ||||||
|   yylex_init_extra(&ctrl, &scanner); |  | ||||||
|   yy_scan_string(cstr, scanner); |  | ||||||
| 
 |  | ||||||
|   val = read_one(scanner); |  | ||||||
| 
 |  | ||||||
|   yylex_destroy(scanner); |  | ||||||
|   xh_destroy(&ctrl.labels); |  | ||||||
| 
 |  | ||||||
|   return val; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pic_list | pic_list | ||||||
| pic_parse_file(pic_state *pic, FILE *file) | pic_parse_file(pic_state *pic, FILE *file) | ||||||
| { | { | ||||||
|   yyscan_t scanner; |   struct pic_port *port; | ||||||
|   struct parser_control ctrl; |  | ||||||
|   pic_value vals; |  | ||||||
| 
 | 
 | ||||||
|   ctrl.pic = pic; |   port = (struct pic_port *)pic_obj_alloc(pic, sizeof(struct pic_port *), PIC_TT_PORT); | ||||||
|   xh_init_int(&ctrl.labels, sizeof(pic_value)); |   port->file = xfpopen(file); | ||||||
|   yylex_init_extra(&ctrl, &scanner); |   port->flags = PIC_PORT_OUT | PIC_PORT_TEXT; | ||||||
|   yyset_in(file, scanner); |   port->status = PIC_PORT_OPEN; | ||||||
| 
 | 
 | ||||||
|   vals = read_many(scanner); |   return pic_parse(pic, port); | ||||||
| 
 |  | ||||||
|   yylex_destroy(scanner); |  | ||||||
|   xh_destroy(&ctrl.labels); |  | ||||||
| 
 |  | ||||||
|   return vals; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pic_list | pic_list | ||||||
| pic_parse_cstr(pic_state *pic, const char *cstr) | pic_parse_cstr(pic_state *pic, const char *str) | ||||||
| { | { | ||||||
|   yyscan_t scanner; |   struct pic_port *port; | ||||||
|   struct parser_control ctrl; |  | ||||||
|   pic_value vals; |  | ||||||
| 
 | 
 | ||||||
|   ctrl.pic = pic; |   port = pic_open_input_string(pic, str); | ||||||
|   xh_init_int(&ctrl.labels, sizeof(pic_value)); |  | ||||||
|   yylex_init_extra(&ctrl, &scanner); |  | ||||||
|   yy_scan_string(cstr, scanner); |  | ||||||
| 
 | 
 | ||||||
|   vals = read_many(scanner); |   return pic_parse(pic, port); | ||||||
| 
 |  | ||||||
|   yylex_destroy(scanner); |  | ||||||
|   xh_destroy(&ctrl.labels); |  | ||||||
| 
 |  | ||||||
|   return vals; |  | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										230
									
								
								src/scan.l
								
								
								
								
							
							
						
						
									
										230
									
								
								src/scan.l
								
								
								
								
							|  | @ -1,230 +0,0 @@ | ||||||
| /** |  | ||||||
|  * See Copyright Notice in picrin.h |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| %{ |  | ||||||
| #include "picrin.h" |  | ||||||
| #include "picrin/parse.h" |  | ||||||
| 
 |  | ||||||
| #define yylval (yyextra->yylval) |  | ||||||
| 
 |  | ||||||
| #define YY_NO_UNISTD_H |  | ||||||
| 
 |  | ||||||
| /* NOTE: |  | ||||||
|  *  An internal function `yy_fatal_error` takes yyscanner for its second |  | ||||||
|  * argument but doesn't use it. This invokes a `unused variable` compiler |  | ||||||
|  * warning and it became super unusable if `-Werror` is turned on the system. |  | ||||||
|  * Since there's no flag to switch `yy_fatal_error` off and replace it with |  | ||||||
|  * a user-defined function, we modify this macro constant to use yyscanner |  | ||||||
|  * at least once avoiding get flex affected in any condition. |  | ||||||
|  */ |  | ||||||
| #define YY_EXIT_FAILURE ( (void)yyscanner, 2 ) |  | ||||||
| %} |  | ||||||
| 
 |  | ||||||
| %option reentrant |  | ||||||
| 
 |  | ||||||
| %option noyyalloc |  | ||||||
| %option noyyrealloc |  | ||||||
| %option noyyfree |  | ||||||
| %option noinput |  | ||||||
| %option nounput |  | ||||||
| %option noyywrap |  | ||||||
| 
 |  | ||||||
| %option extra-type="struct parser_control *" |  | ||||||
| %option never-interactive |  | ||||||
| 
 |  | ||||||
|   /* shebang */ |  | ||||||
| shebang		#!.*$ |  | ||||||
| 
 |  | ||||||
|   /* comment */ |  | ||||||
| comment		;.*$ |  | ||||||
| 
 |  | ||||||
|   /* boolean */ |  | ||||||
| boolean		#t|#f|#true|#false |  | ||||||
| 
 |  | ||||||
|   /* symbol */ |  | ||||||
| identifier	[a-z0-9A-Z+/*!$%&:@^~?<=>_.-]+ |  | ||||||
| 
 |  | ||||||
|   /* number */ |  | ||||||
| digit		[0-9] |  | ||||||
| real		{sign}{ureal}|{infnan} |  | ||||||
| ureal		{uinteger}|\.{digit}+|{digit}+\.{digit}* |  | ||||||
| integer		{sign}{uinteger} |  | ||||||
| uinteger	{digit}+ |  | ||||||
| sign		[+-]? |  | ||||||
| infnan		"+inf.0"|"-inf.0"|"+nan.0"|"-nan.0" |  | ||||||
| 
 |  | ||||||
|   /* char */ |  | ||||||
| %x CHAR |  | ||||||
| 
 |  | ||||||
|   /* string */ |  | ||||||
| %x STRING |  | ||||||
| 
 |  | ||||||
|   /* bytevector */ |  | ||||||
| %x BYTEVECTOR |  | ||||||
| 
 |  | ||||||
|   /* block comment */ |  | ||||||
| %x BLOCK_COMMENT |  | ||||||
| 
 |  | ||||||
|   /* datum label */ |  | ||||||
| label		#{uinteger} |  | ||||||
| %x DATUM_LABEL |  | ||||||
| 
 |  | ||||||
| %% |  | ||||||
| 
 |  | ||||||
| [ \t\n\r]	/* skip whitespace */ |  | ||||||
| {comment}	/* skip comment */ |  | ||||||
| {shebang}	/* skip shebang */ |  | ||||||
| 
 |  | ||||||
| "#|"		{ |  | ||||||
|   BEGIN(BLOCK_COMMENT); |  | ||||||
|   yylval.i = 0; |  | ||||||
| } |  | ||||||
| <BLOCK_COMMENT>"#|" 	{ |  | ||||||
|   yylval.i++; |  | ||||||
| } |  | ||||||
| <BLOCK_COMMENT>"|#"	{ |  | ||||||
|   if (yylval.i == 0) |  | ||||||
|     BEGIN(INITIAL); |  | ||||||
|   else |  | ||||||
|     yylval.i--; |  | ||||||
| } |  | ||||||
| <BLOCK_COMMENT>.|\n	{ |  | ||||||
|   /* skip block comment */ |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| {label}		{ |  | ||||||
|   BEGIN(DATUM_LABEL); |  | ||||||
|   yylval.i = atoi(yytext + 1); |  | ||||||
| } |  | ||||||
| <DATUM_LABEL>=	{ |  | ||||||
|   BEGIN(INITIAL); |  | ||||||
|   return tLABEL_SET; |  | ||||||
| } |  | ||||||
| <DATUM_LABEL>#	{ |  | ||||||
|   BEGIN(INITIAL); |  | ||||||
|   return tLABEL_REF; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| "#;"		return tDATUM_COMMENT; |  | ||||||
| "."		return tDOT; |  | ||||||
| "("		return tLPAREN; |  | ||||||
| ")"		return tRPAREN; |  | ||||||
| "["		return tLBRACKET; |  | ||||||
| "]"		return tRBRACKET; |  | ||||||
| "#("		return tVPAREN; |  | ||||||
| "'"		return tQUOTE; |  | ||||||
| "`"		return tQUASIQUOTE; |  | ||||||
| ","		return tUNQUOTE; |  | ||||||
| ",@"		return tUNQUOTE_SPLICING; |  | ||||||
| 
 |  | ||||||
| {boolean}	{ |  | ||||||
|   yylval.i = (yytext[1] == 't'); |  | ||||||
|   return tBOOLEAN; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| {integer}	{ |  | ||||||
|   yylval.i = atoi(yytext); |  | ||||||
|   return tINT; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| {real} 		{ |  | ||||||
|   yylval.f = atof(yytext); |  | ||||||
|   return tFLOAT; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| {identifier}	{ |  | ||||||
|   yylval.buf.dat = yytext; |  | ||||||
|   yylval.buf.len = yyleng; |  | ||||||
|   return tSYMBOL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| "\""		{ |  | ||||||
|   BEGIN(STRING); |  | ||||||
|   yylval.buf.len = 0; |  | ||||||
|   yylval.buf.dat = yyalloc(yylval.buf.len + 1, yyscanner); |  | ||||||
|   strcpy(yylval.buf.dat, ""); |  | ||||||
| } |  | ||||||
| <STRING>[^\\"]+	{ |  | ||||||
|   yylval.buf.len += yyleng; |  | ||||||
|   yylval.buf.dat = yyrealloc(yylval.buf.dat, yylval.buf.len + 1, yyscanner); |  | ||||||
|   strcpy(yylval.buf.dat + yylval.buf.len - yyleng, yytext); |  | ||||||
| } |  | ||||||
| <STRING>\\.	{ |  | ||||||
|   yylval.buf.len += 1; |  | ||||||
|   yylval.buf.dat = yyrealloc(yylval.buf.dat, yylval.buf.len + 1, yyscanner); |  | ||||||
|   yylval.buf.dat[yylval.buf.len] = '\0'; |  | ||||||
| 
 |  | ||||||
|   switch (yytext[yyleng - 1]) { |  | ||||||
|   case 'a': yylval.buf.dat[yylval.buf.len - 1] = '\a'; break; |  | ||||||
|   case 'b': yylval.buf.dat[yylval.buf.len - 1] = '\b'; break; |  | ||||||
|   case 't': yylval.buf.dat[yylval.buf.len - 1] = '\t'; break; |  | ||||||
|   case 'n': yylval.buf.dat[yylval.buf.len - 1] = '\n'; break; |  | ||||||
|   case 'r': yylval.buf.dat[yylval.buf.len - 1] = '\r'; break; |  | ||||||
|   default: yylval.buf.dat[yylval.buf.len - 1] = yytext[yyleng - 1]; break; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| <STRING>\\[:blank:]*\n[:blank:]* { |  | ||||||
|   /* skip intraline whitespaces */ |  | ||||||
| } |  | ||||||
| <STRING>\"	{ |  | ||||||
|   BEGIN(INITIAL); |  | ||||||
|   return tSTRING; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #\\		{ |  | ||||||
|   BEGIN(CHAR); |  | ||||||
| } |  | ||||||
| <CHAR>alarm	{ yylval.c = '\a'; BEGIN(INITIAL); return tCHAR; } |  | ||||||
| <CHAR>backspace	{ yylval.c = '\b'; BEGIN(INITIAL); return tCHAR; } |  | ||||||
| <CHAR>delete	{ yylval.c = 0x7f; BEGIN(INITIAL); return tCHAR; } |  | ||||||
| <CHAR>escape	{ yylval.c = 0x1b; BEGIN(INITIAL); return tCHAR; } |  | ||||||
| <CHAR>newline	{ yylval.c = '\n'; BEGIN(INITIAL); return tCHAR; } |  | ||||||
| <CHAR>null	{ yylval.c = '\0'; BEGIN(INITIAL); return tCHAR; } |  | ||||||
| <CHAR>return	{ yylval.c = '\r'; BEGIN(INITIAL); return tCHAR; } |  | ||||||
| <CHAR>space	{ yylval.c = ' ';  BEGIN(INITIAL); return tCHAR; } |  | ||||||
| <CHAR>tab	{ yylval.c = '\t'; BEGIN(INITIAL); return tCHAR; } |  | ||||||
| <CHAR>.		{ yylval.c = yytext[0]; BEGIN(INITIAL); return tCHAR; } |  | ||||||
| 
 |  | ||||||
| "#u8("		{ |  | ||||||
|   BEGIN(BYTEVECTOR); |  | ||||||
|   yylval.buf.len = 0; |  | ||||||
|   yylval.buf.dat = NULL; |  | ||||||
| } |  | ||||||
| <BYTEVECTOR>[ \r\n\t]	{ |  | ||||||
|   /* skip whitespace */ |  | ||||||
| } |  | ||||||
| <BYTEVECTOR>{uinteger}	{ |  | ||||||
|   int i = atoi(yytext); |  | ||||||
|   if (0 > i || i > 255) { |  | ||||||
|     yyfree(yylval.buf.dat, yyscanner); |  | ||||||
|     REJECT; |  | ||||||
|   } |  | ||||||
|   yylval.buf.len += 1; |  | ||||||
|   yylval.buf.dat = yyrealloc(yylval.buf.dat, yylval.buf.len, yyscanner); |  | ||||||
|   yylval.buf.dat[yylval.buf.len - 1] = (char)i; |  | ||||||
| } |  | ||||||
| <BYTEVECTOR>")"	{ |  | ||||||
|   BEGIN(INITIAL); |  | ||||||
|   return tBYTEVECTOR; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| %% |  | ||||||
| 
 |  | ||||||
| void * |  | ||||||
| yyalloc(size_t bytes, yyscan_t yyscanner) |  | ||||||
| { |  | ||||||
|   return pic_alloc(yyget_extra(yyscanner)->pic, bytes); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void * |  | ||||||
| yyrealloc(void *ptr, size_t bytes, yyscan_t yyscanner) |  | ||||||
| { |  | ||||||
|   return pic_realloc(yyget_extra(yyscanner)->pic, ptr, bytes); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| yyfree(void * ptr, yyscan_t yyscanner) |  | ||||||
| { |  | ||||||
|   return pic_free(yyget_extra(yyscanner)->pic, ptr); |  | ||||||
| } |  | ||||||
|  | @ -64,6 +64,9 @@ pic_open(int argc, char *argv[], char **envp) | ||||||
|   pic->lib_tbl = pic_nil_value(); |   pic->lib_tbl = pic_nil_value(); | ||||||
|   pic->lib = NULL; |   pic->lib = NULL; | ||||||
| 
 | 
 | ||||||
|  |   /* reader */ | ||||||
|  |   xh_init_int(&pic->rlabels, sizeof(pic_value)); | ||||||
|  | 
 | ||||||
|   /* error handling */ |   /* error handling */ | ||||||
|   pic->jmp = NULL; |   pic->jmp = NULL; | ||||||
|   pic->err = NULL; |   pic->err = NULL; | ||||||
|  | @ -116,8 +119,8 @@ pic_open(int argc, char *argv[], char **envp) | ||||||
|   pic_init_core(pic); |   pic_init_core(pic); | ||||||
| 
 | 
 | ||||||
|   /* set library */ |   /* set library */ | ||||||
|   pic_make_library(pic, pic_read(pic, "(picrin user)")); |   pic_make_library(pic, pic_read_cstr(pic, "(picrin user)")); | ||||||
|   pic_in_library(pic, pic_read(pic, "(picrin user)")); |   pic_in_library(pic, pic_read_cstr(pic, "(picrin user)")); | ||||||
| 
 | 
 | ||||||
|   return pic; |   return pic; | ||||||
| } | } | ||||||
|  | @ -154,6 +157,7 @@ pic_close(pic_state *pic) | ||||||
|   xh_destroy(&pic->syms); |   xh_destroy(&pic->syms); | ||||||
|   xh_destroy(&pic->global_tbl); |   xh_destroy(&pic->global_tbl); | ||||||
|   xh_destroy(&pic->macros); |   xh_destroy(&pic->macros); | ||||||
|  |   xh_destroy(&pic->rlabels); | ||||||
| 
 | 
 | ||||||
|   /* free GC arena */ |   /* free GC arena */ | ||||||
|   free(pic->arena); |   free(pic->arena); | ||||||
|  |  | ||||||
|  | @ -440,8 +440,8 @@ pic_printf(pic_state *pic, const char *fmt, ...) | ||||||
| 
 | 
 | ||||||
|   va_end(ap); |   va_end(ap); | ||||||
| 
 | 
 | ||||||
|   printf("%s", pic_str_cstr(str)); |   xprintf("%s", pic_str_cstr(str)); | ||||||
|   fflush(stdout); |   xfflush(xstdout); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static pic_value | static pic_value | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								tools/main.c
								
								
								
								
							
							
						
						
									
										22
									
								
								tools/main.c
								
								
								
								
							|  | @ -39,16 +39,16 @@ import_repllib(pic_state *pic) | ||||||
| { | { | ||||||
|   int ai = pic_gc_arena_preserve(pic); |   int ai = pic_gc_arena_preserve(pic); | ||||||
| 
 | 
 | ||||||
|   pic_import(pic, pic_read(pic, "(scheme base)")); |   pic_import(pic, pic_read_cstr(pic, "(scheme base)")); | ||||||
|   pic_import(pic, pic_read(pic, "(scheme load)")); |   pic_import(pic, pic_read_cstr(pic, "(scheme load)")); | ||||||
|   pic_import(pic, pic_read(pic, "(scheme process-context)")); |   pic_import(pic, pic_read_cstr(pic, "(scheme process-context)")); | ||||||
|   pic_import(pic, pic_read(pic, "(scheme write)")); |   pic_import(pic, pic_read_cstr(pic, "(scheme write)")); | ||||||
|   pic_import(pic, pic_read(pic, "(scheme file)")); |   pic_import(pic, pic_read_cstr(pic, "(scheme file)")); | ||||||
|   pic_import(pic, pic_read(pic, "(scheme inexact)")); |   pic_import(pic, pic_read_cstr(pic, "(scheme inexact)")); | ||||||
|   pic_import(pic, pic_read(pic, "(scheme cxr)")); |   pic_import(pic, pic_read_cstr(pic, "(scheme cxr)")); | ||||||
|   pic_import(pic, pic_read(pic, "(scheme lazy)")); |   pic_import(pic, pic_read_cstr(pic, "(scheme lazy)")); | ||||||
|   pic_import(pic, pic_read(pic, "(scheme time)")); |   pic_import(pic, pic_read_cstr(pic, "(scheme time)")); | ||||||
|   pic_import(pic, pic_read(pic, "(picrin macro)")); |   pic_import(pic, pic_read_cstr(pic, "(picrin macro)")); | ||||||
| 
 | 
 | ||||||
| #if DEBUG | #if DEBUG | ||||||
|   puts("* imported repl libraries"); |   puts("* imported repl libraries"); | ||||||
|  | @ -289,7 +289,7 @@ main(int argc, char *argv[], char **envp) | ||||||
|   parse_opt(argc, argv); |   parse_opt(argc, argv); | ||||||
| 
 | 
 | ||||||
|   if (mode == INTERACTIVE_MODE || mode == ONE_LINER_MODE) { |   if (mode == INTERACTIVE_MODE || mode == ONE_LINER_MODE) { | ||||||
|     import_repllib(pic); |     // import_repllib(pic);
 | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   switch (mode) { |   switch (mode) { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Yuichi Nishiwaki
						Yuichi Nishiwaki