Compare commits
27
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5d6a9d81f | ||
|
|
3e7efdc741 | ||
|
|
7872408f74 | ||
|
|
4fa37b0b10 | ||
|
|
301af992fe | ||
|
|
439ae24705 | ||
|
|
04112340a0 | ||
|
|
c4470046b3 | ||
|
|
11aa1a5f5b | ||
|
|
f84a72aa37 | ||
|
|
9b606a9004 | ||
|
|
92cb70de2b | ||
|
|
0d63c63d4c | ||
|
|
bb0008f941 | ||
|
|
91046817b1 | ||
|
|
c15d8d7336 | ||
|
|
9b3d014c3e | ||
|
|
9e261a8ffc | ||
|
|
3957f970eb | ||
|
|
0ad0cdef14 | ||
|
|
b1844be9cc | ||
|
|
f744ba3265 | ||
|
|
089762d84a | ||
|
|
317c9173ec | ||
|
|
0510de8634 | ||
|
|
9f29353db3 | ||
|
|
469a6e45d4 |
@@ -123,6 +123,7 @@ include_directories(
|
||||
${SC_BINARY_DIR}/include
|
||||
)
|
||||
|
||||
add_subdirectory(src/auxlib)
|
||||
add_subdirectory(src/base)
|
||||
add_subdirectory(src/express)
|
||||
add_subdirectory(src/exppp)
|
||||
|
||||
+77
-120
@@ -47,42 +47,16 @@
|
||||
find_program(LEMON_EXECUTABLE lemon DOC "path to the lemon executable")
|
||||
mark_as_advanced(LEMON_EXECUTABLE)
|
||||
|
||||
if (LEMON_EXECUTABLE AND NOT LEMON_TEMPLATE)
|
||||
# look for the template in share
|
||||
if (DATA_DIR AND EXISTS "${DATA_DIR}/lemon/lempar.c")
|
||||
set (LEMON_TEMPLATE "${DATA_DIR}/lemon/lempar.c")
|
||||
elseif (EXISTS "share/lemon/lempar.c")
|
||||
set (LEMON_TEMPLATE "share/lemon/lempar.c")
|
||||
elseif (EXISTS "/usr/share/lemon/lempar.c")
|
||||
set (LEMON_TEMPLATE "/usr/share/lemon/lempar.c")
|
||||
endif (DATA_DIR AND EXISTS "${DATA_DIR}/lemon/lempar.c")
|
||||
endif (LEMON_EXECUTABLE AND NOT LEMON_TEMPLATE)
|
||||
|
||||
if (LEMON_EXECUTABLE AND NOT LEMON_TEMPLATE)
|
||||
# look for the template in bin dir
|
||||
get_filename_component(lemon_path ${LEMON_EXECUTABLE} PATH)
|
||||
if (lemon_path)
|
||||
if (EXISTS ${lemon_path}/lempar.c)
|
||||
set (LEMON_TEMPLATE "${lemon_path}/lempar.c")
|
||||
endif (EXISTS ${lemon_path}/lempar.c)
|
||||
if (EXISTS /usr/share/lemon/lempar.c)
|
||||
set (LEMON_TEMPLATE "/usr/share/lemon/lempar.c")
|
||||
endif (EXISTS /usr/share/lemon/lempar.c)
|
||||
endif (lemon_path)
|
||||
endif(LEMON_EXECUTABLE AND NOT LEMON_TEMPLATE)
|
||||
|
||||
if (LEMON_EXECUTABLE AND NOT LEMON_TEMPLATE)
|
||||
# fallback
|
||||
set (LEMON_TEMPLATE "lempar.c")
|
||||
if (NOT EXISTS ${LEMON_TEMPLATE})
|
||||
message(WARNING "Lemon's lempar.c template file could not be found automatically, set LEMON_TEMPLATE")
|
||||
endif (NOT EXISTS ${LEMON_TEMPLATE})
|
||||
endif (LEMON_EXECUTABLE AND NOT LEMON_TEMPLATE)
|
||||
|
||||
mark_as_advanced(LEMON_TEMPLATE)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LEMON DEFAULT_MSG LEMON_EXECUTABLE LEMON_TEMPLATE)
|
||||
if (LEMON_EXECUTABLE)
|
||||
get_filename_component(lemon_dir ${LEMON_EXECUTABLE} DIRECTORY)
|
||||
find_file(LEMON_TEMPLATE lempar.c
|
||||
PATHS "${lemon_dir}" "/usr/share/lemon"
|
||||
NO_DEFAULT_PATH)
|
||||
mark_as_advanced(LEMON_TEMPLATE)
|
||||
|
||||
if(NOT LEMON_TEMPLATE)
|
||||
message(SEND_ERROR "failed to find lemon template (lempar.c)")
|
||||
endif()
|
||||
|
||||
# Define the macro
|
||||
# LEMON_TARGET(<Name> <LemonInput> <LemonSource> <LemonHeader>
|
||||
@@ -104,102 +78,85 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LEMON DEFAULT_MSG LEMON_EXECUTABLE LEMON_TEMPL
|
||||
include(CMakeParseArguments)
|
||||
|
||||
if(NOT COMMAND LEMON_TARGET)
|
||||
macro(LEMON_TARGET Name Input)
|
||||
macro(LEMON_TARGET Name LemonInput LemonOutput)
|
||||
set(LT_ARGS DEFINES_FILE COMPILE_FLAGS)
|
||||
CMAKE_PARSE_ARGUMENTS(LEMON_TARGET_ARG "" "${LT_ARGS}" "" ${ARGN})
|
||||
|
||||
get_filename_component(IN_FILE_WE ${Input} NAME_WE)
|
||||
set(LVAR_PREFIX ${Name}_${IN_FILE_WE})
|
||||
|
||||
if(${ARGC} GREATER 3)
|
||||
CMAKE_PARSE_ARGUMENTS(${LVAR_PREFIX} "" "OUT_SRC_FILE;OUT_HDR_FILE;WORKING_DIR;EXTRA_ARGS" "" ${ARGN})
|
||||
endif(${ARGC} GREATER 3)
|
||||
|
||||
# Need a working directory
|
||||
if("${${LVAR_PREFIX}_WORKING_DIR}" STREQUAL "")
|
||||
set(${LVAR_PREFIX}_WORKING_DIR "${CMAKE_CURRENT_BINARY_DIR}/${LVAR_PREFIX}")
|
||||
endif("${${LVAR_PREFIX}_WORKING_DIR}" STREQUAL "")
|
||||
file(MAKE_DIRECTORY ${${LVAR_PREFIX}_WORKING_DIR})
|
||||
|
||||
# Output source file
|
||||
if ("${${LVAR_PREFIX}_OUT_SRC_FILE}" STREQUAL "")
|
||||
set(${LVAR_PREFIX}_OUT_SRC_FILE ${${LVAR_PREFIX}_WORKING_DIR}/${IN_FILE_WE}.c)
|
||||
else ("${${LVAR_PREFIX}_OUT_SRC_FILE}" STREQUAL "")
|
||||
get_filename_component(specified_out_dir ${${LVAR_PREFIX}_OUT_SRC_FILE} PATH)
|
||||
if(NOT "${specified_out_dir}" STREQUAL "")
|
||||
message(FATAL_ERROR "\nFull path specified for OUT_SRC_FILE - should be filename only.\n")
|
||||
endif(NOT "${specified_out_dir}" STREQUAL "")
|
||||
set(${LVAR_PREFIX}_OUT_SRC_FILE ${${LVAR_PREFIX}_WORKING_DIR}/${${LVAR_PREFIX}_OUT_SRC_FILE})
|
||||
endif ("${${LVAR_PREFIX}_OUT_SRC_FILE}" STREQUAL "")
|
||||
|
||||
# Output header file
|
||||
if ("${${LVAR_PREFIX}_OUT_HDR_FILE}" STREQUAL "")
|
||||
set(${LVAR_PREFIX}_OUT_HDR_FILE ${${LVAR_PREFIX}_WORKING_DIR}/${IN_FILE_WE}.h)
|
||||
else ("${${LVAR_PREFIX}_OUT_HDR_FILE}" STREQUAL "")
|
||||
get_filename_component(specified_out_dir ${${LVAR_PREFIX}_OUT_HDR_FILE} PATH)
|
||||
if(NOT "${specified_out_dir}" STREQUAL "")
|
||||
message(FATAL_ERROR "\nFull path specified for OUT_HDR_FILE - should be filename only.\n")
|
||||
endif(NOT "${specified_out_dir}" STREQUAL "")
|
||||
set(${LVAR_PREFIX}_OUT_HDR_FILE ${${LVAR_PREFIX}_WORKING_DIR}/${${LVAR_PREFIX}_OUT_HDR_FILE})
|
||||
endif ("${${LVAR_PREFIX}_OUT_HDR_FILE}" STREQUAL "")
|
||||
if(NOT "${LEMON_TARGET_ARG_COMPILE_FLAGS}" STREQUAL "")
|
||||
set(LEMON_EXECUTABLE_opts "${LEMON_TARGET_ARG_COMPILE_FLAGS}")
|
||||
separate_arguments(LEMON_EXECUTABLE_opts)
|
||||
else()
|
||||
set(LEMON_EXECUTABLE_opts "")
|
||||
endif()
|
||||
|
||||
# check for LemonOutput
|
||||
get_filename_component(_basename ${LemonOutput} NAME_WE)
|
||||
get_filename_component(_out_src_file ${LemonOutput} NAME)
|
||||
get_filename_component(_out_dir ${LemonOutput} PATH)
|
||||
if(NOT "${_out_dir}" STREQUAL "")
|
||||
message(WARNING "Full path specified for LemonOutput - should be filename only")
|
||||
endif()
|
||||
|
||||
# set report file
|
||||
set(_out_rpt_file "${_basename}.out")
|
||||
|
||||
# check for DEFINES_FILE
|
||||
if ("${LEMON_TARGET_ARG_DEFINES_FILE}" STREQUAL "")
|
||||
set(_out_hdr_file "${_basename}.h")
|
||||
else()
|
||||
get_filename_component(_out_dir ${LEMON_TARGET_ARG_DEFINES_FILE} PATH)
|
||||
get_filename_component(_out_hdr_file ${LEMON_TARGET_ARG_DEFINES_FILE} NAME)
|
||||
if(NOT "${_out_dir}" STREQUAL "")
|
||||
message(WARNING "Full path specified for DEFINES_FILE - should be filename only")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# input file
|
||||
get_filename_component(in_full ${Input} ABSOLUTE)
|
||||
if("${in_full}" STREQUAL "${Input}")
|
||||
set(lemon_in_file ${Input})
|
||||
else("${in_full}" STREQUAL "${Input}")
|
||||
set(lemon_in_file "${CMAKE_CURRENT_SOURCE_DIR}/${Input}")
|
||||
endif("${in_full}" STREQUAL "${Input}")
|
||||
get_filename_component(_in_y_path ${LemonInput} ABSOLUTE)
|
||||
get_filename_component(_in_y_file ${LemonInput} NAME)
|
||||
|
||||
|
||||
# names of lemon output files will be based on the name of the input file
|
||||
set(LEMON_GEN_SOURCE ${${LVAR_PREFIX}_WORKING_DIR}/${IN_FILE_WE}.c)
|
||||
set(LEMON_GEN_HEADER ${${LVAR_PREFIX}_WORKING_DIR}/${IN_FILE_WE}.h)
|
||||
set(LEMON_GEN_OUT ${${LVAR_PREFIX}_WORKING_DIR}/${IN_FILE_WE}.out)
|
||||
|
||||
# copy input to bin directory and run lemon
|
||||
get_filename_component(INPUT_NAME ${Input} NAME)
|
||||
# TODO: is this really necessary?
|
||||
add_custom_command(
|
||||
OUTPUT ${LEMON_GEN_OUT} ${LEMON_GEN_SOURCE} ${LEMON_GEN_HEADER}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${lemon_in_file} ${${LVAR_PREFIX}_WORKING_DIR}/${INPUT_NAME}
|
||||
COMMAND ${LEMON_EXECUTABLE} -T${LEMON_TEMPLATE} ${${LVAR_PREFIX}_WORKING_DIR}/${INPUT_NAME} ${${LVAR_PREFIX}__EXTRA_ARGS}
|
||||
DEPENDS ${Input} ${LEMON_TEMPLATE} ${LEMON_EXECUTABLE_TARGET}
|
||||
WORKING_DIRECTORY ${${LVAR_PREFIX}_WORKING_DIR}
|
||||
COMMENT "[LEMON][${Name}] Building parser with ${LEMON_EXECUTABLE}"
|
||||
)
|
||||
|
||||
# rename generated outputs
|
||||
if(NOT "${${LVAR_PREFIX}_OUT_SRC_FILE}" STREQUAL "${LEMON_GEN_SOURCE}")
|
||||
add_custom_command(
|
||||
OUTPUT ${${LVAR_PREFIX}_OUT_SRC_FILE}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LEMON_GEN_SOURCE} ${${LVAR_PREFIX}_OUT_SRC_FILE}
|
||||
DEPENDS ${LemonInput} ${LEMON_EXECUTABLE_TARGET} ${LEMON_GEN_SOURCE}
|
||||
)
|
||||
set(LEMON_${Name}_OUTPUTS ${${LVAR_PREFIX}_OUT_SRC_FILE} ${LEMON_${Name}_OUTPUTS})
|
||||
endif(NOT "${${LVAR_PREFIX}_OUT_SRC_FILE}" STREQUAL "${LEMON_GEN_SOURCE}")
|
||||
if(NOT "${${LVAR_PREFIX}_OUT_HDR_FILE}" STREQUAL "${LEMON_GEN_HEADER}")
|
||||
add_custom_command(
|
||||
OUTPUT ${${LVAR_PREFIX}_OUT_HDR_FILE}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LEMON_GEN_HEADER} ${${LVAR_PREFIX}_OUT_HDR_FILE}
|
||||
DEPENDS ${LemonInput} ${LEMON_EXECUTABLE_TARGET} ${LEMON_GEN_HEADER}
|
||||
)
|
||||
set(LEMON_${Name}_OUTPUTS ${${LVAR_PREFIX}_OUT_HDR_FILE} ${LEMON_${Name}_OUTPUTS})
|
||||
endif(NOT "${${LVAR_PREFIX}_OUT_HDR_FILE}" STREQUAL "${LEMON_GEN_HEADER}")
|
||||
|
||||
set(LEMON_${Name}_OUTPUTS ${LEMON_${Name}_OUTPUTS} ${LEMON_GEN_OUT})
|
||||
OUTPUT ${_in_y_file}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${_in_y_path} ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
# execute lemon
|
||||
add_custom_command(
|
||||
OUTPUT ${_out_src_file}
|
||||
COMMAND ${LEMON_EXECUTABLE} -T${LEMON_TEMPLATE} ${LEMON_EXECUTABLE_opts} ${_in_y_file}
|
||||
DEPENDS ${_in_y_file}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "[LEMON][${Name}] Building parser with ${LEMON_EXECUTABLE}"
|
||||
)
|
||||
|
||||
# rename the header
|
||||
add_custom_command(
|
||||
OUTPUT ${_out_hdr_file}
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E rename ${_basename}.h ${_out_hdr_file}
|
||||
DEPENDS ${_out_src_file}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
# set the return values
|
||||
# TODO: for generated sources even headers should be target dependencies
|
||||
set(LEMON_${Name}_DEFINED TRUE)
|
||||
set(LEMON_${Name}_OUTPUT_HEADER "${CMAKE_CURRENT_BINARY_DIR}/${_out_hdr_file}")
|
||||
set(LEMON_${Name}_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
set(LEMON_${Name}_OUTPUTS "${_out_src_file}")
|
||||
|
||||
# make sure we clean up generated output and copied input
|
||||
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${LEMON_${Name}_OUTPUTS}")
|
||||
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${${LVAR_PREFIX}_WORKING_DIR}/${INPUT_NAME}")
|
||||
|
||||
# macro ran successfully
|
||||
set(LEMON_${Name}_DEFINED TRUE)
|
||||
|
||||
set(LEMON_${Name}_SRC ${${LVAR_PREFIX}_OUT_SRC_FILE})
|
||||
set(LEMON_${Name}_HDR ${${LVAR_PREFIX}_OUT_HDR_FILE})
|
||||
set(LEMON_${Name}_INCLUDE_DIR ${${LVAR_PREFIX}_WORKING_DIR})
|
||||
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/${_in_y_file}")
|
||||
|
||||
endmacro(LEMON_TARGET)
|
||||
endif(NOT COMMAND LEMON_TARGET)
|
||||
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LEMON REQUIRED_VARS LEMON_EXECUTABLE LEMON_TEMPLATE)
|
||||
|
||||
#============================================================
|
||||
# FindLEMON.cmake ends here
|
||||
|
||||
|
||||
+61
-32
@@ -6,8 +6,20 @@
|
||||
find_program(RE2C_EXECUTABLE re2c DOC "path to the re2c executable")
|
||||
mark_as_advanced(RE2C_EXECUTABLE)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(RE2C DEFAULT_MSG RE2C_EXECUTABLE)
|
||||
if(RE2C_EXECUTABLE)
|
||||
|
||||
execute_process(COMMAND ${RE2C_EXECUTABLE} -v
|
||||
OUTPUT_VARIABLE RE2C_version_output
|
||||
ERROR_VARIABLE RE2C_version_error
|
||||
RESULT_VARIABLE RE2C_version_result
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
if(NOT ${RE2C_version_result} EQUAL 0)
|
||||
message(SEND_ERROR
|
||||
"Command \"${RE2C_EXECUTABLE} -v\" failed with output:\n${RE2C_version_output}\n${RE2C_version_error}")
|
||||
else()
|
||||
string(REGEX REPLACE "^re2c ([0-9]+[^ ]*)( .*)?$" "\\1" RE2C_VERSION "${RE2C_version_output}")
|
||||
endif()
|
||||
|
||||
# Provide a macro to generate custom build rules:
|
||||
|
||||
@@ -80,36 +92,47 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(RE2C DEFAULT_MSG RE2C_EXECUTABLE)
|
||||
# RE2C_TARGET (public macro)
|
||||
#============================================================
|
||||
#
|
||||
# TODO - rework this macro to make use of CMakeParseArguments, see
|
||||
# http://www.cmake.org/pipermail/cmake/2012-July/051309.html
|
||||
if(NOT COMMAND RE2C_TARGET)
|
||||
macro(RE2C_TARGET Name Input Output)
|
||||
set(RE2C_TARGET_usage "RE2C_TARGET(<Name> <Input> <Output> [COMPILE_FLAGS <string>]")
|
||||
if(${ARGC} GREATER 3)
|
||||
if(${ARGC} EQUAL 5)
|
||||
if("${ARGV3}" STREQUAL "COMPILE_FLAGS")
|
||||
set(RE2C_EXECUTABLE_opts "${ARGV4}")
|
||||
SEPARATE_ARGUMENTS(RE2C_EXECUTABLE_opts)
|
||||
else()
|
||||
message(SEND_ERROR ${RE2C_TARGET_usage})
|
||||
endif()
|
||||
else()
|
||||
message(SEND_ERROR ${RE2C_TARGET_usage})
|
||||
endif()
|
||||
macro(RE2C_TARGET Name RE2CInput RE2COutput)
|
||||
set(_re2c_args COMPILE_FLAGS DEFINES_FILE)
|
||||
cmake_parse_arguments(RE2C_TARGET_ARG "" "${_re2c_args}" "" ${ARGN})
|
||||
|
||||
if(NOT "${RE2C_TARGET_ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
|
||||
message(SEND_ERROR "RE2C_TARGET(<Name> <RE2CInput> <RE2COutput>
|
||||
[COMPILE_FLAGS <string>]
|
||||
[DEFINES_FILE <string>])")
|
||||
else()
|
||||
if(NOT "${RE2C_TARGET_ARG_COMPILE_FLAGS}" STREQUAL "")
|
||||
set(RE2C_EXECUTABLE_opts "${RE2C_TARGET_ARG_COMPILE_FLAGS}")
|
||||
separate_arguments(RE2C_EXECUTABLE_opts)
|
||||
else()
|
||||
set(RE2C_EXECUTABLE_opts "")
|
||||
endif()
|
||||
|
||||
if(NOT "${RE2C_TARGET_ARG_DEFINES_FILE}" STREQUAL "")
|
||||
list(APPEND RE2C_EXECUTABLE_opts -t ${RE2C_TARGET_ARG_DEFINES_FILE})
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${RE2COutput}
|
||||
COMMAND ${RE2C_EXECUTABLE}
|
||||
ARGS ${RE2C_EXECUTABLE_opts} -o ${RE2COutput} ${CMAKE_CURRENT_SOURCE_DIR}/${RE2CInput}
|
||||
DEPENDS ${RE2CInput}
|
||||
COMMENT "[RE2C][${Name}] Building scanner with ${RE2C_EXECUTABLE}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
# TODO: check, for generated sources headers should be included in outputs
|
||||
set(RE2C_${Name}_DEFINED TRUE)
|
||||
set(RE2C_${Name}_OUTPUTS ${RE2COutput})
|
||||
if("${RE2C_TARGET_ARG_DEFINES_FILE}" STREQUAL "")
|
||||
set(RE2C_${Name}_OUTPUT_HEADER "")
|
||||
else()
|
||||
set(RE2C_${Name}_OUTPUT_HEADER "${RE2C_TARGET_ARG_DEFINES_FILE}")
|
||||
endif()
|
||||
set(RE2C_${Name}_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${Output}
|
||||
COMMAND ${RE2C_EXECUTABLE}
|
||||
ARGS ${RE2C_EXECUTABLE_opts} -o${Output} ${Input}
|
||||
DEPENDS ${Input} ${RE2C_EXECUTABLE_TARGET}
|
||||
COMMENT "[RE2C][${Name}] Building scanner with ${RE2C_EXECUTABLE}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
set(RE2C_${Name}_DEFINED TRUE)
|
||||
set(RE2C_${Name}_OUTPUTS ${Output})
|
||||
set(RE2C_${Name}_INPUT ${Input})
|
||||
set(RE2C_${Name}_COMPILE_FLAGS ${RE2C_EXECUTABLE_opts})
|
||||
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${Output}")
|
||||
|
||||
endmacro(RE2C_TARGET)
|
||||
endif(NOT COMMAND RE2C_TARGET)
|
||||
#============================================================
|
||||
@@ -125,16 +148,22 @@ if(NOT COMMAND ADD_RE2C_LEMON_DEPENDENCY)
|
||||
message(SEND_ERROR "RE2C target `${RE2CTarget}' does not exists.")
|
||||
endif()
|
||||
|
||||
if(NOT LEMON_${LemonTarget}_HDR)
|
||||
if(NOT LEMON_${LemonTarget}_OUTPUT_HEADER)
|
||||
message(SEND_ERROR "Lemon target `${LemonTarget}' does not exists.")
|
||||
endif()
|
||||
|
||||
set_source_files_properties(${RE2C_${RE2CTarget}_OUTPUTS}
|
||||
PROPERTIES OBJECT_DEPENDS ${LEMON_${LemonTarget}_HDR})
|
||||
PROPERTIES OBJECT_DEPENDS ${LEMON_${LemonTarget}_OUTPUT_HEADER})
|
||||
endmacro(ADD_RE2C_LEMON_DEPENDENCY)
|
||||
endif(NOT COMMAND ADD_RE2C_LEMON_DEPENDENCY)
|
||||
#============================================================
|
||||
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(RE2C REQUIRED_VARS RE2C_EXECUTABLE
|
||||
VERSION_VAR RE2C_VERSION)
|
||||
|
||||
# RE2C_Util.cmake ends here
|
||||
|
||||
# Local Variables:
|
||||
|
||||
+20
-28
@@ -1,4 +1,4 @@
|
||||
# The Express parser uses the tools Perplex, RE2C and Lemon to generate code
|
||||
# The Express parser uses the tools RE2C and Lemon to generate code
|
||||
# from higher level inputs. Depending on available tools and options, the
|
||||
# SC build can either re-generate code as part of the build, or use cached
|
||||
# files that are ready for compilation.
|
||||
@@ -10,45 +10,37 @@
|
||||
# this option is set to ON and the necessary tools are not found, the
|
||||
# configure step will fail. If it is set to OFF, SC will not even try to use
|
||||
# the generators and will instead use the cached sources.
|
||||
if(NOT DEFINED SC_GENERATE_LEXER_PARSER)
|
||||
set(SC_GENERATE_LEXER_PARSER "AUTO" CACHE STRING "Use Perplex, RE2C and Lemon to generate C source code.")
|
||||
set(_verbosity "QUIET")
|
||||
else(NOT DEFINED SC_GENERATE_LEXER_PARSER)
|
||||
string(TOUPPER "${SC_GENERATE_LEXER_PARSER}" SC_GENERATE_LEXER_PARSER)
|
||||
endif(NOT DEFINED SC_GENERATE_LEXER_PARSER)
|
||||
set_property(CACHE SC_GENERATE_LEXER_PARSER PROPERTY STRINGS AUTO ON OFF)
|
||||
if (NOT "${SC_GENERATE_LEXER_PARSER}" STREQUAL "AUTO" AND NOT "${SC_GENERATE_LEXER_PARSER}" STREQUAL "ON" AND NOT "${SC_GENERATE_LEXER_PARSER}" STREQUAL "OFF")
|
||||
|
||||
set(_valid_gen_states AUTO ON OFF)
|
||||
set(_verbosity "QUIET")
|
||||
|
||||
set(SC_GENERATE_LEXER_PARSER "AUTO" CACHE
|
||||
STRING "Use Perplex, RE2C and Lemon to generate C source code.")
|
||||
set_property(CACHE SC_GENERATE_LEXER_PARSER PROPERTY STRINGS ${_valid_gen_states})
|
||||
string(TOUPPER "${SC_GENERATE_LEXER_PARSER}" SC_GENERATE_LEXER_PARSER)
|
||||
|
||||
if(NOT "${SC_GENERATE_LEXER_PARSER}" IN_LIST _valid_gen_states)
|
||||
message(WARNING "Unknown value ${SC_GENERATE_LEXER_PARSER} supplied for SC_GENERATE_LEXER_PARSER - defaulting to AUTO")
|
||||
message(WARNING "Valid options are AUTO, ON and OFF")
|
||||
set(SC_GENERATE_LEXER_PARSER "AUTO" CACHE STRING "Use Perplex, RE2C and Lemon to generate C source code.")
|
||||
endif (NOT "${SC_GENERATE_LEXER_PARSER}" STREQUAL "AUTO" AND NOT "${SC_GENERATE_LEXER_PARSER}" STREQUAL "ON" AND NOT "${SC_GENERATE_LEXER_PARSER}" STREQUAL "OFF")
|
||||
endif()
|
||||
|
||||
# If the generators have not been turned off, we need to check for them
|
||||
if(NOT "${SC_GENERATE_LEXER_PARSER}" STREQUAL "OFF")
|
||||
# NOTE: lemon doesn't have a stable versioning system (it's always 1)
|
||||
find_package(LEMON ${_verbosity})
|
||||
find_package(RE2C ${_verbosity})
|
||||
find_package(PERPLEX ${_verbosity})
|
||||
if(LEMON_EXECUTABLE AND LEMON_TEMPLATE AND PERPLEX_EXECUTABLE AND PERPLEX_TEMPLATE AND RE2C_EXECUTABLE)
|
||||
# Templates may be anywhere - make sure we have a stable path if a relative
|
||||
# path was specified at CMake time
|
||||
get_filename_component(lemon_template_fpath "${LEMON_TEMPLATE}" ABSOLUTE)
|
||||
if(NOT "${lemon_template_fpath}" STREQUAL "${LEMON_TEMPLATE}")
|
||||
get_filename_component(LEMON_TEMPLATE "${CMAKE_BINARY_DIR}/${LEMON_TEMPLATE}" ABSOLUTE)
|
||||
endif(NOT "${lemon_template_fpath}" STREQUAL "${LEMON_TEMPLATE}")
|
||||
get_filename_component(perplex_template_fpath "${PERPLEX_TEMPLATE}" ABSOLUTE)
|
||||
if(NOT "${perplex_template_fpath}" STREQUAL "${PERPLEX_TEMPLATE}")
|
||||
get_filename_component(PERPLEX_TEMPLATE "${CMAKE_BINARY_DIR}/${PERPLEX_TEMPLATE}" ABSOLUTE)
|
||||
endif(NOT "${perplex_template_fpath}" STREQUAL "${PERPLEX_TEMPLATE}")
|
||||
|
||||
find_package(RE2C 1.0.3 ${_verbosity})
|
||||
|
||||
if(LEMON_FOUND AND RE2C_FOUND)
|
||||
set(SC_GENERATE_LP_SOURCES 1)
|
||||
message(".. Found perplex, re2c, and lemon - can regenerate lexer/parser if necessary")
|
||||
else(LEMON_EXECUTABLE AND LEMON_TEMPLATE AND PERPLEX_EXECUTABLE AND PERPLEX_TEMPLATE AND RE2C_EXECUTABLE)
|
||||
message(".. Found re2c, and lemon - can regenerate lexer/parser if necessary")
|
||||
else()
|
||||
if("${SC_GENERATE_LEXER_PARSER}" STREQUAL "ON")
|
||||
message(FATAL_ERROR "\nSC_GENERATE_LEXER_PARSER set to ON, but one or more components of the Perplex/RE2C/Lemon toolchain were not found.\n")
|
||||
message(FATAL_ERROR "\nSC_GENERATE_LEXER_PARSER set to ON, but couldn't find lemon/re2c")
|
||||
else("${SC_GENERATE_LEXER_PARSER}" STREQUAL "ON")
|
||||
set(SC_GENERATE_LP_SOURCES 0)
|
||||
endif("${SC_GENERATE_LEXER_PARSER}" STREQUAL "ON")
|
||||
endif(LEMON_EXECUTABLE AND LEMON_TEMPLATE AND PERPLEX_EXECUTABLE AND PERPLEX_TEMPLATE AND RE2C_EXECUTABLE)
|
||||
endif()
|
||||
else(NOT "${SC_GENERATE_LEXER_PARSER}" STREQUAL "OFF")
|
||||
set(SC_GENERATE_LP_SOURCES 0)
|
||||
endif(NOT "${SC_GENERATE_LEXER_PARSER}" STREQUAL "OFF")
|
||||
|
||||
@@ -21,10 +21,10 @@ set(schema_scanner_src
|
||||
${SC_ROOT}/src/exp2cxx/class_strings.c
|
||||
${SC_ROOT}/src/express/generated/expparse.c
|
||||
${SC_ROOT}/src/express/generated/expscan.c
|
||||
${SC_ROOT}/src/express/lexsupport.c
|
||||
${SC_ROOT}/src/express/alg.c
|
||||
${SC_ROOT}/src/express/alloc.c
|
||||
${SC_ROOT}/src/express/caseitem.c
|
||||
${SC_ROOT}/src/express/dict.c
|
||||
${SC_ROOT}/src/express/entity.c
|
||||
${SC_ROOT}/src/express/error.c
|
||||
${SC_ROOT}/src/express/exp_kw.c
|
||||
@@ -32,7 +32,6 @@ set(schema_scanner_src
|
||||
${SC_ROOT}/src/express/express.c
|
||||
${SC_ROOT}/src/express/factory.c
|
||||
${SC_ROOT}/src/express/hash.c
|
||||
${SC_ROOT}/src/express/lexact.c
|
||||
${SC_ROOT}/src/express/linklist.c
|
||||
${SC_ROOT}/src/express/memory.c
|
||||
${SC_ROOT}/src/express/object.c
|
||||
@@ -45,11 +44,13 @@ set(schema_scanner_src
|
||||
${SC_ROOT}/src/express/symbol.c
|
||||
${SC_ROOT}/src/express/type.c
|
||||
${SC_ROOT}/src/express/variable.c
|
||||
${SC_ROOT}/src/auxlib/bstrlib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/schemaScanner.cc
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${SC_ROOT}/include/
|
||||
${SC_ROOT}/src/auxlib
|
||||
${SC_ROOT}/src/express/
|
||||
${SC_ROOT}/src/express/generated
|
||||
${SC_ROOT}/src/base
|
||||
|
||||
@@ -58,23 +58,12 @@ struct freelist_head {
|
||||
#endif
|
||||
};
|
||||
|
||||
char * nnew();
|
||||
|
||||
#include "error.h"
|
||||
|
||||
/***********************************************/
|
||||
/* space allocation macros with error package: */
|
||||
/***********************************************/
|
||||
|
||||
extern SC_EXPRESS_EXPORT int yylineno;
|
||||
|
||||
/** CALLOC grabs and initializes to all 0s space for the indicated
|
||||
* number of instances of the indicated type */
|
||||
#define CALLOC(ptr, num, type) \
|
||||
if (((ptr) = (type*)calloc((num), (unsigned)sizeof(type)))==NULL) { \
|
||||
fprintf(stderr,"fedex: out of space");\
|
||||
} else {}
|
||||
|
||||
SC_EXPRESS_EXPORT void _ALLOCinitialize( void );
|
||||
SC_EXPRESS_EXPORT void ALLOCinitialize( struct freelist_head * flh, unsigned int size, int alloc1, int alloc2 );
|
||||
SC_EXPRESS_EXPORT void ALLOC_destroy( struct freelist_head *, Freelist * );
|
||||
|
||||
+6
-17
@@ -56,7 +56,7 @@
|
||||
/************/
|
||||
|
||||
typedef struct Hash_Table_ * Dictionary;
|
||||
typedef HashEntry DictionaryEntry;
|
||||
typedef struct Hash_Iterator_ DictionaryEntry;
|
||||
|
||||
/****************/
|
||||
/* modules used */
|
||||
@@ -71,27 +71,15 @@ typedef HashEntry DictionaryEntry;
|
||||
/********************/
|
||||
/* global variables */
|
||||
/********************/
|
||||
|
||||
/*TODO: surely this is not a good thing?! */
|
||||
extern SC_EXPRESS_EXPORT char DICT_type; /**< set as a side-effect of DICT lookup routines to type of object found */
|
||||
|
||||
/*******************************/
|
||||
/* macro function definitions */
|
||||
/*******************************/
|
||||
|
||||
#define DICTcreate(estimated_max_size) HASHcreate(estimated_max_size)
|
||||
/** should really can DICTdo_init and rename do_type_init to do_init! */
|
||||
#define DICTdo_init(dict,de) HASHlistinit((dict),(de))
|
||||
#define DICTdo_type_init(dict,de,t) HASHlistinit_by_type((dict),(de),(t))
|
||||
#define DICTdo_end(hash_entry) HASHlistend(hash_entry)
|
||||
|
||||
/** modify dictionary entry in-place */
|
||||
#define DICTchange(e,obj,sym,typ) { \
|
||||
(e)->data = (obj); \
|
||||
(e)->symbol = (sym); \
|
||||
(e)->type = (typ); \
|
||||
}
|
||||
#define DICTchange_type(e,typ) (e)->type = (typ)
|
||||
|
||||
#define DICTcreate(x) HASHcreate()
|
||||
#define DICTdo_init(dict,de,t) HASHdo_init((dict),(de),(t))
|
||||
|
||||
/***********************/
|
||||
/* function prototypes */
|
||||
@@ -100,8 +88,9 @@ extern SC_EXPRESS_EXPORT char DICT_type; /**< set as a side-effect of DICT look
|
||||
extern SC_EXPRESS_EXPORT void DICTinitialize( void );
|
||||
extern SC_EXPRESS_EXPORT void DICTcleanup( void );
|
||||
extern SC_EXPRESS_EXPORT int DICTdefine( Dictionary, char *, void *, Symbol *, char );
|
||||
extern SC_EXPRESS_EXPORT int DICT_define( Dictionary, char *, void *, Symbol *, char );
|
||||
extern SC_EXPRESS_EXPORT int DICTdefine_enum( Dictionary, char *, void *, Symbol *, char );
|
||||
extern SC_EXPRESS_EXPORT void DICTundefine( Dictionary, char * );
|
||||
/* TODO: could DICTlookup be implemented more generically using function pointers? */
|
||||
extern SC_EXPRESS_EXPORT void * DICTlookup( Dictionary, char * );
|
||||
extern SC_EXPRESS_EXPORT void * DICTlookup_symbol( Dictionary, char *, Symbol ** );
|
||||
extern SC_EXPRESS_EXPORT void * DICTdo( DictionaryEntry * );
|
||||
|
||||
@@ -144,11 +144,11 @@ extern SC_EXPRESS_EXPORT struct Scope_ * ENTITYcreate( struct Symbol_ * );
|
||||
extern SC_EXPRESS_EXPORT void ENTITYinitialize( void );
|
||||
extern SC_EXPRESS_EXPORT void ENTITYadd_attribute( struct Scope_ *, struct Variable_ * );
|
||||
extern SC_EXPRESS_EXPORT struct Scope_ * ENTITYcopy( struct Scope_ * );
|
||||
extern SC_EXPRESS_EXPORT Entity ENTITYfind_inherited_entity( struct Scope_ *, char *, int );
|
||||
extern SC_EXPRESS_EXPORT Variable ENTITYfind_inherited_attribute( struct Scope_ *, char *, struct Symbol_ ** );
|
||||
extern SC_EXPRESS_EXPORT Entity ENTITYfind_inherited_entity( struct Scope_ *, const char *, int );
|
||||
extern SC_EXPRESS_EXPORT Symbol *ENTITYfind_inherited_attribute( struct Scope_ *, const char *, struct Symbol_ ** );
|
||||
extern SC_EXPRESS_EXPORT Variable ENTITYresolve_attr_ref( Entity, Symbol *, Symbol * );
|
||||
extern SC_EXPRESS_EXPORT bool ENTITYhas_immediate_supertype( Entity, Entity );
|
||||
extern SC_EXPRESS_EXPORT Variable ENTITYget_named_attribute( Entity, char * );
|
||||
extern SC_EXPRESS_EXPORT Variable ENTITYget_named_attribute( Entity, const char * );
|
||||
extern SC_EXPRESS_EXPORT Linked_List ENTITYget_all_attributes( Entity );
|
||||
extern SC_EXPRESS_EXPORT bool ENTITYhas_supertype( Entity, Entity );
|
||||
extern SC_EXPRESS_EXPORT void ENTITYadd_instance( Entity, void *);
|
||||
|
||||
@@ -128,6 +128,7 @@ typedef char * Binary;
|
||||
|
||||
/** these represent a different way of selecting classes of objects
|
||||
* these are particularly useful when looking for multiple types concurrently */
|
||||
|
||||
#define OBJ_TYPE_BITS 0x1
|
||||
#define OBJ_ENTITY_BITS 0x2
|
||||
#define OBJ_FUNCTION_BITS 0x4
|
||||
@@ -138,6 +139,10 @@ typedef char * Binary;
|
||||
#define OBJ_SCHEMA_BITS 0x80
|
||||
#define OBJ_VARIABLE_BITS 0x100
|
||||
#define OBJ_WHERE_BITS 0x200
|
||||
#define OBJ_ALIAS_BITS 0x400
|
||||
#define OBJ_REPEAT_BITS 0x800
|
||||
#define OBJ_QUERY_BITS 0x1000
|
||||
|
||||
|
||||
#define OBJ_ANYTHING_BITS 0x0fffffff
|
||||
#define OBJ_UNFINDABLE_BITS 0x10000000 /**< should never be found */
|
||||
@@ -148,6 +153,7 @@ typedef char * Binary;
|
||||
|
||||
/* OBJ_UNUSED should die, but until it does, allow it to work */
|
||||
#define OBJ_UNUSED_BITS OBJ_UNFINDABLE_BITS
|
||||
#define OBJ_DOCROOT_BITS OBJ_UNFINDABLE_BITS
|
||||
|
||||
#endif /*EXPRESS_BASIC_H*/
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@
|
||||
#include "alg.h"
|
||||
#include "schema.h"
|
||||
#include "lexact.h"
|
||||
#include "dict.h"
|
||||
|
||||
/************/
|
||||
/* typedefs */
|
||||
@@ -102,7 +101,7 @@ extern char EXPRESSgetopt_options[]; /* initialized elsewhere */
|
||||
extern SC_EXPRESS_EXPORT int ( *EXPRESSgetopt )( int, char * );
|
||||
extern SC_EXPRESS_EXPORT bool EXPRESSignore_duplicate_schemas;
|
||||
|
||||
extern SC_EXPRESS_EXPORT Dictionary EXPRESSbuiltins; /* procedures/functions */
|
||||
extern SC_EXPRESS_EXPORT Hash_Table EXPRESSbuiltins; /* procedures/functions */
|
||||
|
||||
extern SC_EXPRESS_EXPORT struct Scope_ * FUNC_NVL;
|
||||
extern SC_EXPRESS_EXPORT struct Scope_ * FUNC_USEDIN;
|
||||
|
||||
+31
-92
@@ -80,28 +80,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "basic.h" /* get basic definitions */
|
||||
#include "sc_export.h"
|
||||
|
||||
/*************/
|
||||
/* constants */
|
||||
/*************/
|
||||
|
||||
#define HASH_NULL (Hash_Table)NULL
|
||||
|
||||
#define SEGMENT_SIZE 256
|
||||
#define SEGMENT_SIZE_SHIFT 8 /**< log2(SEGMENT_SIZE) */
|
||||
#define DIRECTORY_SIZE 256
|
||||
#define DIRECTORY_SIZE_SHIFT 8 /**< log2(DIRECTORY_SIZE) */
|
||||
#define PRIME1 37
|
||||
#define PRIME2 1048583
|
||||
#define MAX_LOAD_FACTOR 5
|
||||
|
||||
/*****************/
|
||||
/* packages used */
|
||||
/*****************/
|
||||
|
||||
#include <sc_export.h>
|
||||
#include "alloc.h"
|
||||
#include "expbasic.h"
|
||||
#include "symbol.h"
|
||||
|
||||
/************/
|
||||
/* typedefs */
|
||||
@@ -109,96 +91,53 @@
|
||||
|
||||
typedef enum { HASH_FIND, HASH_INSERT, HASH_DELETE } Action;
|
||||
|
||||
typedef unsigned long Address;
|
||||
|
||||
/****************/
|
||||
/* abstractions */
|
||||
/****************/
|
||||
|
||||
typedef struct Element_ {
|
||||
char * key;
|
||||
char * data;
|
||||
struct Element_ * next;
|
||||
Symbol * symbol; /**< for debugging hash conflicts */
|
||||
char type; /**< user-supplied type */
|
||||
} * Element;
|
||||
typedef Symbol **Segment;
|
||||
|
||||
typedef Element * Segment;
|
||||
|
||||
typedef struct Hash_Table_ {
|
||||
#if 0
|
||||
int in_use; /**< If someone is traversing the hash table */
|
||||
#endif
|
||||
unsigned int p; /**< Next bucket to be split */
|
||||
unsigned int maxp; /**< upper bound on p during expansion */
|
||||
struct Hash_Table_ {
|
||||
unsigned int p; /**< Next bucket to be split */
|
||||
unsigned int maxp; /**< upper bound on p during expansion */
|
||||
unsigned int KeyCount; /**< current # keys */
|
||||
unsigned int SegmentCount; /**< current # segments */
|
||||
unsigned int MinLoadFactor;
|
||||
unsigned int MaxLoadFactor;
|
||||
Segment Directory[DIRECTORY_SIZE];
|
||||
} * Hash_Table;
|
||||
Segment *Directory;
|
||||
unsigned int DirectorySize;
|
||||
unsigned int SegmentSize;
|
||||
#ifdef HASH_DEBUG
|
||||
unsigned int HashCollisions;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned int i; /**< segment index (i think) */
|
||||
unsigned int j; /**< key index in segment (ditto) */
|
||||
Element p; /**< usually the next element to be returned */
|
||||
typedef struct Hash_Table_ *Hash_Table;
|
||||
|
||||
struct Hash_Iterator_ {
|
||||
Hash_Table table;
|
||||
unsigned int hash;
|
||||
Symbol *p;
|
||||
char type;
|
||||
Element e; /**< originally thought of as a place for
|
||||
* the caller of HASHlist to temporarily stash the return value
|
||||
* to allow the caller (i.e., DICTdo) to be macroized, but now
|
||||
* conveniently used by HASHlist, which both stores the ultimate
|
||||
* value here as well as returns it via the return value of HASHlist
|
||||
*/
|
||||
} HashEntry;
|
||||
};
|
||||
|
||||
typedef struct Hash_Iterator_ Hash_Iterator;
|
||||
|
||||
/********************/
|
||||
/* global variables */
|
||||
/********************/
|
||||
|
||||
extern SC_EXPRESS_EXPORT struct freelist_head HASH_Table_fl;
|
||||
extern SC_EXPRESS_EXPORT struct freelist_head HASH_Element_fl;
|
||||
|
||||
/******************************/
|
||||
/* macro function definitions */
|
||||
/******************************/
|
||||
|
||||
/*
|
||||
** Fast arithmetic, relying on powers of 2
|
||||
*/
|
||||
|
||||
/**
|
||||
The centerline compiler was having problems with MUL and DIV. Where DIV
|
||||
was called like this DIV(NewAddress, SEGMENT_SIZE) it is now being called like
|
||||
DIV(NewAddress, SEGMENT_SIZE_SHIFT). The compiler was mentioning some kind of
|
||||
problem with ##. I wonder if maybe the precompiler was expanding SEGMENT_SIZE
|
||||
(which is also defined as a macro) before turning it into SEGMENT_SIZE_SHIFT.
|
||||
SEGMENT_SIZE and DIRECTORY_SIZE were used to call these macros. They are both
|
||||
defined to be 8 though so it seems these are always being used the same way.
|
||||
This change only seems to have affected hash.h and hash.c
|
||||
*/
|
||||
/* #define MUL(x,y) ((x) << (y##_SHIFT)) */
|
||||
#define MUL(x,y) ((x) << (y))
|
||||
/* #define DIV(x,y) ((x) >> (y##_SHIFT)) */
|
||||
#define DIV(x,y) ((x) >> (y))
|
||||
#define MOD(x,y) ((x) & ((y)-1))
|
||||
|
||||
#define HASH_Table_new() (struct Hash_Table_ *)ALLOC_new(&HASH_Table_fl)
|
||||
#define HASH_Table_destroy(x) ALLOC_destroy(&HASH_Table_fl,(Freelist *)x)
|
||||
#define HASH_Element_new() (struct Element_ *)ALLOC_new(&HASH_Element_fl)
|
||||
#define HASH_Element_destroy(x) ALLOC_destroy(&HASH_Element_fl,(Freelist *)(char *)x)
|
||||
|
||||
/***********************/
|
||||
/* function prototypes */
|
||||
/***********************/
|
||||
|
||||
extern SC_EXPRESS_EXPORT void HASHinitialize( void );
|
||||
extern SC_EXPRESS_EXPORT Hash_Table HASHcreate( unsigned );
|
||||
extern SC_EXPRESS_EXPORT Hash_Table HASHcopy( Hash_Table );
|
||||
extern SC_EXPRESS_EXPORT void HASHdestroy( Hash_Table );
|
||||
extern SC_EXPRESS_EXPORT Element HASHsearch( Hash_Table, Element, Action );
|
||||
extern SC_EXPRESS_EXPORT void HASHlistinit( Hash_Table, HashEntry * );
|
||||
extern SC_EXPRESS_EXPORT void HASHlistinit_by_type( Hash_Table, HashEntry *, char );
|
||||
extern SC_EXPRESS_EXPORT Element HASHlist( HashEntry * );
|
||||
extern SC_EXPRESS_EXPORT void HASHinitialize( void );
|
||||
extern SC_EXPRESS_EXPORT Hash_Table HASHcreate( void );
|
||||
extern SC_EXPRESS_EXPORT Hash_Table HASHcopy( Hash_Table );
|
||||
extern SC_EXPRESS_EXPORT void HASHdestroy( Hash_Table );
|
||||
extern SC_EXPRESS_EXPORT Symbol * HASHsearch( Hash_Table, Symbol, Action );
|
||||
extern SC_EXPRESS_EXPORT void HASHdelete( Hash_Table, Symbol * );
|
||||
extern SC_EXPRESS_EXPORT void HASHdo_init( Hash_Table, Hash_Iterator *, char );
|
||||
extern SC_EXPRESS_EXPORT Symbol * HASHdo( Hash_Iterator * );
|
||||
|
||||
#endif /*HASH_H*/
|
||||
#endif /* HASH_H */
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef __SC_FWD_H
|
||||
#define __SC_FWD_H
|
||||
|
||||
struct Symbol_;
|
||||
typedef struct Symbol_ Symbol;
|
||||
|
||||
|
||||
#endif /* __SC_FWD_H */
|
||||
@@ -61,8 +61,8 @@
|
||||
/****************/
|
||||
|
||||
#include "alg.h"
|
||||
#include "dict.h"
|
||||
#include "entity.h"
|
||||
#include "hash.h"
|
||||
#include "linklist.h"
|
||||
|
||||
/***************************/
|
||||
@@ -91,8 +91,8 @@ struct Schema_ {
|
||||
* dictionaries into which are entered renames for each specific
|
||||
* object specified in a rename clause (even if it uses the same
|
||||
* name */
|
||||
Dictionary refdict;
|
||||
Dictionary usedict;
|
||||
Hash_Table refdict;
|
||||
Hash_Table usedict;
|
||||
|
||||
Linked_List use_schemas; /**< lists of schemas that are fully use'd
|
||||
* entries can be 0 if schemas weren't found during RENAMEresolve */
|
||||
@@ -133,7 +133,7 @@ extern SC_EXPRESS_EXPORT int __SCOPE_search_id;
|
||||
/* function prototypes */
|
||||
/***********************/
|
||||
|
||||
extern SC_EXPRESS_EXPORT Variable VARfind( Scope, char *, int );
|
||||
extern SC_EXPRESS_EXPORT Symbol * VARfind( Scope, const char * );
|
||||
extern SC_EXPRESS_EXPORT Schema SCHEMAcreate( void );
|
||||
extern SC_EXPRESS_EXPORT void SCHEMAinitialize( void );
|
||||
extern SC_EXPRESS_EXPORT void SCHEMAadd_use( Schema, Symbol *, Symbol *, Symbol * );
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
/****************/
|
||||
|
||||
#include <sc_export.h>
|
||||
#include "hash.h"
|
||||
#include "type.h"
|
||||
#include "variable.h"
|
||||
#include "entity.h"
|
||||
@@ -62,7 +63,6 @@
|
||||
/*****************/
|
||||
|
||||
#include "expbasic.h" /* get basic definitions */
|
||||
#include "dict.h"
|
||||
#include "symbol.h"
|
||||
|
||||
/***************************/
|
||||
@@ -82,7 +82,7 @@ struct Scope_ {
|
||||
char type; /* see above */
|
||||
ClientData clientData; /**< user may use this for any purpose */
|
||||
int search_id; /**< key to avoid searching this scope twice */
|
||||
Dictionary symbol_table, enum_table;
|
||||
Hash_Table symbol_table, enum_table;
|
||||
struct Scope_ * superscope;
|
||||
union {
|
||||
struct Procedure_ * proc;
|
||||
@@ -115,16 +115,16 @@ struct Scope_ {
|
||||
#define SCOPEput_clientData(s,d) ((s)->clientData = (d))
|
||||
|
||||
|
||||
#define SCOPEdo_types(s,t,de) DICTdo_type_init(s->symbol_table,&de,OBJ_TYPE);{\
|
||||
#define SCOPEdo_types(s,t,de) DICTdo_init(s->symbol_table,&de,OBJ_TYPE);{\
|
||||
Type t; \
|
||||
while (0 != (t = (Type)DICTdo(&de))) {
|
||||
#define SCOPEdo_entities(s,t,de) DICTdo_type_init(s->symbol_table,&de,OBJ_ENTITY); { \
|
||||
#define SCOPEdo_entities(s,t,de) DICTdo_init(s->symbol_table,&de,OBJ_ENTITY); { \
|
||||
Entity t; \
|
||||
while (0 != (t = (Entity)DICTdo(&de))) {
|
||||
#define SCOPEdo_functions(s,t,de) DICTdo_type_init(s->symbol_table,&de,OBJ_FUNCTION); { \
|
||||
#define SCOPEdo_functions(s,t,de) DICTdo_init(s->symbol_table,&de,OBJ_FUNCTION); { \
|
||||
Entity t; \
|
||||
while (0 != (t = (Entity)DICTdo(&de))) {
|
||||
#define SCOPEdo_rules(s,t,de) DICTdo_type_init(s->symbol_table,&de,OBJ_RULE); { \
|
||||
#define SCOPEdo_rules(s,t,de) DICTdo_init(s->symbol_table,&de,OBJ_RULE); { \
|
||||
Entity t; \
|
||||
while (0 != (t = (Entity)DICTdo(&de))) {
|
||||
|
||||
@@ -138,12 +138,12 @@ extern SC_EXPRESS_EXPORT struct Symbol_ * SCOPE_get_symbol( void * );
|
||||
extern SC_EXPRESS_EXPORT void SCOPE_get_entities( Scope, Linked_List );
|
||||
extern SC_EXPRESS_EXPORT Linked_List SCOPEget_entities( Scope );
|
||||
extern SC_EXPRESS_EXPORT Linked_List SCOPEget_entities_superclass_order( Scope );
|
||||
extern SC_EXPRESS_EXPORT void * SCOPEfind( Scope, char *, int );
|
||||
extern SC_EXPRESS_EXPORT Symbol * SCOPEfind( Scope, const char *, int );
|
||||
extern SC_EXPRESS_EXPORT void SCOPE_get_functions( Scope, Linked_List );
|
||||
extern SC_EXPRESS_EXPORT Linked_List SCOPEget_functions( Scope );
|
||||
extern SC_EXPRESS_EXPORT void SCOPE_get_rules( Scope, Linked_List );
|
||||
extern SC_EXPRESS_EXPORT Linked_List SCOPEget_rules( Scope );
|
||||
|
||||
void * SCOPE_find( Scope, char *, int );
|
||||
Symbol * SCOPE_find( Scope, const char *, int );
|
||||
|
||||
#endif /* SCOPE_H */
|
||||
|
||||
+16
-15
@@ -43,27 +43,30 @@
|
||||
/* packages used */
|
||||
/*****************/
|
||||
|
||||
#include <sc_export.h>
|
||||
#include "sc_export.h"
|
||||
|
||||
#include "basic.h" /* get basic definitions */
|
||||
#include "alloc.h"
|
||||
|
||||
/************/
|
||||
/* typedefs */
|
||||
/************/
|
||||
|
||||
typedef struct Symbol_ Symbol;
|
||||
|
||||
/***************************/
|
||||
/* hidden type definitions */
|
||||
/* type definitions */
|
||||
/***************************/
|
||||
|
||||
struct Symbol_ {
|
||||
char * name;
|
||||
const char * filename;
|
||||
const char *name;
|
||||
void *data; /* the AST for this symbol */
|
||||
char type; /* the OBJ_ type, see expbasic.h */
|
||||
int ref_tok; /* the lexer ref_type for this symbol */
|
||||
|
||||
const char *filename;
|
||||
int line;
|
||||
char resolved;
|
||||
char resolved; /* if imported TYPE or ENTITY is unresolved */
|
||||
|
||||
struct Symbol_ *next; /* symbol table clashes */
|
||||
};
|
||||
|
||||
typedef struct Symbol_ Symbol;
|
||||
|
||||
/****************/
|
||||
/* modules used */
|
||||
/****************/
|
||||
@@ -78,9 +81,7 @@ extern SC_EXPRESS_EXPORT struct freelist_head SYMBOL_fl;
|
||||
/* macro function definitions */
|
||||
/******************************/
|
||||
|
||||
#define SYMBOL_new() (struct Symbol_ *)ALLOC_new(&SYMBOL_fl)
|
||||
#define SYMBOL_destroy(x) ALLOC_destroy(&SYMBOL_fl,(Freelist *)x)
|
||||
|
||||
/* TODO: gets called from e.g. type.c, should be set by parser */
|
||||
#define SYMBOLset(obj) obj->symbol.line = yylineno; \
|
||||
obj->symbol.filename = current_filename
|
||||
|
||||
@@ -89,6 +90,6 @@ extern SC_EXPRESS_EXPORT struct freelist_head SYMBOL_fl;
|
||||
/***********************/
|
||||
|
||||
extern SC_EXPRESS_EXPORT void SYMBOLinitialize( void );
|
||||
SC_EXPRESS_EXPORT Symbol * SYMBOLcreate( char * name, int line, const char * filename );
|
||||
SC_EXPRESS_EXPORT Symbol * SYMBOLcreate( char * name, int type, int ref_tok, int line, const char * filename );
|
||||
|
||||
#endif /* SYMBOL_H */
|
||||
|
||||
@@ -129,7 +129,6 @@ typedef enum type_enum Class;
|
||||
/* modules used */
|
||||
/****************/
|
||||
|
||||
#include "dict.h"
|
||||
#include "entity.h"
|
||||
#include "expr.h"
|
||||
#include "scope.h"
|
||||
|
||||
@@ -127,6 +127,6 @@ extern SC_EXPRESS_EXPORT struct freelist_head VAR_fl;
|
||||
|
||||
extern SC_EXPRESS_EXPORT Variable VARcreate( Expression, Type );
|
||||
extern SC_EXPRESS_EXPORT void VARinitialize( void );
|
||||
extern SC_EXPRESS_EXPORT char * VARget_simple_name( Variable );
|
||||
extern SC_EXPRESS_EXPORT const char * VARget_simple_name( Variable );
|
||||
|
||||
#endif /* VARIABLE_H */
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
if (${SC_MEMMGR_ENABLE_CHECKS})
|
||||
add_definitions(-DSC_MEMMGR_ENABLE_CHECKS)
|
||||
endif()
|
||||
|
||||
SC_ADDLIB(auxlib STATIC SOURCES bstrlib.c)
|
||||
|
||||
# Local Variables:
|
||||
# tab-width: 8
|
||||
# mode: cmake
|
||||
# indent-tabs-mode: t
|
||||
# End:
|
||||
# ex: shiftwidth=2 tabstop=8
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* This source file is part of the bstring string library. This code was
|
||||
* written by Paul Hsieh in 2002-2015, and is covered by the BSD open source
|
||||
* license and the GPL. Refer to the accompanying documentation for details
|
||||
* on usage and license.
|
||||
*/
|
||||
|
||||
/*
|
||||
* bstrlib.h
|
||||
*
|
||||
* This file is the interface for the core bstring functions.
|
||||
*/
|
||||
|
||||
#ifndef BSTRLIB_INCLUDE
|
||||
#define BSTRLIB_INCLUDE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP)
|
||||
# if defined (__TURBOC__) && !defined (__BORLANDC__)
|
||||
# define BSTRLIB_NOVSNP
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define BSTR_ERR (-1)
|
||||
#define BSTR_OK (0)
|
||||
#define BSTR_BS_BUFF_LENGTH_GET (0)
|
||||
|
||||
typedef struct tagbstring * bstring;
|
||||
typedef const struct tagbstring * const_bstring;
|
||||
|
||||
/* Version */
|
||||
#define BSTR_VER_MAJOR 1
|
||||
#define BSTR_VER_MINOR 0
|
||||
#define BSTR_VER_UPDATE 0
|
||||
|
||||
/* Copy functions */
|
||||
#define cstr2bstr bfromcstr
|
||||
extern bstring bfromcstr (const char * str);
|
||||
extern bstring bfromcstralloc (int mlen, const char * str);
|
||||
extern bstring bfromcstrrangealloc (int minl, int maxl, const char* str);
|
||||
extern bstring blk2bstr (const void * blk, int len);
|
||||
extern char * bstr2cstr (const_bstring s, char z);
|
||||
extern int bcstrfree (char * s);
|
||||
extern bstring bstrcpy (const_bstring b1);
|
||||
extern int bassign (bstring a, const_bstring b);
|
||||
extern int bassignmidstr (bstring a, const_bstring b, int left, int len);
|
||||
extern int bassigncstr (bstring a, const char * str);
|
||||
extern int bassignblk (bstring a, const void * s, int len);
|
||||
|
||||
/* Destroy function */
|
||||
extern int bdestroy (bstring b);
|
||||
|
||||
/* Space allocation hinting functions */
|
||||
extern int balloc (bstring s, int len);
|
||||
extern int ballocmin (bstring b, int len);
|
||||
|
||||
/* Substring extraction */
|
||||
extern bstring bmidstr (const_bstring b, int left, int len);
|
||||
|
||||
/* Various standard manipulations */
|
||||
extern int bconcat (bstring b0, const_bstring b1);
|
||||
extern int bconchar (bstring b0, char c);
|
||||
extern int bcatcstr (bstring b, const char * s);
|
||||
extern int bcatblk (bstring b, const void * s, int len);
|
||||
extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill);
|
||||
extern int binsertblk (bstring s1, int pos, const void * s2, int len, unsigned char fill);
|
||||
extern int binsertch (bstring s1, int pos, int len, unsigned char fill);
|
||||
extern int breplace (bstring b1, int pos, int len, const_bstring b2, unsigned char fill);
|
||||
extern int bdelete (bstring s1, int pos, int len);
|
||||
extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill);
|
||||
extern int btrunc (bstring b, int n);
|
||||
|
||||
/* Scan/search functions */
|
||||
extern int bstricmp (const_bstring b0, const_bstring b1);
|
||||
extern int bstrnicmp (const_bstring b0, const_bstring b1, int n);
|
||||
extern int biseqcaseless (const_bstring b0, const_bstring b1);
|
||||
extern int biseqcaselessblk (const_bstring b, const void * blk, int len);
|
||||
extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len);
|
||||
extern int biseq (const_bstring b0, const_bstring b1);
|
||||
extern int biseqblk (const_bstring b, const void * blk, int len);
|
||||
extern int bisstemeqblk (const_bstring b0, const void * blk, int len);
|
||||
extern int biseqcstr (const_bstring b, const char * s);
|
||||
extern int biseqcstrcaseless (const_bstring b, const char * s);
|
||||
extern int bstrcmp (const_bstring b0, const_bstring b1);
|
||||
extern int bstrncmp (const_bstring b0, const_bstring b1, int n);
|
||||
extern int binstr (const_bstring s1, int pos, const_bstring s2);
|
||||
extern int binstrr (const_bstring s1, int pos, const_bstring s2);
|
||||
extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2);
|
||||
extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2);
|
||||
extern int bstrchrp (const_bstring b, int c, int pos);
|
||||
extern int bstrrchrp (const_bstring b, int c, int pos);
|
||||
#define bstrchr(b,c) bstrchrp ((b), (c), 0)
|
||||
#define bstrrchr(b,c) bstrrchrp ((b), (c), blength(b)-1)
|
||||
extern int binchr (const_bstring b0, int pos, const_bstring b1);
|
||||
extern int binchrr (const_bstring b0, int pos, const_bstring b1);
|
||||
extern int bninchr (const_bstring b0, int pos, const_bstring b1);
|
||||
extern int bninchrr (const_bstring b0, int pos, const_bstring b1);
|
||||
extern int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos);
|
||||
extern int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos);
|
||||
|
||||
/* List of string container functions */
|
||||
struct bstrList {
|
||||
int qty, mlen;
|
||||
bstring * entry;
|
||||
};
|
||||
extern struct bstrList * bstrListCreate (void);
|
||||
extern int bstrListDestroy (struct bstrList * sl);
|
||||
extern int bstrListAlloc (struct bstrList * sl, int msz);
|
||||
extern int bstrListAllocMin (struct bstrList * sl, int msz);
|
||||
|
||||
/* String split and join functions */
|
||||
extern struct bstrList * bsplit (const_bstring str, unsigned char splitChar);
|
||||
extern struct bstrList * bsplits (const_bstring str, const_bstring splitStr);
|
||||
extern struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr);
|
||||
extern bstring bjoin (const struct bstrList * bl, const_bstring sep);
|
||||
extern bstring bjoinblk (const struct bstrList * bl, const void * s, int len);
|
||||
extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos,
|
||||
int (* cb) (void * parm, int ofs, int len), void * parm);
|
||||
extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos,
|
||||
int (* cb) (void * parm, int ofs, int len), void * parm);
|
||||
extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos,
|
||||
int (* cb) (void * parm, int ofs, int len), void * parm);
|
||||
|
||||
/* Miscellaneous functions */
|
||||
extern int bpattern (bstring b, int len);
|
||||
extern int btoupper (bstring b);
|
||||
extern int btolower (bstring b);
|
||||
extern int bltrimws (bstring b);
|
||||
extern int brtrimws (bstring b);
|
||||
extern int btrimws (bstring b);
|
||||
|
||||
#if !defined (BSTRLIB_NOVSNP)
|
||||
extern bstring bformat (const char * fmt, ...);
|
||||
extern int bformata (bstring b, const char * fmt, ...);
|
||||
extern int bassignformat (bstring b, const char * fmt, ...);
|
||||
extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist);
|
||||
|
||||
#define bvformata(ret, b, fmt, lastarg) { \
|
||||
bstring bstrtmp_b = (b); \
|
||||
const char * bstrtmp_fmt = (fmt); \
|
||||
int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \
|
||||
for (;;) { \
|
||||
va_list bstrtmp_arglist; \
|
||||
va_start (bstrtmp_arglist, lastarg); \
|
||||
bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \
|
||||
va_end (bstrtmp_arglist); \
|
||||
if (bstrtmp_r >= 0) { /* Everything went ok */ \
|
||||
bstrtmp_r = BSTR_OK; \
|
||||
break; \
|
||||
} else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \
|
||||
bstrtmp_r = BSTR_ERR; \
|
||||
break; \
|
||||
} \
|
||||
bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \
|
||||
} \
|
||||
ret = bstrtmp_r; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
typedef int (*bNgetc) (void *parm);
|
||||
typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, void *parm);
|
||||
|
||||
/* Input functions */
|
||||
extern bstring bgets (bNgetc getcPtr, void * parm, char terminator);
|
||||
extern bstring bread (bNread readPtr, void * parm);
|
||||
extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator);
|
||||
extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator);
|
||||
extern int breada (bstring b, bNread readPtr, void * parm);
|
||||
|
||||
/* Stream functions */
|
||||
extern struct bStream * bsopen (bNread readPtr, void * parm);
|
||||
extern void * bsclose (struct bStream * s);
|
||||
extern int bsbufflength (struct bStream * s, int sz);
|
||||
extern int bsreadln (bstring b, struct bStream * s, char terminator);
|
||||
extern int bsreadlns (bstring r, struct bStream * s, const_bstring term);
|
||||
extern int bsread (bstring b, struct bStream * s, int n);
|
||||
extern int bsreadlna (bstring b, struct bStream * s, char terminator);
|
||||
extern int bsreadlnsa (bstring r, struct bStream * s, const_bstring term);
|
||||
extern int bsreada (bstring b, struct bStream * s, int n);
|
||||
extern int bsunread (struct bStream * s, const_bstring b);
|
||||
extern int bspeek (bstring r, const struct bStream * s);
|
||||
extern int bssplitscb (struct bStream * s, const_bstring splitStr,
|
||||
int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
|
||||
extern int bssplitstrcb (struct bStream * s, const_bstring splitStr,
|
||||
int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
|
||||
extern int bseof (const struct bStream * s);
|
||||
|
||||
struct tagbstring {
|
||||
int mlen;
|
||||
int slen;
|
||||
unsigned char * data;
|
||||
};
|
||||
|
||||
/* Accessor macros */
|
||||
#define blengthe(b, e) (((b) == (void *)0 || (b)->slen < 0) ? (int)(e) : ((b)->slen))
|
||||
#define blength(b) (blengthe ((b), 0))
|
||||
#define bdataofse(b, o, e) (((b) == (void *)0 || (b)->data == (void*)0) ? (char *)(e) : ((char *)(b)->data) + (o))
|
||||
#define bdataofs(b, o) (bdataofse ((b), (o), (void *)0))
|
||||
#define bdatae(b, e) (bdataofse (b, 0, e))
|
||||
#define bdata(b) (bdataofs (b, 0))
|
||||
#define bchare(b, p, e) ((((unsigned)(p)) < (unsigned)blength(b)) ? ((b)->data[(p)]) : (e))
|
||||
#define bchar(b, p) bchare ((b), (p), '\0')
|
||||
|
||||
/* Static constant string initialization macro */
|
||||
#define bsStaticMlen(q,m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")}
|
||||
#if defined(_MSC_VER)
|
||||
# define bsStatic(q) bsStaticMlen(q,-32)
|
||||
#endif
|
||||
#ifndef bsStatic
|
||||
# define bsStatic(q) bsStaticMlen(q,-__LINE__)
|
||||
#endif
|
||||
|
||||
/* Static constant block parameter pair */
|
||||
#define bsStaticBlkParms(q) ((void *)("" q "")), ((int) sizeof(q)-1)
|
||||
|
||||
#define bcatStatic(b,s) ((bcatblk)((b), bsStaticBlkParms(s)))
|
||||
#define bfromStatic(s) ((blk2bstr)(bsStaticBlkParms(s)))
|
||||
#define bassignStatic(b,s) ((bassignblk)((b), bsStaticBlkParms(s)))
|
||||
#define binsertStatic(b,p,s,f) ((binsertblk)((b), (p), bsStaticBlkParms(s), (f)))
|
||||
#define bjoinStatic(b,s) ((bjoinblk)((b), bsStaticBlkParms(s)))
|
||||
#define biseqStatic(b,s) ((biseqblk)((b), bsStaticBlkParms(s)))
|
||||
#define bisstemeqStatic(b,s) ((bisstemeqblk)((b), bsStaticBlkParms(s)))
|
||||
#define biseqcaselessStatic(b,s) ((biseqcaselessblk)((b), bsStaticBlkParms(s)))
|
||||
#define bisstemeqcaselessStatic(b,s) ((bisstemeqcaselessblk)((b), bsStaticBlkParms(s)))
|
||||
|
||||
/* Reference building macros */
|
||||
#define cstr2tbstr btfromcstr
|
||||
#define btfromcstr(t,s) { \
|
||||
(t).data = (unsigned char *) (s); \
|
||||
(t).slen = ((t).data) ? ((int) (strlen) ((char *)(t).data)) : 0; \
|
||||
(t).mlen = -1; \
|
||||
}
|
||||
#define blk2tbstr(t,s,l) { \
|
||||
(t).data = (unsigned char *) (s); \
|
||||
(t).slen = l; \
|
||||
(t).mlen = -1; \
|
||||
}
|
||||
#define btfromblk(t,s,l) blk2tbstr(t,s,l)
|
||||
#define bmid2tbstr(t,b,p,l) { \
|
||||
const_bstring bstrtmp_s = (b); \
|
||||
if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \
|
||||
int bstrtmp_left = (p); \
|
||||
int bstrtmp_len = (l); \
|
||||
if (bstrtmp_left < 0) { \
|
||||
bstrtmp_len += bstrtmp_left; \
|
||||
bstrtmp_left = 0; \
|
||||
} \
|
||||
if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) \
|
||||
bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \
|
||||
if (bstrtmp_len <= 0) { \
|
||||
(t).data = (unsigned char *)""; \
|
||||
(t).slen = 0; \
|
||||
} else { \
|
||||
(t).data = bstrtmp_s->data + bstrtmp_left; \
|
||||
(t).slen = bstrtmp_len; \
|
||||
} \
|
||||
} else { \
|
||||
(t).data = (unsigned char *)""; \
|
||||
(t).slen = 0; \
|
||||
} \
|
||||
(t).mlen = -__LINE__; \
|
||||
}
|
||||
#define btfromblkltrimws(t,s,l) { \
|
||||
int bstrtmp_idx = 0, bstrtmp_len = (l); \
|
||||
unsigned char * bstrtmp_s = (s); \
|
||||
if (bstrtmp_s && bstrtmp_len >= 0) { \
|
||||
for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \
|
||||
if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \
|
||||
} \
|
||||
} \
|
||||
(t).data = bstrtmp_s + bstrtmp_idx; \
|
||||
(t).slen = bstrtmp_len - bstrtmp_idx; \
|
||||
(t).mlen = -__LINE__; \
|
||||
}
|
||||
#define btfromblkrtrimws(t,s,l) { \
|
||||
int bstrtmp_len = (l) - 1; \
|
||||
unsigned char * bstrtmp_s = (s); \
|
||||
if (bstrtmp_s && bstrtmp_len >= 0) { \
|
||||
for (; bstrtmp_len >= 0; bstrtmp_len--) { \
|
||||
if (!isspace (bstrtmp_s[bstrtmp_len])) break; \
|
||||
} \
|
||||
} \
|
||||
(t).data = bstrtmp_s; \
|
||||
(t).slen = bstrtmp_len + 1; \
|
||||
(t).mlen = -__LINE__; \
|
||||
}
|
||||
#define btfromblktrimws(t,s,l) { \
|
||||
int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \
|
||||
unsigned char * bstrtmp_s = (s); \
|
||||
if (bstrtmp_s && bstrtmp_len >= 0) { \
|
||||
for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \
|
||||
if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \
|
||||
} \
|
||||
for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \
|
||||
if (!isspace (bstrtmp_s[bstrtmp_len])) break; \
|
||||
} \
|
||||
} \
|
||||
(t).data = bstrtmp_s + bstrtmp_idx; \
|
||||
(t).slen = bstrtmp_len + 1 - bstrtmp_idx; \
|
||||
(t).mlen = -__LINE__; \
|
||||
}
|
||||
|
||||
/* Write protection macros */
|
||||
#define bwriteprotect(t) { if ((t).mlen >= 0) (t).mlen = -1; }
|
||||
#define bwriteallow(t) { if ((t).mlen == -1) (t).mlen = (t).slen + ((t).slen == 0); }
|
||||
#define biswriteprotected(t) ((t).mlen <= 0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -70,10 +70,10 @@ inline void operator delete[]( void * addr ) throw () {
|
||||
#endif /* SC_MEMMGR_CC */
|
||||
|
||||
#else
|
||||
#define sc_malloc(size) malloc(size)
|
||||
#define sc_calloc(count, size) calloc(count, size)
|
||||
#define sc_realloc(addr, size) realloc(addr, size)
|
||||
#define sc_free(addr) free(addr)
|
||||
#define sc_malloc malloc
|
||||
#define sc_calloc calloc
|
||||
#define sc_realloc realloc
|
||||
#define sc_free free
|
||||
#endif /* SC_MEMMGR_ENABLE_CHECKS */
|
||||
|
||||
#endif /* SC_MEMMGR_H */
|
||||
|
||||
@@ -128,7 +128,7 @@ void USEREFout( Schema schema, Dictionary refdict, Linked_List reflist, char * t
|
||||
/* sort each list by schema */
|
||||
|
||||
/* step 1: for each entry, store it in a schema-specific list */
|
||||
DICTdo_init( refdict, &de );
|
||||
DICTdo_init( refdict, &de, '*' );
|
||||
while( 0 != ( r = ( struct Rename * )DICTdo( &de ) ) ) {
|
||||
Linked_List wlist;
|
||||
|
||||
@@ -141,7 +141,7 @@ void USEREFout( Schema schema, Dictionary refdict, Linked_List reflist, char * t
|
||||
}
|
||||
|
||||
/* step 2: for each list, print out the renames */
|
||||
DICTdo_init( dict, &de );
|
||||
DICTdo_init( dict, &de, '*' );
|
||||
while( 0 != ( list = ( Linked_List )DICTdo( &de ) ) ) {
|
||||
bool first_time = true;
|
||||
LISTdo( list, re, struct Rename * ) {
|
||||
|
||||
@@ -1049,7 +1049,7 @@ void ENTITYlib_print( Entity entity, Linked_List neededAttr, FILE * file, Schema
|
||||
*/
|
||||
void ENTITYPrint( Entity entity, FILES * files, Schema schema, bool externMap ) {
|
||||
FILE * hdr, * impl;
|
||||
char * n = ENTITYget_name( entity );
|
||||
const char * n = ENTITYget_name( entity );
|
||||
Linked_List remaining = LISTcreate();
|
||||
filenames_t names = getEntityFilenames( entity );
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@ void TYPEenum_lib_print( const Type type, FILE * f ) {
|
||||
|
||||
fprintf( f, "const char *\n%s::element_at (int n) const {\n", n );
|
||||
fprintf( f, " switch (n) {\n" );
|
||||
DICTdo_type_init( ENUM_TYPEget_items( type ), &de, OBJ_ENUM );
|
||||
DICTdo_init( ENUM_TYPEget_items( type ), &de, OBJ_ENUM );
|
||||
while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
|
||||
strncpy( c_enum_ele, EnumCElementName( type, expr ), BUFSIZ );
|
||||
c_enum_ele[BUFSIZ-1] = '\0';
|
||||
@@ -279,7 +279,7 @@ void TYPEenum_lib_print( const Type type, FILE * f ) {
|
||||
fprintf( f, "\n%s::operator %s () const {\n", n,
|
||||
EnumName( TYPEget_name( type ) ) );
|
||||
fprintf( f, " switch (v) {\n" );
|
||||
DICTdo_type_init( ENUM_TYPEget_items( type ), &de, OBJ_ENUM );
|
||||
DICTdo_init( ENUM_TYPEget_items( type ), &de, OBJ_ENUM );
|
||||
while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
|
||||
strncpy( c_enum_ele, EnumCElementName( type, expr ), BUFSIZ );
|
||||
fprintf( f, " case %s : ", c_enum_ele );
|
||||
@@ -1203,7 +1203,8 @@ char * TYPEget_express_type( const Type t ) {
|
||||
Class_Of_Type class;
|
||||
Type bt;
|
||||
char retval [BUFSIZ];
|
||||
char * n, * permval, * aggr_type;
|
||||
const char *n;
|
||||
char *permval, *aggr_type;
|
||||
|
||||
|
||||
/* 1. "DEFINED" types */
|
||||
|
||||
@@ -203,7 +203,7 @@ void SCOPEPrint( Scope scope, FILES * files, Schema schema, ComplexCollect * col
|
||||
/* The following was `SCOPEdo_types( scope, t, de ) ... SCOPEod;`
|
||||
* Modified Jan 2012 by MAP - moving enums to own dictionary */
|
||||
if( scope->enum_table ) {
|
||||
HASHlistinit_by_type( scope->enum_table, &de, OBJ_TYPE );
|
||||
HASHlistinit( scope->enum_table, &de, OBJ_TYPE );
|
||||
Type t;
|
||||
while( 0 != ( t = ( Type ) DICTdo( &de ) ) ) {
|
||||
// First check for one exception: Say enumeration type B is defined
|
||||
@@ -239,7 +239,7 @@ void SCOPEPrint( Scope scope, FILES * files, Schema schema, ComplexCollect * col
|
||||
fprintf( files->inc, "// ***** Redefined Enumerations:\n" );
|
||||
/* The following was `SCOPEdo_types( scope, t, de ) ... SCOPEod;`
|
||||
* Modified Jan 2012 by MAP - moving enums to own dictionary */
|
||||
HASHlistinit_by_type( scope->enum_table, &de, OBJ_TYPE );
|
||||
HASHlistinit( scope->enum_table, &de, OBJ_TYPE );
|
||||
Type t;
|
||||
while( 0 != ( t = ( Type ) DICTdo( &de ) ) ) {
|
||||
if( t->search_id == CANPROCESS && TYPEis_enumeration( t ) ) {
|
||||
@@ -497,7 +497,7 @@ void SCHEMAprint( Schema schema, FILES * files, void * complexCol, int suffix )
|
||||
fprintf( createall, " reg.AddSchema (*%s::schema);\n", SCHEMAget_name( schema ) );
|
||||
/**************/
|
||||
/* add global RULEs to Schema dictionary entry */
|
||||
DICTdo_type_init( schema->symbol_table, &de, OBJ_RULE );
|
||||
DICTdo_init( schema->symbol_table, &de, OBJ_RULE );
|
||||
while( 0 != ( r = ( Rule )DICTdo( &de ) ) ) {
|
||||
fprintf( createall, " str.clear();\n" );
|
||||
format_for_std_stringout( createall, RULEto_string( r ) );
|
||||
@@ -506,7 +506,7 @@ void SCHEMAprint( Schema schema, FILES * files, void * complexCol, int suffix )
|
||||
}
|
||||
/**************/
|
||||
/* add FUNCTIONs to Schema dictionary entry */
|
||||
DICTdo_type_init( schema->symbol_table, &de, OBJ_FUNCTION );
|
||||
DICTdo_init( schema->symbol_table, &de, OBJ_FUNCTION );
|
||||
while( 0 != ( f = ( Function )DICTdo( &de ) ) ) {
|
||||
fprintf( createall, " str.clear();\n" );
|
||||
format_for_std_stringout( createall, FUNCto_string( f ) );
|
||||
@@ -514,7 +514,7 @@ void SCHEMAprint( Schema schema, FILES * files, void * complexCol, int suffix )
|
||||
}
|
||||
|
||||
/* add PROCEDUREs to Schema dictionary entry */
|
||||
DICTdo_type_init( schema->symbol_table, &de, OBJ_PROCEDURE );
|
||||
DICTdo_init( schema->symbol_table, &de, OBJ_PROCEDURE );
|
||||
while( 0 != ( p = ( Procedure )DICTdo( &de ) ) ) {
|
||||
fprintf( createall, " str.clear();\n" );
|
||||
format_for_std_stringout( createall, PROCto_string( p ) );
|
||||
@@ -582,7 +582,7 @@ void getMCPrint( Express express, FILE * schema_h, FILE * schema_cc ) {
|
||||
"// dictionary (Registry) handle since it doesn't have a\n",
|
||||
"// predetermined way to access to the handle.\n" );
|
||||
fprintf( schema_cc, "\nSDAI_Model_contents_ptr GetModelContents(char *schemaName) {\n" );
|
||||
DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
schema = ( Scope )DICTdo( &de );
|
||||
fprintf( schema_cc, " if(!strcmp(schemaName, \"%s\"))\n", SCHEMAget_name( schema ) );
|
||||
fprintf( schema_cc, " return (SDAI_Model_contents_ptr) new SdaiModel_contents_%s; \n", SCHEMAget_name( schema ) );
|
||||
@@ -673,12 +673,12 @@ void EXPRESSPrint( Express express, ComplexCollect & col, FILES * files ) {
|
||||
fprintf( schemainit, " %sInit (reg);\n", schnm );
|
||||
|
||||
/********** do all schemas ***********/
|
||||
DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) {
|
||||
numberAttributes( schema );
|
||||
}
|
||||
|
||||
DICTdo_init( express->symbol_table, &de );
|
||||
DICTdo_init( express->symbol_table, &de, '*' );
|
||||
bool first = true;
|
||||
while( 0 != ( schema = ( Scope )DICTdo( &de ) ) ) {
|
||||
if( !first ) {
|
||||
|
||||
@@ -70,7 +70,7 @@ void ComplexCollect::remove( ComplexList * c )
|
||||
count--;
|
||||
}
|
||||
|
||||
ComplexList * ComplexCollect::find( char * name )
|
||||
ComplexList * ComplexCollect::find( const char * name )
|
||||
/*
|
||||
* Searches for and returns the ComplexList whose supertype name = name.
|
||||
*/
|
||||
|
||||
@@ -355,10 +355,10 @@ class ComplexList {
|
||||
int operator< ( ComplexList & c ) {
|
||||
return ( strcmp( supertype(), c.supertype() ) < 0 );
|
||||
}
|
||||
int operator< ( char * name ) {
|
||||
int operator< ( const char * name ) {
|
||||
return ( strcmp( supertype(), name ) < 0 );
|
||||
}
|
||||
int operator== ( char * name ) {
|
||||
int operator== ( const char * name ) {
|
||||
return ( strcmp( supertype(), name ) == 0 );
|
||||
}
|
||||
const char * supertype() {
|
||||
@@ -410,7 +410,7 @@ class ComplexCollect {
|
||||
void remove( ComplexList * );
|
||||
// Remove this list but don't delete its hierarchy structure, because
|
||||
// it's used elsewhere.
|
||||
ComplexList * find( char * );
|
||||
ComplexList * find( const char * );
|
||||
int supports( EntNode * );
|
||||
bool externMapping( const char * ent ) {
|
||||
return ( clists ? clists->isDependent( ent ) : 0 );
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
// Local function prototypes:
|
||||
static void initEnts( Express );
|
||||
static Entity findEnt( Entity, char * );
|
||||
static Entity findEnt( Entity, const char * );
|
||||
|
||||
ComplexCollect::ComplexCollect( Express express )
|
||||
/*
|
||||
@@ -38,7 +38,7 @@ ComplexCollect::ComplexCollect( Express express )
|
||||
initEnts( express );
|
||||
|
||||
// Next loop through all the entities, building ComplexLists:
|
||||
DICTdo_type_init( express->symbol_table, &de_sch, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de_sch, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de_sch ) ) != 0 ) {
|
||||
SCOPEdo_entities( schema, ent, de_ent )
|
||||
if( ent->search_id == TRUE ) {
|
||||
@@ -96,7 +96,7 @@ static void initEnts( Express express )
|
||||
DictionaryEntry de_sch, de_ent;
|
||||
Schema schema;
|
||||
|
||||
DICTdo_type_init( express->symbol_table, &de_sch, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de_sch, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de_sch ) ) != 0 ) {
|
||||
SCOPEdo_entities( schema, ent, de_ent )
|
||||
ent->search_id = FALSE;
|
||||
@@ -235,7 +235,7 @@ void MultList::processSubExp( Expression exp, Entity super,
|
||||
}
|
||||
}
|
||||
|
||||
static Entity findEnt( Entity ent0, char * name )
|
||||
static Entity findEnt( Entity ent0, const char * name )
|
||||
/*
|
||||
* Returns an entity named name. The desired entity is likely to be in the
|
||||
* same schema as ent0. findEnt first searches the schema which contains
|
||||
@@ -256,7 +256,7 @@ static Entity findEnt( Entity ent0, char * name )
|
||||
// If we still haven't found it, look through all the entities in the
|
||||
// express file:
|
||||
express = schema->superscope;
|
||||
DICTdo_type_init( express->symbol_table, &de_sch, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de_sch, OBJ_SCHEMA );
|
||||
while( ( sch = ( Scope )DICTdo( &de_sch ) ) != 0 ) {
|
||||
if( sch == schema ) {
|
||||
// Don't redo the schema which contains ent0 - we did it already.
|
||||
|
||||
+11
-10
@@ -75,13 +75,13 @@ void print_schemas_separate( Express express, void * complexCol, FILES * files )
|
||||
/* TODO only print gr, wr, str as needed, from SCHEMAprint in classes_wrapper.cc? */
|
||||
fprintf( files->create, " Global_rule_ptr gr;\n Where_rule_ptr wr;\n std::string str; //for large strings such as functions or global rules\n" );
|
||||
|
||||
DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) {
|
||||
numberAttributes( schema );
|
||||
}
|
||||
while( !complete ) {
|
||||
complete = true;
|
||||
DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) {
|
||||
if( schema->search_id == UNPROCESSED ) {
|
||||
/* i.e., if the schema has more ents/types to process in it */
|
||||
@@ -126,7 +126,7 @@ void print_schemas_separate( Express express, void * complexCol, FILES * files )
|
||||
/*******************
|
||||
*******************/
|
||||
|
||||
DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) {
|
||||
fprintf( files->create,
|
||||
"//////////////// USE statements\n" );
|
||||
@@ -141,7 +141,7 @@ void print_schemas_separate( Express express, void * complexCol, FILES * files )
|
||||
/* Before closing, we have three more situations to deal with (i.e., three
|
||||
// types of declarations etc. which could only be printed at the end).
|
||||
// Each is explained in the header section of its respective function. */
|
||||
DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) {
|
||||
/* (These two tasks are totally unrelated but are done in the same loop
|
||||
// for efficiency.) */
|
||||
@@ -150,7 +150,7 @@ void print_schemas_separate( Express express, void * complexCol, FILES * files )
|
||||
}
|
||||
/* Third situation: (Must be dealt with after first, see header comments
|
||||
// of addAggrTypedefs.) */
|
||||
DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) {
|
||||
addAggrTypedefs( schema, files->classes );
|
||||
}
|
||||
@@ -186,7 +186,7 @@ static void initializeMarks( Express express )
|
||||
DictionaryEntry de_sch, de_ent, de_type;
|
||||
Schema schema;
|
||||
|
||||
DICTdo_type_init( express->symbol_table, &de_sch, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de_sch, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de_sch ) ) != 0 ) {
|
||||
schema->search_id = UNPROCESSED;
|
||||
schema->clientData = ( int * )sc_malloc( sizeof( int ) );
|
||||
@@ -204,7 +204,7 @@ static void cleanupMarks( Express express ) {
|
||||
DictionaryEntry de_sch;
|
||||
Schema schema;
|
||||
|
||||
DICTdo_type_init( express->symbol_table, &de_sch, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de_sch, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de_sch ) ) != 0 ) {
|
||||
if( schema->clientData ) {
|
||||
sc_free( schema->clientData );
|
||||
@@ -691,11 +691,12 @@ static void addUseRefNames( Schema schema, FILE * create ) {
|
||||
Dictionary useRefDict;
|
||||
DictionaryEntry de;
|
||||
Rename * rnm;
|
||||
char * oldnm, schNm[BUFSIZ];
|
||||
const char *oldnm;
|
||||
char schNm[BUFSIZ];
|
||||
static bool firsttime = true;
|
||||
|
||||
if( ( useRefDict = schema->u.schema->usedict ) != NULL ) {
|
||||
DICTdo_init( useRefDict, &de );
|
||||
DICTdo_init( useRefDict, &de, '*' );
|
||||
while( ( rnm = ( Rename * )DICTdo( &de ) ) != 0 ) {
|
||||
oldnm = ( ( Scope )rnm->object )->symbol.name;
|
||||
if( ( strcmp( oldnm, rnm->nnew->name ) ) ) {
|
||||
@@ -724,7 +725,7 @@ static void addUseRefNames( Schema schema, FILE * create ) {
|
||||
}
|
||||
}
|
||||
if( ( useRefDict = schema->u.schema->refdict ) != NULL ) {
|
||||
DICTdo_init( useRefDict, &de );
|
||||
DICTdo_init( useRefDict, &de, '*' );
|
||||
while( ( rnm = ( Rename * )DICTdo( &de ) ) != 0 ) {
|
||||
oldnm = ( ( Scope )rnm->object )->symbol.name;
|
||||
if( ( strcmp( oldnm, rnm->nnew->name ) ) ) {
|
||||
|
||||
@@ -1093,7 +1093,7 @@ LOOPpyout( struct Loop_ *loop, int level, FILE * file ) {
|
||||
DictionaryEntry de;
|
||||
|
||||
/* TODO: if incr != 0 && ((incr > 0 && start < stop) || (incr < 0 && start > stop)): */
|
||||
DICTdo_init( loop->scope->symbol_table, &de );
|
||||
DICTdo_init( loop->scope->symbol_table, &de, '*' );
|
||||
v = ( Variable )DICTdo( &de );
|
||||
fprintf( file, "for %s in range(", v->name->symbol.name );
|
||||
EXPRESSION_out( loop->scope->u.incr->init, 0 , file );
|
||||
@@ -1729,7 +1729,7 @@ TYPEenum_lib_print( const Type type, FILE * f ) {
|
||||
}
|
||||
|
||||
/* set up the dictionary info */
|
||||
DICTdo_type_init( ENUM_TYPEget_items( type ), &de, OBJ_ENUM );
|
||||
DICTdo_init( ENUM_TYPEget_items( type ), &de, OBJ_ENUM );
|
||||
while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
|
||||
if( is_python_keyword( EXPget_name( expr ) ) ) {
|
||||
fprintf( f, "%s_ ", EXPget_name( expr ) );
|
||||
|
||||
@@ -232,7 +232,7 @@ getMCPrint( Express express, FILE * schema_h, FILE * schema_cc ) {
|
||||
"// predetermined way to access to the handle.\n" );
|
||||
fprintf( schema_cc,
|
||||
"\nSCLP23(Model_contents_ptr) GetModelContents(char *schemaName)\n{\n" );
|
||||
DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
schema = ( Scope )DICTdo( &de );
|
||||
fprintf( schema_cc,
|
||||
" if(!strcmp(schemaName, \"%s\"))\n",
|
||||
@@ -285,7 +285,7 @@ EXPRESSPrint( Express express, FILES * files ) {
|
||||
}
|
||||
|
||||
/********** do all schemas ***********/
|
||||
DICTdo_init( express->symbol_table, &de );
|
||||
DICTdo_init( express->symbol_table, &de, '*' );
|
||||
while( 0 != ( schema = ( Scope )DICTdo( &de ) ) ) {
|
||||
SCOPEPrint( schema, files, schema );
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ void print_schemas_separate( Express express, FILES * files )
|
||||
/* fprintf( files->create, " Interface_spec_ptr is;\n Used_item_ptr ui;\n Referenced_item_ptr ri;\n Uniqueness_rule_ptr ur;\n Where_rule_ptr wr;\n Global_rule_ptr gr;\n" ); */
|
||||
while( !complete ) {
|
||||
complete = TRUE;
|
||||
DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) {
|
||||
if( schema->search_id == UNPROCESSED ) {
|
||||
/* i.e., if the schema has more ents/types to process in it */
|
||||
@@ -117,7 +117,7 @@ void print_schemas_separate( Express express, FILES * files )
|
||||
}
|
||||
|
||||
/*
|
||||
DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) {
|
||||
//fprintf( files->create,
|
||||
// "\t//////////////// USE statements\n" );
|
||||
@@ -131,7 +131,7 @@ void print_schemas_separate( Express express, FILES * files )
|
||||
/* Before closing, we have three more situations to deal with (i.e., three
|
||||
// types of declarations etc. which could only be printed at the end).
|
||||
// Each is explained in the header section of its respective function. */
|
||||
DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) {
|
||||
/* (These two tasks are totally unrelated but are done in the same loop
|
||||
// for efficiency.) */
|
||||
@@ -139,7 +139,7 @@ void print_schemas_separate( Express express, FILES * files )
|
||||
}
|
||||
/* Third situation: (Must be dealt with after first, see header comments
|
||||
// of addAggrTypedefs.) */
|
||||
DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) {
|
||||
/* addAggrTypedefs( schema, files->classes ); */
|
||||
addAggrTypedefs( schema );
|
||||
@@ -172,7 +172,7 @@ static void initializeMarks( Express express ) {
|
||||
DictionaryEntry de_sch, de_ent, de_type;
|
||||
Schema schema;
|
||||
|
||||
DICTdo_type_init( express->symbol_table, &de_sch, OBJ_SCHEMA );
|
||||
DICTdo_init( express->symbol_table, &de_sch, OBJ_SCHEMA );
|
||||
while( ( schema = ( Scope )DICTdo( &de_sch ) ) != 0 ) {
|
||||
schema->search_id = UNPROCESSED;
|
||||
schema->clientData = ( int * )malloc( sizeof( int ) );
|
||||
@@ -627,7 +627,7 @@ static void addUseRefNames( Schema schema, FILE * create )
|
||||
static int firsttime = TRUE;
|
||||
|
||||
if( ( useRefDict = schema->u.schema->usedict ) != NULL ) {
|
||||
DICTdo_init( useRefDict, &de );
|
||||
DICTdo_init( useRefDict, &de, '*' );
|
||||
while( ( rnm = ( Rename * )DICTdo( &de ) ) != 0 ) {
|
||||
oldnm = ( ( Scope )rnm->object )->symbol.name;
|
||||
if( ( strcmp( oldnm, rnm->nnew->name ) ) ) {
|
||||
@@ -657,7 +657,7 @@ static void addUseRefNames( Schema schema, FILE * create )
|
||||
}
|
||||
}
|
||||
if( ( useRefDict = schema->u.schema->refdict ) != NULL ) {
|
||||
DICTdo_init( useRefDict, &de );
|
||||
DICTdo_init( useRefDict, &de, '*' );
|
||||
while( ( rnm = ( Rename * )DICTdo( &de ) ) != 0 ) {
|
||||
oldnm = ( ( Scope )rnm->object )->symbol.name;
|
||||
if( ( strcmp( oldnm, rnm->nnew->name ) ) ) {
|
||||
|
||||
@@ -15,7 +15,7 @@ void EXPRESSout( Express e ) {
|
||||
|
||||
exppp_init();
|
||||
|
||||
DICTdo_init( e->symbol_table, &de );
|
||||
DICTdo_init( e->symbol_table, &de, '*' );
|
||||
while( 0 != ( s = ( Schema )DICTdo( &de ) ) ) {
|
||||
( void ) SCHEMAout( s );
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ void LOOPout( struct Loop_ *loop, int level ) {
|
||||
if( loop->scope ) {
|
||||
DictionaryEntry de;
|
||||
|
||||
DICTdo_init( loop->scope->symbol_table, &de );
|
||||
DICTdo_init( loop->scope->symbol_table, &de, '*' );
|
||||
v = ( Variable )DICTdo( &de );
|
||||
wrap( " %s := ", v->name->symbol.name );
|
||||
EXPR_out( loop->scope->u.incr->init, 0 );
|
||||
|
||||
@@ -26,7 +26,7 @@ void REFout( Dictionary refdict, Linked_List reflist, char * type, int level ) {
|
||||
/* sort each list by schema */
|
||||
|
||||
/* step 1: for each entry, store it in a schema-specific list */
|
||||
DICTdo_init( refdict, &de );
|
||||
DICTdo_init( refdict, &de, '*' );
|
||||
while( 0 != ( ren = ( struct Rename * )DICTdo( &de ) ) ) {
|
||||
Linked_List nameList;
|
||||
|
||||
@@ -41,7 +41,7 @@ void REFout( Dictionary refdict, Linked_List reflist, char * type, int level ) {
|
||||
/* step 2: for each list, print out the renames */
|
||||
level = 6; /* no special reason, feels good */
|
||||
indent2 = level + exppp_continuation_indent;
|
||||
DICTdo_init( dict, &de );
|
||||
DICTdo_init( dict, &de, '*' );
|
||||
while( 0 != ( list = ( Linked_List )DICTdo( &de ) ) ) {
|
||||
bool first_time = true;
|
||||
LISTdo( list, r, struct Rename * ) {
|
||||
|
||||
+15
-15
@@ -47,14 +47,14 @@ void SCOPErules_out( Scope s, int level ) {
|
||||
DictionaryEntry de;
|
||||
|
||||
if( exppp_alphabetize == false ) {
|
||||
DICTdo_type_init( s->symbol_table, &de, OBJ_RULE );
|
||||
DICTdo_init( s->symbol_table, &de, OBJ_RULE );
|
||||
while( 0 != ( r = ( Rule )DICTdo( &de ) ) ) {
|
||||
RULE_out( r, level );
|
||||
}
|
||||
} else {
|
||||
Linked_List alpha = LISTcreate();
|
||||
|
||||
DICTdo_type_init( s->symbol_table, &de, OBJ_RULE );
|
||||
DICTdo_init( s->symbol_table, &de, OBJ_RULE );
|
||||
while( 0 != ( r = ( Rule )DICTdo( &de ) ) ) {
|
||||
SCOPEadd_inorder( alpha, r );
|
||||
}
|
||||
@@ -74,14 +74,14 @@ void SCOPEfuncs_out( Scope s, int level ) {
|
||||
DictionaryEntry de;
|
||||
|
||||
if( exppp_alphabetize == false ) {
|
||||
DICTdo_type_init( s->symbol_table, &de, OBJ_FUNCTION );
|
||||
DICTdo_init( s->symbol_table, &de, OBJ_FUNCTION );
|
||||
while( 0 != ( f = ( Function )DICTdo( &de ) ) ) {
|
||||
FUNC_out( f, level );
|
||||
}
|
||||
} else {
|
||||
Linked_List alpha = LISTcreate();
|
||||
|
||||
DICTdo_type_init( s->symbol_table, &de, OBJ_FUNCTION );
|
||||
DICTdo_init( s->symbol_table, &de, OBJ_FUNCTION );
|
||||
while( 0 != ( f = ( Function )DICTdo( &de ) ) ) {
|
||||
SCOPEadd_inorder( alpha, f );
|
||||
}
|
||||
@@ -101,14 +101,14 @@ void SCOPEprocs_out( Scope s, int level ) {
|
||||
DictionaryEntry de;
|
||||
|
||||
if( exppp_alphabetize == false ) {
|
||||
DICTdo_type_init( s->symbol_table, &de, OBJ_PROCEDURE );
|
||||
DICTdo_init( s->symbol_table, &de, OBJ_PROCEDURE );
|
||||
while( 0 != ( p = ( Procedure )DICTdo( &de ) ) ) {
|
||||
PROC_out( p, level );
|
||||
}
|
||||
} else {
|
||||
Linked_List alpha = LISTcreate();
|
||||
|
||||
DICTdo_type_init( s->symbol_table, &de, OBJ_PROCEDURE );
|
||||
DICTdo_init( s->symbol_table, &de, OBJ_PROCEDURE );
|
||||
while( 0 != ( p = ( Procedure )DICTdo( &de ) ) ) {
|
||||
SCOPEadd_inorder( alpha, p );
|
||||
}
|
||||
@@ -188,7 +188,7 @@ void SCOPEconsts_out( Scope s, int level ) {
|
||||
Dictionary d = s->symbol_table;
|
||||
|
||||
/* checks length of constant names */
|
||||
DICTdo_type_init( d, &de, OBJ_VARIABLE );
|
||||
DICTdo_init( d, &de, OBJ_VARIABLE );
|
||||
while( 0 != ( v = ( Variable )DICTdo( &de ) ) ) {
|
||||
if( !v->flags.constant ) {
|
||||
continue;
|
||||
@@ -215,7 +215,7 @@ void SCOPEconsts_out( Scope s, int level ) {
|
||||
indent2 = level + max_indent + strlen( ": ab" ) + exppp_continuation_indent;
|
||||
|
||||
if( !exppp_alphabetize ) {
|
||||
DICTdo_type_init( d, &de, OBJ_VARIABLE );
|
||||
DICTdo_init( d, &de, OBJ_VARIABLE );
|
||||
while( 0 != ( v = ( Variable )DICTdo( &de ) ) ) {
|
||||
if( !v->flags.constant ) {
|
||||
continue;
|
||||
@@ -225,7 +225,7 @@ void SCOPEconsts_out( Scope s, int level ) {
|
||||
} else {
|
||||
Linked_List alpha = LISTcreate();
|
||||
|
||||
DICTdo_type_init( d, &de, OBJ_VARIABLE );
|
||||
DICTdo_init( d, &de, OBJ_VARIABLE );
|
||||
while( 0 != ( v = ( Variable )DICTdo( &de ) ) ) {
|
||||
if( !v->flags.constant ) {
|
||||
continue;
|
||||
@@ -258,7 +258,7 @@ void SCOPElocals_out( Scope s, int level ) {
|
||||
size_t max_indent = 0;
|
||||
Dictionary d = s->symbol_table;
|
||||
|
||||
DICTdo_type_init( d, &de, OBJ_VARIABLE );
|
||||
DICTdo_init( d, &de, OBJ_VARIABLE );
|
||||
while( 0 != ( v = ( Variable )DICTdo( &de ) ) ) {
|
||||
if( v->flags.constant ) {
|
||||
continue;
|
||||
@@ -280,7 +280,7 @@ void SCOPElocals_out( Scope s, int level ) {
|
||||
raw( "%*sLOCAL\n", level, "" );
|
||||
indent2 = level + max_indent + strlen( ": " ) + exppp_continuation_indent;
|
||||
|
||||
DICTdo_type_init( d, &de, OBJ_VARIABLE );
|
||||
DICTdo_init( d, &de, OBJ_VARIABLE );
|
||||
while( 0 != ( v = ( Variable )DICTdo( &de ) ) ) {
|
||||
if( v->flags.constant ) {
|
||||
continue;
|
||||
@@ -325,14 +325,14 @@ void SCOPEentities_out( Scope s, int level ) {
|
||||
DictionaryEntry de;
|
||||
|
||||
if( exppp_alphabetize == false ) {
|
||||
DICTdo_type_init( s->symbol_table, &de, OBJ_ENTITY );
|
||||
DICTdo_init( s->symbol_table, &de, OBJ_ENTITY );
|
||||
while( 0 != ( e = ( Entity )DICTdo( &de ) ) ) {
|
||||
ENTITY_out( e, level );
|
||||
}
|
||||
} else {
|
||||
Linked_List alpha = LISTcreate();
|
||||
|
||||
DICTdo_type_init( s->symbol_table, &de, OBJ_ENTITY );
|
||||
DICTdo_init( s->symbol_table, &de, OBJ_ENTITY );
|
||||
while( 0 != ( e = ( Entity )DICTdo( &de ) ) ) {
|
||||
SCOPEadd_inorder( alpha, e );
|
||||
}
|
||||
@@ -351,14 +351,14 @@ void SCOPEtypes_out( Scope s, int level ) {
|
||||
Type t;
|
||||
|
||||
if( exppp_alphabetize == false ) {
|
||||
DICTdo_type_init( s->symbol_table, &de, OBJ_TYPE );
|
||||
DICTdo_init( s->symbol_table, &de, OBJ_TYPE );
|
||||
while( 0 != ( t = ( Type )DICTdo( &de ) ) ) {
|
||||
TYPE_out( t, level );
|
||||
}
|
||||
} else {
|
||||
Linked_List alpha = LISTcreate();
|
||||
|
||||
DICTdo_type_init( s->symbol_table, &de, OBJ_TYPE );
|
||||
DICTdo_init( s->symbol_table, &de, OBJ_TYPE );
|
||||
while( 0 != ( t = ( Type )DICTdo( &de ) ) ) {
|
||||
SCOPEadd_inorder( alpha, t );
|
||||
}
|
||||
|
||||
@@ -147,12 +147,12 @@ void TYPE_body_out( Type t, int level ) {
|
||||
* to a temporary array. This is trivial since all buckets
|
||||
* will get filled with one and only one object.
|
||||
*/
|
||||
DICTdo_type_init( t->symbol_table, &de, OBJ_EXPRESSION );
|
||||
DICTdo_init( t->symbol_table, &de, OBJ_EXPRESSION );
|
||||
while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
|
||||
count++;
|
||||
}
|
||||
names = ( char ** )sc_malloc( count * sizeof( char * ) );
|
||||
DICTdo_type_init( t->symbol_table, &de, OBJ_EXPRESSION );
|
||||
DICTdo_init( t->symbol_table, &de, OBJ_EXPRESSION );
|
||||
while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
|
||||
names[expr->u.integer - 1] = expr->symbol.name;
|
||||
}
|
||||
|
||||
+16
-11
@@ -2,6 +2,7 @@ include_directories(
|
||||
${CMAKE_BINARY_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SC_SOURCE_DIR}/src/base
|
||||
${SC_SOURCE_DIR}/src/auxlib
|
||||
)
|
||||
|
||||
# Set up the information we need to feed the generated source management
|
||||
@@ -40,16 +41,19 @@ add_custom_target(express_verify DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/express_ver
|
||||
# Depending on whether we're using pre-generated sources or building them on
|
||||
# the fly, set up targets and source lists.
|
||||
if(SC_GENERATE_LP_SOURCES)
|
||||
LEMON_TARGET(ExpParser expparse.y)
|
||||
PERPLEX_TARGET(ExpScanner expscan.l)
|
||||
ADD_PERPLEX_LEMON_DEPENDENCY(ExpScanner ExpParser)
|
||||
LEMON_TARGET(ExpParser expparse.y expparse.c
|
||||
COMPILE_FLAGS "-p -c"
|
||||
DEFINES_FILE "expparse.h")
|
||||
RE2C_TARGET(ExpScanner expscan.l expscan.c
|
||||
COMPILE_FLAGS "-W -Wno-match-empty-string -r -c --tags"
|
||||
DEFINES_FILE "expscan.h")
|
||||
ADD_RE2C_LEMON_DEPENDENCY(ExpScanner ExpParser)
|
||||
|
||||
add_library(objlib_expscan_c OBJECT ${PERPLEX_ExpScanner_SRC})
|
||||
add_library(objlib_expscan_c OBJECT ${RE2C_ExpScanner_OUTPUTS})
|
||||
set_property(TARGET objlib_expscan_c PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
add_library(objlib_expparse_c OBJECT ${LEMON_ExpParser_SRC})
|
||||
add_library(objlib_expparse_c OBJECT ${LEMON_ExpParser_OUTPUTS})
|
||||
set_property(TARGET objlib_expparse_c PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
else(SC_GENERATE_LP_SOURCES)
|
||||
add_subdirectory(generated)
|
||||
include_directories(generated)
|
||||
@@ -68,10 +72,8 @@ set(EXPRESS_SOURCES
|
||||
schema.c
|
||||
resolve.c
|
||||
resolve2.c
|
||||
lexact.c
|
||||
linklist.c
|
||||
error.c
|
||||
dict.c
|
||||
hash.c
|
||||
alloc.c
|
||||
memory.c
|
||||
@@ -80,6 +82,7 @@ set(EXPRESS_SOURCES
|
||||
ordered_attrs.cc
|
||||
info.c
|
||||
factory.c
|
||||
lexsupport.c
|
||||
)
|
||||
|
||||
set(EXPRESS_OBJS)
|
||||
@@ -98,11 +101,12 @@ list(APPEND EXPRESS_OBJS $<TARGET_OBJECTS:objlib_expparse_c>)
|
||||
|
||||
if(SC_GENERATE_LP_SOURCES)
|
||||
set_property(TARGET objlib_expparse_c objlib_express_c objlib_lexact_c
|
||||
APPEND PROPERTY INCLUDE_DIRECTORIES "${PERPLEX_ExpScanner_INCLUDE_DIR}")
|
||||
APPEND PROPERTY INCLUDE_DIRECTORIES "${RE2C_ExpScanner_INCLUDE_DIR}")
|
||||
set_property(TARGET objlib_expscan_c objlib_express_c objlib_lexact_c
|
||||
APPEND PROPERTY INCLUDE_DIRECTORIES "${LEMON_ExpParser_INCLUDE_DIR}")
|
||||
# OBJECT libraries are not targets, and so an explicit dependency is required
|
||||
set_source_files_properties(express.c lexact.c PROPERTIES OBJECT_DEPENDS "${PERPLEX_ExpScanner_HDR};${LEMON_ExpParser_HDR}")
|
||||
set_source_files_properties(express.c lexact.c PROPERTIES OBJECT_DEPENDS
|
||||
"${RE2C_ExpScanner_OUTPUT_HEADER};${LEMON_ExpParser_OUTPUT_HEADER}")
|
||||
endif()
|
||||
|
||||
# TODO
|
||||
@@ -122,6 +126,7 @@ set(CHECK_EXPRESS_SOURCES
|
||||
SET(EXPRESS_PRIVATE_HDRS
|
||||
exptoks.h
|
||||
stack.h
|
||||
lexsupport.h
|
||||
)
|
||||
|
||||
variable_watch(SC_ADDLIB_EXPRESS_ARG_LINK_LIBRARIES)
|
||||
@@ -162,7 +167,7 @@ if($CACHE{SC_BUILD_STATIC_LIBS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
SC_ADDEXEC(check-express SOURCES ${CHECK_EXPRESS_SOURCES} LINK_LIBRARIES express base ${SC_EXEC_NOINSTALL})
|
||||
SC_ADDEXEC(check-express SOURCES ${CHECK_EXPRESS_SOURCES} LINK_LIBRARIES express base auxlib ${SC_EXEC_NOINSTALL})
|
||||
|
||||
if(SC_ENABLE_TESTING)
|
||||
add_subdirectory(test)
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
I'm rewriting the parser - now using RE2C and Lemon (rather than flex/bison previously discussed).
|
||||
|
||||
The principle aim behind this, more than a thousand lines of Python output rewrite - blocked. I
|
||||
need the parser to do more work.
|
||||
|
||||
Features:
|
||||
LEXER P1: Comments are stripped (in theory, these could be passed to e.g. an Express text editor)
|
||||
LEXER P2: Named scopes are resolved
|
||||
LEXER P3: Tokens are returned, and Anonymous scopes added
|
||||
PARSER: Single pass.
|
||||
|
||||
Tests:
|
||||
* test/unitary_schemas (ok, 2 expected failures)
|
||||
* data/*/*.exp (ok, no failures)
|
||||
|
||||
Generally, I believe there should be a more feature complete test set: Fully automated checking of
|
||||
parse trees. Although I don't fully understand how this should be achieved yet.
|
||||
|
||||
Next steps:
|
||||
1. Refactor to improve lexer actions
|
||||
2. Integrate parser
|
||||
3. General error handling strategy (to be discussed)
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
RE2C - versions before 1.0 have significant bugs, I used 1.0.3 - not the version in BRL-CAD.
|
||||
Lemon - I would guess any recent version would work (I haven't tested yet).
|
||||
|
||||
When I get a moment I'll add an equivalently named branch in the baffledCitrus repo.
|
||||
|
||||
Build Instructions
|
||||
==================
|
||||
|
||||
NOTE: currently no generators are supported!
|
||||
|
||||
configure using cmake
|
||||
EXPRESS_ONLY - set ON
|
||||
GENERATORS - turn all generators OFF
|
||||
DEBUG - set appropriate debug flags for your platform
|
||||
TESTING - enable tests
|
||||
|
||||
you can check for parse errors by running check-express
|
||||
|
||||
./check-express some/express/file.exp
|
||||
|
||||
+5
-3
@@ -39,6 +39,8 @@ Now you can say things like:
|
||||
#include "express/alloc.h"
|
||||
#include "express/error.h"
|
||||
|
||||
#include "sc_memmgr.h"
|
||||
|
||||
/* just in case we are compiling by hand */
|
||||
#ifndef ALLOC
|
||||
#define ALLOC
|
||||
@@ -50,7 +52,7 @@ Now you can say things like:
|
||||
* \param bytes new memory size
|
||||
*/
|
||||
Freelist * create_freelist( struct freelist_head * flh, int bytes ) {
|
||||
Freelist * current = ( Freelist * )malloc( bytes );
|
||||
Freelist * current = ( Freelist * )sc_malloc( bytes );
|
||||
if( current == 0 ) {
|
||||
return( 0 );
|
||||
}
|
||||
@@ -123,7 +125,7 @@ void * ALLOC_new( struct freelist_head * flh ) {
|
||||
#endif
|
||||
|
||||
#ifdef REAL_MALLOC
|
||||
return( calloc( 1, flh->size_elt ) );
|
||||
return( sc_calloc( 1, flh->size_elt ) );
|
||||
/*NOTREACHED*/
|
||||
#else
|
||||
if( flh->freelist == NULL && 0 == create_freelist( flh, flh->bytes ) ) {
|
||||
@@ -156,7 +158,7 @@ void ALLOC_destroy( struct freelist_head * flh, Freelist * link ) {
|
||||
#endif
|
||||
|
||||
#ifdef REAL_MALLOC
|
||||
free( link );
|
||||
sc_free( link );
|
||||
return;
|
||||
/*NOTREACHED*/
|
||||
#else
|
||||
|
||||
+2
-2
@@ -43,7 +43,7 @@ void DICTprint( Dictionary dict ) {
|
||||
Element e;
|
||||
DictionaryEntry de;
|
||||
|
||||
HASHlistinit( dict, &de );
|
||||
HASHlistinit( dict, &de, '*' );
|
||||
|
||||
while( 0 != ( e = ( HASHlist( &de ) ) ) ) {
|
||||
fprintf( stderr, "key <%s> data <%s> line <%d> <\"%c\" %s> <%s>\n",
|
||||
@@ -113,7 +113,7 @@ int DICTdefine( Dictionary dict, char * name, void *obj, Symbol * sym, char type
|
||||
* their unusual behavior with respect to scoping and visibility rules
|
||||
* \sa DICTdefine()
|
||||
*/
|
||||
int DICT_define( Dictionary dict, char * name, void *obj, Symbol * sym, char type ) {
|
||||
int DICTdefine_enum( Dictionary dict, char * name, void *obj, Symbol * sym, char type ) {
|
||||
struct Element_ e, *e2;
|
||||
|
||||
e.key = name;
|
||||
|
||||
+39
-29
@@ -130,7 +130,7 @@ int ENTITYdeclares_variable( Entity e, Variable v ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static Entity ENTITY_find_inherited_entity( Entity entity, char * name, int down ) {
|
||||
static Entity ENTITY_find_inherited_entity( Entity entity, const char * name, int down ) {
|
||||
Entity result;
|
||||
|
||||
/* avoid searching scopes that we've already searched */
|
||||
@@ -174,7 +174,7 @@ static Entity ENTITY_find_inherited_entity( Entity entity, char * name, int down
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct Scope_ * ENTITYfind_inherited_entity( struct Scope_ *entity, char * name, int down ) {
|
||||
struct Scope_ * ENTITYfind_inherited_entity( struct Scope_ *entity, const char * name, int down ) {
|
||||
if( !strcmp( name, entity->symbol.name ) ) {
|
||||
return( entity );
|
||||
}
|
||||
@@ -184,8 +184,8 @@ struct Scope_ * ENTITYfind_inherited_entity( struct Scope_ *entity, char * name,
|
||||
}
|
||||
|
||||
/** find a (possibly inherited) attribute */
|
||||
Variable ENTITY_find_inherited_attribute( Entity entity, char * name, int * down, struct Symbol_ ** where ) {
|
||||
Variable result;
|
||||
Symbol *ENTITY_find_inherited_attribute( Entity entity, const char * name, int * down, struct Symbol_ ** where ) {
|
||||
Symbol *ep;
|
||||
|
||||
/* avoid searching scopes that we've already searched */
|
||||
/* this can happen due to several things */
|
||||
@@ -198,19 +198,19 @@ Variable ENTITY_find_inherited_attribute( Entity entity, char * name, int * down
|
||||
entity->search_id = __SCOPE_search_id;
|
||||
|
||||
/* first look locally */
|
||||
result = ( Variable )DICTlookup( entity->symbol_table, name );
|
||||
if( result ) {
|
||||
ep = HASHsearch(entity->symbol_table, (Symbol) {.name = name}, HASH_FIND);
|
||||
if (ep) {
|
||||
if( down && *down && where ) {
|
||||
*where = &entity->symbol;
|
||||
}
|
||||
return result;
|
||||
return ep;
|
||||
}
|
||||
|
||||
/* check supertypes */
|
||||
LISTdo( entity->u.entity->supertypes, super, Entity )
|
||||
result = ENTITY_find_inherited_attribute( super, name, down, where );
|
||||
if( result ) {
|
||||
return result;
|
||||
ep = ENTITY_find_inherited_attribute( super, name, down, where );
|
||||
if( ep ) {
|
||||
return ep;
|
||||
}
|
||||
LISTod;
|
||||
|
||||
@@ -218,18 +218,18 @@ Variable ENTITY_find_inherited_attribute( Entity entity, char * name, int * down
|
||||
if( down ) {
|
||||
++*down;
|
||||
LISTdo( entity->u.entity->subtypes, sub, Entity )
|
||||
result = ENTITY_find_inherited_attribute( sub, name, down, where );
|
||||
if( result ) {
|
||||
return result;
|
||||
ep = ENTITY_find_inherited_attribute( sub, name, down, where );
|
||||
if( ep ) {
|
||||
return ep;
|
||||
}
|
||||
LISTod;
|
||||
--*down;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Variable ENTITYfind_inherited_attribute( struct Scope_ *entity, char * name,
|
||||
Symbol *ENTITYfind_inherited_attribute( struct Scope_ *entity, const char * name,
|
||||
struct Symbol_ ** down_sym ) {
|
||||
extern int __SCOPE_search_id;
|
||||
int down_flag = 0;
|
||||
@@ -246,6 +246,7 @@ Variable ENTITYfind_inherited_attribute( struct Scope_ *entity, char * name,
|
||||
* report errors as appropriate
|
||||
*/
|
||||
Variable ENTITYresolve_attr_ref( Entity e, Symbol * grp_ref, Symbol * attr_ref ) {
|
||||
Symbol *ep;
|
||||
Entity ref_entity;
|
||||
Variable attr;
|
||||
struct Symbol_ *where;
|
||||
@@ -257,13 +258,14 @@ Variable ENTITYresolve_attr_ref( Entity e, Symbol * grp_ref, Symbol * attr_ref )
|
||||
ERRORreport_with_symbol(UNKNOWN_SUPERTYPE, grp_ref, grp_ref->name, e->symbol.name );
|
||||
return 0;
|
||||
}
|
||||
attr = ( Variable )DICTlookup( ref_entity->symbol_table,
|
||||
attr_ref->name );
|
||||
if( !attr ) {
|
||||
ep = HASHsearch(ref_entity->symbol_table, (Symbol) {.name = attr_ref->name}, HASH_FIND);
|
||||
if (!ep) {
|
||||
ERRORreport_with_symbol(UNKNOWN_ATTR_IN_ENTITY, attr_ref, attr_ref->name,
|
||||
ref_entity->symbol.name );
|
||||
/* resolve_failed(e);*/
|
||||
return 0;
|
||||
}
|
||||
attr = ep->data;
|
||||
} else {
|
||||
/* no entity provided, look through supertype chain */
|
||||
where = NULL;
|
||||
@@ -301,18 +303,21 @@ void ENTITYinitialize() {
|
||||
** Add an attribute to an entity.
|
||||
*/
|
||||
void ENTITYadd_attribute( Entity entity, Variable attr ) {
|
||||
int rc;
|
||||
Symbol e, *ep;
|
||||
|
||||
memcpy(&e, &attr->name->symbol, sizeof(Symbol));
|
||||
e.data = attr;
|
||||
e.type = OBJ_VARIABLE;
|
||||
|
||||
if( attr->name->type->u.type->body->type != op_ ) {
|
||||
/* simple id */
|
||||
rc = DICTdefine( entity->symbol_table, attr->name->symbol.name,
|
||||
attr, &attr->name->symbol, OBJ_VARIABLE );
|
||||
ep = HASHsearch(entity->symbol_table, e, HASH_INSERT);
|
||||
} else {
|
||||
/* SELF\ENTITY.SIMPLE_ID */
|
||||
rc = DICTdefine( entity->symbol_table, attr->name->e.op2->symbol.name,
|
||||
attr, &attr->name->symbol, OBJ_VARIABLE );
|
||||
e.name = attr->name->e.op2->symbol.name;
|
||||
ep = HASHsearch( entity->symbol_table, e, HASH_INSERT);
|
||||
}
|
||||
if( rc == 0 ) {
|
||||
if( !ep ) {
|
||||
LISTadd_last( entity->u.entity->attributes, attr );
|
||||
VARput_offset( attr, entity->u.entity->attribute_count );
|
||||
entity->u.entity->attribute_count++;
|
||||
@@ -403,7 +408,7 @@ Linked_List ENTITYget_all_attributes( Entity entity ) {
|
||||
** \note If the entity has no attribute with the given name,
|
||||
** VARIABLE_NULL is returned.
|
||||
*/
|
||||
Variable ENTITYget_named_attribute( Entity entity, char * name ) {
|
||||
Variable ENTITYget_named_attribute( Entity entity, const char * name ) {
|
||||
Variable attribute;
|
||||
|
||||
LISTdo( entity->u.entity->attributes, attr, Variable )
|
||||
@@ -460,14 +465,19 @@ int ENTITYget_attribute_offset( Entity entity, Variable attribute ) {
|
||||
** \note If the entity has no attribute with the given name,
|
||||
** -1 is returned.
|
||||
*/
|
||||
int ENTITYget_named_attribute_offset( Entity entity, char * name ) {
|
||||
int ENTITYget_named_attribute_offset( Entity entity, const char * name ) {
|
||||
int offset;
|
||||
int value;
|
||||
Symbol *ep;
|
||||
|
||||
LISTdo( entity->u.entity->attributes, attr, Variable )
|
||||
if( !strcmp( VARget_simple_name( attr ), name ) )
|
||||
return entity->u.entity->inheritance +
|
||||
VARget_offset( ENTITY_find_inherited_attribute( entity, name, 0, 0 ) );
|
||||
if (!strcmp( VARget_simple_name( attr ), name ) ) {
|
||||
ep = ENTITY_find_inherited_attribute( entity, name, 0, 0 );
|
||||
if (!ep)
|
||||
continue;
|
||||
|
||||
return entity->u.entity->inheritance + VARget_offset((Variable) ep->data);
|
||||
}
|
||||
LISTod;
|
||||
offset = 0;
|
||||
LISTdo( entity->u.entity->supertypes, super, Entity )
|
||||
|
||||
+670
-2299
File diff suppressed because it is too large
Load Diff
+41
-23
@@ -152,8 +152,10 @@ void EXPcleanup( void ) {
|
||||
*/
|
||||
static int EXP_resolve_op_dot_fuzzy( Type selection, Symbol sref, Expression * e,
|
||||
Variable * v, char * dt, struct Symbol_ ** where, int s_id ) {
|
||||
Symbol *ep;
|
||||
Expression item;
|
||||
Variable tmp;
|
||||
Linked_List supert, subt, uniqSubs;
|
||||
int options = 0;
|
||||
struct Symbol_ *w = NULL;
|
||||
|
||||
@@ -170,15 +172,15 @@ static int EXP_resolve_op_dot_fuzzy( Type selection, Symbol sref, Expression * e
|
||||
*where = w;
|
||||
}
|
||||
*v = tmp;
|
||||
*dt = DICT_type;
|
||||
*dt = OBJ_VARIABLE;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
case select_: {
|
||||
Linked_List supert = LISTcreate();
|
||||
Linked_List subt = LISTcreate();
|
||||
Linked_List uniqSubs = LISTcreate();
|
||||
case select_:
|
||||
supert = LISTcreate();
|
||||
subt = LISTcreate();
|
||||
uniqSubs = LISTcreate();
|
||||
selection->search_id = s_id;
|
||||
LISTdo( selection->u.type->body->list, t, Type ) {
|
||||
int nr = EXP_resolve_op_dot_fuzzy( t, sref, e, v, dt, &w, s_id );
|
||||
@@ -224,13 +226,15 @@ static int EXP_resolve_op_dot_fuzzy( Type selection, Symbol sref, Expression * e
|
||||
LISTfree( subt );
|
||||
LISTfree( uniqSubs );
|
||||
return options;
|
||||
}
|
||||
case enumeration_:
|
||||
item = ( Expression )DICTlookup( TYPEget_enum_tags( selection ), sref.name );
|
||||
if( item ) {
|
||||
ep = HASHsearch(TYPEget_enum_tags( selection ), (Symbol) {.name = sref.name}, HASH_FIND);
|
||||
if (ep) {
|
||||
item = ep->data;
|
||||
*e = item;
|
||||
*dt = DICT_type;
|
||||
*dt = OBJ_ENUM;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
@@ -238,6 +242,7 @@ static int EXP_resolve_op_dot_fuzzy( Type selection, Symbol sref, Expression * e
|
||||
}
|
||||
|
||||
Type EXPresolve_op_dot( Expression expr, Scope scope ) {
|
||||
Symbol *ep;
|
||||
Expression op1 = expr->e.op1;
|
||||
Expression op2 = expr->e.op2;
|
||||
Variable v = 0;
|
||||
@@ -318,7 +323,7 @@ Type EXPresolve_op_dot( Expression expr, Scope scope ) {
|
||||
fprintf( stderr, "EXPresolved_op_dot: attribute not an attribute?\n" );
|
||||
ERRORabort( 0 );
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
/* compile-time ambiguous */
|
||||
if( where ) {
|
||||
@@ -337,10 +342,12 @@ Type EXPresolve_op_dot( Expression expr, Scope scope ) {
|
||||
resolve_failed( expr );
|
||||
return( Type_Bad );
|
||||
}
|
||||
/* TODO: now checked in parser?
|
||||
if( DICT_type != OBJ_VARIABLE ) {
|
||||
fprintf( stderr, "EXPresolved_op_dot: attribute not an attribute?\n" );
|
||||
ERRORabort( 0 );
|
||||
}
|
||||
*/
|
||||
|
||||
op2->u.variable = v;
|
||||
op2->return_type = v->type;
|
||||
@@ -357,9 +364,11 @@ Type EXPresolve_op_dot( Expression expr, Scope scope ) {
|
||||
resolve_failed( expr );
|
||||
return( Type_Bad );
|
||||
}
|
||||
/* TODO: now checked in parser?
|
||||
if( DICT_type != OBJ_VARIABLE ) {
|
||||
fprintf( stderr, "ERROR: EXPresolved_op_dot: attribute not an attribute?\n" );
|
||||
}
|
||||
*/
|
||||
|
||||
op2->u.variable = v;
|
||||
/* changed to set return_type */
|
||||
@@ -369,14 +378,16 @@ Type EXPresolve_op_dot( Expression expr, Scope scope ) {
|
||||
case enumeration_:
|
||||
/* enumerations within a select will be handled by `case select_` above,
|
||||
* which calls EXP_resolve_op_dot_fuzzy(). */
|
||||
item = ( Expression )DICTlookup( TYPEget_enum_tags( op1type ), op2->symbol.name );
|
||||
if( !item ) {
|
||||
ep = HASHsearch(TYPEget_enum_tags( op1type ), (Symbol) { .name = op2->symbol.name }, HASH_FIND);
|
||||
if (!ep) {
|
||||
ERRORreport_with_symbol(ENUM_NO_SUCH_ITEM, &op2->symbol,
|
||||
op1type->symbol.name, op2->symbol.name );
|
||||
resolve_failed( expr );
|
||||
return( Type_Bad );
|
||||
}
|
||||
|
||||
|
||||
/* TODO: ep->data, ep->type? */
|
||||
item = ep->data;
|
||||
op2->u.expression = item;
|
||||
op2->return_type = item->type;
|
||||
resolved_all( expr );
|
||||
@@ -600,17 +611,24 @@ Type EXPresolve_op_relational( Expression e, Scope s ) {
|
||||
|
||||
void EXPresolve_op_default( Expression e, Scope s ) {
|
||||
int failed = 0;
|
||||
|
||||
switch( OPget_number_of_operands( e->e.op_code ) ) {
|
||||
case 3:
|
||||
EXPresolve( e->e.op3, s, Type_Dont_Care );
|
||||
failed = is_resolve_failed( e->e.op3 );
|
||||
case 2:
|
||||
EXPresolve( e->e.op2, s, Type_Dont_Care );
|
||||
failed |= is_resolve_failed( e->e.op2 );
|
||||
int nargs = OPget_number_of_operands( e->e.op_code );
|
||||
|
||||
if (nargs == 3) {
|
||||
EXPresolve( e->e.op3, s, Type_Dont_Care );
|
||||
failed = is_resolve_failed( e->e.op3 );
|
||||
}
|
||||
EXPresolve( e->e.op1, s, Type_Dont_Care );
|
||||
if( failed || is_resolve_failed( e->e.op1 ) ) {
|
||||
|
||||
if (nargs >= 2) {
|
||||
EXPresolve( e->e.op2, s, Type_Dont_Care );
|
||||
failed |= is_resolve_failed( e->e.op2 );
|
||||
}
|
||||
|
||||
if (1) { /* (nargs >= 1) */
|
||||
EXPresolve( e->e.op1, s, Type_Dont_Care );
|
||||
failed |= is_resolve_failed( e->e.op1 );
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
resolve_failed( e );
|
||||
} else {
|
||||
resolved_all( e );
|
||||
|
||||
+140
-67
@@ -74,23 +74,28 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "sc_memmgr.h"
|
||||
|
||||
#include "express/memory.h"
|
||||
#include "express/hash.h"
|
||||
#include "express/basic.h"
|
||||
#include "express/express.h"
|
||||
#include "express/resolve.h"
|
||||
#include "express/factory.h"
|
||||
#include "stack.h"
|
||||
#include "express/scope.h"
|
||||
#include "express/exp_kw.h"
|
||||
|
||||
#include "stack.h"
|
||||
#include "token_type.h"
|
||||
#include "lexsupport.h"
|
||||
#include "expparse.h"
|
||||
#include "expscan.h"
|
||||
#include "parse_data.h"
|
||||
#include "express/lexact.h"
|
||||
|
||||
#if 0
|
||||
void * ParseAlloc( void * ( *mallocProc )( size_t ) );
|
||||
void ParseFree( void * parser, void ( *freeProc )( void * ) );
|
||||
void Parse( void * parser, int tokenID, YYSTYPE data, parse_data_t parseData );
|
||||
void ParseTrace(FILE *TraceFILE, char *zTracePrompt);
|
||||
#endif
|
||||
|
||||
Linked_List EXPRESS_path;
|
||||
int EXPRESSpass;
|
||||
@@ -108,13 +113,14 @@ bool EXPRESSignore_duplicate_schemas = false;
|
||||
Function funcdef(char *name, int pcount, Type ret_typ);
|
||||
void procdef(char *name, int pcount);
|
||||
void BUILTINSinitialize();
|
||||
Dictionary EXPRESSbuiltins; /* procedures/functions */
|
||||
Hash_Table EXPRESSbuiltins; /* procedures/functions */
|
||||
|
||||
|
||||
struct Scope_ * FUNC_NVL;
|
||||
struct Scope_ * FUNC_USEDIN;
|
||||
#if 0
|
||||
extern Express yyexpresult;
|
||||
|
||||
#endif
|
||||
|
||||
extern Linked_List PARSEnew_schemas;
|
||||
void SCOPEinitialize( void );
|
||||
@@ -255,7 +261,6 @@ void EXPRESSinitialize( void ) {
|
||||
ERRORinitialize();
|
||||
|
||||
HASHinitialize(); /* comes first - used by just about everything else! */
|
||||
DICTinitialize();
|
||||
LISTinitialize(); /* ditto */
|
||||
STACKinitialize();
|
||||
PASSinitialize();
|
||||
@@ -278,8 +283,6 @@ void EXPRESSinitialize( void ) {
|
||||
/* LOOP_CTLinitialize();*/
|
||||
STMTinitialize();
|
||||
|
||||
SCANinitialize();
|
||||
|
||||
BUILTINSinitialize();
|
||||
|
||||
EXPRESS_PATHinit(); /* note, must follow defn of errors it needs! */
|
||||
@@ -289,12 +292,10 @@ void EXPRESSinitialize( void ) {
|
||||
void EXPRESScleanup( void ) {
|
||||
EXPRESS_PATHfree();
|
||||
|
||||
DICTcleanup();
|
||||
ERRORcleanup();
|
||||
RESOLVEcleanup();
|
||||
TYPEcleanup();
|
||||
EXPcleanup();
|
||||
SCANcleanup();
|
||||
LISTcleanup();
|
||||
}
|
||||
|
||||
@@ -304,8 +305,10 @@ void EXPRESScleanup( void ) {
|
||||
** Parse an Express source file into the Working Form.
|
||||
*/
|
||||
void EXPRESSparse( Express model, FILE * fp, char * filename ) {
|
||||
#if 0
|
||||
yyexpresult = model;
|
||||
|
||||
#endif
|
||||
|
||||
if( !fp ) {
|
||||
fp = fopen( filename, "r" );
|
||||
}
|
||||
@@ -340,12 +343,12 @@ void EXPRESSparse( Express model, FILE * fp, char * filename ) {
|
||||
}
|
||||
|
||||
model->u.express->basename = ( char * )sc_malloc( length + 1 );
|
||||
memcpy( model->u.express->basename, filename, length );
|
||||
memcpy( model->u.express->basename, start, length );
|
||||
model->u.express->basename[length] = '\0';
|
||||
|
||||
/* get new copy of filename to avoid being smashed */
|
||||
/* by subsequent lookups on EXPRESS_path */
|
||||
model->u.express->filename = SCANstrdup( filename );
|
||||
model->u.express->filename = strdup( filename );
|
||||
filename = model->u.express->filename;
|
||||
}
|
||||
|
||||
@@ -353,6 +356,57 @@ void EXPRESSparse( Express model, FILE * fp, char * filename ) {
|
||||
PARSERrun( filename, model->u.express->file = fp );
|
||||
}
|
||||
|
||||
static Express PARSERrun( char * filename, FILE * fp ) {
|
||||
int tok;
|
||||
struct YYSTYPE yylval;
|
||||
struct YYSTATE *pState;
|
||||
void *pParser, *pScanner;
|
||||
|
||||
pScanner = yylexAlloc();
|
||||
pState = yystateAlloc();
|
||||
pParser = yyparseAlloc(sc_malloc);
|
||||
|
||||
if( print_objects_while_running & OBJ_PASS_BITS ) {
|
||||
fprintf( stderr, "parse (pass %d)\n", EXPRESSpass );
|
||||
}
|
||||
|
||||
if( print_objects_while_running & OBJ_SCHEMA_BITS ) {
|
||||
fprintf( stderr, "parse: %s (schema file)\n", filename );
|
||||
}
|
||||
|
||||
yylexInit(pScanner, pState, fp);
|
||||
|
||||
yyparseTrace(stderr, "dbg: ");
|
||||
while ((tok = yylex(pScanner, &yylval))) {
|
||||
yyparse(pParser, tok, &yylval, pState);
|
||||
}
|
||||
yyparse(pParser, 0, &yylval, pState);
|
||||
|
||||
#if 0
|
||||
/* want 0 on success, 1 on invalid input, 2 on memory exhaustion */
|
||||
if( yyerrstatus != 0 ) {
|
||||
fprintf( stderr, ">> Bailing! (yyerrstatus = %d)\n", yyerrstatus );
|
||||
ERRORreport( ERROR_bail_out );
|
||||
/* free model and model->u.express */
|
||||
return 0;
|
||||
}
|
||||
EXPRESSpass = 1;
|
||||
|
||||
#endif
|
||||
|
||||
/* TODO: yylexFree(pScanner) */
|
||||
yyparseFree(pParser, sc_free);
|
||||
/*
|
||||
yylexFree(pScanner);
|
||||
yystateFree(pState);
|
||||
*/
|
||||
|
||||
#if 0
|
||||
return yyexpresult;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* TODO LEMON ought to put this in expparse.h */
|
||||
void parserInitState();
|
||||
|
||||
@@ -364,7 +418,7 @@ static Express PARSERrun( char * filename, FILE * fp ) {
|
||||
int tokenID;
|
||||
parse_data_t parseData;
|
||||
|
||||
void * parser = ParseAlloc( malloc );
|
||||
void * parser = ParseAlloc( sc_malloc );
|
||||
perplex_t scanner = perplexFileScanner( fp );
|
||||
parseData.scanner = scanner;
|
||||
|
||||
@@ -397,10 +451,11 @@ static Express PARSERrun( char * filename, FILE * fp ) {
|
||||
EXPRESSpass = 1;
|
||||
|
||||
perplexFree( scanner );
|
||||
ParseFree( parser, free );
|
||||
ParseFree( parser, sc_free );
|
||||
|
||||
return yyexpresult;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* find the final object to which a rename points
|
||||
@@ -409,52 +464,50 @@ static Express PARSERrun( char * filename, FILE * fp ) {
|
||||
*
|
||||
* Sept 2013 - remove unused param enum rename_type type (TODO should this be used)?
|
||||
*/
|
||||
static void * SCOPEfind_for_rename( Scope schema, char * name ) {
|
||||
void *result;
|
||||
Rename * rename;
|
||||
static Symbol *SCOPEfind_for_rename( Scope schema, const char * name ) {
|
||||
Symbol *ep;
|
||||
|
||||
/* object can only appear in top level symbol table */
|
||||
/* OR in another rename clause */
|
||||
|
||||
result = DICTlookup( schema->symbol_table, name );
|
||||
if( result ) {
|
||||
return result;
|
||||
ep = HASHsearch(schema->symbol_table, (Symbol) {.name = name}, HASH_FIND);
|
||||
if( ep ) {
|
||||
return ep;
|
||||
}
|
||||
|
||||
/* Occurs in a fully USE'd schema? */
|
||||
LISTdo( schema->u.schema->use_schemas, use_schema, Schema ) {
|
||||
/* follow chain'd USEs */
|
||||
result = SCOPEfind_for_rename( use_schema, name );
|
||||
if( result ) {
|
||||
return( result );
|
||||
ep = SCOPEfind_for_rename( use_schema, name );
|
||||
if (ep) {
|
||||
return ep;
|
||||
}
|
||||
} LISTod;
|
||||
|
||||
/* Occurs in a partially USE'd schema? */
|
||||
rename = ( Rename * )DICTlookup( schema->u.schema->usedict, name );
|
||||
if( rename ) {
|
||||
RENAMEresolve( rename, schema );
|
||||
DICT_type = rename->type;
|
||||
return( rename->object );
|
||||
ep = HASHsearch(schema->u.schema->usedict, (Symbol) {.name = name}, HASH_FIND);
|
||||
if( ep ) {
|
||||
RENAMEresolve( ep->data, schema );
|
||||
return ep;
|
||||
}
|
||||
|
||||
LISTdo( schema->u.schema->uselist, r, Rename * )
|
||||
if( !strcmp( ( r->nnew ? r->nnew : r->old )->name, name ) ) {
|
||||
RENAMEresolve( r, schema );
|
||||
DICT_type = r->type;
|
||||
return( r->object );
|
||||
ep = SCOPEfind_for_rename( r->schema, r->old->name );
|
||||
if (ep) {
|
||||
return ep;
|
||||
}
|
||||
}
|
||||
LISTod;
|
||||
|
||||
/* we are searching for an object to be interfaced from this schema. */
|
||||
/* therefore, we *never* want to look at things which are REFERENCE'd */
|
||||
/* *into* the current schema. -snc */
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void RENAMEresolve( Rename * r, Schema s ) {
|
||||
void *remote;
|
||||
Symbol *remote;
|
||||
|
||||
/* if (is_resolved_rename_raw(r->old)) return;*/
|
||||
if( r->object ) {
|
||||
@@ -474,13 +527,13 @@ void RENAMEresolve( Rename * r, Schema s ) {
|
||||
resolve_in_progress_raw( r->old );
|
||||
|
||||
remote = SCOPEfind_for_rename( r->schema, r->old->name );
|
||||
if( remote == 0 ) {
|
||||
if (!remote) {
|
||||
ERRORreport_with_symbol( REF_NONEXISTENT, r->old,
|
||||
r->old->name, r->schema->symbol.name );
|
||||
resolve_failed_raw( r->old );
|
||||
} else {
|
||||
r->object = remote;
|
||||
r->type = DICT_type;
|
||||
r->object = remote->data;
|
||||
r->type = remote->type;
|
||||
switch( r->rename_type ) {
|
||||
case use:
|
||||
SCHEMAdefine_use( s, r );
|
||||
@@ -496,30 +549,35 @@ void RENAMEresolve( Rename * r, Schema s ) {
|
||||
|
||||
#ifdef using_enum_items_is_a_pain
|
||||
static void RENAMEresolve_enum( Type t, Schema s ) {
|
||||
DictionaryEntry de;
|
||||
Hash_Iterator it;
|
||||
Symbol *ep;
|
||||
Expression x;
|
||||
|
||||
DICTdo_type_init( t->symbol_table, &de, OBJ_EXPRESSION );
|
||||
while( 0 != ( x = ( Expression )DICTdo( &de ) ) ) {
|
||||
HASHdo_init( t->symbol_table, &it, OBJ_EXPRESSION );
|
||||
while( (ep = HASHdo( &it )) ) {
|
||||
x = ep->data;
|
||||
/* TODO: if this isn't required, should we delete it? */
|
||||
/* SCHEMAadd_use(s, v*/
|
||||
/* raw(x->symbol.name);*/
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Schema EXPRESSfind_schema( Dictionary modeldict, char * name ) {
|
||||
Schema EXPRESSfind_schema( Hash_Table modeldict, const char *name ) {
|
||||
Symbol *ep;
|
||||
Schema s;
|
||||
FILE * fp;
|
||||
char * src, *dest;
|
||||
char lower[MAX_SCHEMA_FILENAME_SIZE]; /* avoid lowerizing original */
|
||||
const char *src;
|
||||
char lower[MAX_SCHEMA_FILENAME_SIZE], *dest;
|
||||
|
||||
if( print_objects_while_running & OBJ_SCHEMA_BITS ) {
|
||||
fprintf( stderr, "pass %d: %s (schema reference)\n",
|
||||
EXPRESSpass, name );
|
||||
}
|
||||
|
||||
s = ( Schema )DICTlookup( modeldict, name );
|
||||
if( s ) {
|
||||
ep = HASHsearch(modeldict, (Symbol) {.name = name}, HASH_FIND);
|
||||
if (ep) {
|
||||
s = ep->data;
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -545,12 +603,12 @@ Schema EXPRESSfind_schema( Dictionary modeldict, char * name ) {
|
||||
EXPRESSpass, dir->full );
|
||||
}
|
||||
|
||||
express = PARSERrun( SCANstrdup( dir->full ), fp );
|
||||
express = PARSERrun( strdup( dir->full ), fp );
|
||||
if( express ) {
|
||||
s = ( Schema )DICTlookup( modeldict, name );
|
||||
}
|
||||
if( s ) {
|
||||
return s;
|
||||
ep = HASHsearch(modeldict, (Symbol) {.name = name}, HASH_FIND);
|
||||
if( ep ) {
|
||||
return ep->data;
|
||||
}
|
||||
}
|
||||
ERRORreport( SCHEMA_NOT_IN_OWN_SCHEMA_FILE,
|
||||
name, dir->full );
|
||||
@@ -571,7 +629,7 @@ Schema EXPRESSfind_schema( Dictionary modeldict, char * name ) {
|
||||
* because of partial schema references
|
||||
* \sa connect_schema_lists()
|
||||
*/
|
||||
static void connect_lists( Dictionary modeldict, Schema schema, Linked_List list ) {
|
||||
static void connect_lists( Hash_Table modeldict, Schema schema, Linked_List list ) {
|
||||
Rename * r;
|
||||
|
||||
/* translate symbols to schemas */
|
||||
@@ -592,7 +650,7 @@ static void connect_lists( Dictionary modeldict, Schema schema, Linked_List list
|
||||
* same as `connect_lists` except for full schemas
|
||||
* \sa connect_lists()
|
||||
*/
|
||||
static void connect_schema_lists( Dictionary modeldict, Schema schema, Linked_List schema_list ) {
|
||||
static void connect_schema_lists( Hash_Table modeldict, Schema schema, Linked_List schema_list ) {
|
||||
Symbol * sym;
|
||||
Schema ref_schema;
|
||||
|
||||
@@ -620,8 +678,10 @@ void EXPRESSresolve( Express model ) {
|
||||
/* comes first - DEL */
|
||||
|
||||
Schema schema;
|
||||
DictionaryEntry de;
|
||||
Hash_Iterator it;
|
||||
Symbol *ep;
|
||||
|
||||
/* TODO: do we really need to use setjmp? */
|
||||
jmp_buf env;
|
||||
if( setjmp( env ) ) {
|
||||
return;
|
||||
@@ -668,8 +728,10 @@ void EXPRESSresolve( Express model ) {
|
||||
}
|
||||
|
||||
/* connect the object in each rename clause to the real object */
|
||||
DICTdo_type_init( model->symbol_table, &de, OBJ_SCHEMA );
|
||||
while( 0 != ( schema = ( Schema )DICTdo( &de ) ) ) {
|
||||
HASHdo_init( model->symbol_table, &it, OBJ_SCHEMA );
|
||||
while( (ep = HASHdo(&it)) ) {
|
||||
schema = ep->data;
|
||||
|
||||
if( is_not_resolvable( schema ) ) {
|
||||
continue;
|
||||
}
|
||||
@@ -703,8 +765,10 @@ void EXPRESSresolve( Express model ) {
|
||||
fprintf( stderr, "pass %d: resolving sub and supertypes\n", EXPRESSpass );
|
||||
}
|
||||
|
||||
DICTdo_type_init( model->symbol_table, &de, OBJ_SCHEMA );
|
||||
while( 0 != ( schema = ( Schema )DICTdo( &de ) ) ) {
|
||||
HASHdo_init( model->symbol_table, &it, OBJ_SCHEMA );
|
||||
while( (ep = HASHdo(&it)) ) {
|
||||
schema = ep->data;
|
||||
|
||||
if( is_not_resolvable( schema ) ) {
|
||||
continue;
|
||||
}
|
||||
@@ -734,8 +798,10 @@ void EXPRESSresolve( Express model ) {
|
||||
fprintf( stderr, "pass %d: resolving implied USE's\n", EXPRESSpass );
|
||||
}
|
||||
|
||||
DICTdo_type_init( model->symbol_table, &de, OBJ_SCHEMA );
|
||||
while( 0 != ( schema = ( Schema )DICTdo( &de ) ) ) {
|
||||
HASHdo_init( model->symbol_table, &it, OBJ_SCHEMA );
|
||||
while( (ep = HASHdo(&it)) ) {
|
||||
schema = ep->data;
|
||||
|
||||
if( is_not_resolvable( schema ) ) {
|
||||
continue;
|
||||
}
|
||||
@@ -746,8 +812,11 @@ void EXPRESSresolve( Express model ) {
|
||||
}
|
||||
|
||||
if( schema->u.schema->usedict ) {
|
||||
DICTdo_init( schema->u.schema->usedict, &fg )
|
||||
while( 0 != ( r = ( Rename )DICTdo( &fg ) ) ) {
|
||||
Hash_Iterator iv;
|
||||
HASHdo_init( schema->u.schema->usedict, &iv, OBJ_ANY )
|
||||
while( (ep = HASHdo( &iv )) ) {
|
||||
r = ep->data;
|
||||
|
||||
if( ( r->type = OBJ_TYPE ) && ( ( Type )r->object )->body &&
|
||||
TYPEis_enumeration( ( Type )r->object ) ) {
|
||||
RENAMEresolve_enum( ( Type )r->object, schema );
|
||||
@@ -771,12 +840,16 @@ void EXPRESSresolve( Express model ) {
|
||||
}
|
||||
|
||||
/* mark everything resolved if possible */
|
||||
DICTdo_init( model->symbol_table, &de );
|
||||
while( 0 != ( schema = ( Schema )DICTdo( &de ) ) ) {
|
||||
#if 0
|
||||
HASHdo_init( model->symbol_table, &it, '*' );
|
||||
while( (ep = HASHdo( &it ) ) ) {
|
||||
schema = it->data;
|
||||
|
||||
if( is_resolvable( schema ) ) {
|
||||
resolved_all( schema );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Function funcdef(char *name, int pcount, Type ret_typ) {
|
||||
@@ -786,7 +859,7 @@ Function funcdef(char *name, int pcount, Type ret_typ) {
|
||||
f->u.func->return_type = ret_typ;
|
||||
f->u.func->builtin = true;
|
||||
resolved_all(f);
|
||||
DICTdefine(EXPRESSbuiltins, name, f, 0, OBJ_FUNCTION);
|
||||
HASHsearch(EXPRESSbuiltins, (Symbol) {.name = name, .data = f, .type = OBJ_FUNCTION}, HASH_INSERT);
|
||||
return f;
|
||||
}
|
||||
|
||||
@@ -796,11 +869,11 @@ void procdef(char *name, int pcount) {
|
||||
p->u.proc->pcount = pcount;
|
||||
p->u.proc->builtin = true;
|
||||
resolved_all(p);
|
||||
DICTdefine(EXPRESSbuiltins, name, p, 0, OBJ_PROCEDURE);
|
||||
HASHsearch(EXPRESSbuiltins, (Symbol) {.name = name, .data = p, .type = OBJ_PROCEDURE}, HASH_INSERT);
|
||||
}
|
||||
|
||||
void BUILTINSinitialize() {
|
||||
EXPRESSbuiltins = DICTcreate( 35 );
|
||||
EXPRESSbuiltins = HASHcreate();
|
||||
procdef("INSERT", 3 );
|
||||
procdef("REMOVE", 2 );
|
||||
|
||||
|
||||
+823
-314
File diff suppressed because it is too large
Load Diff
+16
-17
@@ -2,7 +2,7 @@
|
||||
#include "express/type.h"
|
||||
#include "express/expr.h"
|
||||
|
||||
#include "express/dict.h"
|
||||
#include "symbol_impl.h"
|
||||
|
||||
/* TODO: use enum? */
|
||||
Type Type_Bad;
|
||||
@@ -137,14 +137,14 @@ void FACTORYinitialize() {
|
||||
/** Create and return an empty scope inside a parent scope. */
|
||||
Scope SCOPEcreate( char type ) {
|
||||
Scope d = SCOPE_new();
|
||||
d->symbol_table = DICTcreate( 50 );
|
||||
d->symbol_table = HASHcreate();
|
||||
d->type = type;
|
||||
return d;
|
||||
}
|
||||
|
||||
Scope SCOPEcreate_tiny( char type ) {
|
||||
Scope d = SCOPE_new();
|
||||
d->symbol_table = DICTcreate( 1 );
|
||||
d->symbol_table = HASHcreate();
|
||||
d->type = type;
|
||||
return d;
|
||||
}
|
||||
@@ -166,7 +166,7 @@ Scope SCOPEcreate_nostab( char type ) {
|
||||
/** Create and return a schema. */
|
||||
Schema SCHEMAcreate( void ) {
|
||||
Scope s = SCOPEcreate( OBJ_SCHEMA );
|
||||
s->enum_table = DICTcreate(50);
|
||||
s->enum_table = HASHcreate();
|
||||
s->u.schema = SCHEMA_new();
|
||||
return s;
|
||||
}
|
||||
@@ -174,13 +174,15 @@ Schema SCHEMAcreate( void ) {
|
||||
/**
|
||||
* create a type with no symbol table
|
||||
*/
|
||||
Type TYPEcreate_nostab( struct Symbol_ *symbol, Scope scope, char objtype ) {
|
||||
Type TYPEcreate_nostab( Symbol *symbol, Scope scope, char objtype ) {
|
||||
Symbol e;
|
||||
Type t = SCOPEcreate_nostab( OBJ_TYPE );
|
||||
TypeHead th = TYPEHEAD_new();
|
||||
|
||||
t->u.type = th;
|
||||
t->symbol = *symbol;
|
||||
DICTdefine( scope->symbol_table, symbol->name, t, &t->symbol, objtype );
|
||||
e = (Symbol) {.name = symbol->name, .data = t, .type = objtype};
|
||||
HASHsearch( scope->symbol_table, e, HASH_INSERT );
|
||||
|
||||
return t;
|
||||
}
|
||||
@@ -212,7 +214,6 @@ Type TYPEcreate_from_body_anonymously( TypeBody tb ) {
|
||||
t->u.type = th;
|
||||
t->u.type->body = tb;
|
||||
t->symbol.name = 0;
|
||||
SYMBOLset( t );
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -222,16 +223,14 @@ TypeBody TYPEBODYcreate( enum type_enum type ) {
|
||||
return tb;
|
||||
}
|
||||
|
||||
Symbol * SYMBOLcreate( char * name, int line, const char * filename ) {
|
||||
Symbol *SYMBOLcreate(char * name, int type, int ref_tok, int line, const char * filename) {
|
||||
Symbol * sym = SYMBOL_new();
|
||||
sym->name = name;
|
||||
sym->type = type;
|
||||
sym->ref_tok = ref_tok;
|
||||
sym->line = line;
|
||||
sym->filename = filename; /* NOTE this used the global 'current_filename',
|
||||
* instead of 'filename'. This func is only
|
||||
* called in two places, and both calls use
|
||||
* 'current_filename'. Changed this to avoid
|
||||
* potential future headaches. (MAP, Jan 12)
|
||||
*/
|
||||
sym->filename = filename;
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
@@ -276,7 +275,6 @@ Variable VARcreate( Expression name, Type type ) {
|
||||
Expression EXPcreate( Type type ) {
|
||||
Expression e;
|
||||
e = EXP_new();
|
||||
SYMBOLset( e );
|
||||
e->type = type;
|
||||
e->return_type = Type_Unknown;
|
||||
return( e );
|
||||
@@ -289,7 +287,6 @@ Expression EXPcreate( Type type ) {
|
||||
Expression EXPcreate_simple( Type type ) {
|
||||
Expression e;
|
||||
e = EXP_new();
|
||||
SYMBOLset( e );
|
||||
e->type = e->return_type = type;
|
||||
return( e );
|
||||
}
|
||||
@@ -366,7 +363,9 @@ Expression QUERYcreate( Symbol * local, Expression aggregate ) {
|
||||
|
||||
Variable v = VARcreate( e2, Type_Attribute );
|
||||
|
||||
DICTdefine( s->symbol_table, local->name, v, &e2->symbol, OBJ_VARIABLE );
|
||||
HASHsearch( s->symbol_table,
|
||||
(Symbol) {.name = local->name, .data = v, .type = OBJ_VARIABLE},
|
||||
HASH_INSERT );
|
||||
e->u.query = QUERY_new();
|
||||
e->u.query->scope = s;
|
||||
e->u.query->local = v;
|
||||
|
||||
+8467
-4096
File diff suppressed because it is too large
Load Diff
+172
-120
@@ -1,120 +1,172 @@
|
||||
#define TOK_EQUAL 1
|
||||
#define TOK_GREATER_EQUAL 2
|
||||
#define TOK_GREATER_THAN 3
|
||||
#define TOK_IN 4
|
||||
#define TOK_INST_EQUAL 5
|
||||
#define TOK_INST_NOT_EQUAL 6
|
||||
#define TOK_LESS_EQUAL 7
|
||||
#define TOK_LESS_THAN 8
|
||||
#define TOK_LIKE 9
|
||||
#define TOK_NOT_EQUAL 10
|
||||
#define TOK_MINUS 11
|
||||
#define TOK_PLUS 12
|
||||
#define TOK_OR 13
|
||||
#define TOK_XOR 14
|
||||
#define TOK_DIV 15
|
||||
#define TOK_MOD 16
|
||||
#define TOK_REAL_DIV 17
|
||||
#define TOK_TIMES 18
|
||||
#define TOK_AND 19
|
||||
#define TOK_ANDOR 20
|
||||
#define TOK_CONCAT_OP 21
|
||||
#define TOK_EXP 22
|
||||
#define TOK_NOT 23
|
||||
#define TOK_DOT 24
|
||||
#define TOK_BACKSLASH 25
|
||||
#define TOK_LEFT_BRACKET 26
|
||||
#define TOK_LEFT_PAREN 27
|
||||
#define TOK_RIGHT_PAREN 28
|
||||
#define TOK_RIGHT_BRACKET 29
|
||||
#define TOK_COLON 30
|
||||
#define TOK_COMMA 31
|
||||
#define TOK_AGGREGATE 32
|
||||
#define TOK_OF 33
|
||||
#define TOK_IDENTIFIER 34
|
||||
#define TOK_ALIAS 35
|
||||
#define TOK_FOR 36
|
||||
#define TOK_END_ALIAS 37
|
||||
#define TOK_ARRAY 38
|
||||
#define TOK_ASSIGNMENT 39
|
||||
#define TOK_BAG 40
|
||||
#define TOK_BOOLEAN 41
|
||||
#define TOK_INTEGER 42
|
||||
#define TOK_REAL 43
|
||||
#define TOK_NUMBER 44
|
||||
#define TOK_LOGICAL 45
|
||||
#define TOK_BINARY 46
|
||||
#define TOK_STRING 47
|
||||
#define TOK_BY 48
|
||||
#define TOK_LEFT_CURL 49
|
||||
#define TOK_RIGHT_CURL 50
|
||||
#define TOK_OTHERWISE 51
|
||||
#define TOK_CASE 52
|
||||
#define TOK_END_CASE 53
|
||||
#define TOK_BEGIN 54
|
||||
#define TOK_END 55
|
||||
#define TOK_PI 56
|
||||
#define TOK_E 57
|
||||
#define TOK_CONSTANT 58
|
||||
#define TOK_END_CONSTANT 59
|
||||
#define TOK_DERIVE 60
|
||||
#define TOK_END_ENTITY 61
|
||||
#define TOK_ENTITY 62
|
||||
#define TOK_ENUMERATION 63
|
||||
#define TOK_ESCAPE 64
|
||||
#define TOK_SELF 65
|
||||
#define TOK_OPTIONAL 66
|
||||
#define TOK_VAR 67
|
||||
#define TOK_END_FUNCTION 68
|
||||
#define TOK_FUNCTION 69
|
||||
#define TOK_BUILTIN_FUNCTION 70
|
||||
#define TOK_LIST 71
|
||||
#define TOK_SET 72
|
||||
#define TOK_GENERIC 73
|
||||
#define TOK_QUESTION_MARK 74
|
||||
#define TOK_IF 75
|
||||
#define TOK_THEN 76
|
||||
#define TOK_END_IF 77
|
||||
#define TOK_ELSE 78
|
||||
#define TOK_INCLUDE 79
|
||||
#define TOK_STRING_LITERAL 80
|
||||
#define TOK_TO 81
|
||||
#define TOK_AS 82
|
||||
#define TOK_REFERENCE 83
|
||||
#define TOK_FROM 84
|
||||
#define TOK_USE 85
|
||||
#define TOK_INVERSE 86
|
||||
#define TOK_INTEGER_LITERAL 87
|
||||
#define TOK_REAL_LITERAL 88
|
||||
#define TOK_STRING_LITERAL_ENCODED 89
|
||||
#define TOK_LOGICAL_LITERAL 90
|
||||
#define TOK_BINARY_LITERAL 91
|
||||
#define TOK_LOCAL 92
|
||||
#define TOK_END_LOCAL 93
|
||||
#define TOK_ONEOF 94
|
||||
#define TOK_UNIQUE 95
|
||||
#define TOK_FIXED 96
|
||||
#define TOK_END_PROCEDURE 97
|
||||
#define TOK_PROCEDURE 98
|
||||
#define TOK_BUILTIN_PROCEDURE 99
|
||||
#define TOK_QUERY 100
|
||||
#define TOK_ALL_IN 101
|
||||
#define TOK_SUCH_THAT 102
|
||||
#define TOK_REPEAT 103
|
||||
#define TOK_END_REPEAT 104
|
||||
#define TOK_RETURN 105
|
||||
#define TOK_END_RULE 106
|
||||
#define TOK_RULE 107
|
||||
#define TOK_END_SCHEMA 108
|
||||
#define TOK_SCHEMA 109
|
||||
#define TOK_SELECT 110
|
||||
#define TOK_SEMICOLON 111
|
||||
#define TOK_SKIP 112
|
||||
#define TOK_SUBTYPE 113
|
||||
#define TOK_ABSTRACT 114
|
||||
#define TOK_SUPERTYPE 115
|
||||
#define TOK_END_TYPE 116
|
||||
#define TOK_TYPE 117
|
||||
#define TOK_UNTIL 118
|
||||
#define TOK_WHERE 119
|
||||
#define TOK_WHILE 120
|
||||
#define T_INVALID 1
|
||||
#define T_DOCROOT 2
|
||||
#define T_RULE_REF 3
|
||||
#define T_RULE_LABEL_REF 4
|
||||
#define T_EQ 5
|
||||
#define T_NEQ 6
|
||||
#define T_LTEQ 7
|
||||
#define T_GTEQ 8
|
||||
#define T_LT 9
|
||||
#define T_GT 10
|
||||
#define T_INST_EQ 11
|
||||
#define T_INST_NEQ 12
|
||||
#define T_IN 13
|
||||
#define T_LIKE 14
|
||||
#define T_PLUS 15
|
||||
#define T_MINUS 16
|
||||
#define T_OR 17
|
||||
#define T_XOR 18
|
||||
#define T_ANDOR 19
|
||||
#define T_TIMES 20
|
||||
#define T_RDIV 21
|
||||
#define T_IDIV 22
|
||||
#define T_MOD 23
|
||||
#define T_AND 24
|
||||
#define T_CONCAT 25
|
||||
#define T_EXP 26
|
||||
#define UNARY_OP 27
|
||||
#define T_LBRKT 28
|
||||
#define T_RBRKT 29
|
||||
#define T_LPAREN 30
|
||||
#define T_RPAREN 31
|
||||
#define T_ONEOF 32
|
||||
#define T_DOT 33
|
||||
#define T_BACKSLASH 34
|
||||
#define T_SIMPLE_ID 35
|
||||
#define T_SCHEMA_REF 36
|
||||
#define T_FUNCTION_REF 37
|
||||
#define T_PROCEDURE_REF 38
|
||||
#define T_TYPE_REF 39
|
||||
#define T_ENTITY_REF 40
|
||||
#define T_PARAMETER_REF 41
|
||||
#define T_VARIABLE_REF 42
|
||||
#define T_CONSTANT_REF 43
|
||||
#define T_ENUMERATION_REF 44
|
||||
#define T_SIMPLE_REF 45
|
||||
#define T_ABSTRACT 46
|
||||
#define T_SUPERTYPE 47
|
||||
#define T_SEMICOLON 48
|
||||
#define T_COMMA 49
|
||||
#define T_AGGREGATE 50
|
||||
#define T_OF 51
|
||||
#define T_COLON 52
|
||||
#define T_ALIAS 53
|
||||
#define T_FOR 54
|
||||
#define T_END_ALIAS 55
|
||||
#define T_ARRAY 56
|
||||
#define T_OPTIONAL 57
|
||||
#define T_UNIQUE 58
|
||||
#define T_ASSIGN 59
|
||||
#define T_BAG 60
|
||||
#define T_BINARY 61
|
||||
#define T_BOOLEAN 62
|
||||
#define T_CONST_E 63
|
||||
#define T_PI 64
|
||||
#define T_SELF 65
|
||||
#define T_QMARK 66
|
||||
#define T_ABS 67
|
||||
#define T_ACOS 68
|
||||
#define T_ASIN 69
|
||||
#define T_ATAN 70
|
||||
#define T_BLENGTH 71
|
||||
#define T_COS 72
|
||||
#define T_EXISTS 73
|
||||
#define T_FORMAT 74
|
||||
#define T_HIBOUND 75
|
||||
#define T_HIINDEX 76
|
||||
#define T_LENGTH 77
|
||||
#define T_LOBOUND 78
|
||||
#define T_LOINDEX 79
|
||||
#define T_LOG 80
|
||||
#define T_LOG2 81
|
||||
#define T_LOG10 82
|
||||
#define T_NVL 83
|
||||
#define T_ODD 84
|
||||
#define T_ROLESOF 85
|
||||
#define T_SIN 86
|
||||
#define T_SIZEOF 87
|
||||
#define T_SQRT 88
|
||||
#define T_TAN 89
|
||||
#define T_TYPEOF 90
|
||||
#define T_USEDIN 91
|
||||
#define T_VALUE 92
|
||||
#define T_VALUE_IN 93
|
||||
#define T_VALUE_UNIQUE 94
|
||||
#define T_INSERT 95
|
||||
#define T_REMOVE 96
|
||||
#define T_OTHERWISE 97
|
||||
#define T_CASE 98
|
||||
#define T_END_CASE 99
|
||||
#define T_BEGIN 100
|
||||
#define T_END 101
|
||||
#define T_CONSTANT 102
|
||||
#define T_END_CONSTANT 103
|
||||
#define T_DERIVE 104
|
||||
#define T_END_ENTITY 105
|
||||
#define T_ENTITY 106
|
||||
#define T_BASED_ON 107
|
||||
#define T_WITH 108
|
||||
#define T_EXTENSIBLE 109
|
||||
#define T_ENUMERATION 110
|
||||
#define T_ESCAPE 111
|
||||
#define T_END_FUNCTION 112
|
||||
#define T_FUNCTION 113
|
||||
#define T_LIST 114
|
||||
#define T_SET 115
|
||||
#define T_GENERIC_ENTITY 116
|
||||
#define T_GENERIC 117
|
||||
#define T_IF 118
|
||||
#define T_THEN 119
|
||||
#define T_ELSE 120
|
||||
#define T_END_IF 121
|
||||
#define T_TO 122
|
||||
#define T_BY 123
|
||||
#define T_INTEGER 124
|
||||
#define T_LCURL 125
|
||||
#define T_RCURL 126
|
||||
#define T_INVERSE 127
|
||||
#define T_BINARY_LITERAL 128
|
||||
#define T_INTEGER_LITERAL 129
|
||||
#define T_REAL_LITERAL 130
|
||||
#define T_LOCAL 131
|
||||
#define T_END_LOCAL 132
|
||||
#define T_FALSE 133
|
||||
#define T_TRUE 134
|
||||
#define T_UNKNOWN 135
|
||||
#define T_LOGICAL 136
|
||||
#define T_AS 137
|
||||
#define T_NUMBER 138
|
||||
#define T_END_PROCEDURE 139
|
||||
#define T_PROCEDURE 140
|
||||
#define T_VAR 141
|
||||
#define T_QUERY 142
|
||||
#define T_ALL_IN 143
|
||||
#define T_PIPE 144
|
||||
#define T_REAL 145
|
||||
#define T_RENAMED 146
|
||||
#define T_REFERENCE 147
|
||||
#define T_FROM 148
|
||||
#define T_REPEAT 149
|
||||
#define T_END_REPEAT 150
|
||||
#define T_RETURN 151
|
||||
#define T_END_RULE 152
|
||||
#define T_RULE 153
|
||||
#define T_SCHEMA 154
|
||||
#define T_END_SCHEMA 155
|
||||
#define T_SELECT 156
|
||||
#define T_NOT 157
|
||||
#define T_SKIP 158
|
||||
#define T_STRING_LITERAL 159
|
||||
#define T_ENCODED_STRING_LITERAL 160
|
||||
#define T_STRING 161
|
||||
#define T_END_SUBTYPE_CONSTRAINT 162
|
||||
#define T_SUBTYPE_CONSTRAINT 163
|
||||
#define T_SUBTYPE 164
|
||||
#define T_TOTAL_OVER 165
|
||||
#define T_TYPE 166
|
||||
#define T_END_TYPE 167
|
||||
#define T_UNTIL 168
|
||||
#define T_USE 169
|
||||
#define T_WHERE 170
|
||||
#define T_WHILE 171
|
||||
#define T_FIXED 172
|
||||
|
||||
+11825
-1696
File diff suppressed because it is too large
Load Diff
@@ -1,100 +1,30 @@
|
||||
#ifndef PERPLEX_H
|
||||
#define PERPLEX_H
|
||||
/* P E R P L E X _ T E M P L A T E . C
|
||||
* BRL-CAD
|
||||
*
|
||||
* Copyright (c) 1990-2011 United States Government as represented by
|
||||
* the U.S. Army Research Laboratory.
|
||||
*
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
/* Parts of this file are based on sources from the flex project.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Vern Paxson.
|
||||
*
|
||||
* The United States Government has rights in this work pursuant
|
||||
* to contract no. DE-AC03-76SF00098 between the United States
|
||||
* Department of Energy and the University of California.
|
||||
*/
|
||||
/** @file perplex_template.c
|
||||
*
|
||||
* template for generated scanners
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
/* Generated by re2c 1.0.3 on Sat Oct 20 22:52:46 2018 */
|
||||
#line 3 "expscan.h"
|
||||
|
||||
#define YYEOF -1
|
||||
|
||||
struct Buf {
|
||||
void *elts; /* elements. */
|
||||
int nelts; /* number of elements. */
|
||||
size_t elt_size; /* in bytes. */
|
||||
int nmax; /* max capacity of elements. */
|
||||
enum YYCONDTYPE {
|
||||
yycP1,
|
||||
yycCOMMENT,
|
||||
yycP2,
|
||||
yycTYPE,
|
||||
yycENUM,
|
||||
yycENTITY,
|
||||
yycARG_LIST,
|
||||
yycRULE,
|
||||
yycQUERY,
|
||||
yycREDECL,
|
||||
yycSTMT,
|
||||
yycINV_FOR_STMT,
|
||||
yycP3,
|
||||
yycSEARCH_SCOPE,
|
||||
yycID_CUR_SCOPE,
|
||||
yycID_LIST,
|
||||
yycENUM_ID_LIST,
|
||||
yycLABEL_OPT,
|
||||
yycENUM_REF,
|
||||
yycENTITY_REF,
|
||||
yycDOT_ATTR,
|
||||
yycCONSTANT,
|
||||
yycLOCAL,
|
||||
yycINV_FOR,
|
||||
yycSUBTYPE_CONS,
|
||||
};
|
||||
|
||||
/* scanner data */
|
||||
typedef struct perplex {
|
||||
void *extra; /* application data */
|
||||
FILE *inFile;
|
||||
struct Buf *buffer;
|
||||
char *tokenText;
|
||||
char *tokenStart;
|
||||
char *cursor;
|
||||
char *marker;
|
||||
char *null;
|
||||
int atEOI;
|
||||
int condition;
|
||||
} *perplex_t;
|
||||
|
||||
perplex_t perplexFileScanner(FILE *input);
|
||||
perplex_t perplexStringScanner(char *firstChar, size_t numChars);
|
||||
void perplexFree(perplex_t scanner);
|
||||
|
||||
void perplexUnput(perplex_t scanner, char c);
|
||||
void perplexSetExtra(perplex_t scanner, void *extra);
|
||||
void* perplexGetExtra(perplex_t scanner);
|
||||
|
||||
#ifndef PERPLEX_LEXER
|
||||
#define PERPLEX_LEXER yylex
|
||||
#endif
|
||||
|
||||
#define PERPLEX_PUBLIC_LEXER PERPLEX_LEXER(perplex_t scanner)
|
||||
#define PERPLEX_PRIVATE_LEXER PERPLEX_LEXER_private(perplex_t scanner)
|
||||
|
||||
#ifndef PERPLEX_ON_ENTER
|
||||
#define PERPLEX_ON_ENTER /* do nothing */
|
||||
#endif
|
||||
|
||||
int PERPLEX_PUBLIC_LEXER;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Autogenerated verification information
|
||||
set(baseline_expscan_l_md5 c86358d3e57ce6916c28a63262fad6e6)
|
||||
set(baseline_expparse_y_md5 3722242f16c679c40323317833757a6d)
|
||||
set(baseline_expscan_c_md5 b6b239869e4c7d169107fe45f760ffa0)
|
||||
set(baseline_expscan_h_md5 3052c058a37045b43f96e4c04039bce3)
|
||||
set(baseline_expparse_c_md5 c170b5e39b5fe56e2c39288fbe2b48a1)
|
||||
set(baseline_expparse_h_md5 e4a5599839b2a9f7a6915a0dcc7747b0)
|
||||
set(baseline_expscan_l_md5 983e80b9716781e77bf9d6d90d2eed0b)
|
||||
set(baseline_expparse_y_md5 1fbdffbb42b05c89fbe1e3e5081880cb)
|
||||
set(baseline_expscan_c_md5 72cddc621499c41fa06662d2663d9cee)
|
||||
set(baseline_expscan_h_md5 24a4cb429db89b70ea094f4dd664206b)
|
||||
set(baseline_expparse_c_md5 b72e8df2237184faf6b593204041f2f0)
|
||||
set(baseline_expparse_h_md5 5cdae8aec1c3e7cdaf238e436bbd43b9)
|
||||
|
||||
@@ -1,229 +1,2 @@
|
||||
expparse.y:2
|
||||
expparse.y:124
|
||||
expparse.y:2440
|
||||
expparse.y:297
|
||||
expparse.y:303
|
||||
expparse.y:320
|
||||
expparse.y:337
|
||||
expparse.y:341
|
||||
expparse.y:347
|
||||
expparse.y:353
|
||||
expparse.y:359
|
||||
expparse.y:364
|
||||
expparse.y:369
|
||||
expparse.y:379
|
||||
expparse.y:387
|
||||
expparse.y:397
|
||||
expparse.y:411
|
||||
expparse.y:423
|
||||
expparse.y:442
|
||||
expparse.y:456
|
||||
expparse.y:463
|
||||
expparse.y:475
|
||||
expparse.y:486
|
||||
expparse.y:491
|
||||
expparse.y:501
|
||||
expparse.y:506
|
||||
expparse.y:510
|
||||
expparse.y:516
|
||||
expparse.y:523
|
||||
expparse.y:529
|
||||
expparse.y:533
|
||||
expparse.y:538
|
||||
expparse.y:543
|
||||
expparse.y:547
|
||||
expparse.y:551
|
||||
expparse.y:557
|
||||
expparse.y:583
|
||||
expparse.y:593
|
||||
expparse.y:599
|
||||
expparse.y:609
|
||||
expparse.y:618
|
||||
expparse.y:628
|
||||
expparse.y:634
|
||||
expparse.y:642
|
||||
expparse.y:646
|
||||
expparse.y:653
|
||||
expparse.y:658
|
||||
expparse.y:663
|
||||
expparse.y:668
|
||||
expparse.y:675
|
||||
expparse.y:694
|
||||
expparse.y:726
|
||||
expparse.y:733
|
||||
expparse.y:738
|
||||
expparse.y:745
|
||||
expparse.y:760
|
||||
expparse.y:775
|
||||
expparse.y:786
|
||||
expparse.y:819
|
||||
expparse.y:834
|
||||
expparse.y:841
|
||||
expparse.y:855
|
||||
expparse.y:862
|
||||
expparse.y:868
|
||||
expparse.y:872
|
||||
expparse.y:878
|
||||
expparse.y:907
|
||||
expparse.y:913
|
||||
expparse.y:919
|
||||
expparse.y:925
|
||||
expparse.y:931
|
||||
expparse.y:937
|
||||
expparse.y:943
|
||||
expparse.y:949
|
||||
expparse.y:955
|
||||
expparse.y:961
|
||||
expparse.y:967
|
||||
expparse.y:973
|
||||
expparse.y:979
|
||||
expparse.y:985
|
||||
expparse.y:995
|
||||
expparse.y:1001
|
||||
expparse.y:1007
|
||||
expparse.y:1013
|
||||
expparse.y:1019
|
||||
expparse.y:1025
|
||||
expparse.y:1031
|
||||
expparse.y:1037
|
||||
expparse.y:1055
|
||||
expparse.y:1059
|
||||
expparse.y:1064
|
||||
expparse.y:1087
|
||||
expparse.y:1092
|
||||
expparse.y:1098
|
||||
expparse.y:1104
|
||||
expparse.y:1129
|
||||
expparse.y:1138
|
||||
expparse.y:1146
|
||||
expparse.y:1154
|
||||
expparse.y:1159
|
||||
expparse.y:1169
|
||||
expparse.y:1178
|
||||
expparse.y:1182
|
||||
expparse.y:1188
|
||||
expparse.y:1194
|
||||
expparse.y:1202
|
||||
expparse.y:1211
|
||||
expparse.y:1224
|
||||
expparse.y:1232
|
||||
expparse.y:1240
|
||||
expparse.y:1245
|
||||
expparse.y:1253
|
||||
expparse.y:1265
|
||||
expparse.y:1278
|
||||
expparse.y:1284
|
||||
expparse.y:1292
|
||||
expparse.y:1296
|
||||
expparse.y:1300
|
||||
expparse.y:1308
|
||||
expparse.y:1313
|
||||
expparse.y:1318
|
||||
expparse.y:1324
|
||||
expparse.y:1342
|
||||
expparse.y:1346
|
||||
expparse.y:1355
|
||||
expparse.y:1365
|
||||
expparse.y:1378
|
||||
expparse.y:1384
|
||||
expparse.y:1397
|
||||
expparse.y:1420
|
||||
expparse.y:1432
|
||||
expparse.y:1437
|
||||
expparse.y:1444
|
||||
expparse.y:1452
|
||||
expparse.y:1460
|
||||
expparse.y:1487
|
||||
expparse.y:1521
|
||||
expparse.y:1529
|
||||
expparse.y:1536
|
||||
expparse.y:1548
|
||||
expparse.y:1565
|
||||
expparse.y:1571
|
||||
expparse.y:1577
|
||||
expparse.y:1583
|
||||
expparse.y:1599
|
||||
expparse.y:1616
|
||||
expparse.y:1640
|
||||
expparse.y:1646
|
||||
expparse.y:1651
|
||||
expparse.y:1658
|
||||
expparse.y:1664
|
||||
expparse.y:1681
|
||||
expparse.y:1686
|
||||
expparse.y:1691
|
||||
expparse.y:1696
|
||||
expparse.y:1707
|
||||
expparse.y:1711
|
||||
expparse.y:1716
|
||||
expparse.y:1720
|
||||
expparse.y:1730
|
||||
expparse.y:1735
|
||||
expparse.y:1742
|
||||
expparse.y:1750
|
||||
expparse.y:1760
|
||||
expparse.y:1786
|
||||
expparse.y:1794
|
||||
expparse.y:1801
|
||||
expparse.y:1810
|
||||
expparse.y:1819
|
||||
expparse.y:1827
|
||||
expparse.y:1835
|
||||
expparse.y:1842
|
||||
expparse.y:1846
|
||||
expparse.y:1850
|
||||
expparse.y:1854
|
||||
expparse.y:1858
|
||||
expparse.y:1862
|
||||
expparse.y:1866
|
||||
expparse.y:1870
|
||||
expparse.y:1878
|
||||
expparse.y:1886
|
||||
expparse.y:1891
|
||||
expparse.y:1896
|
||||
expparse.y:1907
|
||||
expparse.y:1915
|
||||
expparse.y:1936
|
||||
expparse.y:1942
|
||||
expparse.y:1949
|
||||
expparse.y:1957
|
||||
expparse.y:1984
|
||||
expparse.y:1993
|
||||
expparse.y:2012
|
||||
expparse.y:2023
|
||||
expparse.y:2036
|
||||
expparse.y:2041
|
||||
expparse.y:2090
|
||||
expparse.y:2100
|
||||
expparse.y:2106
|
||||
expparse.y:2112
|
||||
expparse.y:2118
|
||||
expparse.y:2131
|
||||
expparse.y:2137
|
||||
expparse.y:2143
|
||||
expparse.y:2149
|
||||
expparse.y:2153
|
||||
expparse.y:2158
|
||||
expparse.y:2169
|
||||
expparse.y:2175
|
||||
expparse.y:2180
|
||||
expparse.y:2185
|
||||
expparse.y:2190
|
||||
expparse.y:2215
|
||||
expparse.y:2223
|
||||
expparse.y:2234
|
||||
expparse.y:2241
|
||||
expparse.y:2284
|
||||
expparse.y:2292
|
||||
expparse.y:2297
|
||||
expparse.y:2301
|
||||
expparse.y:2328
|
||||
expparse.y:2334
|
||||
expparse.y:2341
|
||||
expparse.y:2347
|
||||
expparse.y:2362
|
||||
expparse.y:2371
|
||||
expparse.y:2377
|
||||
expparse.y:2391
|
||||
expparse.y:2396
|
||||
expparse.y:2424
|
||||
expparse.y:159
|
||||
expparse.y:814
|
||||
|
||||
+410
-506
@@ -1,491 +1,144 @@
|
||||
|
||||
|
||||
/*
|
||||
* Dynamic hashing, after CACM April 1988 pp 446-457, by Per-Ake Larson.
|
||||
* https://cacm.acm.org/magazines/1988/4/9970-dynamic-hash-tables/abstract
|
||||
*
|
||||
* Coded into C, with minor code improvements, and with hsearch(3) interface,
|
||||
* by ejp@ausmelb.oz, Jul 26, 1988: 13:16;
|
||||
* also, hcreate/hdestroy routines added to simulate hsearch(3).
|
||||
*
|
||||
* move to local hash table, cleanup abstraction and storage allocation;
|
||||
* convert to ANSII C.
|
||||
* by snc (clark@cme.nbs.gov), 10-Mar-1989
|
||||
*
|
||||
* these routines simulate hsearch(3) and family, with the important
|
||||
* difference that the hash table is dynamic - can grow indefinitely
|
||||
* beyond its original size (as supplied to hcreate()).
|
||||
*
|
||||
* Performance appears to be comparable to that of hsearch(3).
|
||||
* The 'source-code' options referred to in hsearch(3)'s 'man' page
|
||||
* are not implemented; otherwise functionality is identical.
|
||||
*
|
||||
* Compilation controls:
|
||||
* HASH_DEBUG controls some informative traces, mainly for debugging.
|
||||
* HASH_STATISTICS causes HashAccesses and HashCollisions to be maintained;
|
||||
* when combined with HASH_DEBUG, these are displayed by hdestroy().
|
||||
*
|
||||
* Problems & fixes to ejp@ausmelb.oz. WARNING: relies on pre-processor
|
||||
* concatenation property, in probably unnecessary code 'optimisation'.
|
||||
*
|
||||
* snc: fixed concatenation for ANSII C, 10-Mar-1989
|
||||
*
|
||||
* $Log: hash.c,v $
|
||||
* Revision 1.8 1997/10/22 16:36:49 sauderd
|
||||
* Changed the use and definitions of the compiler macros MUL and DIV. They
|
||||
* seem to be defined and used only within hash.h and hash.c
|
||||
*
|
||||
* Revision 1.7 1997/01/21 19:19:51 dar
|
||||
* made C++ compatible
|
||||
*
|
||||
* Revision 1.6 1994/03/23 20:06:51 libes
|
||||
* botched free in hash destroy
|
||||
*
|
||||
* Revision 1.5 1993/10/15 18:49:55 libes
|
||||
* CADDETC certified
|
||||
*
|
||||
* Revision 1.4 1992/08/18 18:27:10 libes
|
||||
* changed DEBUG to HASH_DEBUG
|
||||
*
|
||||
* Revision 1.3 1992/08/18 17:16:22 libes
|
||||
* rm'd extraneous error messages
|
||||
*
|
||||
* Revision 1.2 1992/05/31 08:37:18 libes
|
||||
* multiple files
|
||||
*
|
||||
* Revision 1.1 1992/05/28 03:56:55 libes
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.4 1992/05/14 10:15:04 libes
|
||||
* don't remember
|
||||
*
|
||||
* Revision 1.3 1992/02/12 07:06:49 libes
|
||||
* y
|
||||
* y
|
||||
* do sub/supertype
|
||||
*
|
||||
* Revision 1.2 1992/02/09 00:51:02 libes
|
||||
* does ref/use correctly
|
||||
*
|
||||
* Revision 1.1 1992/02/05 08:34:24 libes
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.0.1.1 1992/01/22 02:40:04 libes
|
||||
* copied from ~pdes
|
||||
*
|
||||
* Revision 1.9 1992/01/22 02:26:58 libes
|
||||
* added code to test hash package
|
||||
*
|
||||
* Revision 1.8 1991/09/17 02:53:23 libes
|
||||
* fixed bug in HASHcopy (new hash tables were coming out empty)
|
||||
*
|
||||
* Revision 1.7 1991/08/30 16:34:36 libes
|
||||
* fixed HASHlist to use state from parameter instead of static
|
||||
*
|
||||
* Revision 1.6 1991/08/13 22:19:39 libes
|
||||
* forgot to declare s, s2, pp, and q. Oops.
|
||||
*
|
||||
* Revision 1.5 1991/08/06 19:03:07 libes
|
||||
* fixed bugs relating to my previous addition (delete function)
|
||||
* added HASHcopy to support DICT_copy via OBJcopy
|
||||
*
|
||||
* Revision 1.4 1991/07/19 03:57:46 libes
|
||||
* added action HASH_DELETE
|
||||
* made action HASH_INSERT return failure upon duplicate entry
|
||||
*
|
||||
* Revision 1.3 1991/02/26 19:40:45 libes
|
||||
* Added functions for visiting every member of the hash table, to duplicate
|
||||
* similar functionality of linked lists. Note that current implementation
|
||||
* can only walk through one hash table at a time. This can be improved, but
|
||||
* the application code doesn't currently need such a feature.
|
||||
*
|
||||
* Revision 1.2 1990/09/06 11:06:56 clark
|
||||
* BPR 2.1 alpha
|
||||
*
|
||||
* Revision 1.1 90/06/11 16:44:43 clark
|
||||
* Initial revision
|
||||
*
|
||||
* ~50% rewritten by Chris Horler for STEPcode
|
||||
*
|
||||
* Specific implementation points (based on empirical data)
|
||||
*
|
||||
* - the maximum SCHEMA symbol table is probably about 4-6k entries
|
||||
* - the typical symbol table is (only!) between 8 and 64 entries
|
||||
* - there's no extended growth behaviour of symbol tables
|
||||
* - ...
|
||||
*
|
||||
* REMARK: This approach is probably overly complex for such a small data set
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef HASH_DEBUG
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#include "bstrlib.h"
|
||||
#include "sc_memmgr.h"
|
||||
|
||||
#include "express/hash.h"
|
||||
#include "hash_impl.h"
|
||||
#include "symbol_impl.h"
|
||||
|
||||
/*
|
||||
** Internal routines
|
||||
*/
|
||||
#define SEGMENT_SZ 32 /* deliberately small segment size! */
|
||||
#define SEGMENT_WIDTH 5 /* log2(SEGMENT_SZ) */
|
||||
#define LOAD_FACTOR 1 /* ensures minimum collisions, maximum size */
|
||||
#define PRIME1 37
|
||||
#define PRIME2 1048583
|
||||
|
||||
static inline Address HASHhash( char *, Hash_Table );
|
||||
static void HASHexpand_table( Hash_Table );
|
||||
extern inline struct Symbol_ *SYMBOL_new();
|
||||
extern inline void SYMBOL_destroy(struct Symbol_ *x);
|
||||
|
||||
/*
|
||||
** Local data
|
||||
*/
|
||||
Hash_Table
|
||||
HASH_Table_new() {
|
||||
return ALLOC_new(&HASH_Table_fl);
|
||||
}
|
||||
|
||||
# ifdef HASH_STATISTICS
|
||||
static long HashAccesses, HashCollisions;
|
||||
# endif
|
||||
|
||||
/*
|
||||
** Code
|
||||
*/
|
||||
void
|
||||
HASH_Table_destroy(Hash_Table x) {
|
||||
ALLOC_destroy(&HASH_Table_fl,(Freelist *)x);
|
||||
}
|
||||
|
||||
void
|
||||
HASHinitialize() {
|
||||
}
|
||||
|
||||
Hash_Table
|
||||
HASHcreate( unsigned count ) {
|
||||
unsigned i;
|
||||
Hash_Table table;
|
||||
HASHcreate()
|
||||
{
|
||||
Hash_Table tbl;
|
||||
unsigned int i;
|
||||
|
||||
tbl = HASH_Table_new();
|
||||
|
||||
/*
|
||||
** Adjust Count to be nearest higher power of 2,
|
||||
** minimum SEGMENT_SIZE, then convert into segments.
|
||||
*/
|
||||
i = SEGMENT_SIZE;
|
||||
while( i < count ) {
|
||||
i <<= 1;
|
||||
/* default to minimum size */
|
||||
tbl->maxp = SEGMENT_SZ;
|
||||
tbl->DirectorySize = tbl->maxp >> SEGMENT_WIDTH;
|
||||
|
||||
/* allocate segments */
|
||||
tbl->Directory = sc_calloc(sizeof(Segment *), tbl->DirectorySize);
|
||||
if (tbl->Directory == NULL) {
|
||||
HASHdestroy(tbl);
|
||||
return NULL;
|
||||
}
|
||||
count = DIV( i, SEGMENT_SIZE_SHIFT );
|
||||
|
||||
table = HASH_Table_new();
|
||||
#if 0
|
||||
table->in_use = 0;
|
||||
#endif
|
||||
table->SegmentCount = table->p = table->KeyCount = 0;
|
||||
/*
|
||||
** Allocate initial 'i' segments of buckets
|
||||
*/
|
||||
for( i = 0; i < count; i++ )
|
||||
CALLOC( table->Directory[i], SEGMENT_SIZE, Element )
|
||||
/*, "segment in HASHcreate");*/
|
||||
|
||||
table->SegmentCount = count;
|
||||
table->maxp = MUL( count, SEGMENT_SIZE_SHIFT );
|
||||
table->MinLoadFactor = 1;
|
||||
table->MaxLoadFactor = MAX_LOAD_FACTOR;
|
||||
# ifdef HASH_DEBUG
|
||||
fprintf( stderr,
|
||||
"[HASHcreate] table %x count %d maxp %d SegmentCount %d\n",
|
||||
table,
|
||||
count,
|
||||
table->maxp,
|
||||
table->SegmentCount );
|
||||
# endif
|
||||
# ifdef HASH_STATISTICS
|
||||
HashAccesses = HashCollisions = 0;
|
||||
# endif
|
||||
return( table );
|
||||
}
|
||||
|
||||
/* initialize pointer to beginning of hash table so we can step through it */
|
||||
/* on repeated calls to HASHlist - DEL */
|
||||
void
|
||||
HASHlistinit( Hash_Table table, HashEntry * he ) {
|
||||
he->i = he->j = 0;
|
||||
he->p = 0;
|
||||
he->table = table;
|
||||
he->type = '*';
|
||||
#if 0
|
||||
table->in_use = 1;
|
||||
/* Allocate initial buckets */
|
||||
for (i = 0; i < tbl->DirectorySize; i++) {
|
||||
tbl->Directory[i] = sc_calloc(sizeof(Segment), SEGMENT_SZ);
|
||||
if (tbl->Directory[i] == NULL) {
|
||||
HASHdestroy(tbl);
|
||||
return NULL;
|
||||
}
|
||||
tbl->SegmentCount++;
|
||||
}
|
||||
|
||||
#ifdef HASH_DEBUG
|
||||
fprintf(stderr, "[hcreate] Table %p Count %u maxp %u SegmentCount %u\n",
|
||||
tbl, tbl->KeyCount, tbl->maxp, tbl->SegmentCount);
|
||||
#endif
|
||||
return tbl;
|
||||
}
|
||||
|
||||
void
|
||||
HASHlistinit_by_type( Hash_Table table, HashEntry * he, char type ) {
|
||||
he->i = he->j = 0;
|
||||
he->p = 0;
|
||||
he->table = table;
|
||||
he->type = type;
|
||||
#if 0
|
||||
table->in_use = 1;
|
||||
HASHdestroy(Hash_Table tbl)
|
||||
{
|
||||
unsigned int i, j;
|
||||
#ifdef HASH_DEBUG
|
||||
float n, r;
|
||||
#endif
|
||||
}
|
||||
Segment s;
|
||||
Symbol *p,*q;
|
||||
|
||||
#if 0
|
||||
/* if you don't step to the end, you can clear the flag this way */
|
||||
void
|
||||
HASHlistend( HashEntry * he ) {
|
||||
he->table->in_use = 0;
|
||||
}
|
||||
#endif
|
||||
assert(tbl != NULL);
|
||||
|
||||
/* provide a way to step through the hash */
|
||||
Element
|
||||
HASHlist( HashEntry * he ) {
|
||||
int i2 = he->i;
|
||||
int j2 = he->j;
|
||||
Segment s;
|
||||
|
||||
he->e = 0;
|
||||
|
||||
for( he->i = i2; he->i < he->table->SegmentCount; he->i++ ) {
|
||||
/* test probably unnecessary */
|
||||
if( ( s = he->table->Directory[he->i] ) != NULL ) {
|
||||
for( he->j = j2; he->j < SEGMENT_SIZE; he->j++ ) {
|
||||
if( !he->p ) {
|
||||
he->p = s[he->j];
|
||||
}
|
||||
|
||||
/* if he->p is defined, prepare to return it (by
|
||||
setting it to he->e) and begin looking for a new value
|
||||
for he->p
|
||||
*/
|
||||
retry:
|
||||
if( he->p ) {
|
||||
if( ( he->type != '*' ) &&
|
||||
( he->type != he->p->type ) ) {
|
||||
he->p = he->p->next;
|
||||
goto retry;
|
||||
}
|
||||
if( he->e ) {
|
||||
return( he->e );
|
||||
}
|
||||
he->e = he->p;
|
||||
he->p = he->p->next;
|
||||
}
|
||||
|
||||
/* avoid incrementing he->j by returning here */
|
||||
if( he->p ) {
|
||||
return( he->e );
|
||||
}
|
||||
}
|
||||
j2 = 0;
|
||||
}
|
||||
}
|
||||
/* if he->e was set then it is last one */
|
||||
#if 0
|
||||
he->table->in_use = 0;
|
||||
#endif
|
||||
return( he->e );
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* this verifies no one else is walking through the table that we might screw up */
|
||||
/* it should be called before adding, deleting or destroying a table */
|
||||
HASH_in_use( Hash_Table table, char * action ) {
|
||||
fprintf( stderr, "HASH: attempted to %s but hash table in use\n", action );
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
HASHdestroy( Hash_Table table ) {
|
||||
Segment s;
|
||||
Element p, q;
|
||||
|
||||
if( table != HASH_NULL ) {
|
||||
unsigned int i, j;
|
||||
#if 0
|
||||
if( table->in_use ) {
|
||||
HASH_in_use( table, "destroy hash table" );
|
||||
}
|
||||
#endif
|
||||
for( i = 0; i < table->SegmentCount; i++ ) {
|
||||
/* test probably unnecessary */
|
||||
if( ( s = table->Directory[i] ) != NULL ) {
|
||||
for( j = 0; j < SEGMENT_SIZE; j++ ) {
|
||||
p = s[j];
|
||||
while( p != NULL ) {
|
||||
q = p->next;
|
||||
HASH_Element_destroy( p );
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
sc_free( table->Directory[i] );
|
||||
for (i = 0; i < tbl->SegmentCount; i++) {
|
||||
s = tbl->Directory[i];
|
||||
assert(s != NULL);
|
||||
|
||||
for (j = 0; j < SEGMENT_SZ; j++) {
|
||||
p = s[j];
|
||||
while (p != NULL) {
|
||||
q = p->next;
|
||||
sc_free(p);
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
HASH_Table_destroy( table );
|
||||
# if defined(HASH_STATISTICS) && defined(HASH_DEBUG)
|
||||
fprintf( stderr,
|
||||
"[hdestroy] Accesses %ld Collisions %ld\n",
|
||||
HashAccesses,
|
||||
HashCollisions );
|
||||
# endif
|
||||
sc_free(s);
|
||||
}
|
||||
}
|
||||
|
||||
Element
|
||||
HASHsearch( Hash_Table table, Element item, Action action ) {
|
||||
Address h;
|
||||
Segment CurrentSegment;
|
||||
int SegmentIndex;
|
||||
int SegmentDir;
|
||||
Segment p;
|
||||
Element q;
|
||||
Element deleteme;
|
||||
|
||||
assert( table != HASH_NULL ); /* Kinder really than return(NULL); */
|
||||
# ifdef HASH_STATISTICS
|
||||
HashAccesses++;
|
||||
# endif
|
||||
h = HASHhash( item->key, table );
|
||||
SegmentDir = DIV( h, SEGMENT_SIZE_SHIFT );
|
||||
SegmentIndex = MOD( h, SEGMENT_SIZE );
|
||||
/*
|
||||
** valid segment ensured by HASHhash()
|
||||
*/
|
||||
CurrentSegment = table->Directory[SegmentDir];
|
||||
assert( CurrentSegment != NULL ); /* bad failure if tripped */
|
||||
p = CurrentSegment + SegmentIndex;
|
||||
q = *p;
|
||||
/*
|
||||
** Follow collision chain
|
||||
** Now and after we finish this loop
|
||||
** p = &element, and
|
||||
** q = element
|
||||
*/
|
||||
while( q != NULL && strcmp( q->key, item->key ) ) {
|
||||
p = &q->next;
|
||||
q = *p;
|
||||
# ifdef HASH_STATISTICS
|
||||
HashCollisions++;
|
||||
# endif
|
||||
}
|
||||
/* at this point, we have either found the element or it doesn't exist */
|
||||
switch( action ) {
|
||||
case HASH_FIND:
|
||||
return( ( Element )q );
|
||||
case HASH_DELETE:
|
||||
if( !q ) {
|
||||
return( 0 );
|
||||
}
|
||||
/* at this point, element exists and action == DELETE */
|
||||
#if 0
|
||||
if( table->in_use ) {
|
||||
HASH_in_use( table, "insert element" );
|
||||
}
|
||||
|
||||
sc_free(tbl->Directory);
|
||||
|
||||
#ifdef HASH_DEBUG
|
||||
r = tbl->KeyCount;
|
||||
n = tbl->SegmentCount << SEGMENT_WIDTH;
|
||||
|
||||
fprintf(
|
||||
stderr,
|
||||
"[hdestroy] Count %u HashSize: %u Collisions %u ExpectedCollisions: %.2f\n",
|
||||
tbl->KeyCount,
|
||||
tbl->SegmentCount << SEGMENT_WIDTH,
|
||||
tbl->HashCollisions,
|
||||
((r - n) + n * powf((n - 1) / n, r))
|
||||
);
|
||||
#endif
|
||||
deleteme = q;
|
||||
*p = q->next;
|
||||
/*STRINGfree(deleteme->key);*/
|
||||
HASH_Element_destroy( deleteme );
|
||||
--table->KeyCount;
|
||||
return( deleteme ); /* of course, user shouldn't deref this! */
|
||||
case HASH_INSERT:
|
||||
/* if trying to insert it (twice), let them know */
|
||||
if( q != NULL ) {
|
||||
return( q ); /* was return(0);!!!!!?!?! */
|
||||
}
|
||||
|
||||
#if 0
|
||||
if( table->in_use ) {
|
||||
HASH_in_use( table, "delete element" );
|
||||
}
|
||||
#endif
|
||||
/* at this point, element does not exist and action == INSERT */
|
||||
q = HASH_Element_new();
|
||||
*p = q; /* link into chain */
|
||||
/*
|
||||
** Initialize new element
|
||||
*/
|
||||
/* I don't see the point of copying the key!!!! */
|
||||
/* q->key = STRINGcopy(item->key);*/
|
||||
q->key = item->key;
|
||||
q->data = item->data;
|
||||
q->symbol = item->symbol;
|
||||
q->type = item->type;
|
||||
q->next = NULL;
|
||||
/*
|
||||
** table over-full?
|
||||
*/
|
||||
if( ++table->KeyCount / MUL( table->SegmentCount, SEGMENT_SIZE_SHIFT ) > table->MaxLoadFactor ) {
|
||||
HASHexpand_table( table ); /* doesn't affect q */
|
||||
}
|
||||
}
|
||||
return( ( Element )0 ); /* was return (Element)q */
|
||||
}
|
||||
|
||||
/*
|
||||
** Internal routines
|
||||
*/
|
||||
|
||||
static inline Address HASHhash( char * Key, Hash_Table table ) {
|
||||
Address h, address;
|
||||
register unsigned char * k = ( unsigned char * )Key;
|
||||
|
||||
h = 0;
|
||||
/*
|
||||
** Convert string to integer
|
||||
*/
|
||||
/*SUPPRESS 112*/
|
||||
assert( Key );
|
||||
while( *k )
|
||||
/*SUPPRESS 8*/ { /*SUPPRESS 112*/
|
||||
h = h * PRIME1 ^ ( *k++ - ' ' );
|
||||
}
|
||||
h %= PRIME2;
|
||||
address = MOD( h, table->maxp );
|
||||
if( address < table->p ) {
|
||||
address = MOD( h, ( table->maxp << 1 ) ); /* h % (2*table->maxp) */
|
||||
}
|
||||
return( address );
|
||||
}
|
||||
|
||||
static void HASHexpand_table( Hash_Table table ) {
|
||||
Segment OldSegment, NewSegment;
|
||||
Element Current, *Previous, *LastOfNew;
|
||||
|
||||
if( table->maxp + table->p < MUL( DIRECTORY_SIZE, SEGMENT_SIZE_SHIFT ) ) {
|
||||
Address NewAddress;
|
||||
int OldSegmentIndex, NewSegmentIndex;
|
||||
int OldSegmentDir, NewSegmentDir;
|
||||
/*
|
||||
** Locate the bucket to be split
|
||||
*/
|
||||
OldSegmentDir = DIV( table->p, SEGMENT_SIZE_SHIFT );
|
||||
OldSegment = table->Directory[OldSegmentDir];
|
||||
OldSegmentIndex = MOD( table->p, SEGMENT_SIZE );
|
||||
/*
|
||||
** Expand address space; if necessary create a new segment
|
||||
*/
|
||||
NewAddress = table->maxp + table->p;
|
||||
NewSegmentDir = DIV( NewAddress, SEGMENT_SIZE_SHIFT );
|
||||
NewSegmentIndex = MOD( NewAddress, SEGMENT_SIZE );
|
||||
if( NewSegmentIndex == 0 ) {
|
||||
CALLOC( table->Directory[NewSegmentDir], SEGMENT_SIZE, Element );
|
||||
}
|
||||
/* "segment in HASHexpand_table");*/
|
||||
NewSegment = table->Directory[NewSegmentDir];
|
||||
/*
|
||||
** Adjust state variables
|
||||
*/
|
||||
table->p++;
|
||||
if( table->p == table->maxp ) {
|
||||
table->maxp <<= 1; /* table->maxp *= 2 */
|
||||
table->p = 0;
|
||||
}
|
||||
table->SegmentCount++;
|
||||
/*
|
||||
** Relocate records to the new bucket
|
||||
*/
|
||||
Previous = &OldSegment[OldSegmentIndex];
|
||||
Current = *Previous;
|
||||
LastOfNew = &NewSegment[NewSegmentIndex];
|
||||
*LastOfNew = NULL;
|
||||
while( Current != NULL ) {
|
||||
if( HASHhash( Current->key, table ) == NewAddress ) {
|
||||
/*
|
||||
** Attach it to the end of the new chain
|
||||
*/
|
||||
*LastOfNew = Current;
|
||||
/*
|
||||
** Remove it from old chain
|
||||
*/
|
||||
*Previous = Current->next;
|
||||
LastOfNew = &Current->next;
|
||||
Current = Current->next;
|
||||
*LastOfNew = NULL;
|
||||
} else {
|
||||
/*
|
||||
** leave it on the old chain
|
||||
*/
|
||||
Previous = &Current->next;
|
||||
Current = Current->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HASH_Table_destroy(tbl);
|
||||
}
|
||||
|
||||
/* make a complete copy of a hash table */
|
||||
@@ -495,72 +148,323 @@ static void HASHexpand_table( Hash_Table table ) {
|
||||
Hash_Table
|
||||
HASHcopy( Hash_Table oldtable ) {
|
||||
Hash_Table newtable;
|
||||
Segment s, s2;
|
||||
Element * pp; /* old element */
|
||||
Element * qq; /* new element */
|
||||
Symbol *p, **q;
|
||||
unsigned int i, j;
|
||||
|
||||
newtable = HASH_Table_new();
|
||||
for( i = 0; i < oldtable->SegmentCount; i++ ) {
|
||||
CALLOC( newtable->Directory[i], SEGMENT_SIZE, Element );
|
||||
/* "segment in HASHcopy");*/
|
||||
}
|
||||
memcpy(newtable, oldtable, sizeof *oldtable);
|
||||
|
||||
newtable->p = oldtable->p;
|
||||
newtable->SegmentCount = oldtable->SegmentCount;
|
||||
newtable->maxp = oldtable->maxp;
|
||||
newtable->MinLoadFactor = oldtable->MinLoadFactor;
|
||||
newtable->MaxLoadFactor = oldtable->MaxLoadFactor;
|
||||
newtable->KeyCount = oldtable->KeyCount;
|
||||
|
||||
for( i = 0; i < oldtable->SegmentCount; i++ ) {
|
||||
/* test probably unnecessary */
|
||||
if( ( s = oldtable->Directory[i] ) != NULL ) {
|
||||
s2 = newtable->Directory[i];
|
||||
for( j = 0; j < SEGMENT_SIZE; j++ ) {
|
||||
qq = &s2[j];
|
||||
for( pp = &s[j]; *pp; pp = &( *pp )->next ) {
|
||||
*qq = HASH_Element_new();
|
||||
/* (*qq)->key = STRINGcopy((*pp)->key);*/
|
||||
/* I really doubt it is necessary to copy the key!!! */
|
||||
( *qq )->key = ( *pp )->key;
|
||||
( *qq )->data = ( *pp )->data;
|
||||
( *qq )->symbol = ( *pp )->symbol;
|
||||
( *qq )->type = ( *pp )->type;
|
||||
( *qq )->next = NULL;
|
||||
qq = &( ( *qq )->next );
|
||||
}
|
||||
newtable->Directory = sc_calloc(newtable->DirectorySize, sizeof(Segment *));
|
||||
if (!newtable->Directory)
|
||||
/* HASHdestroy? */
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < newtable->SegmentCount; i++) {
|
||||
newtable->Directory[i] = sc_calloc(SEGMENT_SZ, sizeof(Segment));
|
||||
if (!newtable->Directory[i])
|
||||
/* HASHdestroy */
|
||||
return NULL;
|
||||
|
||||
for (j = 0; j < SEGMENT_SZ; j++) {
|
||||
p = oldtable->Directory[i][j];
|
||||
q = &newtable->Directory[i][j];
|
||||
while (p) {
|
||||
*q = SYMBOL_new();
|
||||
memcpy(*q, p, sizeof(Symbol));
|
||||
(*q)->next = NULL;
|
||||
q = &(*q)->next;
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
return( newtable );
|
||||
|
||||
return newtable;
|
||||
}
|
||||
|
||||
/* following code is for testing hash package */
|
||||
#ifdef HASHTEST
|
||||
struct Element e1, e2, e3, *e;
|
||||
struct Hash_Table * t;
|
||||
HashEntry he;
|
||||
Symbol *
|
||||
HASHsearch(Hash_Table tbl, Symbol item, Action action) {
|
||||
size_t h;
|
||||
Segment CurrentSegment;
|
||||
int SegmentIndex;
|
||||
int SegmentDir;
|
||||
Symbol **p, *q;
|
||||
|
||||
main() {
|
||||
e1.key = "foo";
|
||||
e1.data = ( char * )1;
|
||||
e2.key = "bar";
|
||||
e2.data = ( char * )2;
|
||||
e3.key = "herschel";
|
||||
e3.data = ( char * )3;
|
||||
assert(tbl != NULL);
|
||||
|
||||
t = HASHcreate( 100 );
|
||||
e = HASHsearch( t, &e1, HASH_INSERT );
|
||||
e = HASHsearch( t, &e2, HASH_INSERT );
|
||||
e = HASHsearch( t, &e3, HASH_INSERT );
|
||||
HASHlistinit( t, &he );
|
||||
for( ;; ) {
|
||||
e = HASHlist( &he );
|
||||
if( !e ) {
|
||||
exit( 0 );
|
||||
h = HASHhash(item.name);
|
||||
if (h % tbl->maxp < tbl->p) {
|
||||
h %= (tbl->maxp << 1);
|
||||
} else {
|
||||
h %= tbl->maxp;
|
||||
}
|
||||
|
||||
SegmentDir = h >> SEGMENT_WIDTH;
|
||||
SegmentIndex = h % SEGMENT_SZ;
|
||||
|
||||
CurrentSegment = tbl->Directory[SegmentDir];
|
||||
assert(CurrentSegment != NULL);
|
||||
|
||||
p = &CurrentSegment[SegmentIndex];
|
||||
q = *p;
|
||||
|
||||
/* Follow collision chain */
|
||||
while (q != NULL && strcasecmp((char *) q->name, (char *) item.name)) {
|
||||
p = &q->next;
|
||||
q = *p;
|
||||
}
|
||||
|
||||
/* TODO: remove HASH_DELETE to force compile error */
|
||||
assert(action != HASH_DELETE);
|
||||
if (action == HASH_DELETE)
|
||||
return NULL;
|
||||
|
||||
/* found, not found - search only, alloc or fail */
|
||||
if (q != NULL || action == HASH_FIND || (q = SYMBOL_new()) == NULL)
|
||||
return q;
|
||||
|
||||
#ifdef HASH_DEBUG
|
||||
/* check for a (new) collision */
|
||||
if (p != &CurrentSegment[SegmentIndex])
|
||||
tbl->HashCollisions++;
|
||||
#endif
|
||||
|
||||
/* link into chain, initialize new element */
|
||||
*p = q;
|
||||
memcpy(q, &item, sizeof(Symbol));
|
||||
q->next = NULL;
|
||||
|
||||
++tbl->KeyCount;
|
||||
|
||||
/* resize the table */
|
||||
if (tbl->KeyCount / (tbl->SegmentCount << SEGMENT_WIDTH ) >= LOAD_FACTOR)
|
||||
HASHexpand_table(tbl);
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
void
|
||||
HASHdelete(Hash_Table tbl, Symbol *item) {
|
||||
size_t h;
|
||||
Segment CurrentSegment;
|
||||
int SegmentIndex;
|
||||
int SegmentDir;
|
||||
Symbol **p, *q;
|
||||
|
||||
assert(tbl != NULL);
|
||||
|
||||
h = HASHhash(item->name);
|
||||
if (h % tbl->maxp < tbl->p) {
|
||||
h %= (tbl->maxp << 1);
|
||||
} else {
|
||||
h %= tbl->maxp;
|
||||
}
|
||||
|
||||
SegmentDir = h >> SEGMENT_WIDTH;
|
||||
SegmentIndex = h % SEGMENT_SZ;
|
||||
|
||||
CurrentSegment = tbl->Directory[SegmentDir];
|
||||
assert(CurrentSegment != NULL);
|
||||
|
||||
p = &CurrentSegment[SegmentIndex];
|
||||
q = *p;
|
||||
|
||||
/* Follow collision chain */
|
||||
while (q != NULL && strcasecmp((char *) q->name, (char *) item->name)) {
|
||||
p = &q->next;
|
||||
q = *p;
|
||||
}
|
||||
|
||||
/* ensure no undefined assignment behaviour */
|
||||
assert(q != item);
|
||||
if (!q)
|
||||
return;
|
||||
|
||||
*p = q->next;
|
||||
memcpy(item, q, sizeof(Symbol));
|
||||
item->next = NULL;
|
||||
tbl->KeyCount--;
|
||||
SYMBOL_destroy(q);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Internal routines
|
||||
*/
|
||||
size_t HASHhash(const unsigned char *key)
|
||||
{
|
||||
size_t h;
|
||||
const unsigned char *k;
|
||||
|
||||
/* Convert string to integer */
|
||||
for (h = 0, k = key; *k; k++)
|
||||
h = h * PRIME1 ^ toupper(*k);
|
||||
h %= PRIME2;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/*
|
||||
* tbl->p the next bucket to be split [x mod N]
|
||||
* tbl->maxp the current table size [N]
|
||||
*
|
||||
* NOTE: the method, as it's not entirely obvious
|
||||
*
|
||||
* e.g. tbl->maxp == 4 [N]
|
||||
* 4, 8, 12, 16 are in bucket 0 (x mod 4 == 0)
|
||||
* 4, 12 are in (new) bucket 4 (x mod 8 == 4)
|
||||
* 8, 16 remain in bucket 0 (x mod 8 == 0)
|
||||
*
|
||||
* general form
|
||||
* x mod N
|
||||
* -> x mod 2N
|
||||
*/
|
||||
void
|
||||
HASHexpand_table(Hash_Table tbl)
|
||||
{
|
||||
size_t NewAddress, h;
|
||||
#ifdef HASH_DEBUG
|
||||
int ci, cj, ck;
|
||||
#endif
|
||||
int OldSegmentIndex, NewSegmentIndex;
|
||||
int OldSegmentDir, NewSegmentDir;
|
||||
Segment OldSegment, NewSegment, *NewDirectory;
|
||||
Symbol *Current,**Previous,**LastOfNew;
|
||||
|
||||
/* check there's enough space for a new bucket, attempt resize */
|
||||
if (tbl->maxp + tbl->p >= (tbl->DirectorySize << SEGMENT_WIDTH)) {
|
||||
NewDirectory = sc_realloc(tbl->Directory, sizeof(Segment *) * (tbl->DirectorySize << 1));
|
||||
if (!NewDirectory)
|
||||
return;
|
||||
tbl->Directory = NewDirectory;
|
||||
memset(tbl->Directory + tbl->SegmentCount, 0, sizeof(Segment *) * tbl->DirectorySize);
|
||||
tbl->DirectorySize <<= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Locate the bucket to be split
|
||||
*/
|
||||
OldSegmentDir = tbl->p >> SEGMENT_WIDTH;
|
||||
OldSegment = tbl->Directory[OldSegmentDir];
|
||||
OldSegmentIndex = tbl->p % SEGMENT_SZ;
|
||||
/*
|
||||
** Expand address space; if necessary create a new segment
|
||||
*/
|
||||
NewAddress = tbl->maxp + tbl->p;
|
||||
NewSegmentDir = NewAddress >> SEGMENT_WIDTH;
|
||||
NewSegmentIndex = NewAddress % SEGMENT_SZ;
|
||||
if (NewSegmentIndex == 0) {
|
||||
#ifdef HASH_DEBUG
|
||||
fprintf(stderr, "[ExpandTable] %p Count %u maxp %d SegmentCount %u Collisions %u\n",
|
||||
tbl, tbl->KeyCount, tbl->maxp, tbl->SegmentCount, tbl->HashCollisions);
|
||||
#endif
|
||||
tbl->Directory[NewSegmentDir] = sc_calloc(sizeof(Segment), SEGMENT_SZ);
|
||||
if (!tbl->Directory[NewSegmentDir])
|
||||
return;
|
||||
tbl->SegmentCount++;
|
||||
}
|
||||
NewSegment = tbl->Directory[NewSegmentDir];
|
||||
|
||||
/*
|
||||
** Relocate records to the new bucket
|
||||
*/
|
||||
Previous = &OldSegment[OldSegmentIndex];
|
||||
Current = *Previous;
|
||||
LastOfNew = &NewSegment[NewSegmentIndex];
|
||||
*LastOfNew = NULL;
|
||||
#ifdef HASH_DEBUG
|
||||
ci = cj = ck = -1;
|
||||
#endif
|
||||
while (Current != NULL)
|
||||
{
|
||||
#ifdef HASH_DEBUG
|
||||
/* collisions to remove */
|
||||
ck++;
|
||||
#endif
|
||||
/* rehash for a factor 2 increase */
|
||||
h = HASHhash(Current->name) % (tbl->maxp << 1);
|
||||
if (h == NewAddress) {
|
||||
/* Attach it to the end of the new chain */
|
||||
*LastOfNew = Current;
|
||||
|
||||
/* Remove it from old chain */
|
||||
*Previous = Current->next;
|
||||
LastOfNew = &Current->next;
|
||||
Current = Current->next;
|
||||
*LastOfNew = NULL;
|
||||
#ifdef HASH_DEBUG
|
||||
/* collisions to add */
|
||||
ci++;
|
||||
#endif
|
||||
} else {
|
||||
/* leave it on the old chain */
|
||||
Previous = &Current->next;
|
||||
Current = Current->next;
|
||||
#ifdef HASH_DEBUG
|
||||
/* collisions to add */
|
||||
cj++;
|
||||
#endif
|
||||
}
|
||||
fprintf( stderr, "found key %s, data %d\n", e->key, ( int )e->data );
|
||||
}
|
||||
|
||||
#ifdef HASH_DEBUG
|
||||
if (ck > 0) {
|
||||
tbl->HashCollisions -= ck;
|
||||
if (ci > 0)
|
||||
tbl->HashCollisions += ci;
|
||||
if (cj > 0)
|
||||
tbl->HashCollisions += cj;
|
||||
}
|
||||
#endif
|
||||
/* increment for the next bucket */
|
||||
tbl->p++;
|
||||
if (tbl->p == tbl->maxp)
|
||||
{
|
||||
tbl->maxp <<= 1;
|
||||
tbl->p = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/****** minimal iterator implementation **********/
|
||||
|
||||
void
|
||||
HASHdo_init(Hash_Table tbl, Hash_Iterator *it, char type) {
|
||||
it->hash = 0;
|
||||
it->table = tbl;
|
||||
it->p = NULL;
|
||||
it->type = type;
|
||||
}
|
||||
|
||||
/* provide a way to step through the hash */
|
||||
Symbol *
|
||||
HASHdo( Hash_Iterator * it ) {
|
||||
Symbol *q;
|
||||
int SegmentDir, SegmentIndex;
|
||||
|
||||
for (; it->hash < (it->table->maxp + it->table->p); it->hash++) {
|
||||
SegmentDir = it->hash >> SEGMENT_WIDTH;
|
||||
SegmentIndex = it->hash % SEGMENT_SZ;
|
||||
|
||||
/* only used segments are initialised */
|
||||
assert(it->table->Directory[SegmentDir] != NULL);
|
||||
|
||||
if (!it->p)
|
||||
it->p = it->table->Directory[SegmentDir][SegmentIndex];
|
||||
|
||||
while (it->p != NULL) {
|
||||
q = it->p;
|
||||
if (q && (it->type == OBJ_ANY || it->type == q->type)) {
|
||||
it->p = q->next;
|
||||
if (!it->p)
|
||||
it->hash++;
|
||||
return q;
|
||||
}
|
||||
|
||||
it->p = q->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef __HASH_IMPL_H
|
||||
#define __HASH_IMPL_H
|
||||
|
||||
#include "express/hash.h"
|
||||
|
||||
inline size_t HASHhash(const unsigned char *);
|
||||
inline void HASHexpand_table(Hash_Table);
|
||||
|
||||
inline Hash_Table HASH_Table_new();
|
||||
inline void HASH_Table_destroy(Hash_Table x);
|
||||
|
||||
#endif /* __HASH_IMPL_H */
|
||||
@@ -0,0 +1,442 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sc_memmgr.h"
|
||||
|
||||
#include "lexsupport.h"
|
||||
#include "expparse.h"
|
||||
#include "expscan.h"
|
||||
|
||||
struct kw_token_def reserved_keywords[] = {
|
||||
{"ABS", T_ABS},
|
||||
{"ABSTRACT", T_ABSTRACT},
|
||||
{"ACOS", T_ACOS},
|
||||
{"AGGREGATE", T_AGGREGATE},
|
||||
{"ALIAS", T_ALIAS},
|
||||
{"AND", T_AND},
|
||||
{"ANDOR", T_ANDOR},
|
||||
{"ARRAY", T_ARRAY},
|
||||
{"AS", T_AS},
|
||||
{"ASIN", T_ASIN},
|
||||
{"ATAN", T_ATAN},
|
||||
{"BAG", T_BAG},
|
||||
{"BASED_ON", T_BASED_ON},
|
||||
{"BEGIN", T_BEGIN},
|
||||
{"BINARY", T_BINARY},
|
||||
{"BLENGTH", T_BLENGTH},
|
||||
{"BOOLEAN", T_BOOLEAN},
|
||||
{"BY", T_BY},
|
||||
{"CASE", T_CASE},
|
||||
{"CONSTANT", T_CONSTANT},
|
||||
{"CONST_E", T_CONST_E},
|
||||
{"COS", T_COS},
|
||||
{"DERIVE", T_DERIVE},
|
||||
{"DIV", T_IDIV},
|
||||
{"ELSE", T_ELSE},
|
||||
{"END", T_END},
|
||||
{"END_ALIAS", T_END_ALIAS},
|
||||
{"END_CASE", T_END_CASE},
|
||||
{"END_CONSTANT", T_END_CONSTANT},
|
||||
{"END_ENTITY", T_END_ENTITY},
|
||||
{"END_FUNCTION", T_END_FUNCTION},
|
||||
{"END_IF", T_END_IF},
|
||||
{"END_LOCAL", T_END_LOCAL},
|
||||
{"END_PROCEDURE", T_END_PROCEDURE},
|
||||
{"END_REPEAT", T_END_REPEAT},
|
||||
{"END_RULE", T_END_RULE},
|
||||
{"END_SCHEMA", T_END_SCHEMA},
|
||||
{"END_SUBTYPE_CONSTRAINT", T_END_SUBTYPE_CONSTRAINT},
|
||||
{"END_TYPE", T_END_TYPE},
|
||||
{"ENTITY", T_ENTITY},
|
||||
{"ENUMERATION", T_ENUMERATION},
|
||||
{"ESCAPE", T_ESCAPE},
|
||||
{"EXISTS", T_EXISTS},
|
||||
{"EXP", T_EXP},
|
||||
{"EXTENSIBLE", T_EXTENSIBLE},
|
||||
{"FALSE", T_FALSE},
|
||||
{"FIXED", T_FIXED},
|
||||
{"FOR", T_FOR},
|
||||
{"FORMAT", T_FORMAT},
|
||||
{"FROM", T_FROM},
|
||||
{"FUNCTION", T_FUNCTION},
|
||||
{"GENERIC", T_GENERIC},
|
||||
{"GENERIC_ENTITY", T_GENERIC_ENTITY},
|
||||
{"HIBOUND", T_HIBOUND},
|
||||
{"HIINDEX", T_HIINDEX},
|
||||
{"IF", T_IF},
|
||||
{"IN", T_IN},
|
||||
{"INSERT", T_INSERT},
|
||||
{"INTEGER", T_INTEGER},
|
||||
{"INVERSE", T_INVERSE},
|
||||
{"LENGTH", T_LENGTH},
|
||||
{"LIKE", T_LIKE},
|
||||
{"LIST", T_LIST},
|
||||
{"LOBOUND", T_LOBOUND},
|
||||
{"LOCAL", T_LOCAL},
|
||||
{"LOG", T_LOG},
|
||||
{"LOG10", T_LOG10},
|
||||
{"LOG2", T_LOG2},
|
||||
{"LOGICAL", T_LOGICAL},
|
||||
{"LOINDEX", T_LOINDEX},
|
||||
{"MOD", T_MOD},
|
||||
{"NOT", T_NOT},
|
||||
{"NUMBER", T_NUMBER},
|
||||
{"NVL", T_NVL},
|
||||
{"ODD", T_ODD},
|
||||
{"OF", T_OF},
|
||||
{"ONEOF", T_ONEOF},
|
||||
{"OPTIONAL", T_OPTIONAL},
|
||||
{"OR", T_OR},
|
||||
{"OTHERWISE", T_OTHERWISE},
|
||||
{"PI", T_PI},
|
||||
{"PROCEDURE", T_PROCEDURE},
|
||||
{"QUERY", T_QUERY},
|
||||
{"REAL", T_REAL},
|
||||
{"REFERENCE", T_REFERENCE},
|
||||
{"REMOVE", T_REMOVE},
|
||||
{"RENAMED", T_RENAMED},
|
||||
{"REPEAT", T_REPEAT},
|
||||
{"RETURN", T_RETURN},
|
||||
{"ROLESOF", T_ROLESOF},
|
||||
{"RULE", T_RULE},
|
||||
{"SCHEMA", T_SCHEMA},
|
||||
{"SELECT", T_SELECT},
|
||||
{"SELF", T_SELF},
|
||||
{"SET", T_SET},
|
||||
{"SIN", T_SIN},
|
||||
{"SIZEOF", T_SIZEOF},
|
||||
{"SKIP", T_SKIP},
|
||||
{"SQRT", T_SQRT},
|
||||
{"STRING", T_STRING},
|
||||
{"SUBTYPE", T_SUBTYPE},
|
||||
{"SUBTYPE_CONSTRAINT", T_SUBTYPE_CONSTRAINT},
|
||||
{"SUPERTYPE", T_SUPERTYPE},
|
||||
{"TAN", T_TAN},
|
||||
{"THEN", T_THEN},
|
||||
{"TO", T_TO},
|
||||
{"TOTAL_OVER", T_TOTAL_OVER},
|
||||
{"TRUE", T_TRUE},
|
||||
{"TYPE", T_TYPE},
|
||||
{"TYPEOF", T_TYPEOF},
|
||||
{"UNIQUE", T_UNIQUE},
|
||||
{"UNKNOWN", T_UNKNOWN},
|
||||
{"UNTIL", T_UNTIL},
|
||||
{"USE", T_USE},
|
||||
{"USEDIN", T_USEDIN},
|
||||
{"VALUE", T_VALUE},
|
||||
{"VALUE_IN", T_VALUE_IN},
|
||||
{"VALUE_UNIQUE", T_VALUE_UNIQUE},
|
||||
{"VAR", T_VAR},
|
||||
{"WHERE", T_WHERE},
|
||||
{"WHILE", T_WHILE},
|
||||
{"WITH", T_WITH},
|
||||
{"XOR", T_XOR},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
struct intList *intListCreate (void) {
|
||||
struct intList * il = sc_malloc(sizeof(struct intList));
|
||||
if (il) {
|
||||
il->entry = sc_malloc(sizeof(int));
|
||||
if (!il->entry) {
|
||||
sc_free(il);
|
||||
il = NULL;
|
||||
} else {
|
||||
il->entry[0] = 0;
|
||||
il->qty = 0;
|
||||
il->mlen = 1;
|
||||
}
|
||||
}
|
||||
return il;
|
||||
}
|
||||
|
||||
int intListDestroy (struct intList * il) {
|
||||
/* dummy implementation */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int intListAllocMin (struct intList * il, int msz) {
|
||||
int *l;
|
||||
size_t nsz;
|
||||
|
||||
if (!il || msz <= 0 || !il->entry || il->qty < 0 || il->mlen <= 0 ||
|
||||
il->qty > il->mlen) return BSTR_ERR;
|
||||
if (msz < il->qty) msz = il->qty;
|
||||
if (il->mlen == msz) return BSTR_OK;
|
||||
nsz = ((size_t) msz) * sizeof(int);
|
||||
if (nsz < (size_t) msz) return BSTR_ERR;
|
||||
l = sc_realloc(il->entry, nsz);
|
||||
if (!l) return BSTR_ERR;
|
||||
il->mlen = msz;
|
||||
il->entry = l;
|
||||
memset(il->entry + il->qty, 0, sizeof(int) * (il->mlen - il->qty));
|
||||
return BSTR_OK;
|
||||
}
|
||||
|
||||
struct scopeList *scopeListCreate (void) {
|
||||
struct scopeList * sl = sc_malloc(sizeof(struct scopeList));
|
||||
if (sl) {
|
||||
sl->entry = sc_malloc(sizeof(struct scope_def));
|
||||
if (!sl->entry) {
|
||||
sc_free(sl);
|
||||
sl = NULL;
|
||||
} else {
|
||||
sl->qty = 0;
|
||||
sl->mlen = 1;
|
||||
}
|
||||
}
|
||||
return sl;
|
||||
}
|
||||
|
||||
int scopeListDestroy (struct scopeList * sl) {
|
||||
/* dummy implementation */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scopeListAllocMin (struct scopeList * sl, int msz) {
|
||||
struct scope_def *l;
|
||||
size_t nsz;
|
||||
|
||||
if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 ||
|
||||
sl->qty > sl->mlen) return BSTR_ERR;
|
||||
if (msz < sl->qty) msz = sl->qty;
|
||||
if (sl->mlen == msz) return BSTR_OK;
|
||||
nsz = ((size_t) msz) * sizeof(struct scope_def);
|
||||
if (nsz < (size_t) msz) return BSTR_ERR;
|
||||
l = sc_realloc(sl->entry, nsz);
|
||||
if (!l) return BSTR_ERR;
|
||||
sl->mlen = msz;
|
||||
sl->entry = l;
|
||||
return BSTR_OK;
|
||||
}
|
||||
|
||||
void yylexReset(struct exp_scanner *s, int new_mode) {
|
||||
s->cur = s->tok = s->mrk = s->ctx = s->buffer->data;
|
||||
memset(s->cond_stack->entry, 0, sizeof(int) * s->cond_stack->mlen);
|
||||
s->cond_top = 0;
|
||||
s->cond_stack->entry[0] = new_mode;
|
||||
s->mode = new_mode;
|
||||
}
|
||||
|
||||
int yylexInit(struct exp_scanner *pScanner, struct YYSTATE *pState, FILE *fp) {
|
||||
bstring buf;
|
||||
|
||||
buf = bread((bNread) fread, fp);
|
||||
if (!buf)
|
||||
yyerror("failed to read input!", 0);
|
||||
|
||||
pScanner->state = pState;
|
||||
pScanner->scope_top = scope_alloc(pState->scope_stack, "DOCROOT", OBJ_DOCROOT_BITS);
|
||||
pState->scope_stack->entry[pScanner->scope_top].parent = -1;
|
||||
|
||||
pScanner->buffer = buf;
|
||||
pScanner->lim = buf->data + buf->slen;
|
||||
pScanner->anon_scope_cnt = 1;
|
||||
|
||||
yylexReset(pScanner, yycP1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct exp_scanner *yylexAlloc() {
|
||||
int chk;
|
||||
struct exp_scanner *scanner;
|
||||
|
||||
scanner = sc_malloc(sizeof *scanner);
|
||||
if (scanner) {
|
||||
memset(scanner, 0, sizeof *scanner);
|
||||
|
||||
scanner->cond_stack = intListCreate();
|
||||
chk = intListAllocMin(scanner->cond_stack, 20);
|
||||
if (chk != BSTR_OK)
|
||||
goto err_out;
|
||||
|
||||
scanner->brkt_nesting = intListCreate();
|
||||
chk = intListAllocMin(scanner->brkt_nesting, 50);
|
||||
if (chk != BSTR_OK)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
return scanner;
|
||||
|
||||
err_out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct YYSTATE *yystateAlloc() {
|
||||
struct YYSTATE *pState = sc_malloc(sizeof(struct YYSTATE));
|
||||
|
||||
if (pState) {
|
||||
pState->scope_stack = scopeListCreate();
|
||||
pState->lineno = 1;
|
||||
}
|
||||
|
||||
return pState;
|
||||
}
|
||||
|
||||
int scope_alloc(struct scopeList *stack, const char *typ, int scope_type) {
|
||||
struct scope_def *sp;
|
||||
const char *nx;
|
||||
char *np;
|
||||
int chk;
|
||||
|
||||
/* TODO: error checking */
|
||||
chk = scopeListAllocMin(stack, stack->qty+1);
|
||||
if (chk != BSTR_OK)
|
||||
goto err_out;
|
||||
|
||||
sp = stack->entry + stack->qty;
|
||||
/* TODO: really this doesn't need a symbol - we only have the "name", which could be assigned later or here */
|
||||
sp->symbol.name = NULL;
|
||||
sp->type = scope_type;
|
||||
sp->parent = 0xDEADBEEF;
|
||||
sp->symbol_table = HASHcreate();
|
||||
|
||||
#ifdef YYDEBUG
|
||||
sp->symbol.stype = strdup(typ);
|
||||
for (nx = typ, np = sp->stype; *nx; nx++, np++)
|
||||
*np = toupper((unsigned char) *nx);
|
||||
#endif
|
||||
|
||||
return stack->qty++;
|
||||
|
||||
err_out:
|
||||
yyerror("scope_alloc failure!", 0);
|
||||
}
|
||||
|
||||
void scope_push(struct YYSTATE *pState, int idx, struct exp_scanner *pScanner) {
|
||||
struct scopeList *stack = pState->scope_stack;
|
||||
struct scope_def *scope = stack->entry + idx;
|
||||
scope->parent = pScanner->scope_top;
|
||||
if (idx < 0) {
|
||||
yyerror("+++scope_push() internal error, pushing nonsense!", pScanner->lineno);
|
||||
}
|
||||
pScanner->scope_top = idx;
|
||||
}
|
||||
|
||||
int scope_pop(struct YYSTATE *pState, struct exp_scanner *pScanner) {
|
||||
struct scopeList *stack = pState->scope_stack;
|
||||
int idx = pScanner->scope_top;
|
||||
struct scope_def *scope = stack->entry + idx;
|
||||
if (scope->parent < 0) {
|
||||
yyerror("+++scope_pop() internal error, popping of the stack", 0);
|
||||
}
|
||||
pScanner->scope_top = scope->parent;
|
||||
return idx;
|
||||
}
|
||||
|
||||
int scope_find(struct YYSTATE *pState, int itype, const char *sname, struct exp_scanner *pScanner) {
|
||||
struct scopeList *stack = pState->scope_stack;
|
||||
struct scope_def *s;
|
||||
int i, idx = -1, pidx = pScanner->scope_top;
|
||||
|
||||
/* need to match parent, name and type */
|
||||
for (i = 0; i < stack->qty; i++) {
|
||||
s = stack->entry + i;
|
||||
if (s->parent == pidx && s->type == itype && !strcasecmp(s->symbol.name, sname)) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx < 0)
|
||||
yyerror("+++ scope_find failed, internal error!\n", 0);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void add_symbol(struct scope_def *scope, const char *id, int ref_tok, struct exp_scanner *pScanner) {
|
||||
Symbol e, *ep;
|
||||
int type;
|
||||
|
||||
switch (ref_tok) {
|
||||
case T_SCHEMA_REF:
|
||||
type = OBJ_SCHEMA;
|
||||
break;
|
||||
case T_FUNCTION_REF:
|
||||
type = OBJ_FUNCTION;
|
||||
break;
|
||||
case T_PROCEDURE_REF:
|
||||
type = OBJ_PROCEDURE;
|
||||
break;
|
||||
case T_RULE_REF:
|
||||
type = OBJ_RULE;
|
||||
break;
|
||||
case T_ENTITY_REF:
|
||||
type = OBJ_ENTITY;
|
||||
break;
|
||||
case T_TYPE_REF:
|
||||
type = OBJ_TYPE;
|
||||
break;
|
||||
case T_ENUMERATION_REF:
|
||||
type = OBJ_ENUM;
|
||||
break;
|
||||
case T_RULE_LABEL_REF:
|
||||
type = OBJ_TAG; /* TODO: check, confirm rule labels are tags */
|
||||
break;
|
||||
case T_VARIABLE_REF:
|
||||
case T_PARAMETER_REF: /* TODO: check - parameter maps to variable? */
|
||||
type = OBJ_VARIABLE;
|
||||
break;
|
||||
default: /* T_CONSTANT_REF, T_INVALID, T_SIMPLE_REF */
|
||||
type = OBJ_UNKNOWN; /* TODO: check for CONSTANT */
|
||||
}
|
||||
e = (Symbol) {.name = strdup(id), .type = type, .ref_tok = ref_tok,
|
||||
.filename = pScanner->filename, .line = pScanner->lineno};
|
||||
ep = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
if (!ep)
|
||||
yyerror("failed to insert symbol into symbol table", pScanner->lineno);
|
||||
}
|
||||
|
||||
int resolve_symbol(struct YYSTATE *pState, const char *id, struct exp_scanner *pScanner) {
|
||||
Symbol *qry, *sym;
|
||||
bool is_enum;
|
||||
int cnt_enum = 0, cnt = 0, chk;
|
||||
struct scopeList *stack = pState->scope_stack;
|
||||
struct scope_def *s = stack->entry + pScanner->scope_top;
|
||||
|
||||
/* basic resolution */
|
||||
qry = NULL;
|
||||
while (s->type != OBJ_DOCROOT_BITS) {
|
||||
qry = HASHsearch(s->symbol_table, (Symbol) {.name = id}, HASH_FIND);
|
||||
if (qry)
|
||||
break;
|
||||
s = stack->entry + s->parent;
|
||||
}
|
||||
|
||||
/* not found, probably an attribute */
|
||||
if (!qry)
|
||||
return T_SIMPLE_REF;
|
||||
|
||||
/* check for enums */
|
||||
sym = qry;
|
||||
while (qry) {
|
||||
if (!strcasecmp(qry->name, id)) {
|
||||
cnt++;
|
||||
if (qry->ref_tok == T_ENUMERATION_REF)
|
||||
cnt_enum++;
|
||||
}
|
||||
qry = qry->next;
|
||||
}
|
||||
|
||||
chk = cnt - cnt_enum;
|
||||
if (chk > 1 || (!chk && cnt_enum > 1)) {
|
||||
yyerror("conflicting token types for id '%s'", pScanner->lineno, id);
|
||||
}
|
||||
|
||||
is_enum = chk > 0 ? false : true;
|
||||
qry = sym;
|
||||
while (qry) {
|
||||
if (!strcasecmp(sym->name, id)) {
|
||||
if ((!is_enum && qry->ref_tok != T_ENUMERATION_REF) ||
|
||||
(is_enum && qry->ref_tok == T_ENUMERATION_REF))
|
||||
break;
|
||||
}
|
||||
qry = qry->next;
|
||||
}
|
||||
|
||||
return qry->ref_tok;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
#ifndef __LEXSUPPORT_H
|
||||
#define __LEXSUPPORT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "bstrlib.h"
|
||||
|
||||
#include "express/expbasic.h"
|
||||
#include "express/linklist.h"
|
||||
|
||||
#include "token_type.h"
|
||||
|
||||
#define yyerror_helper(fmt, lineno, ...) \
|
||||
do { fprintf(stderr, "error, line %i: " fmt "\n", (lineno), __VA_ARGS__); exit(1); } while (0)
|
||||
#define yyerror(...) yyerror_helper(__VA_ARGS__, 0)
|
||||
|
||||
struct intList {
|
||||
int qty, mlen;
|
||||
int *entry;
|
||||
};
|
||||
|
||||
struct exp_scanner {
|
||||
/* lexing pass / debug flag */
|
||||
int mode;
|
||||
bool debug;
|
||||
/* start condition stack */
|
||||
struct intList *cond_stack;
|
||||
int cond_top;
|
||||
/* pointers into the buffer and location */
|
||||
unsigned char *cur, *lim, *tok, *ctx, *mrk;
|
||||
int lineno;
|
||||
/* buffer and input reference */
|
||||
bstring buffer;
|
||||
const char *filename;
|
||||
/* flags for rules based scope */
|
||||
bool in_explicit_attr, in_rules_clause, in_inverse_clause;
|
||||
/* lexical scopes */
|
||||
int scope_aux, scope_top;
|
||||
/* token ref type */
|
||||
int id_ref_typ;
|
||||
/* scope type bits */
|
||||
int scope_typ;
|
||||
/* list of counters for brackets within each scope */
|
||||
struct intList *brkt_nesting;
|
||||
/* counter for anonymous scope names */
|
||||
unsigned int anon_scope_cnt;
|
||||
/* shared state - lexical scopes */
|
||||
struct YYSTATE *state;
|
||||
};
|
||||
|
||||
struct scope_def {
|
||||
int parent;
|
||||
|
||||
Symbol symbol;
|
||||
int type;
|
||||
|
||||
Hash_Table symbol_table;
|
||||
ClientData clientData;
|
||||
|
||||
union {
|
||||
struct Procedure_ * proc;
|
||||
struct Function_ * func;
|
||||
struct Rule_ * rule;
|
||||
struct Entity_ * entity;
|
||||
struct Schema_ * schema;
|
||||
struct Express_ * express;
|
||||
struct Increment_ * incr;
|
||||
struct TypeHead_ * type;
|
||||
/* TBD: struct Query_ * query; */
|
||||
} u;
|
||||
};
|
||||
|
||||
struct scopeList {
|
||||
int qty, mlen;
|
||||
struct scope_def *entry;
|
||||
};
|
||||
|
||||
/* TODO: migrate definitions here? */
|
||||
|
||||
struct YYSTYPE;
|
||||
|
||||
struct YYSTATE {
|
||||
int lineno; /* TODO: remove when parser rebuilds automatically */
|
||||
struct scopeList *scope_stack;
|
||||
};
|
||||
|
||||
struct kw_token_def {
|
||||
const char *kw;
|
||||
int token;
|
||||
};
|
||||
|
||||
extern struct kw_token_def reserved_keywords[];
|
||||
|
||||
/* lemon doesn't provide a header */
|
||||
void *yyparseAlloc(void * (*mallocptr)(size_t));
|
||||
void yyparseFree(void *, void (*freeptr)(void *));
|
||||
void yyparseInit(void *);
|
||||
void yyparse(void *, int, struct YYSTYPE *, struct YYSTATE *);
|
||||
void yyparseTrace(FILE *, char *);
|
||||
|
||||
struct exp_scanner *yylexAlloc();
|
||||
void yylexFree(struct exp_scanner *);
|
||||
int yylexInit(struct exp_scanner *, struct YYSTATE *, FILE *);
|
||||
|
||||
int yylex(struct exp_scanner *, struct YYSTYPE *);
|
||||
void yylexTrace(struct exp_scanner *, bool);
|
||||
void yylexReset(struct exp_scanner *s, int new_mode);
|
||||
|
||||
struct YYSTATE *yystateAlloc();
|
||||
void yystateFree();
|
||||
|
||||
struct intList * intListCreate (void);
|
||||
int intListDestroy (struct intList * il);
|
||||
int intListAllocMin (struct intList * il, int msz);
|
||||
|
||||
struct scopeList * scopeListCreate (void);
|
||||
int scopeListDestroy (struct scopeList * sl);
|
||||
int scopeListAllocMin (struct scopeList * sl, int msz);
|
||||
|
||||
int scope_alloc(struct scopeList *stack, const char *typ, int tok);
|
||||
void scope_push(struct YYSTATE *pState, int idx, struct exp_scanner *scanner);
|
||||
int scope_pop(struct YYSTATE *state, struct exp_scanner *scanner);
|
||||
int scope_find(struct YYSTATE *state, int itype, const char *sname, struct exp_scanner *scanner);
|
||||
int resolve_symbol(struct YYSTATE *state, const char *sym, struct exp_scanner *scanner);
|
||||
void add_symbol(struct scope_def *scope, const char *id, int tok, struct exp_scanner *pScanner);
|
||||
|
||||
|
||||
|
||||
#endif /* __LEXSUPPORT_H */
|
||||
@@ -7,8 +7,9 @@
|
||||
#include "express/schema.h"
|
||||
#include "express/type.h"
|
||||
|
||||
#include "symbol_impl.h"
|
||||
|
||||
struct freelist_head HASH_Table_fl;
|
||||
struct freelist_head HASH_Element_fl;
|
||||
|
||||
struct freelist_head LINK_fl;
|
||||
struct freelist_head LIST_fl;
|
||||
@@ -53,9 +54,8 @@ struct freelist_head INCR_fl;
|
||||
|
||||
void MEMORYinitialize() {
|
||||
_ALLOCinitialize();
|
||||
|
||||
ALLOCinitialize( &HASH_Table_fl, sizeof( struct Hash_Table_ ), 50, 50 );
|
||||
ALLOCinitialize( &HASH_Element_fl, sizeof( struct Element_ ), 500, 100 );
|
||||
|
||||
ALLOCinitialize( &HASH_Table_fl, sizeof( struct Hash_Table_ ), 500, 100 );
|
||||
|
||||
ALLOCinitialize( &LINK_fl, sizeof( struct Link_ ), 500, 100 );
|
||||
ALLOCinitialize( &LIST_fl, sizeof( struct Linked_List_ ), 100, 50 );
|
||||
@@ -100,3 +100,4 @@ void MEMORYinitialize() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ void populateAttrList( oaList & list, Entity ent ) {
|
||||
LISTdo( ent->u.entity->attributes, attr, Variable ) {
|
||||
bool unique = true;
|
||||
for( unsigned int i = attrCount; i < list.size(); i++ ) {
|
||||
if( 0 == strcasecmp( attr->name->symbol.name, list[i]->attr->name->symbol.name ) ) {
|
||||
if(!strcasecmp( (char *) attr->name->symbol.name, (char *) list[i]->attr->name->symbol.name ) ) {
|
||||
// an attr by this name exists in a supertype
|
||||
// originally printed a warning here, but that was misleading - they have more uses than I thought
|
||||
unique = false;
|
||||
@@ -56,8 +56,8 @@ void dedupList( oaList & list ) {
|
||||
oaList::iterator it, jt;
|
||||
for( it = list.begin(); it != list.end(); it++ ) {
|
||||
for( jt = it + 1; jt != list.end(); jt++ ) {
|
||||
if( ( 0 == strcasecmp( ( * it )->attr->name->symbol.name, ( * jt )->attr->name->symbol.name ) ) &&
|
||||
( 0 == strcasecmp( ( * it )->creator->symbol.name, ( * jt )->creator->symbol.name ) ) ) {
|
||||
if( ( !strcasecmp( (char *) ( * it )->attr->name->symbol.name, (char *) ( * jt )->attr->name->symbol.name ) ) &&
|
||||
( !strcasecmp( (char *) ( * it )->creator->symbol.name, (char *) ( * jt )->creator->symbol.name ) ) ) {
|
||||
//fprintf( stderr, "erasing %s created by %s\n", ( * jt )->attr->name->symbol.name, ( * jt )->creator->symbol.name );
|
||||
jt--;
|
||||
list.erase( jt + 1 );
|
||||
|
||||
+92
-96
@@ -125,10 +125,10 @@ Type TYPE_retrieve_aggregate( Type t_select, Type t_agg ) {
|
||||
** \note the macro 'EXPresolve' calls this function after checking if expr is already resolved
|
||||
*/
|
||||
void EXP_resolve( Expression expr, Scope scope, Type typecheck ) {
|
||||
Symbol *ep;
|
||||
Function f = 0;
|
||||
Symbol * sym;
|
||||
void *x;
|
||||
Entity e;
|
||||
Entity ent;
|
||||
Type t;
|
||||
bool func_args_checked = false;
|
||||
|
||||
@@ -137,18 +137,19 @@ void EXP_resolve( Expression expr, Scope scope, Type typecheck ) {
|
||||
*/
|
||||
switch( expr->type->u.type->body->type ) {
|
||||
case funcall_:
|
||||
/* TODO: no longer true - now the parser sees them as funcall_! */
|
||||
/* functions with no arguments get handled elsewhere */
|
||||
/* because the parser sees them just like attributes */
|
||||
|
||||
x = SCOPEfind( scope, expr->symbol.name,
|
||||
ep = SCOPEfind(scope, expr->symbol.name,
|
||||
SCOPE_FIND_FUNCTION | SCOPE_FIND_ENTITY );
|
||||
if( !x ) {
|
||||
if( !ep ) {
|
||||
ERRORreport_with_symbol(UNDEFINED_FUNC, &expr->symbol, expr->symbol.name );
|
||||
resolve_failed( expr );
|
||||
break;
|
||||
}
|
||||
if( ( DICT_type != OBJ_FUNCTION ) && ( DICT_type != OBJ_ENTITY ) ) {
|
||||
sym = OBJget_symbol( x, DICT_type );
|
||||
if (ep->type != OBJ_FUNCTION && ep->type != OBJ_ENTITY) {
|
||||
sym = OBJget_symbol( ep->data, ep->type );
|
||||
ERRORreport_with_symbol(FUNCALL_NOT_A_FUNCTION, &expr->symbol, sym->name );
|
||||
resolve_failed( expr );
|
||||
break;
|
||||
@@ -156,17 +157,17 @@ void EXP_resolve( Expression expr, Scope scope, Type typecheck ) {
|
||||
/* original code accepted rules, too? */
|
||||
|
||||
/* entities are treated like implicit constructor functions */
|
||||
if( DICT_type == OBJ_ENTITY ) {
|
||||
if( ep->type == OBJ_ENTITY ) {
|
||||
Type self_old = self; /* save previous in the unlikely but possible case that
|
||||
* SELF is in a derived initialization of an entity */
|
||||
e = ( Entity )x;
|
||||
self = e->u.entity->type;
|
||||
ent = ( Entity ) ep->data;
|
||||
self = ent->u.entity->type;
|
||||
/* skip parameter resolution for now */
|
||||
/* ARGresolve();*/
|
||||
expr->return_type = e->u.entity->type;
|
||||
expr->return_type = ent->u.entity->type;
|
||||
self = self_old; /* restore old SELF */
|
||||
} else {
|
||||
f = ( Function )x;
|
||||
f = ( Function ) ep->data;
|
||||
expr->return_type = f->u.func->return_type;
|
||||
|
||||
/* do argument typechecking here if requested */
|
||||
@@ -211,7 +212,7 @@ void EXP_resolve( Expression expr, Scope scope, Type typecheck ) {
|
||||
/* add function or entity as first element of list */
|
||||
LISTadd_first( expr->u.list, x );
|
||||
#endif
|
||||
expr->u.funcall.function = ( struct Scope_ * ) x;
|
||||
expr->u.funcall.function = ( struct Scope_ * ) ep->data;
|
||||
|
||||
resolved_all( expr );
|
||||
break;
|
||||
@@ -229,37 +230,26 @@ void EXP_resolve( Expression expr, Scope scope, Type typecheck ) {
|
||||
resolved_all( expr );
|
||||
break;
|
||||
case identifier_:
|
||||
|
||||
x = 0;
|
||||
|
||||
/* assume it's a variable/attribute */
|
||||
if( !x ) {
|
||||
x = VARfind( scope, expr->symbol.name, 0 );
|
||||
}
|
||||
ep = VARfind( scope, expr->symbol.name );
|
||||
/* if not found as a variable, try as function, etc ... */
|
||||
if( !x ) {
|
||||
x = SCOPEfind( scope, expr->symbol.name,
|
||||
SCOPE_FIND_ANYTHING );
|
||||
if( !ep ) {
|
||||
ep = SCOPEfind( scope, expr->symbol.name, SCOPE_FIND_ANYTHING );
|
||||
}
|
||||
/* Not all enums have `typecheck->u.type->body->type` == `enumeration_` - ?! */
|
||||
if( !x ) {
|
||||
if (!ep) {
|
||||
Scope enumscope = scope;
|
||||
while( 1 ) {
|
||||
while (1) {
|
||||
/* look up locally, then go through the superscopes */
|
||||
x = DICTlookup( enumscope->enum_table, expr->symbol.name );
|
||||
if( x ) {
|
||||
ep = HASHsearch(enumscope->enum_table, (Symbol) {.name = expr->symbol.name}, HASH_FIND);
|
||||
if (ep || enumscope->type == OBJ_SCHEMA)
|
||||
break;
|
||||
}
|
||||
if( enumscope->type == OBJ_SCHEMA ) {
|
||||
/* if we get here, this means that we've looked through all scopes */
|
||||
x = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
enumscope = enumscope->superscope;
|
||||
}
|
||||
}
|
||||
|
||||
if( !x ) {
|
||||
if( !ep ) {
|
||||
if( typecheck == Type_Unknown ) {
|
||||
return;
|
||||
} else {
|
||||
@@ -268,9 +258,9 @@ void EXP_resolve( Expression expr, Scope scope, Type typecheck ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch( DICT_type ) {
|
||||
switch( ep->type ) {
|
||||
case OBJ_VARIABLE:
|
||||
expr->u.variable = ( Variable )x;
|
||||
expr->u.variable = ( Variable ) ep->data;
|
||||
#if 0
|
||||
/* gee, I don't see what variables have to go through this right here */
|
||||
VARresolve_expressions( expr->u.variable, scope );
|
||||
@@ -287,28 +277,28 @@ void EXP_resolve( Expression expr, Scope scope, Type typecheck ) {
|
||||
resolved_all( expr );
|
||||
break;
|
||||
case OBJ_ENTITY:
|
||||
expr->return_type = expr->type = ( ( Entity )x )->u.entity->type;
|
||||
expr->return_type = expr->type = ( ( Entity )ep->data )->u.entity->type;
|
||||
/* entity may not actually be resolved by now */
|
||||
/* but I don't think that's a problem */
|
||||
resolved_all( expr );
|
||||
break;
|
||||
case OBJ_EXPRESSION:
|
||||
/* so far only enumerations get returned this way */
|
||||
expr->u.expression = ( Expression )x;
|
||||
expr->type = expr->return_type = ( ( Expression )x )->type;
|
||||
expr->u.expression = ( Expression ) ep->data;
|
||||
expr->type = expr->return_type = ( ( Expression )ep->data )->type;
|
||||
resolved_all( expr );
|
||||
break;
|
||||
case OBJ_FUNCTION:
|
||||
/* functions with no args end up here because the */
|
||||
/* parser doesn't know any better */
|
||||
expr->u.list = LISTcreate();
|
||||
LISTadd_last( expr->u.list, x );
|
||||
LISTadd_last( expr->u.list, ep->data );
|
||||
expr->type = Type_Funcall;
|
||||
expr->return_type = ( ( Function )x )->u.func->return_type;
|
||||
expr->return_type = ( ( Function ) ep->data )->u.func->return_type;
|
||||
/* function may not actually be resolved by now */
|
||||
/* but I don't think that's a problem */
|
||||
|
||||
if( ( ( Function )x )->u.func->pcount != 0 ) {
|
||||
if( ( ( Function ) ep->data )->u.func->pcount != 0 ) {
|
||||
ERRORreport_with_symbol(WRONG_ARG_COUNT, &expr->symbol, expr->symbol.name, 0,
|
||||
f->u.func->pcount );
|
||||
resolve_failed( expr );
|
||||
@@ -318,8 +308,8 @@ void EXP_resolve( Expression expr, Scope scope, Type typecheck ) {
|
||||
break;
|
||||
case OBJ_TYPE:
|
||||
/* enumerations can appear here, I don't know about others */
|
||||
expr->type = ( Type )x;
|
||||
expr->return_type = ( Type )x;
|
||||
expr->type = ( Type ) ep->data;
|
||||
expr->return_type = ( Type ) ep->data;
|
||||
expr->symbol.resolved = expr->type->symbol.resolved;
|
||||
break;
|
||||
default:
|
||||
@@ -396,12 +386,16 @@ void EXP_resolve( Expression expr, Scope scope, Type typecheck ) {
|
||||
}
|
||||
|
||||
int ENTITYresolve_subtype_expression( Expression expr, Entity ent/*was scope*/, Linked_List * flat ) {
|
||||
Symbol *ep;
|
||||
Entity ent_ref;
|
||||
int i = UNRESOLVED;
|
||||
|
||||
/* TODO: TYPEis... should be known by the parser */
|
||||
if( !expr ) {
|
||||
return ( RESOLVED );
|
||||
} else if( TYPEis_expression( expr->type ) ) {
|
||||
return RESOLVED;
|
||||
}
|
||||
|
||||
if( TYPEis_expression( expr->type ) ) {
|
||||
i = ENTITYresolve_subtype_expression( expr->e.op1, ent, flat );
|
||||
i |= ENTITYresolve_subtype_expression( expr->e.op2, ent, flat );
|
||||
} else if( TYPEis_oneof( expr->type ) ) {
|
||||
@@ -410,13 +404,13 @@ int ENTITYresolve_subtype_expression( Expression expr, Entity ent/*was scope*/,
|
||||
LISTod;
|
||||
} else {
|
||||
/* must be a simple entity reference */
|
||||
ent_ref = ( Entity )SCOPEfind( ent->superscope, expr->symbol.name, SCOPE_FIND_ENTITY );
|
||||
if( !ent_ref ) {
|
||||
ep = SCOPEfind(ent->superscope, expr->symbol.name, SCOPE_FIND_ENTITY);
|
||||
if( !ep ) {
|
||||
ERRORreport_with_symbol(UNKNOWN_SUBTYPE, &ent->symbol,
|
||||
expr->symbol.name, ent->symbol.name );
|
||||
i = RESOLVE_FAILED;
|
||||
} else if( DICT_type != OBJ_ENTITY ) {
|
||||
Symbol * sym = OBJget_symbol( ent_ref, DICT_type );
|
||||
} else if( ep->type != OBJ_ENTITY ) {
|
||||
Symbol * sym = OBJget_symbol( ep->data, ep->type );
|
||||
/* line number should really be on supertype name, */
|
||||
/* but all we have easily is the entity line number */
|
||||
ERRORreport_with_symbol(SUBTYPE_RESOLVE, &ent->symbol,
|
||||
@@ -424,6 +418,7 @@ int ENTITYresolve_subtype_expression( Expression expr, Entity ent/*was scope*/,
|
||||
i = RESOLVE_FAILED;
|
||||
} else {
|
||||
bool found = false;
|
||||
ent_ref = ep->data;
|
||||
|
||||
/* link in to flat list */
|
||||
if( !*flat ) {
|
||||
@@ -474,8 +469,8 @@ int ENTITYresolve_subtype_expression( Expression expr, Entity ent/*was scope*/,
|
||||
** Resolve all references in a type.
|
||||
*/
|
||||
void TYPE_resolve( Type * typeaddr /*, Scope scope*/ ) {
|
||||
Symbol *ep;
|
||||
Type type = *typeaddr;
|
||||
Type ref_type;
|
||||
TypeBody body = type->u.type->body;
|
||||
Scope scope = type->superscope;
|
||||
|
||||
@@ -516,35 +511,29 @@ void TYPE_resolve( Type * typeaddr /*, Scope scope*/ ) {
|
||||
}
|
||||
} else {
|
||||
/* simple type reference such as "T" */
|
||||
/* this really is a hack. masking out only variables from */
|
||||
/* the search is to support the (allowed) circumstance of */
|
||||
/* an attribute or formal parameter whose name is the same */
|
||||
/* as its type, i.e. "foo : foo". unfortunately, babys like */
|
||||
/* local variables get thrown out with the bathwater. -snc */
|
||||
ref_type = ( Type )SCOPEfind( scope, type->symbol.name,
|
||||
SCOPE_FIND_ANYTHING ^ SCOPE_FIND_VARIABLE );
|
||||
/* SCOPE_FIND_TYPE | SCOPE_FIND_ENTITY);*/
|
||||
if( !ref_type ) {
|
||||
/* search in the parent scope, to avoid "foo : foo" name type conflicts */
|
||||
ep = SCOPEfind(scope->superscope, type->symbol.name, SCOPE_FIND_TYPE | SCOPE_FIND_ENTITY );
|
||||
if( !ep ) {
|
||||
ERRORreport_with_symbol(UNDEFINED_TYPE, &type->symbol, type->symbol.name );
|
||||
*typeaddr = Type_Bad; /* just in case */
|
||||
resolve_failed( type );
|
||||
} else if( DICT_type == OBJ_TYPE ) {
|
||||
} else if( ep->type == OBJ_TYPE ) {
|
||||
/* due to declarations of multiple attributes off of a */
|
||||
/* single type ref, we have to use reference counts */
|
||||
/* to safely deallocate the TypeHead. It's trivial to do */
|
||||
/* but gaining back the memory isn't worth the CPU time. */
|
||||
/* if (type->refcount--) TYPE_destroy(type); */
|
||||
|
||||
type = *typeaddr = ref_type;
|
||||
type = *typeaddr = ep->data;
|
||||
TYPEresolve( typeaddr ); /* addr doesn't matter here */
|
||||
/* it will not be written through */
|
||||
} else if( DICT_type == OBJ_ENTITY ) {
|
||||
} else if( ep->type == OBJ_ENTITY ) {
|
||||
/* if (type->refcount--) TYPE_destroy(type); see above */
|
||||
|
||||
type = *typeaddr = ( ( Entity )ref_type )->u.entity->type;
|
||||
type = *typeaddr = ( ( Entity )ep->data )->u.entity->type;
|
||||
} else {
|
||||
ERRORreport_with_symbol(NOT_A_TYPE, &type->symbol, type->symbol.name,
|
||||
OBJget_type( DICT_type ) );
|
||||
OBJget_type( ep->type ) );
|
||||
resolve_failed( type );
|
||||
}
|
||||
}
|
||||
@@ -598,7 +587,7 @@ void VAR_resolve_types( Variable v ) {
|
||||
ERRORreport_with_symbol(INVERSE_BAD_ENTITY,
|
||||
&v->name->symbol, v->inverse_symbol->name );
|
||||
} else {
|
||||
attr = VARfind( type->u.type->body->entity, v->inverse_symbol->name, 1 );
|
||||
attr = VARfind( type->u.type->body->entity, v->inverse_symbol->name);
|
||||
if( attr ) {
|
||||
v->inverse_attribute = attr;
|
||||
failed |= is_resolve_failed( attr->name );
|
||||
@@ -659,6 +648,7 @@ void CASE_ITresolve( Case_Item item, Scope scope, Statement statement ) {
|
||||
}
|
||||
|
||||
void STMTresolve( Statement statement, Scope scope ) {
|
||||
Symbol *ep;
|
||||
/* scope is always the function/procedure/rule from SCOPEresolve_expressions_statements(); */
|
||||
Scope proc;
|
||||
|
||||
@@ -698,17 +688,17 @@ void STMTresolve( Statement statement, Scope scope ) {
|
||||
break;
|
||||
case STMT_PCALL:
|
||||
#define proc_name statement->symbol.name
|
||||
proc = ( Scope )SCOPEfind( scope, proc_name,
|
||||
SCOPE_FIND_PROCEDURE );
|
||||
if( proc ) {
|
||||
if( DICT_type != OBJ_PROCEDURE ) {
|
||||
Symbol * newsym = OBJget_symbol( proc, DICT_type );
|
||||
ep = SCOPEfind( scope, proc_name, SCOPE_FIND_PROCEDURE);
|
||||
if( !ep ) {
|
||||
ERRORreport_with_symbol(NO_SUCH_PROCEDURE, &statement->symbol, proc_name );
|
||||
} else {
|
||||
proc = ep->data;
|
||||
if( ep->type != OBJ_PROCEDURE ) {
|
||||
Symbol * newsym = OBJget_symbol( proc, ep->type );
|
||||
ERRORreport_with_symbol(EXPECTED_PROC, &statement->symbol, proc_name, newsym->line );
|
||||
} else {
|
||||
statement->u.proc->procedure = proc;
|
||||
}
|
||||
} else {
|
||||
ERRORreport_with_symbol(NO_SUCH_PROCEDURE, &statement->symbol, proc_name );
|
||||
}
|
||||
LISTdo( statement->u.proc->parameters, e, Expression )
|
||||
EXPresolve( e, scope, Type_Dont_Care );
|
||||
@@ -745,7 +735,7 @@ void STMTresolve( Statement statement, Scope scope ) {
|
||||
}
|
||||
}
|
||||
|
||||
static Variable ENTITY_get_local_attribute( Entity e, char * name ) {
|
||||
static Variable ENTITY_get_local_attribute( Entity e, const char * name ) {
|
||||
LISTdo( e->u.entity->attributes, a, Variable )
|
||||
if( !strcmp( VARget_simple_name( a ), name ) ) {
|
||||
return a;
|
||||
@@ -755,10 +745,11 @@ static Variable ENTITY_get_local_attribute( Entity e, char * name ) {
|
||||
}
|
||||
|
||||
void ENTITYresolve_expressions( Entity e ) {
|
||||
Hash_Iterator it;
|
||||
Symbol *ep;
|
||||
Variable v;
|
||||
int status = 0;
|
||||
DictionaryEntry de;
|
||||
char * sname;
|
||||
const char * sname;
|
||||
Entity sup;
|
||||
|
||||
if( print_objects_while_running & OBJ_ENTITY_BITS ) {
|
||||
@@ -808,8 +799,9 @@ void ENTITYresolve_expressions( Entity e ) {
|
||||
status |= is_resolve_failed( attr->name );
|
||||
} LISTod;
|
||||
|
||||
DICTdo_type_init( e->symbol_table, &de, OBJ_VARIABLE );
|
||||
while( 0 != ( v = ( Variable )DICTdo( &de ) ) ) {
|
||||
HASHdo_init( e->symbol_table, &it, OBJ_VARIABLE );
|
||||
while( (ep = HASHdo( &it )) ) {
|
||||
v = (Variable) ep->data;
|
||||
if( !is_resolve_failed( v->name ) ) {
|
||||
TYPEresolve_expressions( v->type, e );
|
||||
if( v->initializer ) {
|
||||
@@ -924,9 +916,9 @@ void ENTITYresolve_types( Entity e );
|
||||
|
||||
/** also resolves inheritance counts and sub/super consistency */
|
||||
void SCOPEresolve_types( Scope s ) {
|
||||
Hash_Iterator it;
|
||||
Symbol *ep;
|
||||
Variable var;
|
||||
DictionaryEntry de;
|
||||
void *x;
|
||||
|
||||
if( print_objects_while_running & OBJ_SCOPE_BITS &
|
||||
OBJget_bits( s->type ) ) {
|
||||
@@ -934,16 +926,16 @@ void SCOPEresolve_types( Scope s ) {
|
||||
s->symbol.name, OBJget_type( s->type ) );
|
||||
}
|
||||
|
||||
DICTdo_init( s->symbol_table, &de );
|
||||
while( 0 != ( x = DICTdo( &de ) ) ) {
|
||||
switch( DICT_type ) {
|
||||
HASHdo_init( s->symbol_table, &it, '*' );
|
||||
while( (ep = HASHdo( &it )) ) {
|
||||
switch( ep->type ) {
|
||||
case OBJ_TYPE:
|
||||
if( ERRORis_enabled( SELECT_LOOP ) ) {
|
||||
TYPEcheck_select_cyclicity( ( Type )x );
|
||||
TYPEcheck_select_cyclicity( ( Type ) ep->data );
|
||||
}
|
||||
break;
|
||||
case OBJ_VARIABLE: /* really constants */
|
||||
var = ( Variable )x;
|
||||
var = ( Variable ) ep->data;
|
||||
/* before OBJ_BITS hack, we looked in s->superscope */
|
||||
TYPEresolve( &var->type );
|
||||
if( is_resolve_failed( var->type ) ) {
|
||||
@@ -952,26 +944,26 @@ void SCOPEresolve_types( Scope s ) {
|
||||
}
|
||||
break;
|
||||
case OBJ_ENTITY:
|
||||
ENTITYcheck_missing_supertypes( ( Entity )x );
|
||||
ENTITYresolve_types( ( Entity )x );
|
||||
ENTITYcalculate_inheritance( ( Entity )x );
|
||||
ENTITYcheck_missing_supertypes( ( Entity ) ep->data );
|
||||
ENTITYresolve_types( ( Entity ) ep->data );
|
||||
ENTITYcalculate_inheritance( ( Entity ) ep->data );
|
||||
if( ERRORis_enabled( SUBSUPER_LOOP ) ) {
|
||||
ENTITYcheck_subsuper_cyclicity( ( Entity )x );
|
||||
ENTITYcheck_subsuper_cyclicity( ( Entity ) ep->data );
|
||||
}
|
||||
if( is_resolve_failed( ( Entity )x ) ) {
|
||||
if( is_resolve_failed( ( Entity ) ep->data ) ) {
|
||||
resolve_failed( s );
|
||||
}
|
||||
break;
|
||||
case OBJ_SCHEMA:
|
||||
if( is_not_resolvable( ( Schema )x ) ) {
|
||||
if( is_not_resolvable( ( Schema ) ep->data ) ) {
|
||||
break;
|
||||
}
|
||||
/*FALLTHRU*/
|
||||
case OBJ_PROCEDURE:
|
||||
case OBJ_RULE:
|
||||
case OBJ_FUNCTION:
|
||||
SCOPEresolve_types( ( Scope )x );
|
||||
if( is_resolve_failed( ( Scope )x ) ) {
|
||||
SCOPEresolve_types( ( Scope ) ep->data );
|
||||
if( is_resolve_failed( ( Scope ) ep->data ) ) {
|
||||
resolve_failed( s );
|
||||
}
|
||||
break;
|
||||
@@ -986,6 +978,7 @@ void SCOPEresolve_types( Scope s ) {
|
||||
|
||||
/** for each supertype, find the entity it refs to */
|
||||
void ENTITYresolve_supertypes( Entity e ) {
|
||||
Symbol *ep;
|
||||
Entity ref_entity;
|
||||
|
||||
if( print_objects_while_running & OBJ_ENTITY_BITS ) {
|
||||
@@ -1003,17 +996,18 @@ void ENTITYresolve_supertypes( Entity e ) {
|
||||
#endif
|
||||
|
||||
LISTdo( e->u.entity->supertype_symbols, sym, Symbol * ) {
|
||||
ref_entity = ( Entity )SCOPEfind( e->superscope, sym->name, SCOPE_FIND_ENTITY );
|
||||
if( !ref_entity ) {
|
||||
ep = SCOPEfind( e->superscope, sym->name, SCOPE_FIND_ENTITY );
|
||||
if( !ep ) {
|
||||
ERRORreport_with_symbol(UNKNOWN_SUPERTYPE, sym, sym->name, e->symbol.name );
|
||||
/* ENTITY_resolve_failed = 1;*/
|
||||
resolve_failed( e );
|
||||
} else if( DICT_type != OBJ_ENTITY ) {
|
||||
Symbol * newsym = OBJget_symbol( ref_entity, DICT_type );
|
||||
} else if( ep->type != OBJ_ENTITY ) {
|
||||
Symbol * newsym = OBJget_symbol( ep->data, ep->type );
|
||||
ERRORreport_with_symbol(SUPERTYPE_RESOLVE, sym, sym->name, newsym->line );
|
||||
/* ENTITY_resolve_failed = 1;*/
|
||||
resolve_failed( e );
|
||||
} else {
|
||||
ref_entity = ep->data;
|
||||
bool found = false;
|
||||
|
||||
LISTadd_last( e->u.entity->supertypes, ref_entity );
|
||||
@@ -1203,8 +1197,10 @@ int WHEREresolve( Linked_List list, Scope scope, int need_self ) {
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
struct tag * TAGcreate_tags() {
|
||||
extern int tag_count;
|
||||
|
||||
return( ( struct tag * )calloc( tag_count, sizeof( struct tag ) ) );
|
||||
return( ( struct tag * ) sc_calloc( tag_count, sizeof( struct tag ) ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
+27
-25
@@ -7,10 +7,12 @@
|
||||
#include "express/schema.h"
|
||||
#include "express/resolve.h"
|
||||
|
||||
|
||||
/********************************new****************************************/
|
||||
|
||||
void SCOPEresolve_subsupers( Scope scope ) {
|
||||
DictionaryEntry de;
|
||||
void *x;
|
||||
char type;
|
||||
Hash_Iterator it;
|
||||
Symbol *ep;
|
||||
Symbol * sym;
|
||||
Type t;
|
||||
|
||||
@@ -20,27 +22,27 @@ void SCOPEresolve_subsupers( Scope scope ) {
|
||||
scope->symbol.name, OBJget_type( scope->type ) );
|
||||
}
|
||||
|
||||
DICTdo_init( scope->symbol_table, &de );
|
||||
while( 0 != ( x = DICTdo( &de ) ) ) {
|
||||
switch( type = DICT_type ) {
|
||||
HASHdo_init( scope->symbol_table, &it, '*' );
|
||||
while( (ep = HASHdo( &it )) ) {
|
||||
switch( ep->type ) {
|
||||
case OBJ_ENTITY:
|
||||
ENTITYresolve_supertypes( ( Entity )x );
|
||||
ENTITYresolve_subtypes( ( Entity )x );
|
||||
ENTITYresolve_supertypes( ep->data );
|
||||
ENTITYresolve_subtypes( ep->data );
|
||||
break;
|
||||
case OBJ_FUNCTION:
|
||||
case OBJ_PROCEDURE:
|
||||
case OBJ_RULE:
|
||||
SCOPEresolve_subsupers( ( Scope )x );
|
||||
SCOPEresolve_subsupers( ep->data );
|
||||
break;
|
||||
case OBJ_TYPE:
|
||||
t = ( Type )x;
|
||||
t = ( Type ) ep->data;
|
||||
TYPEresolve( &t );
|
||||
break;
|
||||
default:
|
||||
/* ignored everything else */
|
||||
break;
|
||||
}
|
||||
sym = OBJget_symbol( x, type );
|
||||
sym = OBJget_symbol( ep->data, ep->type );
|
||||
if( is_resolve_failed_raw( sym ) ) {
|
||||
resolve_failed( scope );
|
||||
}
|
||||
@@ -48,8 +50,8 @@ void SCOPEresolve_subsupers( Scope scope ) {
|
||||
}
|
||||
|
||||
void SCOPEresolve_expressions_statements( Scope s ) {
|
||||
DictionaryEntry de;
|
||||
void *x;
|
||||
Hash_Iterator it;
|
||||
Symbol *ep;
|
||||
Variable v;
|
||||
|
||||
if( print_objects_while_running & OBJ_SCOPE_BITS &
|
||||
@@ -58,38 +60,38 @@ void SCOPEresolve_expressions_statements( Scope s ) {
|
||||
s->symbol.name, OBJget_type( s->type ) );
|
||||
}
|
||||
|
||||
DICTdo_init( s->symbol_table, &de );
|
||||
while( 0 != ( x = DICTdo( &de ) ) ) {
|
||||
switch( DICT_type ) {
|
||||
HASHdo_init( s->symbol_table, &it, '*' );
|
||||
while( (ep = HASHdo( &it )) ) {
|
||||
switch( ep->type ) {
|
||||
case OBJ_SCHEMA:
|
||||
if( is_not_resolvable( ( Schema )x ) ) {
|
||||
if( is_not_resolvable( ( Schema )ep->data ) ) {
|
||||
break;
|
||||
}
|
||||
SCOPEresolve_expressions_statements( ( Scope )x );
|
||||
SCOPEresolve_expressions_statements( ( Scope )ep->data );
|
||||
break;
|
||||
case OBJ_ENTITY:
|
||||
ENTITYresolve_expressions( ( Entity )x );
|
||||
ENTITYresolve_expressions( ( Entity )ep->data );
|
||||
break;
|
||||
case OBJ_FUNCTION:
|
||||
ALGresolve_expressions_statements( ( Scope )x, ( ( Scope )x )->u.func->body );
|
||||
ALGresolve_expressions_statements( ( Scope )ep->data, ( ( Scope )ep->data )->u.func->body );
|
||||
break;
|
||||
case OBJ_PROCEDURE:
|
||||
ALGresolve_expressions_statements( ( Scope )x, ( ( Scope )x )->u.proc->body );
|
||||
ALGresolve_expressions_statements( ( Scope )ep->data, ( ( Scope )ep->data )->u.proc->body );
|
||||
break;
|
||||
case OBJ_RULE:
|
||||
ALGresolve_expressions_statements( ( Scope )x, ( ( Scope )x )->u.rule->body );
|
||||
ALGresolve_expressions_statements( ( Scope )ep->data, ( ( Scope )ep->data )->u.rule->body );
|
||||
|
||||
WHEREresolve( RULEget_where( ( Scope )x ), ( Scope )x, 0 );
|
||||
WHEREresolve( RULEget_where( ( Scope )ep->data ), ( Scope )ep->data, 0 );
|
||||
break;
|
||||
case OBJ_VARIABLE:
|
||||
v = ( Variable )x;
|
||||
v = ( Variable )ep->data;
|
||||
TYPEresolve_expressions( v->type, s );
|
||||
if( v->initializer ) {
|
||||
EXPresolve( v->initializer, s, v->type );
|
||||
}
|
||||
break;
|
||||
case OBJ_TYPE:
|
||||
TYPEresolve_expressions( ( Type )x, s );
|
||||
TYPEresolve_expressions( ( Type )ep->data, s );
|
||||
break;
|
||||
default:
|
||||
/* ignored everything else */
|
||||
|
||||
+63
-46
@@ -113,37 +113,56 @@ void SCHEMAadd_use( Schema cur_schema, Symbol * ref_schema, Symbol * old, Symbol
|
||||
}
|
||||
|
||||
void SCHEMAdefine_reference( Schema schema, Rename * r ) {
|
||||
Rename * old = 0;
|
||||
char * name = ( r->nnew ? r->nnew : r->old )->name;
|
||||
|
||||
Rename *old;
|
||||
Symbol e, *ep;
|
||||
Symbol *sym;
|
||||
|
||||
if( !schema->u.schema->refdict ) {
|
||||
schema->u.schema->refdict = DICTcreate( 20 );
|
||||
} else {
|
||||
old = ( Rename * )DICTlookup( schema->u.schema->refdict, name );
|
||||
}
|
||||
if( !old || ( DICT_type != OBJ_RENAME ) || ( old->object != r->object ) ) {
|
||||
DICTdefine( schema->u.schema->refdict, name,
|
||||
r, r->old, OBJ_RENAME );
|
||||
schema->u.schema->refdict = HASHcreate();
|
||||
}
|
||||
|
||||
sym = r->nnew ? r->nnew : r->old;
|
||||
|
||||
e = (Symbol) {.name = sym->name, .data = r, .type = OBJ_RENAME};
|
||||
ep = HASHsearch(schema->u.schema->refdict, e, HASH_FIND);
|
||||
old = !ep ? NULL : ep->data;
|
||||
|
||||
if( !ep || ep->type != OBJ_RENAME || old->object != r->object ) {
|
||||
/* TODO: evaluate difference in behaviour with DICTdefine
|
||||
* if there's already an OBJ_RENAME, then DICTdefine would replace it
|
||||
* - this will instead append another
|
||||
*/
|
||||
HASHsearch(schema->u.schema->refdict, e, HASH_INSERT);
|
||||
}
|
||||
}
|
||||
|
||||
void SCHEMAdefine_use( Schema schema, Rename * r ) {
|
||||
Rename * old = 0;
|
||||
char * name = ( r->nnew ? r->nnew : r->old )->name;
|
||||
Rename * old;
|
||||
Symbol *ep, e;
|
||||
Symbol *sym;
|
||||
|
||||
if( !schema->u.schema->usedict ) {
|
||||
schema->u.schema->usedict = DICTcreate( 20 );
|
||||
} else {
|
||||
old = ( Rename * )DICTlookup( schema->u.schema->usedict, name );
|
||||
schema->u.schema->usedict = HASHcreate();
|
||||
}
|
||||
if( !old || ( DICT_type != OBJ_RENAME ) || ( old->object != r->object ) ) {
|
||||
DICTdefine( schema->u.schema->usedict, name,
|
||||
r, r->old, OBJ_RENAME );
|
||||
|
||||
sym = r->nnew ? r->nnew : r->old;
|
||||
e = (Symbol) {.name = sym->name, .data = r, .type = OBJ_RENAME};
|
||||
|
||||
ep = HASHsearch(schema->u.schema->usedict, e, HASH_FIND);
|
||||
old = !ep ? NULL : ep->data;
|
||||
|
||||
if( !ep || ep->type != OBJ_RENAME || old->object != r->object ) {
|
||||
/* TODO: evaluate difference in behaviour with DICTdefine
|
||||
* if there's already an OBJ_RENAME, then DICTdefine would replace it
|
||||
* - this will instead append another
|
||||
*/
|
||||
HASHsearch(schema->u.schema->usedict, e, HASH_INSERT);
|
||||
}
|
||||
}
|
||||
|
||||
static void SCHEMA_get_entities_use( Scope scope, Linked_List result ) {
|
||||
DictionaryEntry de;
|
||||
Hash_Iterator it;
|
||||
Symbol *ep;
|
||||
Rename * rename;
|
||||
|
||||
if( scope->search_id == __SCOPE_search_id ) {
|
||||
@@ -159,9 +178,10 @@ static void SCHEMA_get_entities_use( Scope scope, Linked_List result ) {
|
||||
|
||||
/* partially USE'd schema */
|
||||
if( scope->u.schema->usedict ) {
|
||||
DICTdo_init( scope->u.schema->usedict, &de );
|
||||
while( 0 != ( rename = ( Rename * )DICTdo( &de ) ) ) {
|
||||
LISTadd_last( result, rename->object );
|
||||
HASHdo_init(scope->u.schema->usedict, &it, '*');
|
||||
while ( (ep = HASHdo(&it)) ) {
|
||||
rename = ep->data;
|
||||
LISTadd_last(result, rename->object);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,7 +200,8 @@ Linked_List SCHEMAget_entities_use( Scope scope ) {
|
||||
/** return ref'd entities */
|
||||
void SCHEMA_get_entities_ref( Scope scope, Linked_List result ) {
|
||||
Rename * rename;
|
||||
DictionaryEntry de;
|
||||
Hash_Iterator it;
|
||||
Symbol *ep;
|
||||
|
||||
if( scope->search_id == __SCOPE_search_id ) {
|
||||
return;
|
||||
@@ -196,11 +217,10 @@ void SCHEMA_get_entities_ref( Scope scope, Linked_List result ) {
|
||||
LISTod
|
||||
|
||||
/* partially REF'd schema */
|
||||
DICTdo_init( scope->u.schema->refdict, &de );
|
||||
while( 0 != ( rename = ( Rename * )DICTdo( &de ) ) ) {
|
||||
if( DICT_type == OBJ_ENTITY ) {
|
||||
LISTadd_last( result, rename->object );
|
||||
}
|
||||
HASHdo_init(scope->u.schema->refdict, &it, OBJ_ENTITY);
|
||||
while ( (ep = HASHdo(&it)) ) {
|
||||
rename = ep->data;
|
||||
LISTadd_last(result, rename->object);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,31 +239,28 @@ Linked_List SCHEMAget_entities_ref( Scope scope ) {
|
||||
* look up an attribute reference
|
||||
* if strict false, anything can be returned, not just attributes
|
||||
*/
|
||||
Variable VARfind( Scope scope, char * name, int strict ) {
|
||||
Variable result;
|
||||
Symbol *VARfind( Scope scope, const char * name ) {
|
||||
Symbol *ep;
|
||||
|
||||
/* first look up locally */
|
||||
switch( scope->type ) {
|
||||
case OBJ_ENTITY:
|
||||
result = ENTITYfind_inherited_attribute( scope, name, 0 );
|
||||
if( result ) {
|
||||
if( strict && ( DICT_type != OBJ_VARIABLE ) ) {
|
||||
fprintf( stderr, "ERROR: strict && ( DICT_type != OBJ_VARIABLE )\n" );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
ep = ENTITYfind_inherited_attribute(scope, name, NULL);
|
||||
/* strict is checked when parsing */
|
||||
if (ep)
|
||||
return ep;
|
||||
break;
|
||||
case OBJ_INCREMENT:
|
||||
case OBJ_QUERY:
|
||||
case OBJ_ALIAS:
|
||||
result = ( Variable )DICTlookup( scope->symbol_table, name );
|
||||
if( result ) {
|
||||
if( strict && ( DICT_type != OBJ_VARIABLE ) ) {
|
||||
fprintf( stderr, "ERROR: strict && ( DICT_type != OBJ_VARIABLE )\n" );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return( VARfind( scope->superscope, name, strict ) );
|
||||
ep = HASHsearch(scope->symbol_table, (Symbol) {.name = name, .type = OBJ_VARIABLE}, HASH_FIND);
|
||||
/* strict is checked when parsing */
|
||||
if (ep)
|
||||
return ep;
|
||||
|
||||
ep = VARfind( scope->superscope, name );
|
||||
if (ep)
|
||||
return ep;
|
||||
}
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+83
-80
@@ -39,6 +39,8 @@
|
||||
* prettied up interface to print_objects_when_running
|
||||
*/
|
||||
|
||||
#include "sc_memmgr.h"
|
||||
|
||||
#define SCOPE_C
|
||||
#include "express/scope.h"
|
||||
#include "express/resolve.h"
|
||||
@@ -50,12 +52,12 @@ void SCOPEinitialize( void ) {
|
||||
* \sa SCOPEget_entities()
|
||||
*/
|
||||
void SCOPE_get_entities( Scope scope, Linked_List result ) {
|
||||
DictionaryEntry de;
|
||||
void *x;
|
||||
Hash_Iterator it;
|
||||
Symbol *ep;
|
||||
|
||||
DICTdo_type_init( scope->symbol_table, &de, OBJ_ENTITY );
|
||||
while( 0 != ( x = DICTdo( &de ) ) ) {
|
||||
LISTadd_last( result, x );
|
||||
HASHdo_init( scope->symbol_table, &it, OBJ_ENTITY );
|
||||
while ( (ep = HASHdo(&it)) ) {
|
||||
LISTadd_last(result, ep->data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,12 +65,12 @@ void SCOPE_get_entities( Scope scope, Linked_List result ) {
|
||||
* \sa SCOPEget_functions()
|
||||
*/
|
||||
void SCOPE_get_functions( Scope scope, Linked_List result ) {
|
||||
DictionaryEntry de;
|
||||
void *x;
|
||||
Hash_Iterator it;
|
||||
Symbol *ep;
|
||||
|
||||
DICTdo_type_init( scope->symbol_table, &de, OBJ_FUNCTION );
|
||||
while( 0 != ( x = DICTdo( &de ) ) ) {
|
||||
LISTadd_last( result, x );
|
||||
HASHdo_init( scope->symbol_table, &it, OBJ_FUNCTION );
|
||||
while ( (ep = HASHdo(&it)) ) {
|
||||
LISTadd_last(result, ep->data);
|
||||
}
|
||||
}
|
||||
/**
|
||||
@@ -84,12 +86,12 @@ Linked_List SCOPEget_functions( Scope scope ) {
|
||||
* \sa SCOPEget_rules()
|
||||
*/
|
||||
void SCOPE_get_rules( Scope scope, Linked_List result ) {
|
||||
DictionaryEntry de;
|
||||
void *x;
|
||||
|
||||
DICTdo_type_init( scope->symbol_table, &de, OBJ_RULE );
|
||||
while( 0 != ( x = DICTdo( &de ) ) ) {
|
||||
LISTadd_last( result, x );
|
||||
Hash_Iterator it;
|
||||
Symbol *ep;
|
||||
|
||||
HASHdo_init( scope->symbol_table, &it, OBJ_RULE );
|
||||
while ( (ep = HASHdo(&it)) ) {
|
||||
LISTadd_last(result, ep->data);
|
||||
}
|
||||
}
|
||||
/**
|
||||
@@ -121,17 +123,20 @@ Linked_List SCOPEget_entities( Scope scope ) {
|
||||
/**
|
||||
* \sa SCOPEget_entities_superclass_order()
|
||||
*/
|
||||
void SCOPE_dfs( Dictionary symbols, Entity root, Linked_List result ) {
|
||||
void SCOPE_dfs( Hash_Table symbols, Entity root, Linked_List result ) {
|
||||
Symbol *ep;
|
||||
Entity ent;
|
||||
|
||||
if( ( ENTITYget_mark( root ) != ENTITY_MARK ) ) {
|
||||
ENTITYput_mark( root, ENTITY_MARK );
|
||||
LISTdo( ENTITYget_supertypes( root ), super, Entity )
|
||||
/* if super explicitly defined in scope, recurse. */
|
||||
/* this chops out USEd and REFd entities */
|
||||
if( ( ent = ( Entity )DICTlookup( symbols, ENTITYget_name( super ) ) ) != ENTITY_NULL ) {
|
||||
SCOPE_dfs( symbols, ent, result );
|
||||
}
|
||||
/* if super explicitly defined in scope, recurse. */
|
||||
/* this chops out USEd and REFd entities */
|
||||
ep = HASHsearch(symbols, (Symbol) {.name = ENTITYget_name( super )}, HASH_FIND);
|
||||
if (ep) {
|
||||
ent = ep->data;
|
||||
SCOPE_dfs( symbols, ent, result);
|
||||
}
|
||||
LISTod
|
||||
LISTadd_last( result, root );
|
||||
}
|
||||
@@ -148,13 +153,17 @@ void SCOPE_dfs( Dictionary symbols, Entity root, Linked_List result ) {
|
||||
*/
|
||||
Linked_List SCOPEget_entities_superclass_order( Scope scope ) {
|
||||
Linked_List result;
|
||||
DictionaryEntry de;
|
||||
|
||||
Hash_Iterator it;
|
||||
Symbol *ep;
|
||||
|
||||
result = LISTcreate();
|
||||
++ENTITY_MARK;
|
||||
SCOPEdo_entities( scope, e, de )
|
||||
SCOPE_dfs( scope->symbol_table, e, result );
|
||||
SCOPEod;
|
||||
|
||||
HASHdo_init(scope->symbol_table, &it, OBJ_ENTITY);
|
||||
while( (ep = HASHdo(&it)) ) {
|
||||
SCOPE_dfs( scope->symbol_table, ep->data, result );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -163,21 +172,23 @@ Linked_List SCOPEget_entities_superclass_order( Scope scope ) {
|
||||
* note that object found is not actually checked, only because
|
||||
* caller is in a better position to describe the error with context
|
||||
*/
|
||||
void *SCOPEfind( Scope scope, char * name, int type ) {
|
||||
extern Dictionary EXPRESSbuiltins; /* procedures/functions */
|
||||
void *x;
|
||||
extern Hash_Table EXPRESSbuiltins;
|
||||
|
||||
Symbol *SCOPEfind( Scope scope, const char * name, int type_mask ) {
|
||||
Symbol *ep;
|
||||
|
||||
/* TODO: check, this looks like it should be in the parser */
|
||||
__SCOPE_search_id++;
|
||||
|
||||
ep = SCOPE_find( scope, name, type_mask );
|
||||
if ( ep )
|
||||
return ep;
|
||||
|
||||
x = SCOPE_find( scope, name, type );
|
||||
if( x ) {
|
||||
return x;
|
||||
}
|
||||
/* TODO: rework (order & check overall logic) */
|
||||
if ( type_mask & (SCOPE_FIND_FUNCTION | SCOPE_FIND_PROCEDURE) )
|
||||
ep = HASHsearch(EXPRESSbuiltins, (Symbol) {.name = name}, HASH_FIND);
|
||||
|
||||
if( type & ( SCOPE_FIND_FUNCTION | SCOPE_FIND_PROCEDURE ) ) {
|
||||
x = DICTlookup( EXPRESSbuiltins, name );
|
||||
}
|
||||
return x;
|
||||
return ep;
|
||||
}
|
||||
|
||||
|
||||
@@ -186,69 +197,61 @@ void *SCOPEfind( Scope scope, char * name, int type ) {
|
||||
* the supertype/subtype hierarchy
|
||||
* EH??? -> lookup an object when the current scope is not a schema
|
||||
*/
|
||||
void *SCOPE_find( Scope scope, char * name, int type ) {
|
||||
void *result;
|
||||
Symbol *SCOPE_find( Scope scope, const char * name, int type_mask ) {
|
||||
Symbol *ep;
|
||||
Rename * rename;
|
||||
|
||||
if( scope->search_id == __SCOPE_search_id ) {
|
||||
if ( scope->search_id == __SCOPE_search_id )
|
||||
return 0;
|
||||
}
|
||||
|
||||
scope->search_id = __SCOPE_search_id;
|
||||
|
||||
/* go up the superscopes, looking for object */
|
||||
while( 1 ) {
|
||||
/* first look up locally */
|
||||
result = DICTlookup( scope->symbol_table, name );
|
||||
if( result && OBJtype_is_oneof( DICT_type, type ) ) {
|
||||
return result;
|
||||
}
|
||||
if( scope->type == OBJ_SCHEMA ) {
|
||||
break;
|
||||
}
|
||||
for (;; scope = scope->superscope) {
|
||||
ep = HASHsearch(scope->symbol_table, (Symbol) {.name = name}, HASH_FIND);
|
||||
if (ep && OBJtype_is_oneof( ep->type, type_mask ))
|
||||
return ep->data;
|
||||
|
||||
scope = scope->superscope;
|
||||
if (scope->type == OBJ_SCHEMA)
|
||||
break;
|
||||
}
|
||||
|
||||
if( type & ( SCOPE_FIND_ENTITY | SCOPE_FIND_TYPE ) ) {
|
||||
if ( type_mask & (SCOPE_FIND_ENTITY | SCOPE_FIND_TYPE) ) {
|
||||
/* Occurs in a fully USE'd schema? */
|
||||
LISTdo( scope->u.schema->use_schemas, schema, Schema )
|
||||
/* follow chain'd USEs */
|
||||
if( schema == 0 ) {
|
||||
continue;
|
||||
}
|
||||
result = SCOPE_find( schema, name, type );
|
||||
if( result ) {
|
||||
return( result );
|
||||
}
|
||||
/* follow chain'd USEs */
|
||||
if (!schema)
|
||||
continue;
|
||||
|
||||
ep = SCOPE_find( schema, name, type_mask );
|
||||
if (ep)
|
||||
return ep;
|
||||
LISTod;
|
||||
|
||||
/* Occurs in a partially USE'd schema? */
|
||||
rename = ( Rename * )DICTlookup( scope->u.schema->usedict, name );
|
||||
if( rename ) {
|
||||
DICT_type = rename->type;
|
||||
return( rename->object );
|
||||
}
|
||||
/* TODO: need to resolve the rename */
|
||||
ep = HASHsearch(scope->u.schema->usedict, (Symbol) {.name = name}, HASH_FIND);
|
||||
rename = !ep ? NULL : ep->data;
|
||||
if( rename && OBJtype_is_oneof(rename->type, type_mask) )
|
||||
return rename->object;
|
||||
}
|
||||
|
||||
/* Occurs in a fully REF'd schema? */
|
||||
LISTdo( scope->u.schema->ref_schemas, schema, Schema )
|
||||
if( schema == 0 ) {
|
||||
continue;
|
||||
}
|
||||
result = DICTlookup( schema->symbol_table, name );
|
||||
if( result ) {
|
||||
return result;
|
||||
} else {
|
||||
continue; /* try another schema */
|
||||
}
|
||||
if (!schema)
|
||||
continue;
|
||||
|
||||
ep = HASHsearch(schema->symbol_table, (Symbol) {.name = name}, HASH_FIND);
|
||||
if (ep && OBJtype_is_oneof( ep->type, type_mask ))
|
||||
return ep->data;
|
||||
LISTod;
|
||||
|
||||
/* Occurs in a partially REF'd schema? */
|
||||
rename = ( Rename * )DICTlookup( scope->u.schema->refdict, name );
|
||||
if( rename ) {
|
||||
DICT_type = rename->type;
|
||||
return( rename->object );
|
||||
}
|
||||
/* TODO: need to resolve the rename */
|
||||
ep = HASHsearch(scope->u.schema->refdict, (Symbol) {.name = name}, HASH_FIND);
|
||||
rename = !ep ? NULL : ep->data;
|
||||
if( rename && OBJtype_is_oneof(rename->type, type_mask) )
|
||||
return rename->object;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+4
-3
@@ -48,7 +48,6 @@ Statement STATEMENT_SKIP = STATEMENT_NULL;
|
||||
Statement STMTcreate( int type ) {
|
||||
Statement s;
|
||||
s = STMT_new();
|
||||
SYMBOLset( s );
|
||||
s->type = type;
|
||||
return s;
|
||||
}
|
||||
@@ -173,11 +172,13 @@ Statement ALIAScreate( Scope scope, Variable variable, Linked_List statements )
|
||||
*/
|
||||
Scope INCR_CTLcreate( Symbol * control, Expression start,
|
||||
Expression end, Expression increment ) {
|
||||
Symbol sym;
|
||||
|
||||
Scope s = SCOPEcreate_tiny( OBJ_INCREMENT );
|
||||
Expression e = EXPcreate_from_symbol( Type_Attribute, control );
|
||||
Variable v = VARcreate( e, Type_Number );
|
||||
DICTdefine( s->symbol_table, control->name,
|
||||
v, control, OBJ_VARIABLE );
|
||||
sym = (Symbol) {.name = control->name, .data = v, .type = OBJ_VARIABLE};
|
||||
HASHsearch(s->symbol_table, sym, HASH_INSERT);
|
||||
s->u.incr = INCR_new();
|
||||
s->u.incr->init = start;
|
||||
s->u.incr->end = end;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef __SYMBOL_IMPL_H_
|
||||
#define __SYMBOL_IMPL_H_
|
||||
|
||||
#include "express/symbol.h"
|
||||
|
||||
inline struct Symbol_ *SYMBOL_new() {
|
||||
return ALLOC_new(&SYMBOL_fl);
|
||||
}
|
||||
|
||||
inline void SYMBOL_destroy(struct Symbol_ *x) {
|
||||
ALLOC_destroy(&SYMBOL_fl,(Freelist *)x);
|
||||
}
|
||||
|
||||
#endif /* __SYMBOL_IMPL_H_ */
|
||||
@@ -1,7 +1,7 @@
|
||||
include_directories(..)
|
||||
|
||||
if(SC_GENERATE_LP_SOURCES)
|
||||
include_directories("${PERPLEX_ExpScanner_INCLUDE_DIR}" "${LEMON_ExpParser_INCLUDE_DIR}")
|
||||
include_directories("${RE2C_ExpScanner_INCLUDE_DIR}" "${LEMON_ExpParser_INCLUDE_DIR}")
|
||||
endif(SC_GENERATE_LP_SOURCES)
|
||||
|
||||
set(EXPRESS_CORE_OBJ
|
||||
@@ -21,7 +21,6 @@ set(EXPRESS_CORE_OBJ
|
||||
$<TARGET_OBJECTS:objlib_alg_c>
|
||||
|
||||
# deprecated
|
||||
$<TARGET_OBJECTS:objlib_dict_c>
|
||||
$<TARGET_OBJECTS:objlib_info_c>
|
||||
)
|
||||
|
||||
@@ -59,20 +58,59 @@ add_test(NAME scope_find COMMAND test_scope scope_find)
|
||||
add_executable(test_type driver.c test_type.c $<TARGET_OBJECTS:objlib_type_c> ${EXPRESS_CORE_OBJ})
|
||||
add_test(NAME type_create_user_defined_tag COMMAND test_type type_create_user_defined_tag)
|
||||
|
||||
add_test(NAME build_check_express
|
||||
add_executable(check-hash "hash_test.c;../hash.c;../../auxlib/bstrlib.c")
|
||||
set_property(TARGET check-hash PROPERTY COMPILE_DEFINITIONS "HASH_TESTING;HASH_DEBUG")
|
||||
target_link_libraries(check-hash "m")
|
||||
|
||||
add_test(NAME test_hash_impl
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} --build .
|
||||
--target check-express
|
||||
--config $<CONFIGURATION>
|
||||
COMMAND $<TARGET_FILE:check-hash> "${CMAKE_CURRENT_SOURCE_DIR}/hash_names.txt"
|
||||
)
|
||||
|
||||
add_test(NAME build_check_express
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} --build .
|
||||
--target check-express
|
||||
--config $<CONFIGURATION>
|
||||
)
|
||||
|
||||
set(SHARED_SRC ../lexsupport.c ../hash.c ../../auxlib/bstrlib.c)
|
||||
|
||||
add_executable(check-scanner scanner_test.c $<TARGET_OBJECTS:objlib_expscan_c> ${SHARED_SRC})
|
||||
add_dependencies(check-scanner express)
|
||||
|
||||
add_executable(check-parser
|
||||
parser_test.c
|
||||
$<TARGET_OBJECTS:objlib_expscan_c>
|
||||
$<TARGET_OBJECTS:objlib_expparse_c>
|
||||
${SHARED_SRC})
|
||||
add_dependencies(check-parser express)
|
||||
|
||||
set_property(TARGET check-scanner check-parser
|
||||
APPEND PROPERTY INCLUDE_DIRECTORIES "${RE2C_ExpScanner_INCLUDE_DIR}")
|
||||
set_property(TARGET check-scanner check-parser
|
||||
APPEND PROPERTY INCLUDE_DIRECTORIES "${LEMON_ExpParser_INCLUDE_DIR}")
|
||||
set_property(TARGET check-scanner check-parser
|
||||
PROPERTY COMPILE_DEFINITIONS "HASH_TESTING")
|
||||
|
||||
file(GLOB unit_tests RELATIVE "${CMAKE_BINARY_DIR}" "../../../test/unitary_schemas/*.exp")
|
||||
file(GLOB extended_tests RELATIVE "${CMAKE_BINARY_DIR}" "../../../data/*/*.exp")
|
||||
|
||||
foreach(expfile ${unit_tests} ${extended_tests})
|
||||
get_filename_component(id_suffix "${expfile}" NAME_WE)
|
||||
add_test(NAME "test_scanner:${id_suffix}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMAND $<TARGET_FILE:check-scanner> "${expfile}")
|
||||
add_test(NAME "test_parser:${id_suffix}" WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMAND $<TARGET_FILE:check-parser> "${expfile}")
|
||||
endforeach()
|
||||
|
||||
add_test(NAME test_plib_parse_err
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMAND $<TARGET_FILE:check-express> "${CMAKE_CURRENT_SOURCE_DIR}/plib_parse_err.exp"
|
||||
)
|
||||
|
||||
set_tests_properties( test_plib_parse_err PROPERTIES DEPENDS "build_check_express;$<TARGET_NAME:check-express>" )
|
||||
set_tests_properties( test_plib_parse_err build_check_express PROPERTIES LABELS parser )
|
||||
set_tests_properties( test_plib_parse_err PROPERTIES DEPENDS "test_hash_impl" )
|
||||
set_tests_properties( test_plib_parse_err test_plib_parse_err PROPERTIES LABELS parser )
|
||||
|
||||
sc_addexec(print_schemas SOURCES ../fedex.c print_schemas.c LINK_LIBRARIES express base)
|
||||
sc_addexec(print_attrs SOURCES ../fedex.c print_attrs.c LINK_LIBRARIES express base)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,222 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bstrlib.h"
|
||||
#include "express/hash.h"
|
||||
|
||||
#define error_helper(fmt, ...) \
|
||||
do { fprintf(stderr, "error, line %i: " fmt "\n", __LINE__, __VA_ARGS__); exit(1); } while (0)
|
||||
#define error(...) error_helper(__VA_ARGS__, 0)
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
FILE *fp;
|
||||
bstring buf, id;
|
||||
struct bstrList *testdata;
|
||||
unsigned int i, qty;
|
||||
Hash_Table tbl;
|
||||
Symbol *ep;
|
||||
Symbol e;
|
||||
Hash_Iterator it;
|
||||
|
||||
if (argc < 2)
|
||||
error("no input files");
|
||||
|
||||
fp = fopen(argv[1], "r");
|
||||
if (!fp)
|
||||
error("failed to open input!");
|
||||
|
||||
buf = bread((bNread) fread, fp);
|
||||
if (!buf)
|
||||
error("failed to read input!");
|
||||
|
||||
if (fclose(fp))
|
||||
error("failed to correctly close input file!");
|
||||
|
||||
testdata = bsplit(buf, '\n');
|
||||
qty = testdata->qty;
|
||||
|
||||
tbl = HASHcreate();
|
||||
|
||||
/* HASHsearch INSERT */
|
||||
for (i = 0; i < testdata->qty; i++) {
|
||||
id = testdata->entry[i];
|
||||
if (id->slen > 0 && btrimws(id) == BSTR_ERR)
|
||||
error("btrimws failed?!");
|
||||
|
||||
if (!id->slen) {
|
||||
qty--;
|
||||
continue;
|
||||
}
|
||||
|
||||
ep = HASHsearch(tbl, (Symbol) {.name = id->data, .data = id}, HASH_INSERT);
|
||||
if (!ep)
|
||||
error("HASHsearch HASH_INSERT failed!");
|
||||
}
|
||||
|
||||
/* HASHsearch FIND */
|
||||
for (i = 0; i < testdata->qty; i++) {
|
||||
id = testdata->entry[i];
|
||||
|
||||
if (!id->slen)
|
||||
continue;
|
||||
|
||||
ep = HASHsearch(tbl, (Symbol) {.name = id->data, .data = id}, HASH_FIND);
|
||||
if (!ep)
|
||||
error("HASHsearch HASH_FIND failed!");
|
||||
}
|
||||
|
||||
/* HASHdo */
|
||||
i = 0;
|
||||
HASHdo_init(tbl, &it, OBJ_ANY);
|
||||
while (HASHdo(&it))
|
||||
i++;
|
||||
|
||||
if (i != qty)
|
||||
error("HASHdo failed! expected: %d, got: %d", qty, i);
|
||||
|
||||
if (qty != 6512)
|
||||
error("HASHdelete tests require a specific test input file, and build parameters");
|
||||
|
||||
/* expected collisions
|
||||
* [change_action,
|
||||
* device_terminal_map,
|
||||
* fea_column_normalised_orthotropic_symmetric_tensor4_3d,
|
||||
* fill_area_style_tile_symbol_with_style,
|
||||
* ifcorthogonalcomplement,
|
||||
* time_interval_with_bounds]
|
||||
*
|
||||
*/
|
||||
e = (Symbol) {.name = "fea_column_normalised_orthotropic_symmetric_tensor4_3d"};
|
||||
HASHdelete(tbl, &e);
|
||||
|
||||
i = 0;
|
||||
HASHdo_init(tbl, &it, OBJ_ANY);
|
||||
while (HASHdo(&it))
|
||||
i++;
|
||||
|
||||
qty--;
|
||||
if (i != qty)
|
||||
error("HASHdelete failed (#, #, x, #, #, #, #), expected %d, got %d", qty, i);
|
||||
|
||||
e = (Symbol) {.name = "ifcorthogonalcomplement"};
|
||||
HASHdelete(tbl, &e);
|
||||
|
||||
i = 0;
|
||||
HASHdo_init(tbl, &it, OBJ_ANY);
|
||||
while (HASHdo(&it))
|
||||
i++;
|
||||
|
||||
qty--;
|
||||
if (i != qty)
|
||||
error("HASHdelete failed (#, #, _, #, #, x, #), expected %d, got %d", qty, i);
|
||||
|
||||
/*
|
||||
* expected collisions
|
||||
* [evaluation_product_definition,
|
||||
* ifcfurniture,
|
||||
* ifcreloverridesproperties,
|
||||
* language,
|
||||
* physical_state_domain]
|
||||
*/
|
||||
e = (Symbol) {.name = "ifcfurniture"};
|
||||
HASHdelete(tbl, &e);
|
||||
|
||||
i = 0;
|
||||
HASHdo_init(tbl, &it, OBJ_ANY);
|
||||
while (HASHdo(&it))
|
||||
i++;
|
||||
|
||||
qty--;
|
||||
if (i != qty)
|
||||
error("HASHdelete failed (#, x, #, #, #), expected %d, got %d", qty, i);
|
||||
|
||||
e = (Symbol) {.name = "physical_state_domain"};
|
||||
HASHdelete(tbl, &e);
|
||||
|
||||
i = 0;
|
||||
HASHdo_init(tbl, &it, OBJ_ANY);
|
||||
while (HASHdo(&it))
|
||||
i++;
|
||||
|
||||
qty--;
|
||||
if (i != qty)
|
||||
error("HASHdelete failed (#, _, #, #, x), expected %d, got %d", qty, i);
|
||||
|
||||
/*
|
||||
* [action_resource_relationship,
|
||||
* annotation_occurrence_relationship,
|
||||
* erroneous_data,
|
||||
* ifclinearvelocitymeasure]
|
||||
*/
|
||||
e = (Symbol) {.name = "action_resource_relationship"};
|
||||
HASHdelete(tbl, &e);
|
||||
|
||||
i = 0;
|
||||
HASHdo_init(tbl, &it, OBJ_ANY);
|
||||
while (HASHdo(&it))
|
||||
i++;
|
||||
|
||||
qty--;
|
||||
if (i != qty)
|
||||
error("HASHdelete failed (x, #, #, #), expected %d, got %d", qty, i);
|
||||
|
||||
/*
|
||||
* [choose_representation_context_identifier,
|
||||
* dependent_instantiable_text_style]
|
||||
*/
|
||||
e = (Symbol) {.name = "choose_representation_context_identifier"};
|
||||
HASHdelete(tbl, &e);
|
||||
|
||||
i = 0;
|
||||
HASHdo_init(tbl, &it, OBJ_ANY);
|
||||
while (HASHdo(&it))
|
||||
i++;
|
||||
|
||||
qty--;
|
||||
if (i != qty)
|
||||
error("HASHdelete failed (x, #), expected %d, got %d", qty, i);
|
||||
|
||||
e = (Symbol) {.name = "dependent_instantiable_text_style"};
|
||||
HASHdelete(tbl, &e);
|
||||
|
||||
i = 0;
|
||||
HASHdo_init(tbl, &it, OBJ_ANY);
|
||||
while (HASHdo(&it))
|
||||
i++;
|
||||
|
||||
qty--;
|
||||
if (i != qty)
|
||||
error("HASHdelete failed (_, x), expected %d, got %d", qty, i);
|
||||
|
||||
/*
|
||||
* [connector_based_interconnect_definition]
|
||||
*/
|
||||
e = (Symbol) {.name = "connector_based_interconnect_definition"};
|
||||
HASHdelete(tbl, &e);
|
||||
|
||||
i = 0;
|
||||
HASHdo_init(tbl, &it, OBJ_ANY);
|
||||
while (HASHdo(&it))
|
||||
i++;
|
||||
|
||||
qty--;
|
||||
if (i != qty)
|
||||
error("HASHdelete failed (x,), expected %d, got %d", qty, i);
|
||||
|
||||
e = (Symbol) {.name = "connector_based_interconnect_definition"};
|
||||
HASHdelete(tbl, &e);
|
||||
|
||||
i = 0;
|
||||
HASHdo_init(tbl, &it, OBJ_ANY);
|
||||
while (HASHdo(&it))
|
||||
i++;
|
||||
|
||||
if (i != qty)
|
||||
error("HASHdelete failed (_,), expected %d, got %d", qty, i);
|
||||
|
||||
HASHdestroy(tbl);
|
||||
bstrListDestroy(testdata);
|
||||
bdestroy(buf);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lexsupport.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int tok;
|
||||
struct YYSTYPE yylval;
|
||||
struct YYSTATE *pState;
|
||||
void *pParser, *pScanner;
|
||||
FILE *fp;
|
||||
|
||||
if (argc < 2)
|
||||
yyerror("no input files!", 0);
|
||||
|
||||
fp = fopen(argv[1], "r");
|
||||
if (!fp)
|
||||
yyerror("failed to open input!", 0);
|
||||
|
||||
pScanner = yylexAlloc();
|
||||
pParser = yyparseAlloc(malloc);
|
||||
pState = yystateAlloc();
|
||||
|
||||
yylexInit(pScanner, pState, fp);
|
||||
|
||||
// yyparseTrace(stderr, "dbg: ");
|
||||
while ((tok = yylex(pScanner, &yylval))) {
|
||||
yyparse(pParser, tok, &yylval, pState);
|
||||
}
|
||||
yyparse(pParser, 0, &yylval, pState);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@@ -16,13 +16,16 @@
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <express/info.h>
|
||||
#include <express/express.h>
|
||||
#include <express/scope.h>
|
||||
#include <express/variable.h>
|
||||
#include "ordered_attrs.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "express/info.h"
|
||||
#include "express/express.h"
|
||||
#include "express/scope.h"
|
||||
#include "express/variable.h"
|
||||
#include "express/hash.h"
|
||||
#include "ordered_attrs.h"
|
||||
|
||||
char * entityName, _buf[512] = { 0 };
|
||||
|
||||
/** prints usage info specific to print_attrs */
|
||||
@@ -70,13 +73,14 @@ void print_attrs( Entity ent ) {
|
||||
}
|
||||
|
||||
void find_and_print( Express model ) {
|
||||
DictionaryEntry de;
|
||||
Hash_Iterator it;
|
||||
Schema s;
|
||||
Entity e;
|
||||
DICTdo_init( model->symbol_table, &de );
|
||||
while( 0 != ( s = (Schema) DICTdo( &de ) ) ) {
|
||||
|
||||
HASHdo_init(model->symbol_table, &it, OBJ_ANY);
|
||||
while((s = HASHdo(&it))) {
|
||||
printf( "Schema %s\n", s->symbol.name );
|
||||
e = (Entity) DICTlookup( s->symbol_table, entityName );
|
||||
e = HASHsearch(s->symbol_table, (Symbol) {.name = entityName}, HASH_FIND);
|
||||
if( e ) {
|
||||
print_attrs( e );
|
||||
}
|
||||
|
||||
@@ -13,16 +13,17 @@
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include "express/express.h"
|
||||
#include "express/hash.h"
|
||||
|
||||
void
|
||||
print_schemas( Express model ) {
|
||||
DictionaryEntry de;
|
||||
Hash_Iterator it;
|
||||
Schema s;
|
||||
|
||||
printf( "File: %s\n ", model->u.express->filename );
|
||||
|
||||
DICTdo_init( model->symbol_table, &de );
|
||||
while( 0 != ( s = (Schema) DICTdo( &de ) ) ) {
|
||||
HASHdo_init( model->symbol_table, &it, OBJ_ANY );
|
||||
while((s = HASHdo(&it))) {
|
||||
printf( "%s", s->symbol.name );
|
||||
}
|
||||
printf( "\n" );
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "lexsupport.h"
|
||||
|
||||
/* stubs */
|
||||
Symbol * SYMBOLcreate( char * name, int ref_tok, int line, const char * filename ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
struct YYSTATE *pState;
|
||||
struct exp_scanner *pScanner;
|
||||
YYSTYPE yylval;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "no input files\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fp = fopen(argv[1], "r");
|
||||
if (!fp)
|
||||
yyerror("failed to open input!", 0);
|
||||
|
||||
|
||||
pScanner = yylexAlloc();
|
||||
pState = yystateAlloc();
|
||||
yylexInit(pScanner, pState, fp);
|
||||
|
||||
while(yylex(pScanner, &yylval) != 0)
|
||||
;
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
@@ -5,9 +5,10 @@
|
||||
/* core */
|
||||
#include "express/hash.h"
|
||||
#include "express/linklist.h"
|
||||
#include "expparse.h"
|
||||
|
||||
/* non-core */
|
||||
#include "express/dict.h"
|
||||
#include "express/hash.h"
|
||||
#include "express/variable.h"
|
||||
|
||||
#include "driver.h"
|
||||
@@ -21,10 +22,6 @@ char * EXPRESSprogram_name;
|
||||
int yylineno;
|
||||
int __SCOPE_search_id;
|
||||
|
||||
Error ERROR_warn_unsupported_lang_feat;
|
||||
Error WARNING_case_skip_label;
|
||||
Error ERROR_undefined_attribute;
|
||||
|
||||
/*
|
||||
* mock functions
|
||||
*/
|
||||
@@ -47,18 +44,23 @@ void setup() {
|
||||
RESET_FAKE(EXP_resolve);
|
||||
}
|
||||
|
||||
/* TODO: remove DICTlookup after eliminating DICT_type */
|
||||
void EXP_resolve_type_handler(Expression exp, Scope cxt, Type typ) {
|
||||
(void) typ;
|
||||
Type res_typ = DICTlookup(cxt->symbol_table, exp->symbol.name);
|
||||
exp->type = res_typ;
|
||||
exp->return_type = res_typ;
|
||||
Symbol *ep;
|
||||
|
||||
ep = HASHsearch(cxt->symbol_table, exp->symbol, HASH_FIND);
|
||||
if (!ep)
|
||||
return;
|
||||
|
||||
exp->type = ep->data;
|
||||
exp->return_type = ep->data;
|
||||
exp->symbol.resolved = RESOLVED;
|
||||
}
|
||||
|
||||
int test_resolve_select_enum_member() {
|
||||
Schema scope;
|
||||
Symbol *e_type_id, *enum_id, *s_type_id;
|
||||
Symbol e;
|
||||
Symbol *e_type_id, *enum_id_inner, *enum_id_outer, *s_type_id;
|
||||
Type enum_typ, select_typ, chk_typ;
|
||||
TypeBody tb;
|
||||
Expression expr, op1, op2, exp_enum_id;
|
||||
@@ -68,37 +70,42 @@ int test_resolve_select_enum_member() {
|
||||
*/
|
||||
scope = SCHEMAcreate();
|
||||
|
||||
s_type_id = SYMBOLcreate("sel1", 1, "test1");
|
||||
e_type_id = SYMBOLcreate("enum1", 1, "test1");
|
||||
enum_id = SYMBOLcreate("val1", 1, "test1");
|
||||
e = (Symbol) {.name = "sel1", .type = OBJ_TYPE, .ref_tok = T_TYPE_REF};
|
||||
s_type_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
|
||||
/* TODO: check use of OBJ_ENUM / OBJ_TYPE */
|
||||
e = (Symbol) {.name ="enum1", .type = OBJ_TYPE, .ref_tok = T_TYPE_REF};
|
||||
e_type_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
enum_typ = TYPEcreate_name(e_type_id);
|
||||
enum_typ->symbol_table = DICTcreate(50);
|
||||
enum_typ->symbol_table = HASHcreate();
|
||||
enum_typ->symbol = e;
|
||||
e_type_id->data = enum_typ;
|
||||
|
||||
/* TODO: check use of OBJ_ENUM / OBJ_TYPE */
|
||||
/* TODO: OBJ_ENUM / OBJ_EXPRESSION are used interchangeably, this is confusing. */
|
||||
e = (Symbol) {.name = "val1", .type = OBJ_ENUM, .ref_tok = T_ENUMERATION_REF};
|
||||
enum_id_outer = HASHsearch(scope->enum_table, e, HASH_INSERT);
|
||||
enum_id_inner = HASHsearch(enum_typ->symbol_table, e, HASH_INSERT);
|
||||
exp_enum_id = EXPcreate(enum_typ);
|
||||
exp_enum_id->symbol = *enum_id;
|
||||
exp_enum_id->symbol = e;
|
||||
exp_enum_id->u.integer = 1;
|
||||
enum_id_outer->data = exp_enum_id;
|
||||
enum_id_inner->data = exp_enum_id;
|
||||
|
||||
tb = TYPEBODYcreate(enumeration_);
|
||||
tb->list = LISTcreate();
|
||||
LISTadd_last(tb->list, enum_id);
|
||||
LISTadd_last(tb->list, enum_id_inner);
|
||||
enum_typ->u.type->body = tb;
|
||||
|
||||
DICT_define(scope->symbol_table, e_type_id->name, enum_typ, &enum_typ->symbol, OBJ_TYPE);
|
||||
|
||||
/* TODO: OBJ_ENUM / OBJ_EXPRESSION are used interchangeably, this is confusing. */
|
||||
DICT_define(scope->enum_table, exp_enum_id->symbol.name, exp_enum_id, &exp_enum_id->symbol, OBJ_EXPRESSION);
|
||||
DICT_define(enum_typ->symbol_table, enum_id->name, exp_enum_id, enum_id, OBJ_EXPRESSION);
|
||||
|
||||
select_typ = TYPEcreate_name(s_type_id);
|
||||
s_type_id->data = select_typ;
|
||||
tb = TYPEBODYcreate(select_);
|
||||
tb->list = LISTcreate();
|
||||
LISTadd_last(tb->list, enum_typ);
|
||||
select_typ->u.type->body = tb;
|
||||
DICT_define(scope->symbol_table, s_type_id->name, select_typ, &select_typ->symbol, OBJ_TYPE);
|
||||
|
||||
op1 = EXPcreate_from_symbol(Type_Identifier, s_type_id);
|
||||
op2 = EXPcreate_from_symbol(Type_Identifier, enum_id);
|
||||
op2 = EXPcreate_from_symbol(Type_Identifier, enum_id_inner);
|
||||
expr = BIN_EXPcreate(OP_DOT, op1, op2);
|
||||
|
||||
/*
|
||||
@@ -118,25 +125,35 @@ int test_resolve_select_enum_member() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: remove DICTlookup after eliminating DICT_type */
|
||||
void EXP_resolve_entity_handler(Expression exp, Scope cxt, Type unused) {
|
||||
(void) unused;
|
||||
Entity ent = DICTlookup(cxt->symbol_table, exp->symbol.name);
|
||||
Type typ = ent->u.entity->type;
|
||||
exp->type = typ;
|
||||
exp->return_type = typ;
|
||||
Symbol *ep;
|
||||
Entity ent;
|
||||
|
||||
ep = HASHsearch(cxt->symbol_table, exp->symbol, HASH_FIND);
|
||||
if (!ep)
|
||||
return;
|
||||
|
||||
ent = ep->data;
|
||||
exp->type = ent->u.entity->type;
|
||||
exp->return_type = ent->u.entity->type;
|
||||
exp->symbol.resolved = RESOLVED;
|
||||
}
|
||||
|
||||
Variable ENTITY_resolve_attr_handler(Entity ent, Symbol *grp_ref, Symbol *attr_ref) {
|
||||
(void) grp_ref;
|
||||
Variable v = DICTlookup(ent->symbol_table, attr_ref->name);
|
||||
return v;
|
||||
Symbol *ep;
|
||||
|
||||
ep = HASHsearch(ent->symbol_table, *attr_ref, HASH_FIND);
|
||||
if (!ep)
|
||||
return NULL;
|
||||
|
||||
return ep->data;
|
||||
}
|
||||
|
||||
int test_resolve_entity_attribute() {
|
||||
Schema scope;
|
||||
Symbol *e_type_id, *attr_id;
|
||||
Symbol e, *e_type_id, *attr_id;
|
||||
Entity ent;
|
||||
Type attr_typ, chk_typ;
|
||||
TypeBody tb;
|
||||
@@ -149,22 +166,24 @@ int test_resolve_entity_attribute() {
|
||||
*/
|
||||
scope = SCHEMAcreate();
|
||||
|
||||
e_type_id = SYMBOLcreate("entity1", 1, "test2");
|
||||
e = (Symbol) {.name = "entity1", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
e_type_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
ent = ENTITYcreate(e_type_id);
|
||||
DICT_define(scope->symbol_table, e_type_id->name, ent, &ent->symbol, OBJ_ENTITY);
|
||||
|
||||
attr_id = SYMBOLcreate("attr1", 1, "test2");
|
||||
e_type_id->data = ent;
|
||||
|
||||
e = (Symbol) {.name = "attr1", .type = OBJ_VARIABLE, .ref_tok = T_SIMPLE_REF};
|
||||
attr_id = HASHsearch(ent->symbol_table, e, HASH_INSERT);
|
||||
exp_attr = EXPcreate_from_symbol(Type_Attribute, attr_id);
|
||||
tb = TYPEBODYcreate(number_);
|
||||
attr_typ = TYPEcreate_from_body_anonymously(tb);
|
||||
attr_typ->superscope = ent;
|
||||
var_attr = VARcreate(exp_attr, attr_typ);
|
||||
var_attr->flags.attribute = 1;
|
||||
attr_id->data = var_attr;
|
||||
|
||||
explicit_attr_list = LISTcreate();
|
||||
LISTadd_last(explicit_attr_list, var_attr);
|
||||
|
||||
LISTadd_last(explicit_attr_list, var_attr);
|
||||
LISTadd_last(ent->u.entity->attributes, explicit_attr_list);
|
||||
DICTdefine(ent->symbol_table, attr_id->name, var_attr, &var_attr->name->symbol, OBJ_VARIABLE);
|
||||
|
||||
op1 = EXPcreate_from_symbol(Type_Identifier, e_type_id);
|
||||
op2 = EXPcreate_from_symbol(Type_Attribute, attr_id);
|
||||
|
||||
@@ -5,14 +5,16 @@
|
||||
/* core */
|
||||
#include "express/hash.h"
|
||||
#include "express/linklist.h"
|
||||
#include "expparse.h"
|
||||
|
||||
/* non-core */
|
||||
#include "express/resolve.h"
|
||||
#include "express/schema.h"
|
||||
|
||||
#include "../token_type.h"
|
||||
#include "../parse_data.h"
|
||||
#include "expscan.h"
|
||||
#include "lexsupport.h"
|
||||
#include "expparse.h"
|
||||
|
||||
#include "driver.h"
|
||||
#include "fff.h"
|
||||
@@ -20,10 +22,6 @@
|
||||
/*
|
||||
* mock globals
|
||||
*/
|
||||
|
||||
Error ERROR_circular_reference;
|
||||
Error ERROR_undefined_schema;
|
||||
|
||||
int yylineno;
|
||||
Express yyexpresult;
|
||||
Linked_List PARSEnew_schemas;
|
||||
@@ -48,28 +46,22 @@ FAKE_VOID_FUNC0(ENTITYinitialize)
|
||||
FAKE_VOID_FUNC0(SCHEMAinitialize)
|
||||
FAKE_VOID_FUNC0(CASE_ITinitialize)
|
||||
FAKE_VOID_FUNC0(EXPinitialize)
|
||||
FAKE_VOID_FUNC0(SCANinitialize)
|
||||
FAKE_VOID_FUNC0(EXPKWinitialize)
|
||||
FAKE_VOID_FUNC0(RESOLVEcleanup)
|
||||
FAKE_VOID_FUNC0(TYPEcleanup)
|
||||
FAKE_VOID_FUNC0(EXPcleanup)
|
||||
FAKE_VOID_FUNC0(SCANcleanup)
|
||||
FAKE_VOID_FUNC0(parserInitState)
|
||||
FAKE_VOID_FUNC(SCAN_lex_init, char *, FILE *)
|
||||
FAKE_VOID_FUNC(ParseTrace, FILE *, char *)
|
||||
FAKE_VOID_FUNC(Parse, void *, int, YYSTYPE, parse_data_t)
|
||||
FAKE_VOID_FUNC(perplexFree, perplex_t)
|
||||
FAKE_VOID_FUNC(ParseFree, void *, free_func_t)
|
||||
FAKE_VOID_FUNC(SCHEMAdefine_use, Schema, Rename *)
|
||||
FAKE_VOID_FUNC(SCHEMAdefine_reference, Schema, Rename *)
|
||||
FAKE_VOID_FUNC(SCOPEresolve_subsupers, Scope)
|
||||
FAKE_VOID_FUNC(SCOPEresolve_types, Scope)
|
||||
FAKE_VOID_FUNC(SCOPEresolve_expressions_statements, Scope)
|
||||
|
||||
FAKE_VALUE_FUNC(void *, ParseAlloc, malloc_func_t)
|
||||
FAKE_VALUE_FUNC(char *, SCANstrdup, const char *)
|
||||
FAKE_VALUE_FUNC(perplex_t, perplexFileScanner, FILE *)
|
||||
FAKE_VALUE_FUNC(int, yylex, perplex_t)
|
||||
FAKE_VOID_FUNC(yyparse, void *, int, struct YYSTYPE *, struct YYSTATE *)
|
||||
FAKE_VOID_FUNC(yyparseFree, void *, free_func_t)
|
||||
FAKE_VOID_FUNC(yyparseTrace, FILE *, char *)
|
||||
FAKE_VALUE_FUNC(void *, yyparseAlloc, malloc_func_t)
|
||||
FAKE_VALUE_FUNC0(struct YYSTATE *, yystateAlloc)
|
||||
FAKE_VALUE_FUNC(int, yylex, struct exp_scanner *, struct YYSTYPE *)
|
||||
FAKE_VALUE_FUNC0(struct exp_scanner *, yylexAlloc)
|
||||
FAKE_VALUE_FUNC(int, yylexInit, struct exp_scanner *, struct YYSTATE *, FILE *)
|
||||
|
||||
void setup() {
|
||||
RESET_FAKE(RESOLVEinitialize);
|
||||
@@ -81,58 +73,62 @@ void setup() {
|
||||
RESET_FAKE(SCHEMAinitialize);
|
||||
RESET_FAKE(CASE_ITinitialize);
|
||||
RESET_FAKE(EXPinitialize);
|
||||
RESET_FAKE(SCANinitialize);
|
||||
RESET_FAKE(EXPKWinitialize);
|
||||
RESET_FAKE(RESOLVEcleanup);
|
||||
RESET_FAKE(TYPEcleanup);
|
||||
RESET_FAKE(EXPcleanup);
|
||||
RESET_FAKE(SCANcleanup);
|
||||
RESET_FAKE(parserInitState);
|
||||
RESET_FAKE(SCAN_lex_init);
|
||||
RESET_FAKE(ParseTrace);
|
||||
RESET_FAKE(Parse);
|
||||
RESET_FAKE(perplexFree);
|
||||
RESET_FAKE(ParseFree);
|
||||
RESET_FAKE(SCHEMAdefine_use);
|
||||
RESET_FAKE(SCHEMAdefine_reference);
|
||||
RESET_FAKE(SCOPEresolve_subsupers);
|
||||
RESET_FAKE(SCOPEresolve_types);
|
||||
RESET_FAKE(SCOPEresolve_expressions_statements);
|
||||
RESET_FAKE(ParseAlloc);
|
||||
RESET_FAKE(SCANstrdup);
|
||||
RESET_FAKE(perplexFileScanner);
|
||||
RESET_FAKE(yyparse);
|
||||
RESET_FAKE(yyparseFree);
|
||||
RESET_FAKE(yyparseTrace);
|
||||
RESET_FAKE(yyparseAlloc);
|
||||
RESET_FAKE(yystateAlloc);
|
||||
RESET_FAKE(yylex);
|
||||
RESET_FAKE(yylexAlloc);
|
||||
RESET_FAKE(yylexInit);
|
||||
}
|
||||
|
||||
int test_express_rename_resolve() {
|
||||
Scope model;
|
||||
Schema cur_schema, ref_schema;
|
||||
Rename *use_ref;
|
||||
Entity ent;
|
||||
Symbol *cur_schema_id, *ent_id, *ent_ref, *ref_schema_id;
|
||||
Symbol e, *cur_schema_id, *ent_id, *ent_ref, *ref_schema_id;
|
||||
|
||||
cur_schema_id = SYMBOLcreate("cur_schema", 1, "cur.exp");
|
||||
ent_id = SYMBOLcreate("line", 1, "cur.exp");
|
||||
ent_ref = SYMBOLcreate("line", 1, "ref.exp");
|
||||
ref_schema_id = SYMBOLcreate("ref_schema", 1, "ref.exp");
|
||||
model = SCOPEcreate(OBJ_EXPRESS);
|
||||
|
||||
cur_schema = SCHEMAcreate();
|
||||
cur_schema->u.schema->uselist = LISTcreate();
|
||||
e = (Symbol) {.name = "cur_schema", .type = OBJ_SCHEMA, .data = cur_schema,
|
||||
.ref_tok = T_SCHEMA_REF, .filename = "cur.exp"};
|
||||
cur_schema_id = HASHsearch(model->symbol_table, e, HASH_INSERT);
|
||||
cur_schema->symbol = *cur_schema_id;
|
||||
cur_schema->u.schema->uselist = LISTcreate();
|
||||
|
||||
|
||||
ref_schema = SCHEMAcreate();
|
||||
e = (Symbol) {.name = "ref_schema", .type = OBJ_SCHEMA, .data = ref_schema,
|
||||
.ref_tok = T_SCHEMA_REF, .filename = "ref.exp"};
|
||||
ref_schema_id = HASHsearch(model->symbol_table, e, HASH_INSERT);
|
||||
ref_schema->symbol = *ref_schema_id;
|
||||
|
||||
|
||||
e = (Symbol) {.name = "line", .type = OBJ_ENTITY,
|
||||
.ref_tok = T_ENTITY_REF, .filename = "cur.exp"};
|
||||
ent_id = HASHsearch(ref_schema->symbol_table, e, HASH_INSERT);
|
||||
ent = ENTITYcreate(ent_id);
|
||||
DICTdefine(ref_schema->symbol_table, ent_id->name, ent, ent_id, OBJ_ENTITY);
|
||||
ent_id->data = ent;
|
||||
|
||||
/* TODO: create RENcreate(...), refactor SCHEMAadd_use() */
|
||||
/* TODO: one of the few cases for using SYMBOLcreate(), perhaps refactor */
|
||||
ent_ref = SYMBOLcreate("line", OBJ_ENTITY, T_ENTITY_REF, 1, "ref.exp");
|
||||
use_ref = REN_new();
|
||||
use_ref->schema_sym = ref_schema_id;
|
||||
use_ref->old = ent_ref;
|
||||
use_ref->nnew = ent_ref;
|
||||
use_ref->rename_type = use;
|
||||
use_ref->schema = ref_schema_id->data;
|
||||
LISTadd_last(cur_schema->u.schema->uselist, use_ref);
|
||||
use_ref->schema = ref_schema;
|
||||
|
||||
RENAMEresolve(use_ref, cur_schema);
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "express/schema.h"
|
||||
#include "express/expr.h"
|
||||
#include "express/type.h"
|
||||
#include "expparse.h"
|
||||
|
||||
#include "driver.h"
|
||||
#include "fff.h"
|
||||
@@ -36,8 +37,8 @@ int tag_count;
|
||||
|
||||
DEFINE_FFF_GLOBALS
|
||||
|
||||
FAKE_VALUE_FUNC(void *, SCOPEfind, Scope, char *, int)
|
||||
FAKE_VALUE_FUNC(Variable, VARfind, Scope, char *, int)
|
||||
FAKE_VALUE_FUNC(Symbol *, SCOPEfind, Scope, char *, int)
|
||||
FAKE_VALUE_FUNC(Symbol *, VARfind, Scope, char *)
|
||||
FAKE_VALUE_FUNC(char *, VARget_simple_name, Variable)
|
||||
FAKE_VALUE_FUNC(struct Scope_ *, ENTITYfind_inherited_entity, struct Scope_ *, char *, int)
|
||||
FAKE_VALUE_FUNC(Variable, ENTITYget_named_attribute, Entity, char *)
|
||||
@@ -58,9 +59,11 @@ void setup() {
|
||||
RESET_FAKE(EXPRESS_fail);
|
||||
}
|
||||
|
||||
void * SCOPEfind_handler(Scope scope, char * name, int type) {
|
||||
(void) type;
|
||||
return DICTlookup(scope->symbol_table, name);
|
||||
Symbol *SCOPEfind_handler(Scope scope, char * name, int type) {
|
||||
Symbol *ep;
|
||||
|
||||
ep = HASHsearch(scope->symbol_table, (Symbol) {.name = name, .type = type}, HASH_FIND);
|
||||
return ep;
|
||||
}
|
||||
|
||||
int test_exp_resolve_bad_func_call() {
|
||||
@@ -70,7 +73,7 @@ int test_exp_resolve_bad_func_call() {
|
||||
|
||||
scope = SCHEMAcreate();
|
||||
|
||||
func_id = SYMBOLcreate("func1", 1, "test1");
|
||||
func_id = SYMBOLcreate("func1", OBJ_FUNCTION, T_FUNCTION_REF, 1, "test1");
|
||||
func_call = EXPcreate_from_symbol(Type_Funcall, func_id);
|
||||
|
||||
SCOPEfind_fake.custom_fake = SCOPEfind_handler;
|
||||
@@ -90,7 +93,7 @@ int test_exp_resolve_func_call() {
|
||||
|
||||
scope = SCHEMAcreate();
|
||||
|
||||
func_id = SYMBOLcreate("func1", 1, "test1");
|
||||
func_id = SYMBOLcreate("func1", OBJ_FUNCTION, T_FUNCTION_REF, 1, "test1");
|
||||
func_call = EXPcreate_from_symbol(Type_Funcall, func_id);
|
||||
|
||||
func_def = TYPEcreate_nostab(func_id, scope, OBJ_FUNCTION);
|
||||
@@ -104,33 +107,38 @@ int test_exp_resolve_func_call() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Variable VARfind_handler(Scope scope, char *name, int strict) {
|
||||
(void) strict;
|
||||
return DICTlookup(scope->symbol_table, name);
|
||||
Symbol *VARfind_handler(Scope scope, char *name, int strict) {
|
||||
Symbol *ep;
|
||||
|
||||
ep = HASHsearch(scope->symbol_table, (Symbol) {.name = name}, HASH_FIND);
|
||||
return ep;
|
||||
}
|
||||
|
||||
int test_exp_resolve_local_identifier() {
|
||||
Schema scope;
|
||||
Entity ent;
|
||||
Expression ent_attr, ent_attr_ref;
|
||||
Symbol *attr_id, *attr_ref, *ent_id;
|
||||
Symbol e, *attr_id, *attr_ref, *ent_id;
|
||||
Variable v_attr;
|
||||
Type attr_typ;
|
||||
|
||||
scope = SCHEMAcreate();
|
||||
|
||||
ent_id = SYMBOLcreate("entity1", 1, "test_2");
|
||||
ent = ENTITYcreate(ent_id);
|
||||
DICT_define(scope->symbol_table, ent_id->name, ent, ent_id, OBJ_ENTITY);
|
||||
|
||||
attr_id = SYMBOLcreate("attr1", 1, "test_2");
|
||||
e = (Symbol) {.name = "entity1", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
ent_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
ent = ENTITYcreate(ent_id);
|
||||
ent_id->data = ent;
|
||||
|
||||
e = (Symbol) {.name = "attr1", .type = OBJ_VARIABLE, .ref_tok = T_SIMPLE_REF};
|
||||
attr_id = HASHsearch(ent->symbol_table, e, HASH_INSERT);
|
||||
ent_attr = EXPcreate_from_symbol(Type_Attribute, attr_id);
|
||||
attr_typ = TYPEcreate(real_);
|
||||
v_attr = VARcreate(ent_attr, attr_typ);
|
||||
v_attr->flags.attribute = true;
|
||||
DICT_define(ent->symbol_table, attr_id->name, v_attr, attr_id, OBJ_VARIABLE);
|
||||
attr_id->data = v_attr;
|
||||
|
||||
|
||||
attr_ref = SYMBOLcreate("attr1", 1, "test_2");
|
||||
attr_ref = SYMBOLcreate("attr1", OBJ_ENTITY, T_ENTITY_REF, 1, "test_2");
|
||||
ent_attr_ref = EXPcreate_from_symbol(Type_Identifier, attr_ref);
|
||||
|
||||
VARfind_fake.custom_fake = VARfind_handler;
|
||||
@@ -147,19 +155,22 @@ int test_entity_resolve_subtype_expr_entity() {
|
||||
Schema scope;
|
||||
Entity ent1, ent2;
|
||||
Expression subtype_exp;
|
||||
Symbol *ent1_id, *ent2_id, *ent2_ref;
|
||||
Symbol e, *ent1_id, *ent2_id, *ent2_ref;
|
||||
int chk;
|
||||
|
||||
scope = SCHEMAcreate();
|
||||
ent1_id = SYMBOLcreate("ent1", 1, "test_3");
|
||||
ent2_id = SYMBOLcreate("ent2", 1, "test_3");
|
||||
ent2_ref = SYMBOLcreate("ent2", 1, "test_3");
|
||||
ent1 = ENTITYcreate(ent1_id);
|
||||
ent2 = ENTITYcreate(ent2_id);
|
||||
|
||||
DICTdefine(scope->symbol_table, ent1_id->name, ent1, ent1_id, OBJ_ENTITY);
|
||||
DICTdefine(scope->symbol_table, ent2_id->name, ent2, ent2_id, OBJ_ENTITY);
|
||||
|
||||
e = (Symbol) {.name = "ent1", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
ent1_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
ent1 = ENTITYcreate(ent1_id);
|
||||
ent1_id->data = ent1;
|
||||
|
||||
e = (Symbol) {.name = "ent2", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
ent2_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
ent2 = ENTITYcreate(ent2_id);
|
||||
ent2_id->data = ent2;
|
||||
|
||||
ent2_ref = SYMBOLcreate("ent2", OBJ_ENTITY, T_ENTITY_REF, 1, "test_3");
|
||||
subtype_exp = EXPcreate_from_symbol(Type_Identifier, ent2_ref);
|
||||
ent1->superscope = scope;
|
||||
ent1->u.entity->subtypes = LISTcreate();
|
||||
@@ -177,25 +188,32 @@ int test_type_resolve_entity() {
|
||||
Schema scope;
|
||||
Type sel, ent_base;
|
||||
Entity ent;
|
||||
Symbol *ent_id, *sel_id;
|
||||
Symbol e, *ent_id, *sel_id, *ent_base_id;
|
||||
|
||||
scope = SCHEMAcreate();
|
||||
ent_id = SYMBOLcreate("ent", 1, "test_4");
|
||||
sel_id = SYMBOLcreate("sel_typ", 1, "test_4");
|
||||
|
||||
ent_base = TYPEcreate_name(ent_id);
|
||||
ent_base->superscope = scope;
|
||||
e = (Symbol) {.name = "ent", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
ent_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
ent = ENTITYcreate(ent_id);
|
||||
ent->superscope = scope;
|
||||
sel = TYPEcreate(select_);
|
||||
ent_id->data = ent;
|
||||
|
||||
e = (Symbol) {.name = "sel_typ", .type = OBJ_TYPE, .ref_tok = T_TYPE_REF};
|
||||
sel_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
sel = TYPEcreate_name(sel_id);
|
||||
sel->superscope = scope;
|
||||
sel_id->data = sel;
|
||||
|
||||
ent_base_id = SYMBOLcreate("ent", OBJ_ENTITY, T_ENTITY_REF, 1, "test_5");
|
||||
ent_base = TYPEcreate_name(ent_base_id);
|
||||
ent_base->superscope = sel;
|
||||
ent_base_id->data = ent_base;
|
||||
|
||||
sel->symbol = *sel_id;
|
||||
sel->u.type->body = TYPEBODYcreate(select_);
|
||||
sel->u.type->body->list = LISTcreate();
|
||||
sel->superscope = scope;
|
||||
LISTadd_last(sel->u.type->body->list, ent_base);
|
||||
|
||||
DICTdefine(scope->symbol_table, ent_id->name, ent, ent_id, OBJ_ENTITY);
|
||||
DICTdefine(scope->symbol_table, sel_id->name, sel, sel_id, OBJ_TYPE);
|
||||
|
||||
SCOPEfind_fake.custom_fake = SCOPEfind_handler;
|
||||
|
||||
TYPE_resolve(&sel);
|
||||
@@ -210,20 +228,19 @@ int test_stmt_resolve_pcall_proc() {
|
||||
Function f;
|
||||
Procedure p;
|
||||
Statement s;
|
||||
Symbol *func_id, *proc_id, *proc_ref;
|
||||
Symbol e, *func_id, *proc_id, *proc_ref;
|
||||
|
||||
scope = SCHEMAcreate();
|
||||
|
||||
func_id = SYMBOLcreate("func1", 1, "test_5");
|
||||
proc_id = SYMBOLcreate("proc1", 1, "test_5");
|
||||
proc_ref = SYMBOLcreate("proc1", 1, "test_5");
|
||||
|
||||
f = ALGcreate(OBJ_FUNCTION);
|
||||
DICTdefine(scope->symbol_table, func_id->name, f, func_id, OBJ_FUNCTION);
|
||||
e = (Symbol) {.name = "func1", .type = OBJ_FUNCTION, .ref_tok = T_FUNCTION_REF, .data = f};
|
||||
func_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
|
||||
p = ALGcreate(OBJ_PROCEDURE);
|
||||
DICTdefine(f->symbol_table, proc_id->name, p, proc_id, OBJ_PROCEDURE);
|
||||
e = (Symbol) {.name = "proc1", .type = OBJ_PROCEDURE, .ref_tok = T_PROCEDURE_REF, .data = p};
|
||||
proc_id = HASHsearch(f->symbol_table, e, HASH_INSERT);
|
||||
|
||||
proc_ref = SYMBOLcreate("proc1", OBJ_PROCEDURE, T_PROCEDURE_REF, 1, "test_5");
|
||||
s = PCALLcreate(NULL);
|
||||
s->symbol = *proc_ref;
|
||||
|
||||
@@ -240,11 +257,15 @@ int test_scope_resolve_named_types() {
|
||||
Schema scope;
|
||||
Type sel, ent_base;
|
||||
Entity ent;
|
||||
Symbol *ent_id, *sel_id;
|
||||
Symbol e, *ent_id, *sel_id;
|
||||
|
||||
scope = SCHEMAcreate();
|
||||
sel_id = SYMBOLcreate("sel_typ", 1, "test_4");
|
||||
ent_id = SYMBOLcreate("ent", 1, "test_4");
|
||||
|
||||
e = (Symbol) {.name = "sel_typ", .type = OBJ_TYPE, .ref_tok = T_TYPE_REF};
|
||||
sel_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
|
||||
e = (Symbol) {.name = "ent", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
ent_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
|
||||
ent_base = TYPEcreate(entity_);
|
||||
ent_base->symbol = *ent_id;
|
||||
@@ -256,9 +277,9 @@ int test_scope_resolve_named_types() {
|
||||
sel->u.type->body->list = LISTcreate();
|
||||
sel->superscope = scope;
|
||||
LISTadd_last(sel->u.type->body->list, ent_base);
|
||||
|
||||
DICTdefine(scope->symbol_table, ent_id->name, ent, ent_id, OBJ_ENTITY);
|
||||
DICTdefine(scope->symbol_table, sel_id->name, sel, sel_id, OBJ_TYPE);
|
||||
|
||||
ent_id->data = ent;
|
||||
sel_id->data = sel;
|
||||
|
||||
SCOPEfind_fake.custom_fake = SCOPEfind_handler;
|
||||
|
||||
@@ -274,19 +295,23 @@ int test_scope_resolve_named_types() {
|
||||
int test_entity_resolve_supertypes() {
|
||||
Schema scope;
|
||||
Entity ent1, ent2;
|
||||
Symbol *ent1_id, *ent2_id, *ent1_ref;
|
||||
Symbol e, *ent1_id, *ent2_id, *ent1_ref;
|
||||
|
||||
scope = SCHEMAcreate();
|
||||
ent1_id = SYMBOLcreate("ent1", 1, "test_3");
|
||||
ent2_id = SYMBOLcreate("ent2", 1, "test_3");
|
||||
ent1_ref = SYMBOLcreate("ent1", 1, "test_3");
|
||||
|
||||
e = (Symbol) {.name = "ent1", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
ent1_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
ent1 = ENTITYcreate(ent1_id);
|
||||
ent2 = ENTITYcreate(ent2_id);
|
||||
ent1->superscope = scope;
|
||||
ent2->superscope = scope;
|
||||
ent1_id->data = ent1;
|
||||
|
||||
DICTdefine(scope->symbol_table, ent1_id->name, ent1, ent1_id, OBJ_ENTITY);
|
||||
DICTdefine(scope->symbol_table, ent2_id->name, ent2, ent2_id, OBJ_ENTITY);
|
||||
e = (Symbol) {.name = "ent2", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
ent2_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
ent2 = ENTITYcreate(ent2_id);
|
||||
ent2->superscope = scope;
|
||||
ent2_id->data = ent2;
|
||||
|
||||
ent1_ref = SYMBOLcreate("ent1", OBJ_ENTITY, T_ENTITY_REF, 1, "test_3");
|
||||
|
||||
ent2->u.entity->supertype_symbols = LISTcreate();
|
||||
LISTadd_last(ent2->u.entity->supertype_symbols, ent1_ref);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
/* non-core */
|
||||
#include "express/type.h"
|
||||
#include "expparse.h"
|
||||
|
||||
#include "driver.h"
|
||||
#include "fff.h"
|
||||
@@ -55,25 +56,29 @@ int test_scope_resolve_expr_stmt() {
|
||||
Schema scope;
|
||||
Type sel, ent_base;
|
||||
Entity ent;
|
||||
Symbol *ent_id, *sel_id;
|
||||
Symbol e, *ent_id, *sel_id, *ent_ref;
|
||||
|
||||
scope = SCHEMAcreate();
|
||||
ent_id = SYMBOLcreate("ent", 1, "test_4");
|
||||
sel_id = SYMBOLcreate("sel_typ", 1, "test_4");
|
||||
|
||||
ent_base = TYPEcreate_name(ent_id);
|
||||
ent_base->superscope = scope;
|
||||
e = (Symbol) {.name = "ent", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
ent_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
ent = ENTITYcreate(ent_id);
|
||||
ent->superscope = scope;
|
||||
ent_id->data = ent;
|
||||
|
||||
e = (Symbol) {.name = "sel_typ", .type = OBJ_TYPE, .ref_tok = T_TYPE_REF};
|
||||
sel_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
sel = TYPEcreate(select_);
|
||||
sel->symbol = *sel_id;
|
||||
sel->u.type->body->list = LISTcreate();
|
||||
sel->superscope = scope;
|
||||
sel_id->data = sel;
|
||||
|
||||
ent_ref = SYMBOLcreate("ent", OBJ_ENTITY, T_ENTITY_REF, 1, "test_5");
|
||||
ent_base = TYPEcreate_name(ent_ref);
|
||||
ent_base->superscope = sel;
|
||||
LISTadd_last(sel->u.type->body->list, ent_base);
|
||||
|
||||
DICTdefine(scope->symbol_table, ent_id->name, ent, ent_id, OBJ_ENTITY);
|
||||
DICTdefine(scope->symbol_table, sel_id->name, sel, sel_id, OBJ_TYPE);
|
||||
|
||||
SCOPEresolve_expressions_statements(scope);
|
||||
|
||||
assert(ENTITYresolve_expressions_fake.call_count == 1);
|
||||
@@ -86,24 +91,28 @@ int test_scope_resolve_subsupers() {
|
||||
Schema scope;
|
||||
Type sel, ent_base;
|
||||
Entity ent;
|
||||
Symbol *ent_id, *sel_id;
|
||||
Symbol e, *ent_id, *sel_id, *ent_ref;
|
||||
|
||||
scope = SCHEMAcreate();
|
||||
ent_id = SYMBOLcreate("ent", 1, "test_4");
|
||||
sel_id = SYMBOLcreate("sel_typ", 1, "test_4");
|
||||
|
||||
ent_base = TYPEcreate_name(ent_id);
|
||||
ent_base->superscope = scope;
|
||||
e = (Symbol) {.name = "ent", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
ent_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
ent = ENTITYcreate(ent_id);
|
||||
ent->superscope = scope;
|
||||
ent_id->data = ent;
|
||||
|
||||
e = (Symbol) {.name = "sel_typ", .type = OBJ_TYPE, .ref_tok = T_TYPE_REF};
|
||||
sel_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
sel = TYPEcreate(select_);
|
||||
sel->symbol = *sel_id;
|
||||
sel->u.type->body->list = LISTcreate();
|
||||
sel->superscope = scope;
|
||||
LISTadd_last(sel->u.type->body->list, ent_base);
|
||||
sel_id->data = sel;
|
||||
|
||||
DICTdefine(scope->symbol_table, ent_id->name, ent, ent_id, OBJ_ENTITY);
|
||||
DICTdefine(scope->symbol_table, sel_id->name, sel, sel_id, OBJ_TYPE);
|
||||
ent_ref = SYMBOLcreate("ent", OBJ_ENTITY, T_ENTITY_REF, 1, "test_6");
|
||||
ent_base = TYPEcreate_name(ent_id);
|
||||
ent_base->superscope = sel;
|
||||
LISTadd_last(sel->u.type->body->list, ent_base);
|
||||
|
||||
SCOPEresolve_subsupers(scope);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
/* non-core */
|
||||
#include "express/variable.h"
|
||||
#include "express/scope.h"
|
||||
#include "expparse.h"
|
||||
|
||||
#include "driver.h"
|
||||
#include "fff.h"
|
||||
@@ -31,7 +32,7 @@ DEFINE_FFF_GLOBALS
|
||||
|
||||
FAKE_VALUE_FUNC(int, EXPRESS_fail, Express)
|
||||
FAKE_VOID_FUNC(SCOPE_get_entities, Scope, Linked_List)
|
||||
FAKE_VALUE_FUNC(Variable, ENTITYfind_inherited_attribute, struct Scope_ *, char *, struct Symbol_ **)
|
||||
FAKE_VALUE_FUNC(Symbol *, ENTITYfind_inherited_attribute, struct Scope_ *, char *, struct Symbol_ **)
|
||||
|
||||
void setup() {
|
||||
RESET_FAKE(EXPRESS_fail)
|
||||
@@ -40,28 +41,36 @@ void setup() {
|
||||
}
|
||||
|
||||
int test_schema_define_ref() {
|
||||
Express model;
|
||||
Schema cur_schema, ref_schema;
|
||||
Rename *ref_rename;
|
||||
Symbol *cur_schema_id, *ent_ref, *ref_schema_id;
|
||||
Symbol e, *cur_schema_id, *ent_ref, *ref_schema_id;
|
||||
|
||||
cur_schema_id = SYMBOLcreate("cur_schema", 1, "cur.exp");
|
||||
ent_ref = SYMBOLcreate("line", 1, "ref.exp");
|
||||
ref_schema_id = SYMBOLcreate("ref_schema", 1, "ref.exp");
|
||||
model = SCOPEcreate(OBJ_EXPRESS);
|
||||
|
||||
e = (Symbol) {.name = "cur_schema", .type = OBJ_SCHEMA, .ref_tok = T_SCHEMA_REF};
|
||||
cur_schema_id = HASHsearch(model->symbol_table, e, HASH_INSERT);
|
||||
cur_schema = SCHEMAcreate();
|
||||
cur_schema->symbol = *cur_schema_id;
|
||||
cur_schema->u.schema->refdict = DICTcreate(20);
|
||||
cur_schema->u.schema->refdict = HASHcreate();
|
||||
cur_schema_id->data = cur_schema;
|
||||
|
||||
e = (Symbol) {.name = "ref_schema", .type = OBJ_SCHEMA, .ref_tok = T_SCHEMA_REF};
|
||||
ref_schema_id = HASHsearch(model->symbol_table, e, HASH_INSERT);
|
||||
ref_schema = SCHEMAcreate();
|
||||
ref_schema->symbol = *ref_schema_id;
|
||||
ref_schema_id->data = ref_schema;
|
||||
|
||||
e = (Symbol) {.name = "line", .type = OBJ_RENAME, .ref_tok = T_SIMPLE_REF};
|
||||
ent_ref = HASHsearch(cur_schema->u.schema->refdict, e, HASH_INSERT);
|
||||
ref_rename = REN_new();
|
||||
ent_ref->data = ref_rename;
|
||||
|
||||
ref_rename->schema_sym = ref_schema_id;
|
||||
ref_rename->old = ent_ref;
|
||||
ref_rename->nnew = ent_ref;
|
||||
ref_rename->rename_type = ref;
|
||||
ref_rename->schema = ref_schema;
|
||||
DICTdefine(cur_schema->u.schema->refdict, ent_ref->name, ref_rename, ent_ref, OBJ_RENAME);
|
||||
|
||||
SCHEMAdefine_reference(cur_schema, ref_rename);
|
||||
|
||||
@@ -71,28 +80,36 @@ int test_schema_define_ref() {
|
||||
}
|
||||
|
||||
int test_schema_define_use() {
|
||||
Express model;
|
||||
Schema cur_schema, ref_schema;
|
||||
Rename *use_rename;
|
||||
Symbol *cur_schema_id, *ent_ref, *ref_schema_id;
|
||||
Symbol e, *cur_schema_id, *ent_ref, *ref_schema_id;
|
||||
|
||||
cur_schema_id = SYMBOLcreate("cur_schema", 1, "cur.exp");
|
||||
ent_ref = SYMBOLcreate("line", 1, "ref.exp");
|
||||
ref_schema_id = SYMBOLcreate("ref_schema", 1, "ref.exp");
|
||||
model = SCOPEcreate(OBJ_EXPRESS);
|
||||
|
||||
e = (Symbol) {.name = "cur_schema", .type = OBJ_SCHEMA, .ref_tok = T_SCHEMA_REF};
|
||||
cur_schema_id = HASHsearch(model->symbol_table, e, HASH_INSERT);
|
||||
cur_schema = SCHEMAcreate();
|
||||
cur_schema->symbol = *cur_schema_id;
|
||||
cur_schema->u.schema->usedict = DICTcreate(20);
|
||||
cur_schema->u.schema->usedict = HASHcreate();
|
||||
cur_schema_id->data = cur_schema;
|
||||
|
||||
e = (Symbol) {.name = "ref_schema", .type = OBJ_SCHEMA, .ref_tok = T_SCHEMA_REF};
|
||||
ref_schema_id = HASHsearch(model->symbol_table, e, HASH_INSERT);
|
||||
ref_schema = SCHEMAcreate();
|
||||
ref_schema->symbol = *ref_schema_id;
|
||||
ref_schema_id->data = ref_schema;
|
||||
|
||||
e = (Symbol) {.name = "line", .type = OBJ_RENAME, .ref_tok = T_SIMPLE_REF};
|
||||
ent_ref = HASHsearch(cur_schema->u.schema->usedict, e, HASH_INSERT);
|
||||
use_rename = REN_new();
|
||||
ent_ref->data = use_rename;
|
||||
|
||||
use_rename->schema_sym = ref_schema_id;
|
||||
use_rename->old = ent_ref;
|
||||
use_rename->nnew = ent_ref;
|
||||
use_rename->rename_type = use;
|
||||
use_rename->schema = ref_schema;
|
||||
DICTdefine(cur_schema->u.schema->usedict, ent_ref->name, use_rename, ent_ref, OBJ_RENAME);
|
||||
|
||||
SCHEMAdefine_use(cur_schema, use_rename);
|
||||
|
||||
@@ -106,35 +123,41 @@ int test_schema_define_use() {
|
||||
* (to indicate partial reference)
|
||||
*/
|
||||
int test_schema_get_entities_ref() {
|
||||
Express model;
|
||||
Schema cur_schema, ref_schema;
|
||||
Rename *ref_rename;
|
||||
Entity ent;
|
||||
Symbol *cur_schema_id, *ent_id, *ent_ref, *ref_schema_id;
|
||||
Symbol e, *cur_schema_id, *ent_id, *ent_ref, *ref_schema_id;
|
||||
Linked_List r;
|
||||
|
||||
cur_schema_id = SYMBOLcreate("cur_schema", 1, "cur.exp");
|
||||
ent_id = SYMBOLcreate("line", 1, "cur.exp");
|
||||
ent_ref = SYMBOLcreate("line", 1, "ref.exp");
|
||||
ref_schema_id = SYMBOLcreate("ref_schema", 1, "ref.exp");
|
||||
model = SCOPEcreate(OBJ_EXPRESS);
|
||||
|
||||
e = (Symbol) {.name = "cur_schema", .type = OBJ_SCHEMA, .ref_tok = T_SCHEMA_REF};
|
||||
cur_schema_id = HASHsearch(model->symbol_table, e, HASH_INSERT);
|
||||
cur_schema = SCHEMAcreate();
|
||||
cur_schema->symbol = *cur_schema_id;
|
||||
cur_schema->u.schema->refdict = DICTcreate(20);
|
||||
cur_schema->u.schema->refdict = HASHcreate();
|
||||
|
||||
e = (Symbol) {.name = "ref_schema", .type = OBJ_SCHEMA, .ref_tok = T_SCHEMA_REF};
|
||||
ref_schema_id = HASHsearch(model->symbol_table, e, HASH_INSERT);
|
||||
ref_schema = SCHEMAcreate();
|
||||
ref_schema->symbol = *ref_schema_id;
|
||||
|
||||
ent = ENTITYcreate(ent_id);
|
||||
DICTdefine(ref_schema->symbol_table, ent_id->name, ent, ent_id, OBJ_ENTITY);
|
||||
|
||||
e = (Symbol) {.name = "line", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
ent_id = HASHsearch(ref_schema->symbol_table, e, HASH_INSERT);
|
||||
ent = ENTITYcreate(ent_id);
|
||||
|
||||
e = (Symbol) {.name = "line", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
ent_ref = HASHsearch(cur_schema->u.schema->refdict, e, HASH_INSERT);
|
||||
ref_rename = REN_new();
|
||||
ent_ref->data = ref_rename;
|
||||
|
||||
ref_rename->schema_sym = ref_schema_id;
|
||||
ref_rename->old = ent_ref;
|
||||
ref_rename->nnew = ent_ref;
|
||||
ref_rename->rename_type = ref;
|
||||
ref_rename->schema = ref_schema;
|
||||
ref_rename->object = ent;
|
||||
DICTdefine(cur_schema->u.schema->refdict, ent_ref->name, ref_rename, ent_ref, OBJ_ENTITY);
|
||||
|
||||
r = LISTcreate();
|
||||
cur_schema->search_id = -1;
|
||||
@@ -145,32 +168,37 @@ int test_schema_get_entities_ref() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Variable
|
||||
Symbol *
|
||||
ENTITY_find_attr_handler(struct Scope_ *entity, char * name, struct Symbol_** down_sym)
|
||||
{
|
||||
Variable r;
|
||||
Symbol e, *ep;
|
||||
(void) down_sym;
|
||||
r = DICTlookup(entity->symbol_table, name);
|
||||
return r;
|
||||
|
||||
e = (Symbol) {.name = name};
|
||||
ep = HASHsearch(entity->symbol_table, e, HASH_FIND);
|
||||
|
||||
return ep;
|
||||
}
|
||||
|
||||
int test_var_find() {
|
||||
Schema scope;
|
||||
Symbol *e_type_id, *attr_id;
|
||||
Symbol e, *e_type_id, *attr_id, *var_ref;
|
||||
Entity ent;
|
||||
Type attr_typ;
|
||||
TypeBody tb;
|
||||
Expression exp_attr;
|
||||
Variable var_attr, var_ref;
|
||||
Variable var_attr;
|
||||
Linked_List explicit_attr_list;
|
||||
|
||||
scope = SCHEMAcreate();
|
||||
|
||||
e_type_id = SYMBOLcreate("entity1", 1, "test2");
|
||||
e = (Symbol) {.name = "entity1", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
e_type_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
ent = ENTITYcreate(e_type_id);
|
||||
DICT_define(scope->symbol_table, e_type_id->name, ent, &ent->symbol, OBJ_ENTITY);
|
||||
e_type_id->data = ent;
|
||||
|
||||
attr_id = SYMBOLcreate("attr1", 1, "test2");
|
||||
e = (Symbol) {.name = "attr1", .type = OBJ_VARIABLE, .ref_tok = T_SIMPLE_REF};
|
||||
attr_id = HASHsearch(ent->symbol_table, e, HASH_INSERT);
|
||||
exp_attr = EXPcreate_from_symbol(Type_Attribute, attr_id);
|
||||
tb = TYPEBODYcreate(number_);
|
||||
attr_typ = TYPEcreate_from_body_anonymously(tb);
|
||||
@@ -181,11 +209,11 @@ int test_var_find() {
|
||||
LISTadd_last(explicit_attr_list, var_attr);
|
||||
|
||||
LISTadd_last(ent->u.entity->attributes, explicit_attr_list);
|
||||
DICTdefine(ent->symbol_table, attr_id->name, var_attr, &var_attr->name->symbol, OBJ_VARIABLE);
|
||||
attr_id->data = var_attr;
|
||||
|
||||
ENTITYfind_inherited_attribute_fake.custom_fake = ENTITY_find_attr_handler;
|
||||
|
||||
var_ref = VARfind(ent, "attr1", 1);
|
||||
var_ref = VARfind(ent, "attr1");
|
||||
|
||||
assert(var_ref != NULL);
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
/* core */
|
||||
#include "express/hash.h"
|
||||
#include "express/linklist.h"
|
||||
#include "expparse.h"
|
||||
|
||||
/* non-core */
|
||||
|
||||
#include "driver.h"
|
||||
#include "fff.h"
|
||||
|
||||
@@ -21,7 +21,7 @@ int __SCOPE_search_id;
|
||||
|
||||
int ENTITY_MARK;
|
||||
|
||||
Dictionary EXPRESSbuiltins;
|
||||
Hash_Table EXPRESSbuiltins;
|
||||
|
||||
|
||||
/*
|
||||
@@ -41,25 +41,26 @@ int test_scope_find() {
|
||||
Schema scope;
|
||||
Type sel, ent_base, chk_sel;
|
||||
Entity ent, chk_ent;
|
||||
Symbol *ent_id, *sel_id;
|
||||
Symbol e, *ent_id, *sel_id;
|
||||
|
||||
scope = SCHEMAcreate();
|
||||
ent_id = SYMBOLcreate("ent", 1, "test_4");
|
||||
sel_id = SYMBOLcreate("sel_typ", 1, "test_4");
|
||||
|
||||
e = (Symbol) {.name = "ent", .type = OBJ_ENTITY, .ref_tok = T_ENTITY_REF};
|
||||
ent_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
ent = ent_id->data = ENTITYcreate(ent_id);
|
||||
ent->superscope = scope;
|
||||
|
||||
ent_base = TYPEcreate_name(ent_id);
|
||||
ent_base->superscope = scope;
|
||||
ent = ENTITYcreate(ent_id);
|
||||
ent->superscope = scope;
|
||||
sel = TYPEcreate(select_);
|
||||
sel->symbol = *sel_id;
|
||||
|
||||
e = (Symbol) {.name = "sel_typ", .type = OBJ_TYPE,
|
||||
.ref_tok = T_TYPE_REF, .data = TYPEcreate(select_)};
|
||||
sel_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
sel = sel_id->data;
|
||||
sel->u.type->body->list = LISTcreate();
|
||||
sel->superscope = scope;
|
||||
LISTadd_last(sel->u.type->body->list, ent_base);
|
||||
|
||||
DICTdefine(scope->symbol_table, ent_id->name, ent, ent_id, OBJ_ENTITY);
|
||||
DICTdefine(scope->symbol_table, sel_id->name, sel, sel_id, OBJ_TYPE);
|
||||
|
||||
|
||||
scope->search_id = -1;
|
||||
chk_sel = SCOPE_find(scope, "sel_typ", SCOPE_FIND_ENTITY | SCOPE_FIND_TYPE);
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
/* core */
|
||||
#include "express/hash.h"
|
||||
#include "express/linklist.h"
|
||||
#include "expparse.h"
|
||||
|
||||
/* non-core */
|
||||
|
||||
#include "driver.h"
|
||||
#include "fff.h"
|
||||
|
||||
@@ -36,23 +36,23 @@ void setup() {
|
||||
|
||||
int test_type_create_user_defined_tag() {
|
||||
Schema scope;
|
||||
Function f;
|
||||
Type t, g, chk;
|
||||
Symbol *func_id, *tag_id;
|
||||
Symbol e, *func_id, *tag_id;
|
||||
|
||||
scope = SCHEMAcreate();
|
||||
|
||||
func_id = SYMBOLcreate("func1", 1, "test_5");
|
||||
tag_id = SYMBOLcreate("item1", 1, "test_5");
|
||||
e = (Symbol) {.name = "func1", .type = OBJ_FUNCTION,
|
||||
.ref_tok = T_FUNCTION_REF, .data = ALGcreate(OBJ_FUNCTION)};
|
||||
func_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
|
||||
f = ALGcreate(OBJ_FUNCTION);
|
||||
f->symbol = *func_id;
|
||||
DICTdefine(scope->symbol_table, func_id->name, f, func_id, OBJ_FUNCTION);
|
||||
e = (Symbol) {.name = "item1", .type = OBJ_TAG,
|
||||
.ref_tok = T_RULE_LABEL_REF};
|
||||
tag_id = HASHsearch(scope->symbol_table, e, HASH_INSERT);
|
||||
|
||||
g = TYPEcreate(generic_);
|
||||
t = TYPEcreate_nostab(tag_id, f, OBJ_TAG);
|
||||
t = TYPEcreate_nostab(tag_id, func_id->data, OBJ_TAG);
|
||||
|
||||
chk = TYPEcreate_user_defined_tag(g, f, tag_id);
|
||||
chk = TYPEcreate_user_defined_tag(g, func_id->data, tag_id);
|
||||
|
||||
assert(chk == t);
|
||||
|
||||
|
||||
+33
-25
@@ -52,31 +52,39 @@ struct qualifier {
|
||||
};
|
||||
|
||||
/** simple (single-valued) node types */
|
||||
typedef union YYSTYPE {
|
||||
Binary binary;
|
||||
Case_Item case_item;
|
||||
Expression expression;
|
||||
Integer iVal;
|
||||
Linked_List list;
|
||||
Logical logical;
|
||||
Op_Code op_code;
|
||||
Qualified_Attr * qualified_attr;
|
||||
Real rVal;
|
||||
Statement statement;
|
||||
Symbol * symbol;
|
||||
char * string;
|
||||
Type type;
|
||||
TypeBody typebody;
|
||||
Variable variable;
|
||||
Where where;
|
||||
|
||||
struct type_either type_either;
|
||||
struct type_flags type_flags;
|
||||
struct entity_body entity_body;
|
||||
struct subsuper_decl subsuper_decl;
|
||||
struct subtypes subtypes;
|
||||
struct upper_lower upper_lower;
|
||||
struct qualifier qualifier;
|
||||
unsigned int val;
|
||||
typedef struct YYSTYPE {
|
||||
int scope_idx;
|
||||
|
||||
union {
|
||||
Binary binary;
|
||||
Case_Item case_item;
|
||||
Expression expression;
|
||||
Integer iVal;
|
||||
Linked_List list;
|
||||
Logical logical;
|
||||
Op_Code op_code;
|
||||
Qualified_Attr * qualified_attr;
|
||||
Real rVal;
|
||||
Statement statement;
|
||||
Symbol * symbol;
|
||||
char * string;
|
||||
/* TODO: remove after parser rebuild / reconsider */
|
||||
char *cstr;
|
||||
Type type;
|
||||
TypeBody typebody;
|
||||
Variable variable;
|
||||
Where where;
|
||||
|
||||
/* TODO: can probably have one integrated structure */
|
||||
struct type_either type_either;
|
||||
struct type_flags type_flags;
|
||||
struct entity_body entity_body;
|
||||
struct subsuper_decl subsuper_decl;
|
||||
struct subtypes subtypes;
|
||||
struct upper_lower upper_lower;
|
||||
struct qualifier qualifier;
|
||||
unsigned int val;
|
||||
};
|
||||
} YYSTYPE;
|
||||
#endif
|
||||
|
||||
+12
-26
@@ -124,45 +124,31 @@ This module implements the type abstraction. It is
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "sc_memmgr.h"
|
||||
#include "express/hash.h"
|
||||
#include "express/type.h"
|
||||
|
||||
Type TYPEcreate_user_defined_tag( Type base, Scope scope, struct Symbol_ *symbol ) {
|
||||
Symbol *ep;
|
||||
Type t;
|
||||
extern int tag_count;
|
||||
|
||||
t = ( Type )DICTlookup( scope->symbol_table, symbol->name );
|
||||
if( t ) {
|
||||
if( DICT_type == OBJ_TAG ) {
|
||||
return( t );
|
||||
ep = HASHsearch( scope->symbol_table, (Symbol) { .name = symbol->name }, HASH_FIND );
|
||||
if (ep) {
|
||||
t = (Type) ep->data;
|
||||
if( ep->type == OBJ_TAG ) {
|
||||
return t;
|
||||
} else {
|
||||
/* easiest to just generate the error this way!
|
||||
* following call WILL fail intentionally
|
||||
*/
|
||||
DICTdefine( scope->symbol_table, symbol->name, 0, symbol, OBJ_TAG );
|
||||
return( 0 );
|
||||
/* TODO: print error message (duplicate parameter) */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* tag is undefined
|
||||
* if we are outside a formal parameter list (hack, hack)
|
||||
* then we can only refer to existing tags, so produce an error
|
||||
*/
|
||||
if( tag_count < 0 ) {
|
||||
ERRORreport_with_symbol( UNDEFINED_TAG, symbol,
|
||||
symbol->name );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* otherwise, we're in a formal parameter list,
|
||||
* so it's ok to define it
|
||||
*/
|
||||
/* otherwise, define it */
|
||||
t = TYPEcreate_nostab( symbol, scope, OBJ_TAG );
|
||||
t->u.type->head = base;
|
||||
|
||||
/* count unique type tags inside PROC and FUNC headers */
|
||||
tag_count++;
|
||||
|
||||
return( t );
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -97,7 +97,7 @@ void VARinitialize() {
|
||||
* returns simple name of variable
|
||||
* for example, if var is named SELF\xxx.yyy, return yyy
|
||||
*/
|
||||
extern char * VARget_simple_name( Variable v ) {
|
||||
extern const char * VARget_simple_name( Variable v ) {
|
||||
Expression e = VARget_name( v );
|
||||
|
||||
while( TYPEis_expression( EXPget_type( e ) ) ) {
|
||||
|
||||
Reference in New Issue
Block a user