diff --git a/Doxyfile b/Doxyfile index b16ca93..ac62a32 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1,4 +1,4 @@ -# Doxyfile 1.6.1 +# Doxyfile 1.7.3 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project @@ -14,276 +14,300 @@ # Project related configuration options #--------------------------------------------------------------------------- -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = lci -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = +PROJECT_NUMBER = 0.10.0 -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "A LOLCODE interpreter written in C." + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = ./lci.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. -OUTPUT_DIRECTORY = +OUTPUT_DIRECTORY = . -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" -ABBREVIATE_BRIEF = +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the # path to strip. -STRIP_FROM_PATH = +STRIP_FROM_PATH = -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. -STRIP_FROM_INC_PATH = +STRIP_FROM_INC_PATH = -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) -JAVADOC_AUTOBRIEF = YES +JAVADOC_AUTOBRIEF = NO -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it # re-implements. -INHERIT_DOCS = YES +INHERIT_DOCS = NO -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO -# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. -ALIASES = +ALIASES = -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO -# Doxygen selects the parser to use depending on the extension of the files it parses. -# With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this tag. -# The format is ext=language, where ext is a file extension, and language is one of -# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, -# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), -# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. -EXTENSION_MAPPING = +EXTENSION_MAPPING = -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO -# If you use Microsoft's C++/CLI language, you should set this option to YES to +# If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. -IDL_PROPERTY_SUPPORT = YES +IDL_PROPERTY_SUPPORT = NO -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. -TYPEDEF_HIDES_STRUCT = YES +TYPEDEF_HIDES_STRUCT = NO -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 @@ -292,772 +316,940 @@ SYMBOL_CACHE_SIZE = 0 # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES -EXTRACT_ALL = NO +EXTRACT_ALL = YES -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file +# If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. -CASE_SENSE_NAMES = YES +CASE_SENSE_NAMES = NO -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation # of that file. -SHOW_INCLUDE_FILES = NO +SHOW_INCLUDE_FILES = YES -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in # declaration order. -SORT_MEMBER_DOCS = YES +SORT_MEMBER_DOCS = NO -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in # declaration order. -SORT_BRIEF_DOCS = YES +SORT_BRIEF_DOCS = NO -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES -# The ENABLED_SECTIONS tag can be used to enable conditional +# The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. -ENABLED_SECTIONS = +ENABLED_SECTIONS = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. -FILE_VERSION_FILTER = +FILE_VERSION_FILTER = -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by -# doxygen. The layout file controls the global structure of the generated output files -# in an output format independent way. The create the layout file that represents -# doxygen's defaults, run doxygen with the -l option. You can optionally specify a -# file name after the option, if omitted DoxygenLayout.xml will be used as the name -# of the layout file. +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. -LAYOUT_FILE = +LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated +# The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of # documentation. -WARN_NO_PARAMDOC = NO +WARN_NO_PARAMDOC = YES -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written # to stderr. -WARN_LOGFILE = +WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = +INPUT = . -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl -FILE_PATTERNS = +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = +EXCLUDE = -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* -EXCLUDE_PATTERNS = */test/* +EXCLUDE_PATTERNS = -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = +EXAMPLE_PATH = -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left # blank all files are included. -EXAMPLE_PATTERNS = +EXAMPLE_PATTERNS = * -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = +IMAGE_PATH = -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. -INPUT_FILTER = +INPUT_FILTER = -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. -FILTER_PATTERNS = +FILTER_PATTERNS = -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO -# Setting the INLINE_SOURCES tag to YES will include the body +# Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. -REFERENCES_LINK_SOURCE = NO +REFERENCES_LINK_SOURCE = YES -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. -VERBATIM_HEADERS = NO +VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. -ALPHABETICAL_INDEX = NO +ALPHABETICAL_INDEX = YES -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. -IGNORE_PREFIX = +IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a # standard header. -HTML_HEADER = +HTML_HEADER = -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a # standard footer. -HTML_FOOTER = +HTML_FOOTER = -# If the HTML_TIMESTAMP tag is set to YES then the generated HTML -# documentation will contain the timesstamp. - -HTML_TIMESTAMP = NO - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! -HTML_STYLESHEET = +HTML_STYLESHEET = -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. GENERATE_DOCSET = NO -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be # written to the html output directory. -CHM_FILE = +CHM_FILE = -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. -HHC_LOCATION = +HHC_LOCATION = -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. -CHM_INDEX_ENCODING = +CHM_INDEX_ENCODING = -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO -# The TOC_EXPAND flag can be set to YES to add extra items for group members +# The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER -# are set, an additional index file will be generated that can be used as input for -# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated -# HTML documentation. +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. -QCH_FILE = +QCH_FILE = -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace -QHP_NAMESPACE = +QHP_NAMESPACE = org.doxygen.Project -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. -# For more information please see +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters -QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_NAME = -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see -# Qt Help Project / Custom Filters. +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. -QHP_CUST_FILTER_ATTRS = +QHP_CUST_FILTER_ATTRS = -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's -# filter section matches. -# Qt Help Project / Filter Attributes. +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. -QHP_SECT_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. -QHG_LOCATION = +QHG_LOCATION = -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. +# This tag can be used to set the number of enum values (range [0,1..20]) +# that doxygen will group on one line in the generated HTML documentation. +# Note that a value of 0 will completely suppress the enum values from +# appearing in the overview section. ENUM_VALUES_PER_LINE = 4 -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NO -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 -# When the SEARCHENGINE tag is enable doxygen will generate a search box for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP) -# there is already a search function so this one should typically -# be disabled. +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. -GENERATE_LATEX = NO +GENERATE_LATEX = YES -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. LATEX_CMD_NAME = latex -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. -PAPER_TYPE = a4wide +PAPER_TYPE = a4 -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. -EXTRA_PACKAGES = +EXTRA_PACKAGES = -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! -LATEX_HEADER = +LATEX_HEADER = -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO -# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO @@ -1065,68 +1257,68 @@ LATEX_SOURCE_CODE = NO # configuration options related to the RTF output #--------------------------------------------------------------------------- -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. -RTF_STYLESHEET_FILE = +RTF_STYLESHEET_FILE = -# Set optional variables used in the generation of an rtf document. +# Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. -RTF_EXTENSIONS_FILE = +RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man -# The MAN_EXTENSION tag determines the extension that is added to +# The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO @@ -1135,33 +1327,33 @@ MAN_LINKS = NO # configuration options related to the XML output #--------------------------------------------------------------------------- -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the # syntax of the XML files. -XML_SCHEMA = +XML_SCHEMA = -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the # syntax of the XML files. -XML_DTD = +XML_DTD = -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES @@ -1170,10 +1362,10 @@ XML_PROGRAMLISTING = YES # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO @@ -1182,100 +1374,98 @@ GENERATE_AUTOGEN_DEF = NO # configuration options related to the Perl module output #--------------------------------------------------------------------------- -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. -PERLMOD_MAKEVAR_PREFIX = +PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by # the preprocessor. -INCLUDE_PATH = +INCLUDE_PATH = -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. -INCLUDE_FILE_PATTERNS = +INCLUDE_FILE_PATTERNS = -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = +PREDEFINED = -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. -EXPAND_AS_DEFINED = +EXPAND_AS_DEFINED = -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES @@ -1283,43 +1473,41 @@ SKIP_FUNCTION_MACROS = YES # Configuration::additions related to external references #--------------------------------------------------------------------------- -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. -TAGFILES = +TAGFILES = -# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. -GENERATE_TAGFILE = +GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES -# The PERL_PATH should be the absolute path and name of the perl script +# The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl @@ -1328,192 +1516,204 @@ PERL_PATH = /usr/bin/perl # Configuration options related to the dot tool #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. -MSCGEN_PATH = +MSCGEN_PATH = -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called Helvetica to the output +# directory and reference it in all dot files that doxygen generates. +# When you want a differently looking font you can specify the font name +# using DOT_FONTNAME. You need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. -DOT_FONTNAME = FreeSans +DOT_FONTNAME = Helvetica -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. -DOT_FONTPATH = +DOT_FONTPATH = -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO -# If set to YES, the inheritance and collaboration graphs will show the +# If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, svg, gif or svg. # If left blank png will be used. DOT_IMAGE_FORMAT = png -# The tag DOT_PATH can be used to specify the path where the dot tool can be +# The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. -DOT_PATH = +DOT_PATH = -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the # \dotfile command). -DOTFILE_DIRS = +DOTFILE_DIRS = -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES diff --git a/Makefile b/Makefile index b686aec..04306c0 100644 --- a/Makefile +++ b/Makefile @@ -13,21 +13,24 @@ testdir = ./test all: $(TARGET) -$(TARGET): $(OBJS) $(LIBS) +$(TARGET): $(OBJS) $(CC) $(CPPFLAGS) -o $(TARGET) $(OBJS) $(LIBS) pedantic: $(OBJS) $(LIBS) - $(CC) -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wundef -Wall -ansi -pedantic -g -o $(TARGET) $(SRCS) $(HDRS) $(LIBS) + $(CC) -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wundef -Wall -ansi -pedantic -o $(TARGET) $(SRCS) $(HDRS) $(LIBS) lint: all $(LINT) $(SRCS) +debug: $(OBJS) $(LIBS) + $(CC) -g -o $(TARGET) $(SRCS) $(LIBS) + check: all - @cd $(testdir) && ./testDir.sh -q ../$(TARGET) 1.3-Tests/ + @cd $(testdir) && ./testDir.sh -q ../$(TARGET) 1.3-Tests check-mem: all @echo "This will take a long time! Be patient!" - @cd $(testdir) && ./testDir.sh -q -m ../$(TARGET) 1.3-Tests/ + @cd $(testdir) && ./testDir.sh -q -m ../$(TARGET) 1.3-Tests install: all $(INSTALL) $(TARGET) $(bindir)/$(TARGET) diff --git a/README b/README index d1b1319..81f6a75 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ LICENSE - Copyright (C) 2010 Justin J. Meza + Copyright (C) 2010-2011 Justin J. Meza This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,15 +22,15 @@ ABOUT lci is a LOLCODE interpreter written in C and is designed to be correct, portable, fast, and precisely documented. - * correct: Every effort has been made to test lci's conformance to the + - correct: Every effort has been made to test lci's conformance to the LOLCODE language specification. Unit tests come packaged with the lci source code. - * portable: lci follows the widely ported ANSI C specification allowing it + - portable: lci follows the widely ported ANSI C specification allowing it to compile on a broad range of systems. - * fast: Much effort has gone into producing simple and efficient code + - fast: Much effort has gone into producing simple and efficient code whenever possible to the extent that the above points are not compromized. - * precisely documented: lci uses Doxygen to generate literate code + - precisely documented: lci uses Doxygen to generate literate code documentation, browsable here. This project's homepage is at http://icanhaslolcode.org. For help, visit diff --git a/interpreter.c b/interpreter.c index ddfca4a..8276007 100644 --- a/interpreter.c +++ b/interpreter.c @@ -1,11 +1,53 @@ #include "interpreter.h" -/** Creates a string by copying the contents of another string. - * - * \return A pointer to a string containing the copied contents of \a data. - * - * \retval NULL malloc was unable to allocate memory. */ -char *createString(char *data) /**< [in] A pointer to the string data to store. */ +/** + * Prints out an interpreter error message. + * + * The verbosity of the message depends on the number of arguments supplied. + * - If all arguments are supplied, the error message will be of the form + * "FILE:LINE: INFO before: NEXT.\n", where FILE and LINE are the file and + * line that \a target appears on, INFO is the string \a info, and NEXT is the + * image of \a target, as evaluated in \a scope. + * - If only \a info and \a target are supplied (and \a scope is NULL), then the + * error message will be of the form "FILE:LINE: INFO.\n". + * - If only \a info is supplied (and \a target and \a scope are both NULL), + * then the error message will be of the form "INFO.\n". + * + * \param [in] info The error message to print. + * + * \param [in] target The optional identifier to reference in the error message. + * + * \param [in] scope The optional scope to evaluate \a target in. + */ +void printInterpreterError(const char *info, + IdentifierNode *target, + ScopeObject *scope) +{ + if (!info) return; + + if (target && scope) { + char *name = resolveIdentifierName(target, scope); + fprintf(stderr, "%s:%u: %s at: %s\n", target->fname, target->line, info, name); + free(name); + } + else if (target && !scope) { + fprintf(stderr, "%s:%u: %s.\n", target->fname, target->line, info); + } + else { + fprintf(stderr, "%s.\n", info); + } +} + +/** + * Creates a new string by copying the contents of another string. + * + * \param [in] data The string to copy. + * + * \return A new string whose contents is a copy of \a data. + * + * \retval NULL Memory allocation failed. + */ +char *copyString(char *data) { char *p = malloc(sizeof(char) * (strlen(data) + 1)); if (!p) { @@ -16,275 +58,85 @@ char *createString(char *data) /**< [in] A pointer to the string data to store. return p; } -/** Creates a nil type ValueObject structure. - * - * \return A pointer to a nil type ValueObject structure. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see createBooleanValueObject(int) - * \see createIntegerValueObject(int) - * \see createFloatValueObject(float) - * \see createStringValueObject(char *) - * \see createFunctionValueObject(FuncDefStmtNode *) - * \see deleteValueObject(ValueObject *) */ -ValueObject *createNilValueObject(void) +/** + * Checks if a string follows the format of a decimal number. + * + * \param [in] data The string to check the format of. + * + * \retval 0 The string is not a decimal number. + * + * \retval 1 The string is a decimal number. + */ +unsigned int isDecString(const char *data) { - ValueObject *p = malloc(sizeof(ValueObject)); - if (!p) { - perror("malloc"); - return NULL; + size_t n; + size_t len = strlen(data); + + /* Check for an empty string */ + if (len == 0) return 0; + + /* Check for non-digit, non-hyphen, and non-period characters */ + for (n = 0; n < len; n++) { + if (!isdigit(data[n]) + && data[n] != '.' + && data[n] != '-') + return 0; } - p->type = VT_NIL; - p->semaphore = 1; - return p; + + return 1; } -/** Creates a boolean type ValueObject structure. - * - * \return A pointer to a boolean type ValueObject structure with value - * \c 0 if \a data equals 0 and \c 1 otherwise. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see createNilValueObject(void) - * \see createIntegerValueObject(int) - * \see createFloatValueObject(float) - * \see createStringValueObject(char *) - * \see createFunctionValueObject(FuncDefStmtNode *) - * \see deleteValueObject(ValueObject *) */ -ValueObject *createBooleanValueObject(int data) /**< [in] The boolean data to store. */ +/** + * Checks if a string follows the format of a hexadecimal number. + * + * \param [in] data The characters to check the format of. + * + * \retval 0 The string is not a hexadecimal number. + * + * \retval 1 The string is a hexadecimal number. + */ +unsigned int isHexString(const char *data) { - ValueObject *p = malloc(sizeof(ValueObject)); - if (!p) { - perror("malloc"); - return NULL; + size_t n; + size_t len = strlen(data); + + /* Check for empty string */ + if (len == 0) return 0; + + /* Check for non-digit and non-A-through-F characters */ + for (n = 0; n < len; n++) { + if (!isdigit(data[n]) + && data[n] != 'A' + && data[n] != 'B' + && data[n] != 'C' + && data[n] != 'D' + && data[n] != 'E' + && data[n] != 'F' + && data[n] != 'a' + && data[n] != 'b' + && data[n] != 'c' + && data[n] != 'd' + && data[n] != 'e' + && data[n] != 'f') + return 0; } - p->type = VT_BOOLEAN; - p->data.i = (data != 0); - p->semaphore = 1; - return p; + + return 1; } -/** Creates an integer type ValueObject structure. - * - * \return A pointer to an integer type ValueObject structure with value - * \a data. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see createNilValueObject(void) - * \see createBooleanValueObject(int) - * \see createFloatValueObject(float) - * \see createStringValueObject(char *) - * \see createFunctionValueObject(FuncDefStmtNode *) - * \see deleteValueObject(ValueObject *) */ -ValueObject *createIntegerValueObject(int data) /**< [in] The integer data to store. */ -{ - ValueObject *p = malloc(sizeof(ValueObject)); - if (!p) { - perror("malloc"); - return NULL; - } - p->type = VT_INTEGER; - p->data.i = data; - p->semaphore = 1; - return p; -} - -/** Creates a floating point data decimal type ValueObject structure. - * - * \return A pointer to a floating point decimal type ValueObject structure - * with value \a data. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see createNilValueObject(void) - * \see createBooleanValueObject(int) - * \see createIntegerValueObject(int) - * \see createStringValueObject(char *) - * \see createFunctionValueObject(FuncDefStmtNode *) - * \see deleteValueObject(ValueObject *) */ -ValueObject *createFloatValueObject(float data) /**< [in] The floating point data to store. */ -{ - ValueObject *p = malloc(sizeof(ValueObject)); - if (!p) { - perror("malloc"); - return NULL; - } - p->type = VT_FLOAT; - p->data.f = data; - p->semaphore = 1; - return p; -} - -/** Creates a string type ValueObject structure. - * - * \return A pointer to a string type ValueObject structure with value \a data. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see createNilValueObject(void) - * \see createBooleanValueObject(int) - * \see createIntegerValueObject(int) - * \see createFloatValueObject(float) - * \see createFunctionValueObject(FuncDefStmtNode *) - * \see deleteValueObject(ValueObject *) */ -ValueObject *createStringValueObject(char *data) /**< [in] The string data to store. */ -{ - ValueObject *p = malloc(sizeof(ValueObject)); - if (!p) { - perror("malloc"); - return NULL; - } - p->type = VT_STRING; - p->data.s = data; - p->semaphore = 1; - return p; -} - -/** Creates a function type ValueObject structure. - * - * \return A pointer to a function type ValueObject structure with definition \a data. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see createNilValueObject(void) - * \see createBooleanValueObject(int) - * \see createIntegerValueObject(int) - * \see createFloatValueObject(float) - * \see createStringValueObject(char *) - * \see deleteValueObject(ValueObject *) */ -ValueObject *createFunctionValueObject(FuncDefStmtNode *data) /**< [in] The function definition to store. */ -{ - ValueObject *p = malloc(sizeof(ValueObject)); - if (!p) { - perror("malloc"); - return NULL; - } - p->type = VT_FUNC; - p->data.fn = data; - p->semaphore = 1; - return p; -} - -/** Copies a ValueObject structure. - * - * \note What this function actually does is increment a semaphore in \a value - * and return \a value. The semaphore gets decremented when \a value - * gets deleted by deleteValueObject(ValueObject *). This way, an - * immutable copy of a ValueObject structure may be made without actaully - * copying its blocks of memory; this reduces the overhead associated - * with copying a ValueObject strcuture while still preserving its - * functionality. - * - * \pre \a value was created by either createNilValueObject(void), createBooleanValueObject(int), - * createIntegerValueObject(int), createFloatValueObject(float), createStringValueObject(char *), - * or copied with copyValueObject(ValueObject *). - * - * \return A pointer to a ValueObject with the same type and contents as - * \a value. - * - * \retval NULL The type of \a value is unknown. - * - * \see createNilValueObject(void) - * \see createBooleanValueObject(int) - * \see createIntegerValueObject(int) - * \see createFloatValueObject(float) - * \see createStringValueObject(char *) - * \see deleteValueObject(ValueObject *) */ -ValueObject *copyValueObject(ValueObject *value) /**< [in,out] The ValueObject structure to create a copy of. */ -{ - V(value); - return value; -} - -/** Deletes a ValueObject structure. - * - * \pre \a value was created by either createNilValueObject(void), createBooleanValueObject(int), - * createIntegerValueObject(int), createFloatValueObject(float), createStringValueObject(char *), - * or copied with copyValueObject(ValueObject *). - * - * \post The memory at \a value and any of its associated members will be - * freed (see note). - * - * \note What this function actually does is decrement a semaphore in \a value - * and delete \a value if the semaphore reaches 0 as a result of the - * decrement. The semaphore gets incremented when either the value is - * created or it gets copied by copyValueObject(ValueObject *). This - * way, an immutable copy of a ValueObject structure may be made without - * actually copying its blocks of memory. - * - * \see createNilValueObject(void) - * \see createBooleanValueObject(int) - * \see createIntegerValueObject(int) - * \see createFloatValueObject(float) - * \see createStringValueObject(char *) - * \see copyValueObject(ValueObject *) */ -void deleteValueObject(ValueObject *value) /**< [in,out] A pointer to the ValueObject structure to be deleted. */ -{ - if (!value) return; - P(value); - if (!value->semaphore) { - if (value->type == VT_STRING) free(value->data.s); - /* FuncDefStmtNode structures get freed with the parse tree */ - free(value); - } -} - -/** Creates a ReturnObject structure. - * - * \pre \a value was created by either createNilValueObject(void), createBooleanValueObject(int), - * createIntegerValueObject(int), createFloatValueObject(float), createStringValueObject(char *), - * or copied with copyValueObject(ValueObject *). - * - * \return A pointer to a ReturnObject structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteReturnObject(ReturnObject *) */ -ReturnObject *createReturnObject(ReturnType type, /**< [in] The type of return encountered. */ - ValueObject *value) /**< [in] A pointer to the ValueObject structure specifying the return value (optional, \c NULL if unused). */ -{ - ReturnObject *p = malloc(sizeof(ReturnObject)); - if (!p) { - perror("malloc"); - return NULL; - } - p->type = type; - p->value = value; - return p; -} - -/** Deletes a ReturnObject structure. - * - * \pre \a object was created by createReturnObject(ReturnType, ValueObject *). - * - * \post The memory at \a object and any of its associated members will be - * freed. - * - * \see createReturnObject(ReturnType, ValueObject *) */ -void deleteReturnObject(ReturnObject *object) /**< [in,out] The ReturnObject structure to be deleted. */ -{ - if (!object) return; - if (object->type == RT_RETURN) - deleteValueObject(object->value); - free(object); -} - -/** Translates an identifier into a string naming a variable. - * - * \pre \a id was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A newly-allocated array of characters representing the name of the - * identifier. - * - * \retval NULL malloc was unable to allocate memory. */ -char *resolveIdentifierName(IdentifierNode *id, /**< [in] A pointer to the IdentifierNode structure to translate. */ - ScopeObject *scope) /**< [in] A pointer to the ScopeObject structure to translate \a id under. */ +/** + * Evaluates an identifier to produce its name as a string. + * + * \param [in] id The identifier to evaluate. + * + * \param [in] scope The scope to evaluate \a id under. + * + * \return A new string containing the evaluated name of the identifier. + * + * \retval NULL Memory allocation failed. + */ +char *resolveIdentifierName(IdentifierNode *id, + ScopeObject *scope) { ValueObject *val = NULL; ValueObject *str = NULL; @@ -311,12 +163,12 @@ char *resolveIdentifierName(IdentifierNode *id, /**< [in] A pointer to the Ident deleteValueObject(val); /* Copy the evaluated string */ - ret = createString(getString(str)); + ret = copyString(getString(str)); if (!ret) goto resolveIdentifierNameAbort; deleteValueObject(str); } else { - fprintf(stderr, "%s:%u: invalid identifier type\n", id->fname, id->line); + printInterpreterError("invalid identifier type", id, scope); } return ret; @@ -331,19 +183,228 @@ resolveIdentifierNameAbort: /* Exception handline */ return NULL; } -/** Creates a ScopeObject structure. - * - * \pre \a parent was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *) - * or is \c NULL if creating the root parent. - * - * \return A pointer to a ScopeObject structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteScopeObject(ScopeObject *) */ -ScopeObject *createScopeObject(ScopeObject *parent) /**< [in] A pointer to the parent ScopeObject structure. */ +/** + * Creates a nil-type value. + * + * \return A new nil-type value. + * + * \retval NULL Memory allocation failed. + */ +ValueObject *createNilValueObject(void) +{ + ValueObject *p = malloc(sizeof(ValueObject)); + if (!p) { + perror("malloc"); + return NULL; + } + p->type = VT_NIL; + p->semaphore = 1; + return p; +} + +/** + * Creates a boolean-type value. + * + * \param [in] data The boolean data to store. + * + * \return A boolean-type value equalling 0 if \a data equals 0 and 1 otherwise. + * + * \retval NULL Memory allocation failed. + */ +ValueObject *createBooleanValueObject(int data) +{ + ValueObject *p = malloc(sizeof(ValueObject)); + if (!p) { + perror("malloc"); + return NULL; + } + p->type = VT_BOOLEAN; + p->data.i = (data != 0); + p->semaphore = 1; + return p; +} + +/** + * Creates a integer-type value. + * + * \param [in] data The integer data to store. + * + * \return An integer-type value equalling \a data. + * + * \retval NULL Memory allocation failed. + */ +ValueObject *createIntegerValueObject(int data) +{ + ValueObject *p = malloc(sizeof(ValueObject)); + if (!p) { + perror("malloc"); + return NULL; + } + p->type = VT_INTEGER; + p->data.i = data; + p->semaphore = 1; + return p; +} + +/** + * Creates a floating-point-type value. + * + * \param [in] data The floating-point data to store. + * + * \return A floating-point-type value equalling \a data. + * + * \retval NULL Memory allocation failed. + */ +ValueObject *createFloatValueObject(float data) +{ + ValueObject *p = malloc(sizeof(ValueObject)); + if (!p) { + perror("malloc"); + return NULL; + } + p->type = VT_FLOAT; + p->data.f = data; + p->semaphore = 1; + return p; +} + +/** + * Creates a string-type value. + * + * \param [in] data The string data to store. + * + * \note \a data is stored as-is; no copy of it is made. + * + * \return A string-type value equalling \a data. + * + * \retval NULL Memory allocation failed. + */ +ValueObject *createStringValueObject(char *data) +{ + ValueObject *p = malloc(sizeof(ValueObject)); + if (!p) { + perror("malloc"); + return NULL; + } + p->type = VT_STRING; + p->data.s = data; + p->semaphore = 1; + return p; +} + +/** + * Creates a function-type value. + * + * \param [in] def The function definition to store. + * + * \return A function-type value containing \a data. + * + * \retval NULL Memory allocation failed. + */ +ValueObject *createFunctionValueObject(FuncDefStmtNode *def) +{ + ValueObject *p = malloc(sizeof(ValueObject)); + if (!p) { + perror("malloc"); + return NULL; + } + p->type = VT_FUNC; + p->data.fn = def; + p->semaphore = 1; + return p; +} + +/** + * Creates an array-type value. + * + * \param [in] parent The optional parent scope to use. + * + * \note \a parent may be NULL, in which case this array is treated as the root. + * + * \return An empty array-type value with parent \a parent. + * + * \retval NULL Memory allocation failed. + */ +ValueObject *createArrayValueObject(ScopeObject *parent) +{ + ValueObject *p = malloc(sizeof(ValueObject)); + if (!p) { + perror("malloc"); + return NULL; + } + p->type = VT_ARRAY; + p->data.a = createScopeObject(parent); + if (!p->data.a) { + free(p); + return NULL; + } + p->semaphore = 1; + return p; +} + +/** + * Copies a value. + * + * Instead of actually performing a copy of memory, this function increments a + * semaphore in \a value and returns \a value again. The semaphore gets + * decremented when \a value gets deleted. This way, an immutable copy of a + * value may be made without actually copying its blocks of memory; this reduces + * the overhead associated with copying a value--a fairly common + * operation--while still preserving its usability. + * + * \param [in,out] value The value to copy. + * + * \return A value with the same type and contents as \a value. + * + * \retval NULL The type of \a value is unrecognized. + */ +ValueObject *copyValueObject(ValueObject *value) +{ + V(value); + return value; +} + +/** + * Deletes a value. + * + * This function decrements a semaphore in \a value and deletes \a value if the + * semaphore reaches 0 (no copies of this value are need anymore). The + * semaphore gets incremented when either the value is created or it gets + * copied. This way, an immutable copy of the value may be made without + * actually copying its memory. + * + * \param [in,out] value The value to delete. + * + * \post The memory at \a value and any of its members will be freed (although + * see note for full details). + */ +void deleteValueObject(ValueObject *value) +{ + if (!value) return; + P(value); + if (!value->semaphore) { + if (value->type == VT_STRING) + free(value->data.s); + /* FuncDefStmtNode structures get freed with the parse tree */ + else if (value->type == VT_ARRAY) + deleteScopeObject(value->data.a); + free(value); + } +} + +/** + * Creates a scope. + * + * Scopes are used to map identifiers to values. Scopes are organized + * hierarchically. + * + * \param [in] parent The optional parent scope to use. + * + * \return An empty scope with parent \a parent. + * + * \retval NULL Memory allocation failed. + */ +ScopeObject *createScopeObject(ScopeObject *parent) { ScopeObject *p = malloc(sizeof(ScopeObject)); if (!p) { @@ -362,17 +423,14 @@ ScopeObject *createScopeObject(ScopeObject *parent) /**< [in] A pointer to the p return p; } -/** Deletes a ScopeObject structure. - * - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \post The memory at \a scope and any of its associated members will be - * freed. - * - * \see createScopeObject(ScopeObject *) */ -void deleteScopeObject(ScopeObject *scope) /**< [in,out] The ScopeObject structure to delete. */ +/** + * Deletes a scope. + * + * \param [in,out] scope The scope to delete. + * + * \post The memory at \a scope and any of its members will be freed. + */ +void deleteScopeObject(ScopeObject *scope) { unsigned int n; if (!scope) return; @@ -386,31 +444,216 @@ void deleteScopeObject(ScopeObject *scope) /**< [in,out] The ScopeObject structu free(scope); } -/** Retrieves a named ValueObject structure from a ScopeObject structure, - * traversing its parents if necessary. - * - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * - * \return A pointer to the stored ValueObject structure named by \a target. - * - * \retval NULL \a target could not be found in \a scope. - * - * \see getLocalScopeValue(ScopeObject *, IdentifierNode *) - * \see createScopeValue(ScopeObject *, IdentifierNode *) - * \see updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *) - * \see deleteScopeValue(ScopeObject *, IdentifierNode *) */ -ValueObject *getScopeValue(ScopeObject *scope, /**< [in] The ScopeObject structure to check. */ - IdentifierNode *target) /**< [in] The name of the value to find. */ +/** + * Creates a new, nil-type value in a scope. + * + * \param [in] src The scope to evaluate \a target under. + * + * \param [in,out] dest The scope to create the new value in. + * + * \param [in] target The name of the value to create. + * + * \return The newly-created value. + * + * \retval NULL Memory allocation failed. + */ +ValueObject *createScopeValue(ScopeObject *src, + ScopeObject *dest, + IdentifierNode *target) { - ScopeObject *current = scope; + ScopeObject *parent = dest; + IdentifierNode *child = target; + int status; + unsigned int newnumvals; + void *mem1 = NULL; + void *mem2 = NULL; + char *name = NULL; + + /* Traverse the target to the terminal child and parent */ + status = resolveTerminalSlot(src, dest, target, &parent, &child); + if (!status) goto createScopeValueAbort; + + /* Store the new number of values */ + newnumvals = dest->numvals + 1; + + /* Look up the identifier name */ + name = resolveIdentifierName(target, src); + if (!name) goto createScopeValueAbort; + + /* Add value to local scope */ + mem1 = realloc(dest->names, sizeof(IdentifierNode *) * newnumvals); + if (!mem1) { + perror("realloc"); + goto createScopeValueAbort; + } + mem2 = realloc(dest->values, sizeof(ValueObject *) * newnumvals); + if (!mem2) { + perror("realloc"); + goto createScopeValueAbort; + } + + dest->names = mem1; + dest->values = mem2; + dest->names[dest->numvals] = name; + dest->values[dest->numvals] = createNilValueObject(); + if (!dest->values[dest->numvals]) goto createScopeValueAbort; + dest->numvals = newnumvals; + + return dest->values[dest->numvals - 1]; + +createScopeValueAbort: /* In case something goes wrong... */ + + /* Clean up any allocated structures */ + if (name) free(name); + if (mem1) free(mem1); + if (mem2) free(mem2); + + return NULL; +} + +/** + * Updates a value in a scope. + * + * \param [in] src The scope to evaluate \a target under. + * + * \param [in,out] dest The scope to update the value in. + * + * \param [in] target The name of the value to create. + * + * \param [in] value The new value to assign. + * + * \return The updated value (will be the same as \a val). + * + * \retval NULL Either \a target could not be evaluated in \a src or \a target + * could not be found in \a dest. + */ +ValueObject *updateScopeValue(ScopeObject *src, + ScopeObject *dest, + IdentifierNode *target, + ValueObject *value) +{ + ScopeObject *parent = dest; + IdentifierNode *child = target; + int status; + char *name = NULL; + + /* Traverse the target to the terminal child and parent */ + status = resolveTerminalSlot(src, dest, target, &parent, &child); + if (!status) goto updateScopeValueAbort; + + /* Look up the identifier name */ + name = resolveIdentifierName(child, src); + if (!name) goto updateScopeValueAbort; + + /* Traverse upwards through scopes */ + do { + unsigned int n; + /* Check for existing value in current scope */ + for (n = 0; n < parent->numvals; n++) { + if (!strcmp(parent->names[n], name)) { + free(name); + /* Wipe out the old value */ + deleteValueObject(parent->values[n]); + /* Assign the new value */ + if (value) { + parent->values[n] = value; + } + else { + parent->values[n] = createNilValueObject(); + } + return parent->values[n]; + } + } + } while ((parent = parent->parent)); + + printInterpreterError("unable to store variable", target, src); + +updateScopeValueAbort: /* In case something goes wrong... */ + + /* Clean up any allocated structures */ + if (name) free(name); + + return NULL; +} + +/** + * Gets a stored value in a scope. + * + * \param [in] src The scope to evaluate \a target under. + * + * \param [in,out] dest The scope to update the value in. + * + * \param [in] target The name of the value to get. + * + * \return The value in \a dest, named by evaluating \a target under \a src. + * + * \retval NULL Either \a target could not be evaluated in \a src or \a target + * could not be found in \a dest. + */ +ValueObject *getScopeValue(ScopeObject *src, + ScopeObject *dest, + IdentifierNode *target) +{ + ScopeObject *parent = dest; + IdentifierNode *child = target; + char *name = NULL; + int status; + + /* Traverse the target to the terminal child and parent */ + status = resolveTerminalSlot(src, dest, target, &parent, &child); + if (!status) goto getScopeValueAbort; + + /* Look up the identifier name */ + name = resolveIdentifierName(child, src); + if (!name) goto getScopeValueAbort; + + /* Traverse upwards through scopes */ + do { + unsigned int n; + /* Check for value in current scope */ + for (n = 0; n < parent->numvals; n++) { + if (!strcmp(parent->names[n], name)) { + free(name); + return parent->values[n]; + } + } + } while ((parent = parent->parent)); + + printInterpreterError("variable does not exist", child, src); + +getScopeValueAbort: /* In case something goes wrong... */ + + /* Clean up any allocated structures */ + if (name) free(name); + + return NULL; +} + +/** + * Gets a value from a scope without accessing any arrays. + * + * \param [in] src The scope to evaluate \a target under. + * + * \param [in,out] dest The scope to update the value in. + * + * \param [in] target The name of the value to get. + * + * \return The value in \a dest, named by evaluating \a target under \a src, + * without accessing any arrays. + * + * \retval NULL Either \a target could not be evaluated in \a src or \a target + * could not be found in \a dest. + */ +ValueObject *getScopeValueArray(ScopeObject *src, + ScopeObject *dest, + IdentifierNode *target) +{ + ScopeObject *current = dest; char *name = NULL; /* Look up the identifier name */ - name = resolveIdentifierName(target, scope); - if (!name) return NULL; + name = resolveIdentifierName(target, src); + if (!name) goto getScopeValueArrayAbort; /* Traverse upwards through scopes */ do { @@ -423,173 +666,162 @@ ValueObject *getScopeValue(ScopeObject *scope, /**< [in] The ScopeObject str } } } while ((current = current->parent)); - free(name); + +getScopeValueArrayAbort: /* In case something goes wrong... */ + + /* Clean up any allocated structures */ + if (name) free(name); + return NULL; } -/** Retrieves a named ValueObject structure from a ScopeObject structure without - * traversing through its parents. - * - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * - * \return A pointer to the stored ValueObject structure named by \a target. - * - * \retval NULL \a target could not be found in \a scope. - * - * \see getScopeValue(ScopeObject *, IdentifierNode *) - * \see createScopeValue(ScopeObject *, IdentifierNode *) - * \see updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *) - * \see deleteScopeValue(ScopeObject *, IdentifierNode *) */ -ValueObject *getLocalScopeValue(ScopeObject *scope, /**< [in] The ScopeObject structure to check. */ - IdentifierNode *target) /**< [in] The name of the value to find. */ +/** + * Gets a value from a scope without accessing its ancestors. + * + * \param [in] src The scope to evaluate \a target under. + * + * \param [in,out] dest The scope to update the value in. + * + * \param [in] target The name of the value to get. + * + * \return The value in \a dest, named by evaluating \a target under \a src, + * without accessing any ancestors of \a dest. + * + * \retval NULL Either \a target could not be evaluated in \a src or \a target + * could not be found in \a dest. + */ +ValueObject *getScopeValueLocal(ScopeObject *src, + ScopeObject *dest, + IdentifierNode *target) { unsigned int n; char *name = NULL; + /* Access any slots */ + while (target->slot) { + ValueObject *val = getScopeValueArray(src, dest, target); + if (!val) goto getScopeValueLocalAbort; + if (val->type != VT_ARRAY) { + printInterpreterError("variable is not an array", +target, src); + goto getScopeValueLocalAbort; + } + dest = getArray(val); + target = target->slot; + } + /* Look up the identifier name */ - name = resolveIdentifierName(target, scope); - if (!name) return NULL; + name = resolveIdentifierName(target, src); + if (!name) goto getScopeValueLocalAbort; /* Check for value in current scope */ - for (n = 0; n < scope->numvals; n++) { - if (!strcmp(scope->names[n], name)) { + for (n = 0; n < dest->numvals; n++) { + if (!strcmp(dest->names[n], name)) { free(name); - return scope->values[n]; + return dest->values[n]; } } - free(name); + +getScopeValueLocalAbort: /* In case something goes wrong... */ + + /* Clean up any allocated structures */ + if (name) free(name); + return NULL; } -/** Creates a new, nil, named ValueObject structure in a ScopeObject structure. - * - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * - * \return A pointer to the newly created ValueObject structure named by - * \a target. - * - * \retval NULL realloc was unable to allocate memory. - * - * \see getScopeValue(ScopeObject *, IdentifierNode *) - * \see getLocalScopeValue(ScopeObject *, IdentifierNode *) - * \see updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *) - * \see deleteScopeValue(ScopeObject *, IdentifierNode *) */ -ValueObject *createScopeValue(ScopeObject *scope, /**< [in,out] The ScopeObject structure to add a value to. */ - IdentifierNode *target) /**< [in] The name of the value to add. */ +/** + * Gets a scope from within another scope. + * + * \param [in] src The scope to evaluate \a target under. + * + * \param [in,out] dest The scope to update the value in. + * + * \param [in] target The name of the scope to get. + * + * \return The value in \a dest, named by evaluating \a target under \a src, + * without accessing any ancestors of \a dest. + * + * \retval NULL Either \a target could not be evaluated in \a src or \a target + * could not be found in \a dest. + */ +ScopeObject *getScopeObject(ScopeObject *src, + ScopeObject *dest, + IdentifierNode *target) { - unsigned int newnumvals = scope->numvals + 1; - void *mem1 = NULL, *mem2 = NULL; + ValueObject *val = NULL; char *name = NULL; - - /* Look up the identifier name */ - name = resolveIdentifierName(target, scope); - if (!name) return NULL; - - /* Add value to local scope */ - mem1 = realloc(scope->names, sizeof(IdentifierNode *) * newnumvals); - if (!mem1) { - perror("realloc"); - free(name); - return NULL; - } - mem2 = realloc(scope->values, sizeof(ValueObject *) * newnumvals); - if (!mem2) { - perror("realloc"); - free(name); - return NULL; - } - scope->names = mem1; - scope->values = mem2; - scope->names[scope->numvals] = name; - scope->values[scope->numvals] = createNilValueObject(); - if (!scope->values[scope->numvals]) - return NULL; - scope->numvals = newnumvals; - return scope->values[scope->numvals - 1]; -} - -/** Updates a ValueObject structure named by an IdentifierNode structure in a - * ScopeObject structure. - * - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * \pre The value named by \a target was created by createScopeValue(ScopeObject *, IdentifierNode *). - * \pre \a value was created by either createNilValueObject(void), createBooleanValueObject(int), - * createIntegerValueObject(int), createFloatValueObject(float), createStringValueObject(char *), - * or copied with copyValueObject(ValueObject *). - * - * \return A pointer to the updated ValueObject structure named by \a target - * (will be the same as \a val). - * - * \retval NULL \a target could not be found in \a scope. - * - * \see getScopeValue(ScopeObject *, IdentifierNode *) - * \see getLocalScopeValue(ScopeObject *, IdentifierNode *) - * \see createScopeValue(ScopeObject *, IdentifierNode *) - * \see deleteScopeValue(ScopeObject *, IdentifierNode *) */ -ValueObject *updateScopeValue(ScopeObject *scope, /**< [in,out] A pointer to the ScopeObject structure to update. */ - IdentifierNode *target, /**< [in] A pointer to the IdentifierNode structure containing the name of the value to update. */ - ValueObject *value) /**< [in] A pointer to the ValueObject structure containing the value to copy for the update. */ -{ - ScopeObject *current = scope; - char *name = NULL; - - /* Look up the identifier name */ - name = resolveIdentifierName(target, scope); - if (!name) return NULL; - - /* Traverse upwards through scopes */ - do { - unsigned int n; - /* Check for existing value in current scope */ - for (n = 0; n < current->numvals; n++) { - if (!strcmp(current->names[n], name)) { - free(name); - /* Wipe out the old value */ - deleteValueObject(current->values[n]); - /* Assign the new value */ - if (value) - current->values[n] = value; - else - current->values[n] = createNilValueObject(); - return current->values[n]; - } + int status; + + /* Access any slots */ + while (target->slot) { + ValueObject *val = getScopeValueArray(src, dest, target); + if (!val) goto getScopeObjectAbort; + if (val->type != VT_ARRAY) { + printInterpreterError("variable is not an array", +target, src); + goto getScopeObjectAbort; } - } while ((current = current->parent)); - fprintf(stderr, "%s:%u: unable to store variable at: %s\n", target->fname, target->line, name); + dest = getArray(val); + target = target->slot; + } + + /* Look up the identifier name */ + name = resolveIdentifierName(target, src); + if (!name) goto getScopeObjectAbort; + + status = strcmp(name, "I"); free(name); + if (!status) return src; + + val = getScopeValue(src, dest, target); + if (!val) goto getScopeObjectAbort; + + return getArray(val); + +getScopeObjectAbort: /* In case something goes wrong... */ + + /* Clean up any allocated structures */ + if (name) free(name); + return NULL; } -/** Deletes a ValueObject structure named by an IdentifierNode structure in a - * ScopeObject structure. - * - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * - * \see getScopeValue(ScopeObject *, IdentifierNode *) - * \see getLocalScopeValue(ScopeObject *, IdentifierNode *) - * \see createScopeValue(ScopeObject *, IdentifierNode *) - * \see updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *) */ -void deleteScopeValue(ScopeObject *scope, /**< [in,out] A pointer to the ScopeObject structure to delete from. */ - IdentifierNode *target) /**< [in] A pointer to the IdentifierNode structure containing the name of the value to delete. */ +/** + * Deletes a value from a scope. + * + * \param [in] src The scope to evaluate \a target under. + * + * \param [in,out] dest The scope to update the value in. + * + * \param [in] target The name of the value to delete. + */ +void deleteScopeValue(ScopeObject *src, + ScopeObject *dest, + IdentifierNode *target) { - ScopeObject *current = scope; + ScopeObject *current = NULL; char *name = NULL; + void *mem1 = NULL; + void *mem2 = NULL; + + /* Access any slots */ + while (target->slot) { + ValueObject *val = getScopeValueArray(src, dest, target); + if (!val) goto deleteScopeValue; + if (val->type != VT_ARRAY) { + printInterpreterError("value is not an array", target, +src); + goto deleteScopeValue; + } + dest = getArray(val); + target = target->slot; + } + current = dest; /* Look up the identifier name */ - name = resolveIdentifierName(target, scope); - if (!name) return; + name = resolveIdentifierName(target, src); + if (!name) goto deleteScopeValue; /* Traverse upwards through scopes */ do { @@ -598,8 +830,7 @@ void deleteScopeValue(ScopeObject *scope, /**< [in,out] A pointer to the Sco for (n = 0; n < current->numvals; n++) { if (!strcmp(current->names[n], name)) { unsigned int i; - unsigned int newnumvals = scope->numvals - 1; - void *mem1 = NULL, *mem2 = NULL; + unsigned int newnumvals = dest->numvals - 1; free(name); /* Wipe out the name and value */ free(current->names[n]); @@ -610,122 +841,178 @@ void deleteScopeValue(ScopeObject *scope, /**< [in,out] A pointer to the Sco current->values[i] = current->values[i + 1]; } /* Resize the tables */ - mem1 = realloc(scope->names, sizeof(IdentifierNode *) * newnumvals); + mem1 = realloc(dest->names, sizeof(IdentifierNode *) * newnumvals); if (!mem1) { perror("realloc"); - return; + goto deleteScopeValue; } - mem2 = realloc(scope->values, sizeof(ValueObject *) * newnumvals); + mem2 = realloc(dest->values, sizeof(ValueObject *) * newnumvals); if (!mem2) { perror("realloc"); - return; + goto deleteScopeValue; } - scope->names = mem1; - scope->values = mem2; - scope->numvals = newnumvals; + dest->names = mem1; + dest->values = mem2; + dest->numvals = newnumvals; return; } } } while ((current = current->parent)); + free(name); + + return; + +deleteScopeValue: /* In case something goes wrong... */ + + /* Clean up any allocated structures */ + if (name) free(name); + if (mem1) free(mem1); + if (mem2) free(mem2); + + return; } -/** Checks if a string of characters follows the format for a number. - * - * \retval 0 The string of characters is not a number. - * \retval 1 The string of characters is a number. */ -unsigned int isNumString(const char *stringdata) /**< [in] The array of characters to check the format of. */ +/** + * Creates a returned value. + * + * \param [in] type The type of returned value. + * + * \param [in] value An optional value to return. + * + * \return A pointer to a returned value with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +ReturnObject *createReturnObject(ReturnType type, + ValueObject *value) { - size_t n; - size_t len = strlen(stringdata); - /* Check for empty string */ - if (len == 0) return 0; - /* Check for non-digit, non-hyphen, and non-period characters */ - for (n = 0; n < len; n++) { - if (!isdigit(stringdata[n]) - && stringdata[n] != '.' - && stringdata[n] != '-') - return 0; + ReturnObject *p = malloc(sizeof(ReturnObject)); + if (!p) { + perror("malloc"); + return NULL; } + p->type = type; + p->value = value; + return p; +} + +/** + * Deletes a returned value. + * + * \param [in,out] object The returned value to be deleted. + * + * \post The memory at \a object and all of its members will be freed. + */ +void deleteReturnObject(ReturnObject *object) +{ + if (!object) return; + if (object->type == RT_RETURN) + deleteValueObject(object->value); + free(object); +} + +/** + * Starting from an initial parent scope and target identifier, traverses down + * until the target identifier is not a scope. Stores the value of the terminal + * child identifier and its parent scope. + * + * \param [in] src The scope to resolve \a target in. + * + * \param [in] dest The scope to retrieve \a target from. + * + * \param [in] target The array slot to traverse. + * + * \param [out] parent The parent of the terminal child identifier of \a target. + * + * \param [out] child The terminal child identifier of \a target. + * + * \return A status code indicating success or failure. + * + * \retval 0 Failed to traverse array. + * + * \retval 1 Succeeded to traverse array. + * + * \post \a parent will point to the parent scope containing the terminal child. + * + * \post \a child will point to the terminal child. + */ +int resolveTerminalSlot(ScopeObject *src, + ScopeObject *dest, + IdentifierNode *target, + ScopeObject **parent, + IdentifierNode **child) +{ + /* Start with default values */ + *parent = dest; + *child = target; + + /* Access any slots */ + while (target->slot) { + /* Look up the target in the dest scope, using the src scope + * for resolving variables in indirect identifiers */ + ValueObject *val = getScopeValueArray(src, dest, target); + if (!val) return 0; + + /* Make sure the target contains an array */ + if (val->type != VT_ARRAY) { + printInterpreterError("value is not an array", target, dest); + return 0; + } + + /* Change the dest scope to the target */ + dest = getArray(val); + + /* Change the target to the old target's slot */ + target = target->slot; + } + + /* Store the output values */ + *parent = dest; + *child = target; + return 1; } -/** Checks if a string of characters follows the format for a hexadecimal - * number. - * - * \retval 0 The string of characters is not a hexadecimal number. - * \retval 1 The string of characters is a hexadecimal number. */ -unsigned int isHexString(const char *stringdata) /**< [in] The array of characters to check the format of. */ -{ - size_t n; - size_t len = strlen(stringdata); - /* Check for empty string */ - if (len == 0) return 0; - /* Check for non-digit and non-A-through-F characters */ - for (n = 0; n < len; n++) { - if (!isdigit(stringdata[n]) - && stringdata[n] != 'A' - && stringdata[n] != 'B' - && stringdata[n] != 'C' - && stringdata[n] != 'D' - && stringdata[n] != 'E' - && stringdata[n] != 'F' - && stringdata[n] != 'a' - && stringdata[n] != 'b' - && stringdata[n] != 'c' - && stringdata[n] != 'd' - && stringdata[n] != 'e' - && stringdata[n] != 'f') - return 0; - } - return 1; -} +/** \todo Investigate segfault within a loop: array HAS A SRS I IZ slot YR 1 (NO_MKAY) */ -/** Casts the contents of a ValueObject structure to boolean type in an - * implicit context. Casting is not done directly to the ValueObject structure - * pointed to by \a node, instead, it is performed on a copy of that structure, - * which is what is returned. - * - * \pre \a node was created by either createNilValueObject(void), createBooleanValueObject(int), - * createIntegerValueObject(int), createFloatValueObject(float), createStringValueObject(char *), - * or copied with copyValueObject(ValueObject *). - * \pre \a scope was created by createScopeObject(ScopeObject *). - * - * \return A pointer to a ValueObject structure with a copy of the contents of - * \a node, cast to boolean type. - * - * \retval NULL An error occurred while casting. - * - * \see castIntegerImplicit(ValueObject *, ScopeObject *) - * \see castFloatImplicit(ValueObject *, ScopeObject *) - * \see castStringImplicit(ValueObject *, ScopeObject *) */ -ValueObject *castBooleanImplicit(ValueObject *node, /**< [in] The ValueObject structure to cast. */ - ScopeObject *scope) /**< [in] The ScopeObject structure to use for variable interpolation. */ +/** + * Casts the contents of a value to boolean type in an implicit way. Casting is + * not done directly to \a node, instead, it is performed on a copy which is + * what is returned. + * + * \param [in] node The value to cast. + * + * \param [in] scope The scope to use for variable interpolation. + * + * \return A pointer to a value with a copy of the contents of \a node, cast to + * boolean type. + * + * \retval NULL An error occurred while casting. + */ +ValueObject *castBooleanImplicit(ValueObject *node, + ScopeObject *scope) { if (!node) return NULL; return castBooleanExplicit(node, scope); } -/** Casts the contents of a ValueObject structure to integer type in an - * implicit context. Casting is not done directly to the ValueObject structure - * pointed to by \a node, instead, it is performed on a copy of that structure, - * which is what is returned. - * - * \pre \a node was created by either createNilValueObject(void), createBooleanValueObject(int), - * createIntegerValueObject(int), createFloatValueObject(float), createStringValueObject(char *), - * or copied with copyValueObject(ValueObject *). - * \pre \a scope was created by createScopeObject(ScopeObject *). - * - * \return A pointer to a ValueObject structure with a copy of the contents of - * \a node, cast to integer type. - * - * \retval NULL An error occurred while casting. - * - * \see castBooleanImplicit(ValueObject *, ScopeObject *) - * \see castFloatImplicit(ValueObject *, ScopeObject *) - * \see castStringImplicit(ValueObject *, ScopeObject *) */ -ValueObject *castIntegerImplicit(ValueObject *node, /**< [in] The ValueObject structure to cast. */ - ScopeObject *scope) /**< [in] The ScopeObject structure to use for variable interpolation. */ +/** + * Casts the contents of a value to integer type in an implicit way. Casting is + * not done directly to \a node, instead, it is performed on a copy which is + * what is returned. + * + * \param [in] node The value to cast. + * + * \param [in] scope The scope to use for variable interpolation. + * + * \return A pointer to a value with a copy of the contents of \a node, cast to + * integer type. + * + * \retval NULL An error occurred while casting. + */ +ValueObject *castIntegerImplicit(ValueObject *node, + ScopeObject *scope) { if (!node) return NULL; if (node->type == VT_NIL) { @@ -735,26 +1022,22 @@ ValueObject *castIntegerImplicit(ValueObject *node, /**< [in] The ValueObject s else return castIntegerExplicit(node, scope); } -/** Casts the contents of a ValueObject structure to floating point decimal - * type in an implicit context. Casting is not done directly to the - * ValueObject structure pointed to by \a node, instead, it is performed on a - * copy of that structure, which is what is returned. - * - * \pre \a node was created by either createNilValueObject(void), createBooleanValueObject(int), - * createIntegerValueObject(int), createFloatValueObject(float), createStringValueObject(char *), - * or copied with copyValueObject(ValueObject *). - * \pre \a scope was created by createScopeObject(ScopeObject *). - * - * \return A pointer to a ValueObject structure with a copy of the contents of - * \a node, cast to floating point decimal type. - * - * \retval NULL An error occurred while casting. - * - * \see castBooleanImplicit(ValueObject *, ScopeObject *) - * \see castIntegerImplicit(ValueObject *, ScopeObject *) - * \see castStringImplicit(ValueObject *, ScopeObject *) */ -ValueObject *castFloatImplicit(ValueObject *node, /**< [in] The ValueObject structure to cast. */ - ScopeObject *scope) /**< [in] The ScopeObject structure to use for variable interpolation. */ +/** + * Casts the contents of a value to decimal type in an implicit way. Casting is + * not done directly to \a node, instead, it is performed on a copy which is + * what is returned. + * + * \param [in] node The value to cast. + * + * \param [in] scope The scope to use for variable interpolation. + * + * \return A pointer to a value with a copy of the contents of \a node, cast to + * decimal type. + * + * \retval NULL An error occurred while casting. + */ +ValueObject *castFloatImplicit(ValueObject *node, + ScopeObject *scope) { if (!node) return NULL; if (node->type == VT_NIL) { @@ -764,30 +1047,26 @@ ValueObject *castFloatImplicit(ValueObject *node, /**< [in] The ValueObject str else return castFloatExplicit(node, scope); } -/** Casts the contents of a ValueObject structure to string type in an implicit - * context. Casting is not done directly to the ValueObject structure pointed - * to by \a node, instead, it is performed on a copy of that structure, which - * is what is returned. - * - * \note \a scope is used to resolve variable interpolation within the string - * before casting it. Therefore, a simple way to interpolate the - * variables within a string is to call this function with it. - * - * \pre \a node was created by either createNilValueObject(void), createBooleanValueObject(int), - * createIntegerValueObject(int), createFloatValueObject(float), createStringValueObject(char *), - * or copied with copyValueObject(ValueObject *). - * \pre \a scope was created by createScopeObject(ScopeObject *). - * - * \return A pointer to a ValueObject structure with a copy of the contents of - * \a node, cast to string type. - * - * \retval NULL An error occurred while casting. - * - * \see castBooleanImplicit(ValueObject *, ScopeObject *) - * \see castIntegerImplicit(ValueObject *, ScopeObject *) - * \see castFloatImplicit(ValueObject *, ScopeObject *) */ -ValueObject *castStringImplicit(ValueObject *node, /**< [in] The ValueObject structure to cast. */ - ScopeObject *scope) /**< [in] The ScopeObject structure to use for variable interpolation. */ +/** + * Casts the contents of a value to string type in an implicit way. Casting is + * not done directly to \a node, instead, it is performed on a copy which is + * what is returned. + * + * \param [in] node The value to cast. + * + * \param [in] scope The scope to use for variable interpolation. + * + * \note \a scope is used to resolve variable interpolation within the string + * before casting it. Therefore, a simple way to interpolate the variables + * within a string is to call this function with it. + * + * \return A pointer to a value with a copy of the contents of \a node, cast to + * string type. + * + * \retval NULL An error occurred while casting. + */ +ValueObject *castStringImplicit(ValueObject *node, + ScopeObject *scope) { if (!node) return NULL; if (node->type == VT_NIL) { @@ -797,26 +1076,22 @@ ValueObject *castStringImplicit(ValueObject *node, /**< [in] The ValueObject st else return castStringExplicit(node, scope); } -/** Casts the contents of a ValueObject structure to boolean type in an - * explicit context. Casting is not done directly to the ValueObject structure - * pointed to by \a node, instead, it is performed on a copy of that structure, - * which is what is returned. - * - * \pre \a node was created by either createNilValueObject(void), createBooleanValueObject(int), - * createIntegerValueObject(int), createFloatValueObject(float), createStringValueObject(char *), - * or copied with copyValueObject(ValueObject *). - * \pre \a scope was created by createScopeObject(ScopeObject *). - * - * \return A pointer to a ValueObject structure with a copy of the contents of - * \a node, cast to boolean type. - * - * \retval NULL An error occurred while casting. - * - * \see castIntegerExplicit(ValueObject *, ScopeObject *) - * \see castFloatExplicit(ValueObject *, ScopeObject *) - * \see castStringExplicit(ValueObject *, ScopeObject *) */ -ValueObject *castBooleanExplicit(ValueObject *node, /**< [in] The ValueObject structure to cast. */ - ScopeObject *scope) /**< [in] The ScopeObject structure to use for variable interpolation. */ +/** + * Casts the contents of a value to boolean type in an explicit way. Casting is + * not done directly to \a node, instead, it is performed on a copy which is + * what is returned. + * + * \param [in] node The value to cast. + * + * \param [in] scope The scope to use for variable interpolation. + * + * \return A pointer to a value with a copy of the contents of \a node, cast to + * boolean type. + * + * \retval NULL An error occurred while casting. + */ +ValueObject *castBooleanExplicit(ValueObject *node, + ScopeObject *scope) { if (!node) return NULL; switch (node->type) { @@ -843,32 +1118,31 @@ ValueObject *castBooleanExplicit(ValueObject *node, /**< [in] The ValueObject s case VT_FUNC: fprintf(stderr, "Cannot cast functions to booleans\n"); return NULL; + case VT_ARRAY: + fprintf(stderr, "Cannot cast arrays to booleans\n"); + return NULL; default: fprintf(stderr, "Unknown value type encountered during boolean cast\n"); return NULL; } } -/** Casts the contents of a ValueObject structure to integer type in an - * explicit context. Casting is not done directly to the ValueObject structure - * pointed to by \a node, instead, it is performed on a copy of that structure, - * which is what is returned. - * - * \pre \a node was created by either createNilValueObject(void), createBooleanValueObject(int), - * createIntegerValueObject(int), createFloatValueObject(float), createStringValueObject(char *), - * or copied with copyValueObject(ValueObject *). - * \pre \a scope was created by createScopeObject(ScopeObject *). - * - * \return A pointer to a ValueObject structure with a copy of the contents of - * \a node, cast to integer type. - * - * \retval NULL An error occurred while casting. - * - * \see castBooleanExplicit(ValueObject *, ScopeObject *) - * \see castFloatExplicit(ValueObject *, ScopeObject *) - * \see castStringExplicit(ValueObject *, ScopeObject *) */ -ValueObject *castIntegerExplicit(ValueObject *node, /**< [in] The ValueObject structure to cast. */ - ScopeObject *scope) /**< [in] The ScopeObject structure to use for variable interpolation. */ +/** + * Casts the contents of a value to integer type in an explicit way. Casting is + * not done directly to \a node, instead, it is performed on a copy which is + * what is returned. + * + * \param [in] node The value to cast. + * + * \param [in] scope The scope to use for variable interpolation. + * + * \return A pointer to a value with a copy of the contents of \a node, cast to + * integer type. + * + * \retval NULL An error occurred while casting. + */ +ValueObject *castIntegerExplicit(ValueObject *node, + ScopeObject *scope) { if (!node) return NULL; switch (node->type) { @@ -886,7 +1160,7 @@ ValueObject *castIntegerExplicit(ValueObject *node, /**< [in] The ValueObject s ValueObject *interp = castStringExplicit(node, scope); int value; if (!interp) return NULL; - if (!isNumString(getString(interp))) { + if (!isDecString(getString(interp))) { fprintf(stderr, "Unable to cast value\n"); deleteValueObject(interp); return NULL; @@ -902,7 +1176,7 @@ ValueObject *castIntegerExplicit(ValueObject *node, /**< [in] The ValueObject s } else { int value; - if (!isNumString(getString(node))) { + if (!isDecString(getString(node))) { fprintf(stderr, "Unable to cast value\n"); return NULL; } @@ -915,32 +1189,31 @@ ValueObject *castIntegerExplicit(ValueObject *node, /**< [in] The ValueObject s case VT_FUNC: fprintf(stderr, "Cannot cast functions to integers\n"); return NULL; + case VT_ARRAY: + fprintf(stderr, "Cannot cast arrays to integers\n"); + return NULL; default: fprintf(stderr, "Unknown value type encountered during integer cast\n"); return NULL; } } -/** Casts the contents of a ValueObject structure to floating point decimal - * type in an explicit context. Casting is not done directly to the - * ValueObject structure pointed to by \a node, instead, it is performed on a - * copy of that structure, which is what is returned. - * - * \pre \a node was created by either createNilValueObject(void), createBooleanValueObject(int), - * createIntegerValueObject(int), createFloatValueObject(float), createStringValueObject(char *), - * or copied with copyValueObject(ValueObject *). - * \pre \a scope was created by createScopeObject(ScopeObject *). - * - * \return A pointer to a ValueObject structure with a copy of the contents of - * \a node, cast to floating point decimal type. - * - * \retval NULL An error occurred while casting. - * - * \see castBooleanExplicit(ValueObject *, ScopeObject *) - * \see castIntegerExplicit(ValueObject *, ScopeObject *) - * \see castStringExplicit(ValueObject *, ScopeObject *) */ -ValueObject *castFloatExplicit(ValueObject *node, /**< [in] The ValueObject structure to cast. */ - ScopeObject *scope) /**< [in] The ScopeObject structure to use for variable interpolation. */ +/** + * Casts the contents of a value to decimal type in an explicit way. Casting is + * not done directly to \a node, instead, it is performed on a copy which is + * what is returned. + * + * \param [in] node The value to cast. + * + * \param [in] scope The scope to use for variable interpolation. + * + * \return A pointer to a value with a copy of the contents of \a node, cast to + * decimal type. + * + * \retval NULL An error occurred while casting. + */ +ValueObject *castFloatExplicit(ValueObject *node, + ScopeObject *scope) { if (!node) return NULL; switch (node->type) { @@ -958,7 +1231,7 @@ ValueObject *castFloatExplicit(ValueObject *node, /**< [in] The ValueObject str ValueObject *interp = castStringExplicit(node, scope); float value; if (!interp) return NULL; - if (!isNumString(getString(interp))) { + if (!isDecString(getString(interp))) { fprintf(stderr, "Unable to cast value\n"); deleteValueObject(interp); return NULL; @@ -974,7 +1247,7 @@ ValueObject *castFloatExplicit(ValueObject *node, /**< [in] The ValueObject str } else { float value; - if (!isNumString(getString(node))) { + if (!isDecString(getString(node))) { fprintf(stderr, "Unable to cast value\n"); return NULL; } @@ -987,54 +1260,57 @@ ValueObject *castFloatExplicit(ValueObject *node, /**< [in] The ValueObject str case VT_FUNC: fprintf(stderr, "Cannot cast functions to floats\n"); return NULL; + case VT_ARRAY: + fprintf(stderr, "Cannot cast arrays to floats\n"); + return NULL; default: fprintf(stderr, "Unknown value type encountered during floating point decimal cast\n"); return NULL; } } -/** Casts the contents of a ValueObject structure to string type in an explicit - * context. Casting is not done to directly the ValueObject structure pointed - * to by \a node, instead, it is performed on a copy of that structure, which - * is what is returned. - * - * \note \a scope is used to resolve variable interpolation within the string - * before casting it. Therefore, a simple way to interpolate the - * variables within a string is to call this function with it. - * - * \pre \a node was created by either createNilValueObject(void), createBooleanValueObject(int), - * createIntegerValueObject(int), createFloatValueObject(float), createStringValueObject(char *), - * or copied with copyValueObject(ValueObject *). - * \pre \a scope was created by createScopeObject(ScopeObject *). - * - * \return A pointer to a ValueObject structure with a copy of the contents of - * \a node, cast to string type. - * - * \retval NULL An error occurred while casting. - * - * \see castBooleanExplicit(ValueObject *, ScopeObject *) - * \see castIntegerExplicit(ValueObject *, ScopeObject *) - * \see castFloatExplicit(ValueObject *, ScopeObject *) */ -ValueObject *castStringExplicit(ValueObject *node, /**< [in] The ValueObject structure to cast. */ - ScopeObject *scope) /**< [in] The ScopeObject structure to use for variable interpolation. */ +/** + * Casts the contents of a value to string type in an explicit way. Casting is + * not done directly to \a node, instead, it is performed on a copy which is + * what is returned. + * + * \param [in] node The value to cast. + * + * \param [in] scope The scope to use for variable interpolation. + * + * \note \a scope is used to resolve variable interpolation within the string + * before casting it. Therefore, a simple way to interpolate the variables + * within a string is to call this function with it. + * + * \return A pointer to a value with a copy of the contents of \a node, cast to + * string type. + * + * \retval NULL An error occurred while casting. + */ +ValueObject *castStringExplicit(ValueObject *node, + ScopeObject *scope) { if (!node) return NULL; switch (node->type) { case VT_NIL: { - char *str = createString(""); + char *str = copyString(""); if (!str) return NULL; return createStringValueObject(str); } case VT_BOOLEAN: { - /** \note The spec does not define how TROOFs may be - * cast to YARNs. */ + /* + * \note The spec does not define how TROOFs may be cast + * to YARNs. + */ fprintf(stderr, "Cannot cast TROOF to YARN\n"); return NULL; } case VT_INTEGER: { char *data = NULL; - /* One character per integer bit plus one more for the - * null character */ + /* + * One character per integer bit plus one more for the + * null character + */ size_t size = sizeof(int) * 8 + 1; data = malloc(sizeof(char) * size); if (!data) return NULL; @@ -1044,8 +1320,10 @@ ValueObject *castStringExplicit(ValueObject *node, /**< [in] The ValueObject st case VT_FLOAT: { char *data = NULL; unsigned int precision = 2; - /* One character per float bit plus one more for the - * null character */ + /* + * One character per float bit plus one more for the + * null character + */ size_t size = sizeof(float) * 8 + 1; data = malloc(sizeof(char) * size); if (!data) return NULL; @@ -1191,15 +1469,17 @@ ValueObject *castStringExplicit(ValueObject *node, /**< [in] The ValueObject st /* Lookup implicit variable */ val = scope->impvar; else { - /* Create a new IdentifierNode + /* + * Create a new IdentifierNode * structure and lookup its - * value */ - target = createIdentifierNode(IT_DIRECT, image, NULL, 0); + * value + */ + target = createIdentifierNode(IT_DIRECT, image, NULL, NULL, 0); if (!target) { free(temp); return NULL; } - val = getScopeValue(scope, target); + val = getScopeValue(scope, scope, target); if (!val) { fprintf(stderr, "Variable does not exist at: %s\n", image); deleteIdentifierNode(target); @@ -1241,58 +1521,50 @@ ValueObject *castStringExplicit(ValueObject *node, /**< [in] The ValueObject st fprintf(stderr, "Cannot cast functions to strings\n"); return NULL; } + case VT_ARRAY: + fprintf(stderr, "Cannot cast arrays to strings\n"); + return NULL; default: fprintf(stderr, "Unknown value type encountered during string cast\n"); return NULL; } } -/** Interprets an implicit variable expression. - * - * \pre \a node was created by createExprNode(ExprType type, void *expr) - * where \a type is ET_IMPVAR and \a expr is NULL. - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \note \a node is not used by this function but is still included in its - * prototype to allow this function to be stored in a jump table for fast - * execution. - * - * \return A pointer to a ValueObject structure containing the value of the - * current scope's implicit variable. - * - * \see interpretCastExprNode(ExprNode *, ScopeObject *) - * \see interpretFuncCallExprNode(ExprNode *, ScopeObject *) - * \see interpretIdentifierExprNode(ExprNode *, ScopeObject *) - * \see interpretConstantExprNode(ExprNode *, ScopeObject *) */ -ValueObject *interpretImpVarExprNode(ExprNode *node, /**< [in] A pointer to an ExprNode structure with type set to ET_IMPVAR. */ - ScopeObject *scope) /**< Not used (see note). */ +/** + * Interprets an implicit variable. + * + * \param [in] node Not used (see note). + * + * \param [in] scope The scope from which to use the implicit variable. + * + * \note \a node is not used by this function but is still included in its + * prototype to allow this function to be stored in a jump table for fast + * execution. + * + * \return A pointer to the value of \a scope's implicit variable. + */ +ValueObject *interpretImpVarExprNode(ExprNode *node, + ScopeObject *scope) { node = NULL; return scope->impvar; } -/** Interprets a cast expression. - * - * \pre \a node was created by createExprNode(ExprType type, void *expr) - * where \a type is ET_CAST and \a expr is a CastExprNode structure - * created by createCastExprNode(ExprNode *, TypeNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ValueObject structure containing the result of the - * cast. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretImpVarExprNode(ExprNode *, ScopeObject *) - * \see interpretFuncCallExprNode(ExprNode *, ScopeObject *) - * \see interpretIdentifierExprNode(ExprNode *, ScopeObject *) - * \see interpretConstantExprNode(ExprNode *, ScopeObject *) */ -ValueObject *interpretCastExprNode(ExprNode *node, /**< [in] A pointer to an ExprNode structure containing the CastExprNode structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to a ScopeObject structure to evaluate \a node under. */ +/** + * Interprets a cast. + * + * \param [in] node A pointer to the expression to interpret. + * + * \param [in] scope A pointer to a scope to evaluate \a node under. + * + * \pre \a node contains a expression created by createCastExprNode(). + * + * \return A pointer to the cast value. + * + * \retval NULL An error occurred during interpretation. + */ +ValueObject *interpretCastExprNode(ExprNode *node, + ScopeObject *scope) { CastExprNode *expr = (CastExprNode *)node->expr; ValueObject *val = interpretExprNode(expr->target, scope); @@ -1325,26 +1597,21 @@ ValueObject *interpretCastExprNode(ExprNode *node, /**< [in] A pointer to an } } -/** Interprets a function call expression. - * - * \pre \a node was created by createExprNode(ExprType type, void *expr) - * where \a type is ET_FUNCCALL and \a expr is a FunctionCallExprNode - * structure created by createFuncCallExprNode(IdentifierNode *, IdentifierNode *, ExprNodeList *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ValueObject structure containing the return value of - * function. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretImpVarExprNode(ExprNode *, ScopeObject *) - * \see interpretCastExprNode(ExprNode *, ScopeObject *) - * \see interpretIdentifierExprNode(ExprNode *, ScopeObject *) - * \see interpretConstantExprNode(ExprNode *, ScopeObject *) */ -ValueObject *interpretFuncCallExprNode(ExprNode *node, /**< [in] A pointer to an ExprNode structure containing the FuncCallExprNode structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to a ScopeObject structure to evaluate \a node under. */ +/** + * Interprets a function call. + * + * \param [in] node A pointer to the expression to interpret. + * + * \param [in,out] scope A pointer to a scope to evaluate \a node under. + * + * \pre \a node contains an expression created by createFuncCallExprNode(). + * + * \return A pointer to the returned value. + * + * \retval NULL An error occurred during interpretation. + */ +ValueObject *interpretFuncCallExprNode(ExprNode *node, + ScopeObject *scope) { FuncCallExprNode *expr = (FuncCallExprNode *)node->expr; unsigned int n; @@ -1352,8 +1619,10 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node, /**< [in] A pointer t ValueObject *def = NULL; ReturnObject *retval = NULL; ValueObject *ret = NULL; + ScopeObject *dest = NULL; + dest = getScopeObject(scope, scope, expr->scope); if (!outer) return NULL; - def = getScopeValue(scope, expr->name); + def = getScopeValue(scope, dest, expr->name); if (!def || def->type != VT_FUNC) { IdentifierNode *id = (IdentifierNode *)(expr->name); char *name = resolveIdentifierName(id, scope); @@ -1377,7 +1646,7 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node, /**< [in] A pointer t } for (n = 0; n < getFunction(def)->args->num; n++) { ValueObject *val = NULL; - if (!createScopeValue(outer, getFunction(def)->args->ids[n])) { + if (!createScopeValue(scope, outer, getFunction(def)->args->ids[n])) { deleteScopeObject(outer); return NULL; } @@ -1385,16 +1654,17 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node, /**< [in] A pointer t deleteScopeObject(outer); return NULL; } - if (!updateScopeValue(outer, getFunction(def)->args->ids[n], val)) { + if (!updateScopeValue(scope, outer, getFunction(def)->args->ids[n], val)) { deleteScopeObject(outer); deleteValueObject(val); return NULL; } } - /* \note We use interpretStmtNodeList(StmtNodeList *, ScopeObject *) - * here because we want to have access to the function's ScopeObject - * as we may need to retrieve the implicit variable in the case of - * a default return. */ + /** + * \note We use interpretStmtNodeList here because we want to have + * access to the function's scope as we may need to retrieve the + * implicit variable in the case of a default return. + */ if (!(retval = interpretStmtNodeList(getFunction(def)->body->stmts, outer))) { deleteScopeObject(outer); return NULL; @@ -1422,69 +1692,47 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node, /**< [in] A pointer t return ret; } -/** Interprets an identifier expression. - * - * \pre \a node was created by createExprNode(ExprType type, void *expr) - * where \a type is ET_IDENTIFIER and \a expr is an IdentifierNode - * structure created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \note \a scope is not used by this function but is still included in its - * prototype to allow this function to be stored in a jump table for fast - * execution. - * - * \return A pointer to a ValueObject structure containing the return value of - * function. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretImpVarExprNode(ExprNode *, ScopeObject *) - * \see interpretCastExprNode(ExprNode *, ScopeObject *) - * \see interpretFuncCallExprNode(ExprNode *, ScopeObject *) - * \see interpretConstantExprNode(ExprNode *, ScopeObject *) */ -ValueObject *interpretIdentifierExprNode(ExprNode *node, /**< [in] A pointer to an ExprNode structure containing the IdentifierNode structure to interpret. */ - ScopeObject *scope) /**< Not used (see note). */ +/** + * Interprets an identifier. + * + * \param [in] node A pointer to the expression to interpret. + * + * \param [in,out] scope A pointer to a scope to evaluate \a node under. + * + * \pre \a node contains an identifier created by createIdentifierNode(). + * + * \return A pointer to the cast value. + * + * \retval NULL An error occurred during interpretation. + */ +ValueObject *interpretIdentifierExprNode(ExprNode *node, + ScopeObject *scope) { - ValueObject *val = getScopeValue(scope, node->expr); - if (!val) { - IdentifierNode *id = (IdentifierNode *)(node->expr); - char *name = resolveIdentifierName(id, scope); - if (name) { - fprintf(stderr, "%s:%u: variable does not exist at: %s\n", id->fname, id->line, name); - free(name); - } - return NULL; - } + ValueObject *val = getScopeValue(scope, scope, node->expr); + if (!val) return NULL; return copyValueObject(val); } -/** Interprets a constant expression. - * - * \pre \a node was created by createExprNode(ExprType type, void *expr) - * where \a type is ET_CONSTANT and \a expr is a ConstantNode structure - * created by either createBooleanConstantNode(int), createIntegerConstantNode(int), - * createFloatConstantNode(float), or createStringConstantNode(char *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \note \a scope is not used by this function but is still included in its - * prototype to allow this function to be stored in a jump table for fast - * execution. - * - * \return A pointer to a ValueObject structure containing the return value of - * function. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretImpVarExprNode(ExprNode *, ScopeObject *) - * \see interpretCastExprNode(ExprNode *, ScopeObject *) - * \see interpretFuncCallExprNode(ExprNode *, ScopeObject *) - * \see interpretIdentifierExprNode(ExprNode *, ScopeObject *) */ -ValueObject *interpretConstantExprNode(ExprNode *node, /**< [in] A pointer to an ExprNode structure containing the ConstantNode structure to interpret. */ - ScopeObject *scope) /**< Not used (see note). */ +/** + * Interprets a constant. + * + * \param [in] node A pointer to the expression to interpret. + * + * \param [in] scope Not used (see note). + * + * \note \a node is not used by this function but is still included in its + * prototype to allow this function to be stored in a jump table for fast + * execution. + * + * \pre \a node contains a constant created by createXConstantNode(), where X is + * either Boolean, Integer, Float, or String. + * + * \return A pointer to the constant value. + * + * \retval NULL An error occurred during interpretation. + */ +ValueObject *interpretConstantExprNode(ExprNode *node, + ScopeObject *scope) { ConstantNode *expr = (ConstantNode *)node->expr; scope = NULL; @@ -1498,10 +1746,12 @@ ValueObject *interpretConstantExprNode(ExprNode *node, /**< [in] A pointer t case CT_FLOAT: return createFloatValueObject(expr->data.f); case CT_STRING: { - /** \note For efficiency, string interpolation should be - * performed by caller because it only needs to - * be performed when necessary. */ - char *str = createString(expr->data.s); + /* + * \note For efficiency, string interpolation should be + * performed by caller because it only needs to be + * performed when necessary. + */ + char *str = copyString(expr->data.s); if (!str) return NULL; return createStringValueObject(str); } @@ -1511,28 +1761,22 @@ ValueObject *interpretConstantExprNode(ExprNode *node, /**< [in] A pointer t } } -/** Interprets a logical NOT operation expression. - * - * \pre \a expr was created by createOpExprNode(OpType type, ExprNodeList *args) - * where \a type is OP_NOT and \a args was created by createExprNodeList(void) - * and populated with ExprNode structures using addExprNode(ExprNodeList *, ExprNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \note Only the first element in \a args is considered. - * - * \return A pointer to a ValueObject structure containing the interpreted - * operation expression value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretArithOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretBoolOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretEqualityOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretConcatOpExprNode(OpExprNode *, ScopeObject *) */ -ValueObject *interpretNotOpExprNode(OpExprNode *expr, /**< [in] A pointer to the OpExprNode structure to interpret. */ - ScopeObject *scope) /**< [in] A pointer to the ScopeObject structure to evaluate \a expr under. */ +/** + * Interprets a logical NOT operation. + * + * \param [in] expr A pointer to the expression to interpret. + * + * \param [in] scope A pointer to a scope to evaluate \a node under. + * + * \note Only the first element of \a args is used. + * + * \return A pointer to the value of the logical negation of the first element + * of \a args. + * + * \retval NULL An error occurred during interpretation. + */ +ValueObject *interpretNotOpExprNode(OpExprNode *expr, + ScopeObject *scope) { ValueObject *val = interpretExprNode(expr->args->exprs[0], scope); ValueObject *use = val; @@ -1553,80 +1797,64 @@ ValueObject *interpretNotOpExprNode(OpExprNode *expr, /**< [in] A pointer to t return createBooleanValueObject(!retval); } -/** Adds two integers. - * - * \pre \a a and \a b were created by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the sum of the - * values \a a and \a b. - * - * \see opSubIntegerInteger(ValueObject *, ValueObject *) - * \see opMultIntegerInteger(ValueObject *, ValueObject *) - * \see opDivIntegerInteger(ValueObject *, ValueObject *) - * \see opMaxIntegerInteger(ValueObject *, ValueObject *) - * \see opMinIntegerInteger(ValueObject *, ValueObject *) - * \see opModIntegerInteger(ValueObject *, ValueObject *) */ -ValueObject *opAddIntegerInteger(ValueObject *a, /**< [in] The first term to add. */ - ValueObject *b) /**< [in] The second term to add. */ +/** + * Adds an integer to an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the sum of \a a and \a b. + */ +ValueObject *opAddIntegerInteger(ValueObject *a, + ValueObject *b) { return createIntegerValueObject(getInteger(a) + getInteger(b)); } -/** Subtracts two integers. - * - * \pre \a a and \a b were created by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the difference of - * the values \a a and \a b. - * - * \see opAddIntegerInteger(ValueObject *, ValueObject *) - * \see opMultIntegerInteger(ValueObject *, ValueObject *) - * \see opDivIntegerInteger(ValueObject *, ValueObject *) - * \see opMaxIntegerInteger(ValueObject *, ValueObject *) - * \see opMinIntegerInteger(ValueObject *, ValueObject *) - * \see opModIntegerInteger(ValueObject *, ValueObject *) */ -ValueObject *opSubIntegerInteger(ValueObject *a, /**< [in] The minuend. */ - ValueObject *b) /**< [in] The subtrahend. */ +/** + * Subtracts an integer from an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the difference of \a a and \a b. + */ +ValueObject *opSubIntegerInteger(ValueObject *a, + ValueObject *b) { return createIntegerValueObject(getInteger(a) - getInteger(b)); } -/** Multiplies two integers. - * - * \pre \a a and \a b were created by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the product of the - * values \a a and \a b. - * - * \see opAddIntegerInteger(ValueObject *, ValueObject *) - * \see opSubIntegerInteger(ValueObject *, ValueObject *) - * \see opDivIntegerInteger(ValueObject *, ValueObject *) - * \see opMaxIntegerInteger(ValueObject *, ValueObject *) - * \see opMinIntegerInteger(ValueObject *, ValueObject *) - * \see opModIntegerInteger(ValueObject *, ValueObject *) */ -ValueObject *opMultIntegerInteger(ValueObject *a, /**< [in] The first factor to multiply. */ - ValueObject *b) /**< [in] The second factor to multiply. */ +/** + * Multiplies an integer by an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the product of \a a and \a b. + */ +ValueObject *opMultIntegerInteger(ValueObject *a, + ValueObject *b) { return createIntegerValueObject(getInteger(a) * getInteger(b)); } -/** Divides two integers. - * - * \pre \a a and \a b were created by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the quotient of the - * values \a a and \a b. - * - * \retval NULL Division by zero was attempted. - * - * \see opAddIntegerInteger(ValueObject *, ValueObject *) - * \see opSubIntegerInteger(ValueObject *, ValueObject *) - * \see opMultIntegerInteger(ValueObject *, ValueObject *) - * \see opMaxIntegerInteger(ValueObject *, ValueObject *) - * \see opMinIntegerInteger(ValueObject *, ValueObject *) - * \see opModIntegerInteger(ValueObject *, ValueObject *) */ -ValueObject *opDivIntegerInteger(ValueObject *a, /**< [in] The dividend. */ - ValueObject *b) /**< [in] The divisor. */ +/** + * Divides an integer by an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the quotient of \a a and \a b. + * + * \retval NULL Division by zero. + */ +ValueObject *opDivIntegerInteger(ValueObject *a, + ValueObject *b) { if (getInteger(b) == 0) { fprintf(stderr, "Division by zero undefined\n"); @@ -1635,59 +1863,47 @@ ValueObject *opDivIntegerInteger(ValueObject *a, /**< [in] The dividend. */ return createIntegerValueObject(getInteger(a) / getInteger(b)); } -/** Finds the maximum of two integers. - * - * \pre \a a and \a b were created by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the maximum of the - * values \a a and \a b. - * - * \see opAddIntegerInteger(ValueObject *, ValueObject *) - * \see opSubIntegerInteger(ValueObject *, ValueObject *) - * \see opMultIntegerInteger(ValueObject *, ValueObject *) - * \see opDivIntegerInteger(ValueObject *, ValueObject *) - * \see opMinIntegerInteger(ValueObject *, ValueObject *) - * \see opModIntegerInteger(ValueObject *, ValueObject *) */ -ValueObject *opMaxIntegerInteger(ValueObject *a, /**< [in] The first number to compare. */ - ValueObject *b) /**< [in] The second number to compare. */ +/** + * Finds the maximum of an integer and an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the maximum of \a a and \a b. + */ +ValueObject *opMaxIntegerInteger(ValueObject *a, + ValueObject *b) { return createIntegerValueObject(getInteger(a) > getInteger(b) ? getInteger(a) : getInteger(b)); } -/** Finds the minimum of two integers. - * - * \pre \a a and \a b were created by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the minimum of the - * values \a a and \a b. - * - * \see opAddIntegerInteger(ValueObject *, ValueObject *) - * \see opSubIntegerInteger(ValueObject *, ValueObject *) - * \see opMultIntegerInteger(ValueObject *, ValueObject *) - * \see opDivIntegerInteger(ValueObject *, ValueObject *) - * \see opMaxIntegerInteger(ValueObject *, ValueObject *) - * \see opModIntegerInteger(ValueObject *, ValueObject *) */ -ValueObject *opMinIntegerInteger(ValueObject *a, /**< [in] The first number to compare. */ - ValueObject *b) /**< [in] The second number to compare. */ +/** + * Finds the minimum of an integer and an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the minimum of \a a and \a b. + */ +ValueObject *opMinIntegerInteger(ValueObject *a, + ValueObject *b) { return createIntegerValueObject(getInteger(a) < getInteger(b) ? getInteger(a) : getInteger(b)); } -/** Calculates the modulus of two integers. - * - * \pre \a a and \a b were created by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the modulus of the - * values \a a and \a b. - * - * \see opAddIntegerInteger(ValueObject *, ValueObject *) - * \see opSubIntegerInteger(ValueObject *, ValueObject *) - * \see opMultIntegerInteger(ValueObject *, ValueObject *) - * \see opDivIntegerInteger(ValueObject *, ValueObject *) - * \see opMaxIntegerInteger(ValueObject *, ValueObject *) - * \see opMinIntegerInteger(ValueObject *, ValueObject *) */ -ValueObject *opModIntegerInteger(ValueObject *a, /**< [in] The dividend. */ - ValueObject *b) /**< [in] The divisor. */ +/** + * Calculates the modulus of an integer and an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the modulus of \a a and \a b. + */ +ValueObject *opModIntegerInteger(ValueObject *a, + ValueObject *b) { if (getInteger(b) == 0) { fprintf(stderr, "Division by zero undefined\n"); @@ -1696,84 +1912,64 @@ ValueObject *opModIntegerInteger(ValueObject *a, /**< [in] The dividend. */ return createIntegerValueObject(getInteger(a) % getInteger(b)); } -/** Adds an integer and a float. - * - * \pre \a a was created by createIntegerValueObject(int) and \a b was created - * by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the sum of the - * values \a a and \a b. - * - * \see opSubIntegerFloat(ValueObject *, ValueObject *) - * \see opMultIntegerFloat(ValueObject *, ValueObject *) - * \see opDivIntegerFloat(ValueObject *, ValueObject *) - * \see opMaxIntegerFloat(ValueObject *, ValueObject *) - * \see opMinIntegerFloat(ValueObject *, ValueObject *) - * \see opModIntegerFloat(ValueObject *, ValueObject *) */ -ValueObject *opAddIntegerFloat(ValueObject *a, /**< [in] The first term to add. */ - ValueObject *b) /**< [in] The second term to add. */ +/** + * Adds an integer to a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the sum of \a a and \a b. + */ +ValueObject *opAddIntegerFloat(ValueObject *a, + ValueObject *b) { return createFloatValueObject((float)(getInteger(a) + getFloat(b))); } -/** Subtracts an integer and a float. - * - * \pre \a a was created by createIntegerValueObject(int) and \a b was created - * by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the difference of - * the values \a a and \a b. - * - * \see opAddIntegerFloat(ValueObject *, ValueObject *) - * \see opMultIntegerFloat(ValueObject *, ValueObject *) - * \see opDivIntegerFloat(ValueObject *, ValueObject *) - * \see opMaxIntegerFloat(ValueObject *, ValueObject *) - * \see opMinIntegerFloat(ValueObject *, ValueObject *) - * \see opModIntegerFloat(ValueObject *, ValueObject *) */ -ValueObject *opSubIntegerFloat(ValueObject *a, /**< [in] The minuend. */ - ValueObject *b) /**< [in] The subtrahend. */ +/** + * Subtracts an integer from a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the difference of \a a and \a b. + */ +ValueObject *opSubIntegerFloat(ValueObject *a, + ValueObject *b) { return createFloatValueObject((float)(getInteger(a) - getFloat(b))); } -/** Multiplies an integer and a float. - * - * \pre \a a was created by createIntegerValueObject(int) and \a b was created - * by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the product of the - * values \a a and \a b. - * - * \see opAddIntegerFloat(ValueObject *, ValueObject *) - * \see opSubIntegerFloat(ValueObject *, ValueObject *) - * \see opDivIntegerFloat(ValueObject *, ValueObject *) - * \see opMaxIntegerFloat(ValueObject *, ValueObject *) - * \see opMinIntegerFloat(ValueObject *, ValueObject *) - * \see opModIntegerFloat(ValueObject *, ValueObject *) */ -ValueObject *opMultIntegerFloat(ValueObject *a, /**< [in] The first factor to multiply. */ - ValueObject *b) /**< [in] The second factor to multiply. */ +/** + * Multiplies an integer by a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the product of \a a and \a b. + */ +ValueObject *opMultIntegerFloat(ValueObject *a, + ValueObject *b) { return createFloatValueObject((float)(getInteger(a) * getFloat(b))); } -/** Divides an integer and a float. - * - * \pre \a a was created by createIntegerValueObject(int) and \a b was created - * by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the quotient of the - * values \a a and \a b. - * - * \retval NULL Division by zero was attempted. - * - * \see opAddIntegerFloat(ValueObject *, ValueObject *) - * \see opSubIntegerFloat(ValueObject *, ValueObject *) - * \see opMultIntegerFloat(ValueObject *, ValueObject *) - * \see opMaxIntegerFloat(ValueObject *, ValueObject *) - * \see opMinIntegerFloat(ValueObject *, ValueObject *) - * \see opModIntegerFloat(ValueObject *, ValueObject *) */ -ValueObject *opDivIntegerFloat(ValueObject *a, /**< [in] The dividend. */ - ValueObject *b) /**< [in] The divisor. */ +/** + * Divides an integer by a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the quotient of \a a and \a b. + * + * \retval NULL Division by zero. + */ +ValueObject *opDivIntegerFloat(ValueObject *a, + ValueObject *b) { if (fabs(getFloat(b) - 0.0) < FLT_EPSILON) { fprintf(stderr, "Division by zero undefined\n"); @@ -1782,62 +1978,47 @@ ValueObject *opDivIntegerFloat(ValueObject *a, /**< [in] The dividend. */ return createFloatValueObject((float)(getInteger(a) / getFloat(b))); } -/** Finds the maximum of an integer and a float. - * - * \pre \a a was created by createIntegerValueObject(int) and \a b was created - * by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the maximum of the - * values \a a and \a b. - * - * \see opAddIntegerFloat(ValueObject *, ValueObject *) - * \see opSubIntegerFloat(ValueObject *, ValueObject *) - * \see opMultIntegerFloat(ValueObject *, ValueObject *) - * \see opDivIntegerFloat(ValueObject *, ValueObject *) - * \see opMinIntegerFloat(ValueObject *, ValueObject *) - * \see opModIntegerFloat(ValueObject *, ValueObject *) */ -ValueObject *opMaxIntegerFloat(ValueObject *a, /**< [in] The first number to compare. */ - ValueObject *b) /**< [in] The second number to compare. */ +/** + * Finds the maximum of an integer and a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the maximum of \a a and \a b. + */ +ValueObject *opMaxIntegerFloat(ValueObject *a, + ValueObject *b) { return createFloatValueObject((float)(getInteger(a)) > getFloat(b) ? (float)(getInteger(a)) : getFloat(b)); } -/** Finds the minimum of an integer and a float. - * - * \pre \a a was created by createIntegerValueObject(int) and \a b was created - * by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the minimum of the - * values \a a and \a b. - * - * \see opAddIntegerFloat(ValueObject *, ValueObject *) - * \see opSubIntegerFloat(ValueObject *, ValueObject *) - * \see opMultIntegerFloat(ValueObject *, ValueObject *) - * \see opDivIntegerFloat(ValueObject *, ValueObject *) - * \see opMaxIntegerFloat(ValueObject *, ValueObject *) - * \see opModIntegerFloat(ValueObject *, ValueObject *) */ -ValueObject *opMinIntegerFloat(ValueObject *a, /**< [in] The first number to compare. */ - ValueObject *b) /**< [in] The second number to compare. */ +/** + * Finds the minimum of an integer and a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the minimum of \a a and \a b. + */ +ValueObject *opMinIntegerFloat(ValueObject *a, + ValueObject *b) { return createFloatValueObject((float)(getInteger(a)) < getFloat(b) ? (float)(getInteger(a)) : getFloat(b)); } -/** Calculates the modulus of an integer and a float. - * - * \pre \a a was created by createIntegerValueObject(int) and \a b was created - * by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the modulus of the - * values \a a and \a b. - * - * \see opAddIntegerFloat(ValueObject *, ValueObject *) - * \see opSubIntegerFloat(ValueObject *, ValueObject *) - * \see opMultIntegerFloat(ValueObject *, ValueObject *) - * \see opDivIntegerFloat(ValueObject *, ValueObject *) - * \see opMaxIntegerFloat(ValueObject *, ValueObject *) - * \see opMinIntegerFloat(ValueObject *, ValueObject *) */ -ValueObject *opModIntegerFloat(ValueObject *a, /**< [in] The dividend. */ - ValueObject *b) /**< [in] The divisor. */ +/** + * Calculates the modulus of an integer and a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the modulus of \a a and \a b. + */ +ValueObject *opModIntegerFloat(ValueObject *a, + ValueObject *b) { if (fabs(getFloat(b) - 0.0) < FLT_EPSILON) { fprintf(stderr, "Division by zero undefined\n"); @@ -1846,83 +2027,64 @@ ValueObject *opModIntegerFloat(ValueObject *a, /**< [in] The dividend. */ return createFloatValueObject((float)(fmod((double)(getInteger(a)), getFloat(b)))); } -/** Adds a float and an integer. - * - * \pre \a a was created by createFloatValueObject(float) and \a b was created - * by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the sum of the - * values \a a and \a b. - * - * \see opSubFloatInteger(ValueObject *, ValueObject *) - * \see opMultFloatInteger(ValueObject *, ValueObject *) - * \see opDivFloatInteger(ValueObject *, ValueObject *) - * \see opMaxFloatInteger(ValueObject *, ValueObject *) - * \see opMinFloatInteger(ValueObject *, ValueObject *) - * \see opModFloatInteger(ValueObject *, ValueObject *) */ -ValueObject *opAddFloatInteger(ValueObject *a, /**< [in] The first term to add. */ - ValueObject *b) /**< [in] The second term to add. */ +/** + * Adds a decimal to an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the sum of \a a and \a b. + */ +ValueObject *opAddFloatInteger(ValueObject *a, + ValueObject *b) { return createFloatValueObject(getFloat(a) + getInteger(b)); } -/** Subtracts a float and an integer. - * - * \pre \a a was created by createFloatValueObject(float) and \a b was created - * by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the difference of - * the values \a a and \a b. - * - * \see opAddFloatInteger(ValueObject *, ValueObject *) - * \see opMultFloatInteger(ValueObject *, ValueObject *) - * \see opDivFloatInteger(ValueObject *, ValueObject *) - * \see opMaxFloatInteger(ValueObject *, ValueObject *) - * \see opMinFloatInteger(ValueObject *, ValueObject *) - * \see opModFloatInteger(ValueObject *, ValueObject *) */ -ValueObject *opSubFloatInteger(ValueObject *a, /**< [in] The minuend. */ - ValueObject *b) /**< [in] The subtrahend. */ +/** + * Subtracts a decimal from an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the difference of \a a and \a b. + */ +ValueObject *opSubFloatInteger(ValueObject *a, + ValueObject *b) { return createFloatValueObject(getFloat(a) - getInteger(b)); } -/** Multiplies a float and an integer. - * - * \pre \a a was created by createFloatValueObject(float) and \a b was created - * by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the product of the - * values \a a and \a b. - * - * \see opAddFloatInteger(ValueObject *, ValueObject *) - * \see opSubFloatInteger(ValueObject *, ValueObject *) - * \see opDivFloatInteger(ValueObject *, ValueObject *) - * \see opMaxFloatInteger(ValueObject *, ValueObject *) - * \see opMinFloatInteger(ValueObject *, ValueObject *) - * \see opModFloatInteger(ValueObject *, ValueObject *) */ ValueObject *opMultFloatInteger(ValueObject *a, /**< [in] The first factor to multiply. */ - ValueObject *b) /**< [in] The second factor to multiply. */ +/** + * Multiplies a decimal by an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the product of \a a and \a b. + */ +ValueObject *opMultFloatInteger(ValueObject *a, + ValueObject *b) { return createFloatValueObject(getFloat(a) * getInteger(b)); } -/** Divides a float and an integer. - * - * \pre \a a was created by createFloatValueObject(float) and \a b was created - * by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the quotient of the - * values \a a and \a b. - * - * \retval NULL Division by zero was attempted. - * - * \see opAddFloatInteger(ValueObject *, ValueObject *) - * \see opSubFloatInteger(ValueObject *, ValueObject *) - * \see opMultFloatInteger(ValueObject *, ValueObject *) - * \see opMaxFloatInteger(ValueObject *, ValueObject *) - * \see opMinFloatInteger(ValueObject *, ValueObject *) - * \see opModFloatInteger(ValueObject *, ValueObject *) */ -ValueObject *opDivFloatInteger(ValueObject *a, /**< [in] The dividend. */ - ValueObject *b) /**< [in] The divisor. */ +/** + * Divides a decimal by an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the quotient of \a a and \a b. + * + * \retval NULL Division by zero. + */ +ValueObject *opDivFloatInteger(ValueObject *a, + ValueObject *b) { if (getInteger(b) == 0) { fprintf(stderr, "Division by zero undefined\n"); @@ -1931,62 +2093,47 @@ ValueObject *opDivFloatInteger(ValueObject *a, /**< [in] The dividend. */ return createFloatValueObject(getFloat(a) / getInteger(b)); } -/** Finds the maximum of a float and an integer. - * - * \pre \a a was created by createFloatValueObject(float) and \a b was created - * by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the maximum of the - * values \a a and \a b. - * - * \see opAddFloatInteger(ValueObject *, ValueObject *) - * \see opSubFloatInteger(ValueObject *, ValueObject *) - * \see opMultFloatInteger(ValueObject *, ValueObject *) - * \see opDivFloatInteger(ValueObject *, ValueObject *) - * \see opMinFloatInteger(ValueObject *, ValueObject *) - * \see opModFloatInteger(ValueObject *, ValueObject *) */ -ValueObject *opMaxFloatInteger(ValueObject *a, /**< [in] The first number to compare. */ - ValueObject *b) /**< [in] The second number to compare. */ +/** + * Finds the maximum of a decimal and an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the maximum of \a a and \a b. + */ +ValueObject *opMaxFloatInteger(ValueObject *a, + ValueObject *b) { return createFloatValueObject(getFloat(a) > (float)(getInteger(b)) ? getFloat(a) : (float)(getInteger(b))); } -/** Finds the minimum of a float and an integer. - * - * \pre \a a was created by createFloatValueObject(float) and \a b was created - * by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the minimum of the - * values \a a and \a b. - * - * \see opAddFloatInteger(ValueObject *, ValueObject *) - * \see opSubFloatInteger(ValueObject *, ValueObject *) - * \see opMultFloatInteger(ValueObject *, ValueObject *) - * \see opDivFloatInteger(ValueObject *, ValueObject *) - * \see opMaxFloatInteger(ValueObject *, ValueObject *) - * \see opModFloatInteger(ValueObject *, ValueObject *) */ -ValueObject *opMinFloatInteger(ValueObject *a, /**< [in] The first number to compare. */ - ValueObject *b) /**< [in] The second number to compare. */ +/** + * Finds the minimum of a decimal and an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the minimum of \a a and \a b. + */ +ValueObject *opMinFloatInteger(ValueObject *a, + ValueObject *b) { return createFloatValueObject(getFloat(a) < (float)(getInteger(b)) ? getFloat(a) : (float)(getInteger(b))); } -/** Calculates the modulus of a float and an integer. - * - * \pre \a a was created by createFloatValueObject(float) and \a b was created - * by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing the modulus of the - * values \a a and \a b. - * - * \see opAddFloatInteger(ValueObject *, ValueObject *) - * \see opSubFloatInteger(ValueObject *, ValueObject *) - * \see opMultFloatInteger(ValueObject *, ValueObject *) - * \see opDivFloatInteger(ValueObject *, ValueObject *) - * \see opMaxFloatInteger(ValueObject *, ValueObject *) - * \see opMinFloatInteger(ValueObject *, ValueObject *) */ -ValueObject *opModFloatInteger(ValueObject *a, /**< [in] The dividend. */ - ValueObject *b) /**< [in] The divisor. */ +/** + * Calculates the modulus of a decimal and an integer. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the modulus of \a a and \a b. + */ +ValueObject *opModFloatInteger(ValueObject *a, + ValueObject *b) { if (getInteger(b) == 0) { fprintf(stderr, "Division by zero undefined\n"); @@ -1995,80 +2142,64 @@ ValueObject *opModFloatInteger(ValueObject *a, /**< [in] The dividend. */ return createFloatValueObject((float)(fmod(getFloat(a), (double)(getInteger(b))))); } -/** Adds two floats. - * - * \pre \a a and \a b were created by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the sum of the - * values \a a and \a b. - * - * \see opSubFloatFloat(ValueObject *, ValueObject *) - * \see opMultFloatFloat(ValueObject *, ValueObject *) - * \see opDivFloatFloat(ValueObject *, ValueObject *) - * \see opMaxFloatFloat(ValueObject *, ValueObject *) - * \see opMinFloatFloat(ValueObject *, ValueObject *) - * \see opModFloatFloat(ValueObject *, ValueObject *) */ -ValueObject *opAddFloatFloat(ValueObject *a, /**< [in] The first term to add. */ - ValueObject *b) /**< [in] The second term to add. */ +/** + * Adds a decimal to a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the sum of \a a and \a b. + */ +ValueObject *opAddFloatFloat(ValueObject *a, + ValueObject *b) { return createFloatValueObject(getFloat(a) + getFloat(b)); } -/** Subtracts two floats. - * - * \pre \a a and \a b were created by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the difference of - * the values \a a and \a b. - * - * \see opAddFloatFloat(ValueObject *, ValueObject *) - * \see opMultFloatFloat(ValueObject *, ValueObject *) - * \see opDivFloatFloat(ValueObject *, ValueObject *) - * \see opMaxFloatFloat(ValueObject *, ValueObject *) - * \see opMinFloatFloat(ValueObject *, ValueObject *) - * \see opModFloatFloat(ValueObject *, ValueObject *) */ -ValueObject *opSubFloatFloat(ValueObject *a, /**< [in] The minuend. */ - ValueObject *b) /**< [in] The subtrahend. */ +/** + * Subtracts a decimal from a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the difference of \a a and \a b. + */ +ValueObject *opSubFloatFloat(ValueObject *a, + ValueObject *b) { return createFloatValueObject(getFloat(a) - getFloat(b)); } -/** Multiplies two floats. - * - * \pre \a a and \a b were created by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the product of the - * values \a a and \a b. - * - * \see opAddFloatFloat(ValueObject *, ValueObject *) - * \see opSubFloatFloat(ValueObject *, ValueObject *) - * \see opDivFloatFloat(ValueObject *, ValueObject *) - * \see opMaxFloatFloat(ValueObject *, ValueObject *) - * \see opMinFloatFloat(ValueObject *, ValueObject *) - * \see opModFloatFloat(ValueObject *, ValueObject *) */ -ValueObject *opMultFloatFloat(ValueObject *a, /**< [in] The first factor to multiply. */ - ValueObject *b) /**< [in] The second factor to multiply. */ +/** + * Multiplies a decimal by a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the product of \a a and \a b. + */ +ValueObject *opMultFloatFloat(ValueObject *a, + ValueObject *b) { return createFloatValueObject(getFloat(a) * getFloat(b)); } -/** Divides two floats. - * - * \pre \a a and \a b were created by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the quotient of the - * values \a a and \a b. - * - * \retval NULL Division by zero was attempted. - * - * \see opAddFloatFloat(ValueObject *, ValueObject *) - * \see opSubFloatFloat(ValueObject *, ValueObject *) - * \see opMultFloatFloat(ValueObject *, ValueObject *) - * \see opMaxFloatFloat(ValueObject *, ValueObject *) - * \see opMinFloatFloat(ValueObject *, ValueObject *) - * \see opModFloatFloat(ValueObject *, ValueObject *) */ -ValueObject *opDivFloatFloat(ValueObject *a, /**< [in] The dividend. */ - ValueObject *b) /**< [in] The divisor. */ +/** + * Divides a decimal by a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the quotient of \a a and \a b. + * + * \retval NULL Division by zero. + */ +ValueObject *opDivFloatFloat(ValueObject *a, + ValueObject *b) { if (fabs(getFloat(b) - 0.0) < FLT_EPSILON) { fprintf(stderr, "Division by zero undefined\n"); @@ -2077,59 +2208,47 @@ ValueObject *opDivFloatFloat(ValueObject *a, /**< [in] The dividend. */ return createFloatValueObject(getFloat(a) / getFloat(b)); } -/** Finds the maximum of two floats. - * - * \pre \a a and \a b were created by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the maximum of the - * values \a a and \a b. - * - * \see opAddFloatFloat(ValueObject *, ValueObject *) - * \see opSubFloatFloat(ValueObject *, ValueObject *) - * \see opMultFloatFloat(ValueObject *, ValueObject *) - * \see opDivFloatFloat(ValueObject *, ValueObject *) - * \see opMinFloatFloat(ValueObject *, ValueObject *) - * \see opModFloatFloat(ValueObject *, ValueObject *) */ -ValueObject *opMaxFloatFloat(ValueObject *a, /**< [in] The first number to compare. */ - ValueObject *b) /**< [in] The second number to compare. */ +/** + * Finds the maximum of a decimal and a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the maximum of \a a and \a b. + */ +ValueObject *opMaxFloatFloat(ValueObject *a, + ValueObject *b) { return createFloatValueObject(getFloat(a) > getFloat(b) ? getFloat(a) : getFloat(b)); } -/** Finds the minimum of two floats. - * - * \pre \a a and \a b were created by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the minimum of the - * values \a a and \a b. - * - * \see opAddFloatFloat(ValueObject *, ValueObject *) - * \see opSubFloatFloat(ValueObject *, ValueObject *) - * \see opMultFloatFloat(ValueObject *, ValueObject *) - * \see opDivFloatFloat(ValueObject *, ValueObject *) - * \see opMaxFloatFloat(ValueObject *, ValueObject *) - * \see opModFloatFloat(ValueObject *, ValueObject *) */ -ValueObject *opMinFloatFloat(ValueObject *a, /**< [in] The first number to compare. */ - ValueObject *b) /**< [in] The second number to compare. */ +/** + * Finds the minimum of a decimal and a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the minimum of \a a and \a b. + */ +ValueObject *opMinFloatFloat(ValueObject *a, + ValueObject *b) { return createFloatValueObject(getFloat(a) < getFloat(b) ? getFloat(a) : getFloat(b)); } -/** Calculates the modulus of two floats. - * - * \pre \a a and \a b were created by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing the modulus of the - * values \a a and \a b. - * - * \see opAddFloatFloat(ValueObject *, ValueObject *) - * \see opSubFloatFloat(ValueObject *, ValueObject *) - * \see opMultFloatFloat(ValueObject *, ValueObject *) - * \see opDivFloatFloat(ValueObject *, ValueObject *) - * \see opMaxFloatFloat(ValueObject *, ValueObject *) - * \see opMinFloatFloat(ValueObject *, ValueObject *) */ -ValueObject *opModFloatFloat(ValueObject *a, /**< [in] The dividend. */ - ValueObject *b) /**< [in] The divisor. */ +/** + * Calculates the modulus of a decimal and a decimal. + * + * \param [in] a The first operand. + * + * \param [in] b The second operand. + * + * \return A pointer to the value of the modulus of \a a and \a b. + */ +ValueObject *opModFloatFloat(ValueObject *a, + ValueObject *b) { if (fabs(getFloat(b) - 0.0) < FLT_EPSILON) { fprintf(stderr, "Division by zero undefined\n"); @@ -2138,10 +2257,12 @@ ValueObject *opModFloatFloat(ValueObject *a, /**< [in] The dividend. */ return createFloatValueObject((float)(fmod(getFloat(a), getFloat(b)))); } -/* A jump table for arithmetic operations. The first index determines the - * particular arithmetic operation to parform, the second index determines the +/* + * A jump table for arithmetic operations. The first index determines the + * particular arithmetic operation to perform, the second index determines the * type of the first argument, and the third index determines the type of the - * second object. */ + * second object. + */ static ValueObject *(*ArithOpJumpTable[7][2][2])(ValueObject *, ValueObject *) = { { { opAddIntegerInteger, opAddIntegerFloat }, { opAddFloatInteger, opAddFloatFloat } }, { { opSubIntegerInteger, opSubIntegerFloat }, { opSubFloatInteger, opSubFloatFloat } }, @@ -2152,29 +2273,21 @@ static ValueObject *(*ArithOpJumpTable[7][2][2])(ValueObject *, ValueObject *) = { { opMinIntegerInteger, opMinIntegerFloat }, { opMinFloatInteger, opMinFloatFloat } } }; -/** Interprets an arithmetic operation expression. - * - * \pre \a expr was created by createOpExprNode(OpType type, ExprNodeList *args) - * where \a type is either OP_ADD, OP_SUB, OP_MULT, OP_DIV, or OP_MOD and - * \a args was created by createExprNodeList(void) and populated with - * ExprNode structures using addExprNode(ExprNodeList *, ExprNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \note Only the first two elements in \a args are considered. - * - * \return A pointer to a ValueObject structure containing the interpreted - * operation expression value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretNotOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretBoolOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretEqualityOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretConcatOpExprNode(OpExprNode *, ScopeObject *) */ -ValueObject *interpretArithOpExprNode(OpExprNode *expr, /**< [in] A pointer to the OpExprNode structure to interpret. */ - ScopeObject *scope) /**< [in] A pointer to the ScopeObject structure to evaluate \a expr under. */ +/** + * Interprets an arithmetic operation. + * + * \param [in] expr The operation to interpret. + * + * \param [in] scope The scope to evaluate \a expr under. + * + * \note Only supports binary arithmetic operations. + * + * \return A pointer to the value of the arithmetic operation. + * + * \retval NULL An error occurred during interpretation. + */ +ValueObject *interpretArithOpExprNode(OpExprNode *expr, + ScopeObject *scope) { ValueObject *val1 = interpretExprNode(expr->args->exprs[0], scope); ValueObject *val2 = interpretExprNode(expr->args->exprs[1], scope); @@ -2278,32 +2391,26 @@ ValueObject *interpretArithOpExprNode(OpExprNode *expr, /**< [in] A pointer to return ret; } -/** Interprets a boolean operation expression. - * - * \pre \a expr was created by createOpExprNode(OpType type, ExprNodeList *args) - * where \a type is either OP_AND, OP_OR, or OP_XOR and \a args was - * created by createExprNodeList(void) and populated with ExprNode - * structures using addExprNode(ExprNodeList *, ExprNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ValueObject structure containing the interpreted - * operation expression value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretArithOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretNotOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretEqualityOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretConcatOpExprNode(OpExprNode *, ScopeObject *) */ -ValueObject *interpretBoolOpExprNode(OpExprNode *expr, /**< [in] A pointer to the OpExprNode structure to interpret. */ - ScopeObject *scope) /**< [in] A pointer to the ScopeObject structure to evaluate \a expr under. */ +/** + * Interprets a boolean operation. + * + * \param [in] expr The operation to interpret. + * + * \param [in] scope The scope to evaluate \a expr under. + * + * \return A pointer to the value of the boolean operation. + * + * \retval NULL An error occurred during interpretation. + */ +ValueObject *interpretBoolOpExprNode(OpExprNode *expr, + ScopeObject *scope) { unsigned int n; int acc = 0; - /* Proceed to apply the same operation on the accumulator for the - * remaining arguments. */ + /* + * Proceed to apply the same operation on the accumulator for the + * remaining arguments. + */ for (n = 0; n < expr->args->num; n++) { ValueObject *val = interpretExprNode(expr->args->exprs[n], scope); ValueObject *use = val; @@ -2338,231 +2445,236 @@ ValueObject *interpretBoolOpExprNode(OpExprNode *expr, /**< [in] A pointer to return NULL; } } - /** \note The specification does not say whether boolean logic - * short circuits or not. Here, we assume it does. */ + /** + * \note The specification does not say whether boolean logic + * short circuits or not. Here, we assume it does. + */ if (expr->type == OP_AND && acc == 0) break; else if (expr->type == OP_OR && acc == 1) break; } return createBooleanValueObject(acc); } -/** Tests if two integers are equal. - * - * \pre \a a and \a b were created by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is equal to \a b. - * - * \see opNeqIntegerInteger(ValueObject *, ValueObject *) */ -ValueObject *opEqIntegerInteger(ValueObject *a, /**< [in] The first value to test. */ - ValueObject *b) /**< [in] The second value to test. */ +/** + * Checks if an integer value is equal to another integer value. + * + * \param [in] a The first value to check. + * + * \param [in] b The second value to check. + * + * \return A pointer to a boolean value indicating if \a is equal to \a b. + */ +ValueObject *opEqIntegerInteger(ValueObject *a, + ValueObject *b) { return createBooleanValueObject(getInteger(a) == getInteger(b)); } -/** Tests if two integers are not equal. - * - * \pre \a a and \a b were created by createIntegerValueObject(int). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is not equal to \a b. - * - * \see opEqIntegerInteger(ValueObject *, ValueObject *) */ -ValueObject *opNeqIntegerInteger(ValueObject *a, /**< [in] The first value to test. */ - ValueObject *b) /**< [in] The second value to test. */ +/** + * Checks if an integer value is not equal to another integer value. + * + * \param [in] a The first value to check. + * + * \param [in] b The second value to check. + * + * \return A pointer to a boolean value indicating if \a is not equal to \a b. + */ +ValueObject *opNeqIntegerInteger(ValueObject *a, + ValueObject *b) { return createBooleanValueObject(getInteger(a) != getInteger(b)); } -/** Tests if an integer and a float are equal. - * - * \pre \a a was created by createIntegerValueObject(int) and \a b was created - * by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is equal to \a b. - * - * \see opNeqIntegerFloat(ValueObject *, ValueObject *) */ -ValueObject *opEqIntegerFloat(ValueObject *a, /**< [in] The first value to test. */ - ValueObject *b) /**< [in] The second value to test. */ +/** + * Checks if an integer value is equal to a decimal value. + * + * \param [in] a The first value to check. + * + * \param [in] b The second value to check. + * + * \return A pointer to a boolean value indicating if \a is equal to \a b. + */ +ValueObject *opEqIntegerFloat(ValueObject *a, + ValueObject *b) { return createBooleanValueObject(fabs((float)(getInteger(a)) - getFloat(b)) < FLT_EPSILON); } -/** Tests if an integer and a float are not equal. - * - * \pre \a a was created by createIntegerValueObject(int) and \a b was created - * by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is not equal to \a b. - * - * \see opEqIntegerFloat(ValueObject *, ValueObject *) */ -ValueObject *opNeqIntegerFloat(ValueObject *a, /**< [in] The first value to test. */ - ValueObject *b) /**< [in] The second value to test. */ +/** + * Checks if an integer value is not equal to a decimal value. + * + * \param [in] a The first value to check. + * + * \param [in] b The second value to check. + * + * \return A pointer to a boolean value indicating if \a is not equal to \a b. + */ +ValueObject *opNeqIntegerFloat(ValueObject *a, + ValueObject *b) { return createBooleanValueObject(fabs((float)(getInteger(a)) - getFloat(b)) > FLT_EPSILON); } -/** Tests if a float and an integer are equal. - * - * \pre \a a was created by createFloatValueObject(float) and \a b was created - * by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is equal to \a b. - * - * \see opNeqFloatInteger(ValueObject *, ValueObject *) */ -ValueObject *opEqFloatInteger(ValueObject *a, /**< [in] The first value to test. */ - ValueObject *b) /**< [in] The second value to test. */ +/** + * Checks if a decimal value is equal to an integer value. + * + * \param [in] a The first value to check. + * + * \param [in] b The second value to check. + * + * \return A pointer to a boolean value indicating if \a is equal to \a b. + */ +ValueObject *opEqFloatInteger(ValueObject *a, + ValueObject *b) { return createBooleanValueObject(fabs(getFloat(a) - (float)(getInteger(b))) < FLT_EPSILON); } -/** Tests if a float and an integer are not equal. - * - * \pre \a a was created by createFloatValueObject(float) and \a b was created - * by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is not equal to \a b. - * - * \see opEqFloatInteger(ValueObject *, ValueObject *) */ -ValueObject *opNeqFloatInteger(ValueObject *a, /**< [in] The first value to test. */ - ValueObject *b) /**< [in] The second value to test. */ +/** + * Checks if a decimal value is not equal to an integer value. + * + * \param [in] a The first value to check. + * + * \param [in] b The second value to check. + * + * \return A pointer to a boolean value indicating if \a is not equal to \a b. + */ +ValueObject *opNeqFloatInteger(ValueObject *a, + ValueObject *b) { return createBooleanValueObject(fabs(getFloat(a) - (float)(getInteger(b))) > FLT_EPSILON); } -/** Tests if two floats are equal. - * - * \pre \a a and \a b were created by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is equal to \a b. - * - * \see opNeqFloatFloat(ValueObject *, ValueObject *) */ -ValueObject *opEqFloatFloat(ValueObject *a, /**< [in] The first value to test. */ - ValueObject *b) /**< [in] The second value to test. */ +/** + * Checks if a decimal value is equal to another decimal value. + * + * \param [in] a The first value to check. + * + * \param [in] b The second value to check. + * + * \return A pointer to a boolean value indicating if \a is equal to \a b. + */ +ValueObject *opEqFloatFloat(ValueObject *a, + ValueObject *b) { return createBooleanValueObject(fabs(getFloat(a) - getFloat(b)) < FLT_EPSILON); } -/** Tests if two floats are not equal. - * - * \pre \a a and \a b were created by createFloatValueObject(float). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is not equal to \a b. - * - * \see opNeqFloatFloat(ValueObject *, ValueObject *) */ -ValueObject *opNeqFloatFloat(ValueObject *a, /**< [in] The first value to test. */ - ValueObject *b) /**< [in] The second value to test. */ +/** + * Checks if a decimal value is not equal to another decimal value. + * + * \param [in] a The first value to check. + * + * \param [in] b The second value to check. + * + * \return A pointer to a boolean value indicating if \a is not equal to \a b. + */ +ValueObject *opNeqFloatFloat(ValueObject *a, + ValueObject *b) { return createBooleanValueObject(fabs(getFloat(a) - getFloat(b)) > FLT_EPSILON); } -/** Tests if two boolean values are equal. - * - * \pre \a a and \a b were created by createBooleanValueObject(int). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is equal to \a b. - * - * \see opNeqBooleanBoolean(ValueObject *, ValueObject *) */ -ValueObject *opEqBooleanBoolean(ValueObject *a, /**< [in] The first value to test. */ - ValueObject *b) /**< [in] The second value to test. */ +/** + * Checks if a boolean value is equal to another boolean value. + * + * \param [in] a The first value to check. + * + * \param [in] b The second value to check. + * + * \return A pointer to a boolean value indicating if \a is equal to \a b. + */ +ValueObject *opEqBooleanBoolean(ValueObject *a, + ValueObject *b) { return createBooleanValueObject(getInteger(a) == getInteger(b)); } -/** Tests if two boolean values are not equal. - * - * \pre \a a and \a b were created by createBooleanValueObject(int). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is not equal to \a b. - * - * \see opEqBooleanBoolean(ValueObject *, ValueObject *) */ -ValueObject *opNeqBooleanBoolean(ValueObject *a, /**< [in] The first value to test. */ - ValueObject *b) /**< [in] The second value to test. */ +/** + * Checks if a boolean value is not equal to another boolean value. + * + * \param [in] a The first value to check. + * + * \param [in] b The second value to check. + * + * \return A pointer to a boolean value indicating if \a is not equal to \a b. + */ +ValueObject *opNeqBooleanBoolean(ValueObject *a, + ValueObject *b) { return createBooleanValueObject(getInteger(a) != getInteger(b)); } -/** Tests if two strings are equal. - * - * \pre \a a and \a b were created by createStringValueObject(char *). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is equal to \a b. - * - * \see opNeqStringString(ValueObject *, ValueObject *) */ -ValueObject *opEqStringString(ValueObject *a, /**< [in] The first value to test. */ - ValueObject *b) /**< [in] The second value to test. */ +/** + * Checks if a string value is equal to another string value. + * + * \param [in] a The first value to check. + * + * \param [in] b The second value to check. + * + * \return A pointer to a boolean value indicating if \a is equal to \a b. + */ +ValueObject *opEqStringString(ValueObject *a, + ValueObject *b) { return createBooleanValueObject(strcmp(getString(a), getString(b)) == 0); } -/** Tests if two strings are not equal. - * - * \pre \a a and \a b were created by createStringValueObject(char *). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is not equal to \a b. - * - * \see opEqStringString(ValueObject *, ValueObject *) */ -ValueObject *opNeqStringString(ValueObject *a, /**< [in] The first value to test. */ - ValueObject *b) /**< [in] The second value to test. */ +/** + * Checks if a string value is not equal to another string value. + * + * \param [in] a The first value to check. + * + * \param [in] b The second value to check. + * + * \return A pointer to a boolean value indicating if \a is not equal to \a b. + */ +ValueObject *opNeqStringString(ValueObject *a, + ValueObject *b) { return createBooleanValueObject(strcmp(getString(a), getString(b)) != 0); } -/** Tests if two nil values are equal. - * - * \note Two nil values are \b always equal, therefore \a a and \a b are not - * used by this function but are still included in its prototype to allow - * this function to be stored in a jump table for fast execution. - * - * \pre \a a and \a b were created by createNilValueObject(void). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is equal to \a b. - * - * \see opNeqNilNil(ValueObject *, ValueObject *) */ -ValueObject *opEqNilNil(ValueObject *a, /**< Not used (see note). */ - ValueObject *b) /**< Not used (see note). */ +/** + * Returns true because two nil values are always equal. + * + * \param [in] a Not used. + * + * \param [in] b Not used. + * + * \return A true boolean value. + */ +ValueObject *opEqNilNil(ValueObject *a, + ValueObject *b) { a = NULL; b = NULL; return createBooleanValueObject(1); } -/** Tests if two nil values are not equal. - * - * \note Two nil values are \b always equal and thus \b never not equal, - * therefore \a a and \a b are not used by this function but are still - * included in its prototype to allow this function to be stored in a - * jump table for fast execution. - * - * \pre \a a and \a b were created by createNilValueObject(void). - * - * \return A pointer to a ValueObject structure containing a boolean value - * indicating whether \a a is not equal to \a b. - * - * \see opEqNilNil(ValueObject *, ValueObject *) */ -ValueObject *opNeqNilNil(ValueObject *a, /**< Not used (see note). */ - ValueObject *b) /**< Not used (see note). */ +/** + * Returns false because two nil values are never not equal. + * + * \param [in] a Not used. + * + * \param [in] b Not used. + * + * \return A false boolean value. + */ +ValueObject *opNeqNilNil(ValueObject *a, + ValueObject *b) { a = NULL; b = NULL; return createBooleanValueObject(0); } -/* A jump table for boolean operations. The first index determines the - * particular boolean operation to perform, the second index determines the - * type of the first argument, and the third index determines the type of the - * second object. */ +/* + * A jump table for boolean operations. The first index determines the + * particular boolean operation to perform, the second index determines the type + * of the first argument, and the third index determines the type of the second + * object. + */ static ValueObject *(*BoolOpJumpTable[2][5][5])(ValueObject *, ValueObject *) = { { /* OP_EQ */ /* Integer, Float, Boolean, String, Nil */ @@ -2582,29 +2694,19 @@ static ValueObject *(*BoolOpJumpTable[2][5][5])(ValueObject *, ValueObject *) = } }; -/** Interprets an equality operation expression. - * - * \pre \a expr was created by createOpExprNode(OpType type, ExprNodeList *args) - * where \a type is either OP_EQ or OP_NEQ and \a args was created by - * createExprNodeList(void) and populated with ExprNode structures using - * addExprNode(ExprNodeList *, ExprNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \note Only the first two elements in \a args are considered. - * - * \return A pointer to a ValueObject structure containing the interpreted - * operation expression value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretArithOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretNotOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretBoolOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretConcatOpExprNode(OpExprNode *, ScopeObject *) */ -ValueObject *interpretEqualityOpExprNode(OpExprNode *expr, /**< [in] A pointer to the OpExprNode structure to interpret. */ - ScopeObject *scope) /**< [in] A pointer to the ScopeObject structure to evaluate \a expr under. */ +/** + * Interprets an equality operation. + * + * \param [in] expr The operation to interpret. + * + * \param [in] scope The scope to evaluate \a expr under. + * + * \return A pointer to the resulting value of the equality operation. + * + * \retval NULL An error occurred during interpretation. + */ +ValueObject *interpretEqualityOpExprNode(OpExprNode *expr, + ScopeObject *scope) { ValueObject *val1 = interpretExprNode(expr->args->exprs[0], scope); ValueObject *val2 = interpretExprNode(expr->args->exprs[1], scope); @@ -2614,8 +2716,10 @@ ValueObject *interpretEqualityOpExprNode(OpExprNode *expr, /**< [in] A pointer deleteValueObject(val2); return NULL; } - /* Since there is no automatic casting, an equality (inequality) test - * against a non-number type will always fail (succeed). */ + /* + * Since there is no automatic casting, an equality (inequality) test + * against a non-number type will always fail (succeed). + */ if ((val1->type != val2->type) && ((val1->type != VT_INTEGER && val1->type != VT_FLOAT) || (val2->type != VT_INTEGER && val2->type != VT_FLOAT))) { @@ -2640,26 +2744,19 @@ ValueObject *interpretEqualityOpExprNode(OpExprNode *expr, /**< [in] A pointer return ret; } -/** Interprets a concatenation operation expression. - * - * \pre \a expr was created by createOpExprNode(OpType type, ExprNodeList *args) - * where \a type is OP_CAT and \a args was created by createExprNodeList(void) - * and populated with ExprNode structures using addExprNode(ExprNodeList *, ExprNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ValueObject structure containing the concatenation of - * all the arguments in \a args. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretNotOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretArithOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretBoolOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretEqualityOpExprNode(OpExprNode *, ScopeObject *) */ -ValueObject *interpretConcatOpExprNode(OpExprNode *expr, /**< [in] A pointer to the OpExprNode structure to interpret. */ - ScopeObject *scope) /**< [in] A pointer to the ScopeObject structure to evaluate \a expr under. */ +/** + * Interprets a concatenation operation. + * + * \param [in] expr The operation to interpret. + * + * \param [in] scope The scope to evaluate \a expr under. + * + * \return A pointer to the resulting value of the concatenation operation. + * + * \retval NULL An error occurred during interpretation. + */ +ValueObject *interpretConcatOpExprNode(OpExprNode *expr, + ScopeObject *scope) { unsigned int n; /* Start out with the first string to concatenate. */ @@ -2713,8 +2810,10 @@ ValueObject *interpretConcatOpExprNode(OpExprNode *expr, /**< [in] A pointer t return createStringValueObject(acc); } -/* A jump table for operations. The index of a function in the table is given - * by its its index in the enumerated OpType type. */ +/* + * A jump table for operations. The index of a function in the table is given + * by its its index in the enumerated OpType type. + */ static ValueObject *(*OpExprJumpTable[14])(OpExprNode *, ScopeObject *) = { interpretArithOpExprNode, interpretArithOpExprNode, @@ -2731,32 +2830,28 @@ static ValueObject *(*OpExprJumpTable[14])(OpExprNode *, ScopeObject *) = { interpretEqualityOpExprNode, interpretConcatOpExprNode }; -/** Interprets an operation expression. - * - * \pre \a expr was created by createOpExprNode(OpType, ExprNodeList *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ValueObject structure containing the interpreted - * operation expression value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretNotOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretArithOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretBoolOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretEqualityOpExprNode(OpExprNode *, ScopeObject *) - * \see interpretConcatOpExprNode(OpExprNode *, ScopeObject *) */ -ValueObject *interpretOpExprNode(ExprNode *node, /**< [in] A pointer to an ExprNode structure to interpret. */ - ScopeObject *scope) /**< [in] A pointer to a ScopeObject structure to evaluate \a node under. */ +/** + * Interprets an operation. + * + * \param [in] node The operation to interpret. + * + * \param [in] scope The scope to evaluate \a expr under. + * + * \return A pointer to the resulting value of the operation. + * + * \retval NULL An error occurred during interpretation. + */ +ValueObject *interpretOpExprNode(ExprNode *node, + ScopeObject *scope) { OpExprNode *expr = (OpExprNode *)node->expr; return OpExprJumpTable[expr->type](expr, scope); } -/* A jump table for expressions. The index of a function in the table is given - * by its its index in the enumerated ExprType type. */ +/* + * A jump table for expressions. The index of a function in the table is given + * by its its index in the enumerated ExprType type. + */ static ValueObject *(*ExprJumpTable[6])(ExprNode *, ScopeObject *) = { interpretCastExprNode, interpretConstantExprNode, @@ -2765,57 +2860,41 @@ static ValueObject *(*ExprJumpTable[6])(ExprNode *, ScopeObject *) = { interpretOpExprNode, interpretImpVarExprNode }; -/** Interprets the contents of an ExprNode structure. - * - * \pre \a node was created by parseExprNode(Token ***). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ValueObject structure with the evaluated contents of - * \a node in the scope \a scope. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretStmtNode(StmtNode *, ScopeObject *) - * \see interpretStmtNodeList(StmtNodeList *, ScopeObject *) - * \see interpretBlockNode(BlockNode *, ScopeObject *) - * \see interpretMainNode(MainNode *) */ -ValueObject *interpretExprNode(ExprNode *node, /**< [in] A pointer to an ExprNode structure to interpret. */ - ScopeObject *scope) /**< [in] A pointer to a ScopeObject structure to evaluate \a node under. */ +/** + * Interprets an expression. + * + * \param [in] node The expression to interpret. + * + * \param [in] scope The scope to evaluate \a expr under. + * + * \return A pointer to the value of \a expr evaluated under \a scope. + * + * \retval NULL An error occurred during interpretation. + */ +ValueObject *interpretExprNode(ExprNode *node, + ScopeObject *scope) { return ExprJumpTable[node->type](node, scope); } -/** Interprets a cast statement. - * - * \pre \a node was created by createStmtNode(StmtType type, void *stmt) - * where \a type is ST_CAST and \a stmt was created by createCastStmtNode(IdentifierNode *, TypeNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the default return value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretPrintStmtNode(StmtNode *, ScopeObject *) - * \see interpretInputStmtNode(StmtNode *, ScopeObject *) - * \see interpretAssignmentStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeclarationStmtNode(StmtNode *, ScopeObject *) - * \see interpretIfThenElseStmtNode(StmtNode *, ScopeObject *) - * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) - * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) - * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) - * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) - * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) - * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ -ReturnObject *interpretCastStmtNode(StmtNode *node, /**< [in] A pointer to the StmtNode structure containing the CastStmtNode structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a node under. */ +/** + * Interprets a cast statement. + * + * \param [in] node The statement to interpret. + * + * \param [in] scope The scope to evaluate \a node under. + * + * \pre \a node contains a statement created by createCastStmtNode(). + * + * \return A pointer to a default return value. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretCastStmtNode(StmtNode *node, + ScopeObject *scope) { CastStmtNode *stmt = (CastStmtNode *)node->stmt; - ValueObject *val = getScopeValue(scope, stmt->target); + ValueObject *val = getScopeValue(scope, scope, stmt->target); ValueObject *cast = NULL; if (!val) { IdentifierNode *id = (IdentifierNode *)(stmt->target); @@ -2843,39 +2922,28 @@ ReturnObject *interpretCastStmtNode(StmtNode *node, /**< [in] A pointer to t if (!(cast = castStringExplicit(val, scope))) return NULL; break; } - if (!updateScopeValue(scope, stmt->target, cast)) { + if (!updateScopeValue(scope, scope, stmt->target, cast)) { deleteValueObject(cast); return NULL; } return createReturnObject(RT_DEFAULT, NULL); } -/** Interprets a print statement. - * - * \pre \a node was created by createStmtNode(StmtType type, void *stmt) - * where \a type is ST_PRINT and \a stmt was created by createPrintStmtNode(ExprNodeList *, int). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the default return value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretCastStmtNode(StmtNode *, ScopeObject *) - * \see interpretInputStmtNode(StmtNode *, ScopeObject *) - * \see interpretAssignmentStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeclarationStmtNode(StmtNode *, ScopeObject *) - * \see interpretIfThenElseStmtNode(StmtNode *, ScopeObject *) - * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) - * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) - * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) - * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) - * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) - * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ -ReturnObject *interpretPrintStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing the PrintStmtNode structure to interpret. */ - ScopeObject *scope) /**< [in] A pointer to the ScopeObject structure to evaluate \a node under. */ +/** + * Interprets a print statement. + * + * \param [in] node The statement to interpret. + * + * \param [in] scope The scope to evaluate \a node under. + * + * \pre \a node contains a statement created by createPrintStmtNode(). + * + * \return A pointer to a default return value. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretPrintStmtNode(StmtNode *node, + ScopeObject *scope) { PrintStmtNode *stmt = (PrintStmtNode *)node->stmt; unsigned int n; @@ -2896,32 +2964,21 @@ ReturnObject *interpretPrintStmtNode(StmtNode *node, /**< [in] A pointer to return createReturnObject(RT_DEFAULT, NULL); } -/** Interprets an input statement. - * - * \pre \a node was created by createStmtNode(StmtType type, void *stmt) where - * \a type is ST_INPUT and \a stmt was created by createInputStmtNode(IdentifierNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the default return value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretCastStmtNode(StmtNode *, ScopeObject *) - * \see interpretPrintStmtNode(StmtNode *, ScopeObject *) - * \see interpretAssignmentStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeclarationStmtNode(StmtNode *, ScopeObject *) - * \see interpretIfThenElseStmtNode(StmtNode *, ScopeObject *) - * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) - * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) - * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) - * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) - * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) - * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ -ReturnObject *interpretInputStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing an InputStmtNode structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a node under. */ +/** + * Interprets an input statement. + * + * \param [in] node The statement to interpret. + * + * \param [in] scope The scope to evaluate \a node under. + * + * \pre \a node contains a statement created by createInputStmtNode(). + * + * \return A pointer to a default return value. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretInputStmtNode(StmtNode *node, + ScopeObject *scope) { unsigned int size = 16; unsigned int cur = 0; @@ -2931,9 +2988,11 @@ ReturnObject *interpretInputStmtNode(StmtNode *node, /**< [in] A pointer to InputStmtNode *stmt = (InputStmtNode *)node->stmt; ValueObject *val = NULL; while ((c = getchar())) { - /** \note The specification is unclear as to the exact semantics - * of input. Here, we read up until the first newline or - * EOF but do not store it. */ + /** + * \note The specification is unclear as to the exact semantics + * of input. Here, we read up until the first newline or EOF + * but do not store it. + */ if (c == EOF || c == (int)'\r' || c == (int)'\n') break; if (cur > size - 1) { /* Increasing buffer size. */ @@ -2955,80 +3014,60 @@ ReturnObject *interpretInputStmtNode(StmtNode *node, /**< [in] A pointer to free(temp); return NULL; } - if (!updateScopeValue(scope, stmt->target, val)) { + if (!updateScopeValue(scope, scope, stmt->target, val)) { deleteValueObject(val); return NULL; } return createReturnObject(RT_DEFAULT, NULL); } -/** Interprets an assignment statement. - * - * \pre \a node was created by createStmtNode(StmtType type, void *stmt) where - * \a type is ST_ASSIGNMENT and \a stmt was created by createAssignmentStmtNode(IdentifierNode *, ExprNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the default return value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretCastStmtNode(StmtNode *, ScopeObject *) - * \see interpretPrintStmtNode(StmtNode *, ScopeObject *) - * \see interpretInputStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeclarationStmtNode(StmtNode *, ScopeObject *) - * \see interpretIfThenElseStmtNode(StmtNode *, ScopeObject *) - * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) - * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) - * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) - * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) - * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) - * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ -ReturnObject *interpretAssignmentStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing the AssignmentStmtNode structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a node under. */ +/** + * Interprets an assignment statement. + * + * \param [in] node The statement to interpret. + * + * \param [in] scope The scope to evaluate \a node under. + * + * \pre \a node contains a statement created by createAssignmentStmtNode(). + * + * \return A pointer to a default return value. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretAssignmentStmtNode(StmtNode *node, + ScopeObject *scope) { AssignmentStmtNode *stmt = (AssignmentStmtNode *)node->stmt; ValueObject *val = interpretExprNode(stmt->expr, scope); if (!val) return NULL; - if (!updateScopeValue(scope, stmt->target, val)) { + if (!updateScopeValue(scope, scope, stmt->target, val)) { deleteValueObject(val); return NULL; } return createReturnObject(RT_DEFAULT, NULL); } -/** Interprets a declaration statement. - * - * \pre \a node was created by createStmtNode(StmtType type, void *stmt) where - * \a type is ST_DECLARATION and \a stmt was created by createDeclarationStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, TypeNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the default return value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretCastStmtNode(StmtNode *, ScopeObject *) - * \see interpretPrintStmtNode(StmtNode *, ScopeObject *) - * \see interpretInputStmtNode(StmtNode *, ScopeObject *) - * \see interpretAssignmentStmtNode(StmtNode *, ScopeObject *) - * \see interpretIfThenElseStmtNode(StmtNode *, ScopeObject *) - * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) - * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) - * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) - * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) - * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) - * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ -ReturnObject *interpretDeclarationStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing the DeclarationStmtNode structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a node under. */ +/** + * Interprets a declaration statement. + * + * \param [in] node The statement to interpret. + * + * \param [in] scope The scope to evaluate \a node under. + * + * \pre \a node contains a statement created by createDeclarationStmtNode(). + * + * \return A pointer to a default return value. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretDeclarationStmtNode(StmtNode *node, + ScopeObject *scope) { DeclarationStmtNode *stmt = (DeclarationStmtNode *)node->stmt; ValueObject *init = NULL; - if (getLocalScopeValue(scope, stmt->target)) { + ScopeObject *dest = NULL; + dest = getScopeObject(scope, scope, stmt->scope); + if (getScopeValueLocal(scope, dest, stmt->target)) { IdentifierNode *id = (IdentifierNode *)(stmt->target); char *name = resolveIdentifierName(id, scope); if (name) { @@ -3054,50 +3093,46 @@ ReturnObject *interpretDeclarationStmtNode(StmtNode *node, /**< [in] A point init = createFloatValueObject(0.0); break; case CT_STRING: - init = createStringValueObject(createString("")); + init = createStringValueObject(copyString("")); break; + case CT_ARRAY: + init = createArrayValueObject(scope); + break; + default: + fprintf(stderr, "Unknown declaration type!\n"); + return NULL; } } else init = createNilValueObject(); if (!init) return NULL; - if (!createScopeValue(scope, stmt->target)) { + /** \todo Okay, here is the problem, we can store to a different scope than where we evaluate the target from. So, stmt->target needs to be evaluated under ``scope'' but created in ``dest'' */ + if (!createScopeValue(scope, dest, stmt->target)) { deleteValueObject(init); return NULL; } - if (!updateScopeValue(scope, stmt->target, init)) { + if (!updateScopeValue(scope, dest, stmt->target, init)) { deleteValueObject(init); return NULL; } return createReturnObject(RT_DEFAULT, NULL); } -/** Interprets an if/then/else statement. - * - * \pre \a node was created by createStmtNode(StmtType type, void *stmt) where - * \a type is ST_IFTHENELSE and \a stmt was created by createIfThenElseStmtNode(BlockNode *, BlockNode *, ExprNodeList *, BlockNodeList *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the default return value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretCastStmtNode(StmtNode *, ScopeObject *) - * \see interpretPrintStmtNode(StmtNode *, ScopeObject *) - * \see interpretInputStmtNode(StmtNode *, ScopeObject *) - * \see interpretAssignmentStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeclarationStmtNode(StmtNode *, ScopeObject *) - * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) - * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) - * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) - * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) - * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) - * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ -ReturnObject *interpretIfThenElseStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing the IfThenElseStmtNode structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a node under. */ +/** + * Interprets an if/then/else statement. + * + * \param [in] node The statement to interpret. + * + * \param [in] scope The scope to evaluate \a node under. + * + * \pre \a node contains a statement created by createIfThenElseStmtNode(). + * + * \return A pointer to a default return value. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretIfThenElseStmtNode(StmtNode *node, + ScopeObject *scope) { IfThenElseStmtNode *stmt = (IfThenElseStmtNode *)node->stmt; ValueObject *use1 = scope->impvar; @@ -3156,45 +3191,34 @@ ReturnObject *interpretIfThenElseStmtNode(StmtNode *node, /**< [in] A pointe return createReturnObject(RT_DEFAULT, NULL); } -/** Interprets a switch statement. - * - * \note The specification is unclear as to whether guards are implicitly cast - * to the type of the implicit variable. This only matters in the case - * that mixed guard types are present and in this code, the action that - * is performed is the same as the comparison operator, that is, in order - * for a guard to match, both its type and value must match the implicit - * variable. - * - * \pre \a node was created by createStmtNode(StmtType type, void *stmt) where - * \a type is ST_SWITCH and \a stmt was created by createSwitchStmtNode(ExprNodeList *, BlockNodeList *, BlockNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the return value after - * interpreting \a node in the scope \a scope. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretCastStmtNode(StmtNode *, ScopeObject *) - * \see interpretPrintStmtNode(StmtNode *, ScopeObject *) - * \see interpretInputStmtNode(StmtNode *, ScopeObject *) - * \see interpretAssignmentStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeclarationStmtNode(StmtNode *, ScopeObject *) - * \see interpretIfThenElseStmtNode(StmtNode *, ScopeObject *) - * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) - * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) - * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) - * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) - * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ -ReturnObject *interpretSwitchStmtNode(StmtNode *node, /**< [in] A pointer to the StmtNode structure containing the SwitchStmtNode structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a node under. */ +/** + * Interprets a switch statement. + * + * \param [in] node The statement to interpret. + * + * \param [in] scope The scope to evaluate \a node under. + * + * \pre \a node contains a statement created by createSwitchStmtNode(). + * + * \note The specification is unclear as to whether guards are implicitly cast + * to the type of the implicit variable. This only matters in the case that + * mixed guard types are present, and in this code, the action that is performed + * is the same as the comparison operator, that is, in order for a guard to + * match, both its type and value must match the implicit variable. + * + * \return A pointer to a default return value. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretSwitchStmtNode(StmtNode *node, + ScopeObject *scope) { SwitchStmtNode *stmt = (SwitchStmtNode *)node->stmt; unsigned int n; - /* Loop over each of the guards, checking if any match the implicit - * variable. */ + /* + * Loop over each of the guards, checking if any match the implicit + * variable. + */ for (n = 0; n < stmt->guards->num; n++) { ValueObject *use1 = scope->impvar; ValueObject *use2 = interpretExprNode(stmt->guards->exprs[n], scope); @@ -3214,9 +3238,10 @@ ReturnObject *interpretSwitchStmtNode(StmtNode *node, /**< [in] A pointer to done = 1; break; case VT_STRING: - /** \note Strings with interpolation - * should have already been - * checked for. */ + /** + * \note Strings with interpolation + * should have already been checked for. + */ if (!strcmp(getString(use1), getString(use2))) done = 1; break; @@ -3240,8 +3265,10 @@ ReturnObject *interpretSwitchStmtNode(StmtNode *node, /**< [in] A pointer to deleteReturnObject(r); } else { - /* Keep interpreting blocks starting at n until a break or - * return is encountered. */ + /* + * Keep interpreting blocks starting at n until a break or + * return is encountered. + */ for (; n < stmt->blocks->num; n++) { ReturnObject *r = interpretBlockNode(stmt->blocks->blocks[n], scope); if (!r) @@ -3259,69 +3286,47 @@ ReturnObject *interpretSwitchStmtNode(StmtNode *node, /**< [in] A pointer to return createReturnObject(RT_DEFAULT, NULL); } -/** Interprets a break statement. - * - * \pre \a node was created by createStmtNode(StmtType type, void *stmt) where - * \a type is ST_BREAK and \a stmt is NULL. - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \note \a node and \a scope are not used by this function but are still - * included in its prototype to allow this function to be stored in a - * jump table for fast execution. - * - * \return A pointer to a ReturnObject structure indicating a break occurred. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretCastStmtNode(StmtNode *, ScopeObject *) - * \see interpretPrintStmtNode(StmtNode *, ScopeObject *) - * \see interpretInputStmtNode(StmtNode *, ScopeObject *) - * \see interpretAssignmentStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeclarationStmtNode(StmtNode *, ScopeObject *) - * \see interpretIfThenElseStmtNode(StmtNode *, ScopeObject *) - * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) - * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) - * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) - * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) - * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ -ReturnObject *interpretBreakStmtNode(StmtNode *node, /**< Not used (see note). */ - ScopeObject *scope) /**< Not used (see note). */ +/** + * Interprets a break statement. + * + * \param [in] node Not used (see note). + * + * \param [in] scope Not used (see note). + * + * \pre \a node contains a statement created by createStmtNode() with arguments + * ST_BREAK and NULL. + * + * \note \a node and \a scope are not used by this function but are still + * included in its prototype to allow this function to be stored in a jump table + * for fast execution. + * + * \return A pointer to a break return value. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretBreakStmtNode(StmtNode *node, + ScopeObject *scope) { node = NULL; scope = NULL; return createReturnObject(RT_BREAK, NULL); } -/** Interprets a return statement. - * - * \pre \a node was created by createStmtNode(StmtType type, void *stmt) where - * \a type is ST_RETURN and \a stmt was created by createReturnStmtNode(ExprNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the return value after - * interpreting \a node in the scope \a scope. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretCastStmtNode(StmtNode *, ScopeObject *) - * \see interpretPrintStmtNode(StmtNode *, ScopeObject *) - * \see interpretInputStmtNode(StmtNode *, ScopeObject *) - * \see interpretAssignmentStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeclarationStmtNode(StmtNode *, ScopeObject *) - * \see interpretIfThenElseStmtNode(StmtNode *, ScopeObject *) - * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) - * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) - * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) - * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) - * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ -ReturnObject *interpretReturnStmtNode(StmtNode *node, /**< [in] A pointer to the StmtNode structure containing the ReturnStmtNode structure to interpret. */ - ScopeObject *scope) /**< [in] A pointer to the ScopeObject structure to evaluate \a node under. */ +/** + * Interprets a return statement. + * + * \param [in] node The statement to interpret. + * + * \param [in] scope The scope to evaluate \a node under. + * + * \pre \a node contains a statement created by createReturnStmtNode(). + * + * \return A pointer to a return value of \a node interpreted under \a scope. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretReturnStmtNode(StmtNode *node, + ScopeObject *scope) { /* Evaluate and return the expression. */ ReturnStmtNode *stmt = (ReturnStmtNode *)node->stmt; @@ -3330,33 +3335,21 @@ ReturnObject *interpretReturnStmtNode(StmtNode *node, /**< [in] A pointer to return createReturnObject(RT_RETURN, value); } -/** Interprets a loop statement. - * - * \pre \a node was created by createStmtNode(StmtType type, void *stmt) where - * \a type is ST_LOOP and \a stmt was created by createLoopStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, ExprNode *, BlockNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the return value after - * interpreting \a node in the scope \a scope. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretCastStmtNode(StmtNode *, ScopeObject *) - * \see interpretPrintStmtNode(StmtNode *, ScopeObject *) - * \see interpretInputStmtNode(StmtNode *, ScopeObject *) - * \see interpretAssignmentStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeclarationStmtNode(StmtNode *, ScopeObject *) - * \see interpretIfThenElseStmtNode(StmtNode *, ScopeObject *) - * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) - * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) - * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) - * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) - * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ -ReturnObject *interpretLoopStmtNode(StmtNode *node, /**< [in] A pointer to the StmtNode structure containing the LoopStmtNode structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a node under. */ +/** + * Interprets a loop statement. + * + * \param [in] node The statement to interpret. + * + * \param [in] scope The scope to evaluate \a node under. + * + * \pre \a node contains a statement created by createLoopStmtNode(). + * + * \return A pointer to a return value of \a node interpreted under \a scope. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretLoopStmtNode(StmtNode *node, + ScopeObject *scope) { LoopStmtNode *stmt = (LoopStmtNode *)node->stmt; ScopeObject *outer = createScopeObject(scope); @@ -3364,7 +3357,7 @@ ReturnObject *interpretLoopStmtNode(StmtNode *node, /**< [in] A pointer to t if (!outer) return NULL; /* Create a temporary loop variable if required */ if (stmt->var) { - var = createScopeValue(outer, stmt->var); + var = createScopeValue(scope, outer, stmt->var); if (!var) { deleteScopeObject(outer); return NULL; @@ -3411,11 +3404,14 @@ ReturnObject *interpretLoopStmtNode(StmtNode *node, /**< [in] A pointer to t deleteReturnObject(result); } if (stmt->update) { - /* A little efficiency hack: if we know the operation - * to perform, don't bother evaluating the ExprNode + /* + * A little efficiency hack: if we know the operation to + * perform, don't bother evaluating the ExprNode * structure, just go ahead and do it to the loop - * variable. */ + * variable. + */ if (stmt->update->type == ET_OP) { + var = getScopeValue(scope, outer, stmt->var); OpExprNode *op = (OpExprNode *)stmt->update->expr; if (op->type == OP_ADD) var->data.i++; @@ -3428,7 +3424,7 @@ ReturnObject *interpretLoopStmtNode(StmtNode *node, /**< [in] A pointer to t deleteScopeObject(outer); return NULL; } - if (!updateScopeValue(outer, stmt->var, update)) { + if (!updateScopeValue(scope, outer, stmt->var, update)) { deleteScopeObject(outer); deleteValueObject(update); return NULL; @@ -3440,75 +3436,53 @@ ReturnObject *interpretLoopStmtNode(StmtNode *node, /**< [in] A pointer to t return createReturnObject(RT_DEFAULT, NULL); } -/** Interprets a deallocation statement. - * - * \pre \a node was created by createStmtNode(StmtType type, void *stmt) where - * \a type is ST_DEALLOCATION and \a stmt was created by createDeallocationStmtNode(IdentifierNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the default return value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretCastStmtNode(StmtNode *, ScopeObject *) - * \see interpretPrintStmtNode(StmtNode *, ScopeObject *) - * \see interpretInputStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeclarationStmtNode(StmtNode *, ScopeObject *) - * \see interpretIfThenElseStmtNode(StmtNode *, ScopeObject *) - * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) - * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) - * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) - * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) - * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ -ReturnObject *interpretDeallocationStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing the DeallocationStmtNode structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a node under. */ +/** + * Interprets a deallocation statement. + * + * \param [in] node The statement to interpret. + * + * \param [in] scope The scope to evaluate \a node under. + * + * \pre \a node contains a statement created by createDeallocationStmtNode(). + * + * \return A pointer to a default return value. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretDeallocationStmtNode(StmtNode *node, + ScopeObject *scope) { DeallocationStmtNode *stmt = (DeallocationStmtNode *)node->stmt; - if (!updateScopeValue(scope, stmt->target, NULL)) return NULL; + if (!updateScopeValue(scope, scope, stmt->target, NULL)) return NULL; /* If we want to completely remove the variable, use: deleteScopeValue(scope, stmt->target); */ return createReturnObject(RT_DEFAULT, NULL); } -/** Interprets a function definition statement. - * - * \pre \a node was created by createStmtNode(StmtType type, void *stmt) where - * \a type is ST_SWITCH and \a stmt was created by createSwitchStmtNode(ExprNodeList *, BlockNodeList *, BlockNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \note \a node and \a scope are not used by this function but are still - * included in its prototype to allow this function to be stored in a - * jump table for fast execution. - * - * \return A pointer to a ReturnObject structure with the default return value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretCastStmtNode(StmtNode *, ScopeObject *) - * \see interpretPrintStmtNode(StmtNode *, ScopeObject *) - * \see interpretInputStmtNode(StmtNode *, ScopeObject *) - * \see interpretAssignmentStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeclarationStmtNode(StmtNode *, ScopeObject *) - * \see interpretIfThenElseStmtNode(StmtNode *, ScopeObject *) - * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) - * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) - * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) - * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) - * \see interpretExprStmtNode(StmtNode *, ScopeObject *) */ -ReturnObject *interpretFuncDefStmtNode(StmtNode *node, /**< Not used (see note). */ - ScopeObject *scope) /**< Not used (see note). */ +/** + * Interprets a function definition statement. + * + * \param [in] node The statement to interpret. + * + * \param [in] scope The scope to evaluate \a node under. + * + * \pre \a node contains a statement created by createFuncDefStmtNode(). + * + * \return A pointer to a default return value. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretFuncDefStmtNode(StmtNode *node, + ScopeObject *scope) { /* Add the function to the current scope */ FuncDefStmtNode *stmt = (FuncDefStmtNode *)node->stmt; ValueObject *init = NULL; - if (getLocalScopeValue(scope, stmt->name)) { + ScopeObject *dest = NULL; + dest = getScopeObject(scope, scope, stmt->scope); + /** \todo Figure out if this makes sense: we want to check if the local scope contains the function name, but if the name of the function contains a SRS expression, we want to evaluate that using the local scope */ + if (getScopeValueLocal(scope, dest, stmt->name)) { IdentifierNode *id = (IdentifierNode *)(stmt->name); char *name = resolveIdentifierName(id, scope); if (name) { @@ -3519,43 +3493,35 @@ ReturnObject *interpretFuncDefStmtNode(StmtNode *node, /**< Not used (see no } init = createFunctionValueObject(stmt); if (!init) return NULL; - if (!createScopeValue(scope, stmt->name)) { + if (!createScopeValue(scope, dest, stmt->name)) { deleteValueObject(init); return NULL; } - if (!updateScopeValue(scope, stmt->name, init)) { + if (!updateScopeValue(scope, dest, stmt->name, init)) { deleteValueObject(init); return NULL; } return createReturnObject(RT_DEFAULT, NULL); } -/** Interprets an expression statement. - * - * \pre \a node was created by createStmtNode(StmtType type, void *stmt) where - * \a type is ST_EXPR and \a stmt was created by createExprNode(ExprType, void *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the default return value. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretCastStmtNode(StmtNode *, ScopeObject *) - * \see interpretPrintStmtNode(StmtNode *, ScopeObject *) - * \see interpretInputStmtNode(StmtNode *, ScopeObject *) - * \see interpretAssignmentStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeclarationStmtNode(StmtNode *, ScopeObject *) - * \see interpretIfThenElseStmtNode(StmtNode *, ScopeObject *) - * \see interpretSwitchStmtNode(StmtNode *, ScopeObject *) - * \see interpretBreakStmtNode(StmtNode *, ScopeObject *) - * \see interpretReturnStmtNode(StmtNode *, ScopeObject *) - * \see interpretLoopStmtNode(StmtNode *, ScopeObject *) - * \see interpretDeallocationStmtNode(StmtNode *, ScopeObject *) - * \see interpretFuncDefStmtNode(StmtNode *, ScopeObject *) */ -ReturnObject *interpretExprStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure containing the ExprNode structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a node under. */ +/** + * Interprets an expression statement. + * + * \param [in] node The statement to interpret. + * + * \param [in] scope The scope to evaluate \a node under. + * + * \pre \a node contains a statement created by createExprNode(). + * + * \post The implicit variable of \a scope will be set the the value of \a node + * evaluated under \a scope. + * + * \return A pointer to a default return value. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretExprStmtNode(StmtNode *node, + ScopeObject *scope) { /* Set the implicit variable to the result of the expression */ ExprNode *expr = (ExprNode *)node->stmt; @@ -3565,8 +3531,10 @@ ReturnObject *interpretExprStmtNode(StmtNode *node, /**< [in] A pointer to a return createReturnObject(RT_DEFAULT, NULL); } -/* A jump table for statements. The index of a function in the table is given - * by its its index in the enumerated StmtType type. */ +/* + * A jump table for statements. The index of a function in the table is given + * by its its index in the enumerated StmtType type. + */ static ReturnObject *(*StmtJumpTable[13])(StmtNode *, ScopeObject *) = { interpretCastStmtNode, interpretPrintStmtNode, @@ -3582,47 +3550,40 @@ static ReturnObject *(*StmtJumpTable[13])(StmtNode *, ScopeObject *) = { interpretFuncDefStmtNode, interpretExprStmtNode }; -/** Interprets the contents of a StmtNode structure. - * - * \pre \a node was created by parseStmtNode(Token ***). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the return state of the - * interpreted \a node. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretExprNode(ExprNode *, ScopeObject *) - * \see interpretStmtNodeList(StmtNodeList *, ScopeObject *) - * \see interpretBlockNode(BlockNode *, ScopeObject *) - * \see interpretMainNode(MainNode *) */ -ReturnObject *interpretStmtNode(StmtNode *node, /**< [in] A pointer to a StmtNode structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to a ScopeObject structure to evaluate \a node under. */ +/** + * Interprets a statement. + * + * \param [in] node The statement to interpret. + * + * \param [in] scope The scope to evaluate \a node under. + * + * \pre \a node contains a statement created by parseStmtNode(). + * + * \return A pointer to a return value set appropriately depending on the + * statement interpreted. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretStmtNode(StmtNode *node, + ScopeObject *scope) { return StmtJumpTable[node->type](node, scope); } -/** Interprets the contents of a StmtNodeList structure. - * - * \pre \a list was created by createStmtNodeList(void) and contains contents - * added by addStmtNode(StmtNodeList *, StmtNode *). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the return state of the - * interpreted \a list. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretExprNode(ExprNode *, ScopeObject *) - * \see interpretStmtNode(StmtNode *, ScopeObject *) - * \see interpretBlockNode(BlockNode *, ScopeObject *) - * \see interpretMainNode(MainNode *) */ -ReturnObject *interpretStmtNodeList(StmtNodeList *list, /**< [in] A pointer to the StmtNodeList structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to the ScopeObject structure to evaluate \a list under. */ +/** + * Interprets a list of statements. + * + * \param [in] list The statements to interpret. + * + * \param [in] scope The scope to evaluate \a list under. + * + * \return A pointer to a return value set appropriately depending on the + * statements interpreted. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretStmtNodeList(StmtNodeList *list, + ScopeObject *scope) { ReturnObject *ret = NULL; unsigned int n; @@ -3641,24 +3602,22 @@ ReturnObject *interpretStmtNodeList(StmtNodeList *list, /**< [in] A pointer to t return ret; } -/** Interprets the contents of a BlockNode structure. - * - * \pre \a node was created by parseBlockNode(Token ***). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return A pointer to a ReturnObject structure with the return state of the - * interpreted \a node. - * - * \retval NULL An error occurred during interpretation. - * - * \see interpretExprNode(ExprNode *, ScopeObject *) - * \see interpretStmtNode(StmtNode *, ScopeObject *) - * \see interpretStmtNodeList(StmtNodeList *, ScopeObject *) - * \see interpretMainNode(MainNode *) */ -ReturnObject *interpretBlockNode(BlockNode *node, /**< [in] A pointer to a BlockNode structure to interpret. */ - ScopeObject *scope) /**< [in,out] A pointer to a ScopeObject structure to evaluate \a node under. */ +/** + * Interprets a block of code. + * + * \param [in] node The block of code to interpret. + * + * \param [in] scope The scope to evaluate \a block under. + * + * \pre \a block contains a block of code created by parseBlockNode(). + * + * \return A pointer to a return value set appropriately depending on the + * statements interpreted. + * + * \retval NULL An error occurred during interpretation. + */ +ReturnObject *interpretBlockNode(BlockNode *node, + ScopeObject *scope) { ReturnObject *ret = NULL; ScopeObject *inner = createScopeObject(scope); @@ -3668,23 +3627,20 @@ ReturnObject *interpretBlockNode(BlockNode *node, /**< [in] A pointer to a Bl return ret; } -/** Interprets the contents of a MainNode structure. - * - * \pre \a node was created by parseMainNode(Token **). - * \pre \a scope was created by createScopeObject(ScopeObject *) and contains - * contents added by createScopeValue(ScopeObject *, IdentifierNode *) and - * contents updated by updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *). - * - * \return The return status of the interpreted MainNode structure. - * - * \retval 0 \a main was interpreted without any errors. - * \retval 1 An error occurred while interpreting \a main. - * - * \see interpretExprNode(ExprNode *, ScopeObject *) - * \see interpretStmtNode(StmtNode *, ScopeObject *) - * \see interpretStmtNodeList(StmtNodeList *, ScopeObject *) - * \see interpretBlockNode(BlockNode *, ScopeObject *) */ -int interpretMainNode(MainNode *main) /**< [in] A pointer to the MainNode structure to interpret. */ +/** + * Interprets a the main block of code. + * + * \param [in] main The main block of code to interpret. + * + * \pre \a main contains a block of code created by parseMainNode(). + * + * \return The final status of the program. + * + * \retval 0 \a main was interpreted without any errors. + * + * \retval 1 An error occurred while interpreting \a main. + */ +int interpretMainNode(MainNode *main) { ReturnObject *ret = NULL; if (!main) return 1; diff --git a/interpreter.h b/interpreter.h index 41d0d88..b895f73 100644 --- a/interpreter.h +++ b/interpreter.h @@ -1,13 +1,15 @@ -/** Structures and functions for interpreting a parse tree. The interpreter - * traverses a parse tree in a depth-first manner, interpreting each node it - * reaches along the way. This is the last stage of the processing of a source - * code file. - * - * \file interpreter.h - * - * \author Justin J. Meza - * - * \date 2010 */ +/** + * Structures and functions for interpreting a parse tree. The interpreter + * traverses a parse tree in a depth-first manner, interpreting each node it + * reaches along the way. This is the last stage of the processing of a source + * code file. + * + * \file interpreter.h + * + * \author Justin J. Meza + * + * \date 2010-2011 + */ #ifndef __INTERPRETER_H__ #define __INTERPRETER_H__ @@ -19,127 +21,221 @@ #include "parser.h" #include "unicode.h" -/** Gets the integer data associated with a ValueObject structure. */ +/** + * Retrieves a value's integer data. + */ #define getInteger(value) (value->data.i) -/** Gets the floating point data associated with a ValueObject structure. */ + +/** + * Retrieves a value's decimal data. + */ #define getFloat(value) (value->data.f) -/** Gets the string data associated with a ValueObject structure. */ + +/** + * Retrieves a value's string data. + */ #define getString(value) (value->data.s) -/** Gets the function definition associated with a ValueObject structure. */ + +/** + * Retrieves a value's function data. + */ #define getFunction(value) (value->data.fn) -/** Denotes the type of a value. */ +/** + * Retrieves a value's array data. + */ +#define getArray(value) (value->data.a) + +/** + * Represents a value type. + */ typedef enum { VT_INTEGER, /**< An integer value. */ - VT_FLOAT, /**< A floating point decimal value. */ - VT_BOOLEAN, /**< A true/false value. */ - VT_STRING, /**< A character string value. */ + VT_FLOAT, /**< A decimal value. */ + VT_BOOLEAN, /**< A boolean value. */ + VT_STRING, /**< A string value. */ VT_NIL, /**< Represents no value. */ - VT_FUNC /**< A function. */ + VT_FUNC, /**< A function. */ + VT_ARRAY /**< An array. */ } ValueType; -/** Stores the data associated with a ValueObject structure. */ +/** + * Stores value data. + */ typedef union { - int i; /**< Integer data. */ - float f; /**< Floating point data. */ - char *s; /**< Character string data. */ - FuncDefStmtNode *fn; /**< Function definition. */ + int i; /**< Integer data. */ + float f; /**< Decimal data. */ + char *s; /**< String data. */ + FuncDefStmtNode *fn; /**< Function data. */ + struct scopeobject *a; /**< Array data. */ } ValueData; -/** Increments the semaphore of a ValueObject structure. */ +/** + * Increments a value's semaphore. + */ #define V(value) (value->semaphore++) -/** Decrements the semaphore of a ValueObject structure. */ +/** + * Decrements a value's semaphore. + */ #define P(value) (value->semaphore--) -/** Stores a value. - * - * \see copyValueObject(ValueObject *) - * \see deleteValueObject(ValueObject *) */ +/** + * Stores a value. + */ typedef struct { ValueType type; /**< The type of value stored. */ - ValueData data; /**< The stored data. */ + ValueData data; /**< The value data. */ unsigned short semaphore; /**< A semaphore for value usage. */ } ValueObject; -/** Denotes the type of return encountered. */ +/** + * Represents the return type. + */ typedef enum { - RT_DEFAULT, /**< A block of code returned after evaluating all of its statements. */ - RT_BREAK, /**< A block of code within a LoopStmtNode or SwitchStmtNode returned via a break statement. */ - RT_RETURN /**< A block of code within a FuncDefStmtNode called by a FuncCallExprNode returned (either with or without a value). */ + RT_DEFAULT, /**< Code block completed successfully. */ + RT_BREAK, /**< Broke out of a loop or switch statement. */ + RT_RETURN /**< Returned from a function. */ } ReturnType; -/** Stores a return state. Returns are encountered when - * - a block of code evaluates all of its statements, - * - a block of code within a LoopStmt or SwitchStmt encountered a break statement, or - * - a block of code within a FunctionDefStmt called by a FunctionCallExpr encounters a ReturnStmt. */ +/** + * Stores return state. + */ typedef struct { ReturnType type; /**< The type of return encountered. */ ValueObject *value; /**< The optional return value. */ } ReturnObject; -/** Stores the variables in a particular scope. Scopes are arranged - * heirarchically from global (the ancestor of all other scopes) to local (the - * temporary scope of a BlockNode). - * - * \see createScopeObject(ScopeObject *) - * \see deleteScopeObject(ScopeObject *) */ +/** + * Stores a set of variables hierarchically. + */ typedef struct scopeobject { - struct scopeobject *parent; /**< A pointer to the parent ScopeObject. */ - ValueObject *impvar; /**< A pointer to the ValueObject representing the implicit variable for this scope. */ - unsigned int numvals; /**< The number of ValueObject structures in \a values. */ - char **names; /**< A pointer to the array of character strings naming the values in the scope. */ - ValueObject **values; /**< A pointer to an array of ValueObject structures in the scope. */ + struct scopeobject *parent; /**< The parent scope. */ + ValueObject *impvar; /**< The \ref impvar "implicit variable". */ + unsigned int numvals; /**< The number of values in the scope. */ + char **names; /**< The names of the values. */ + ValueObject **values; /**< The values in the scope. */ } ScopeObject; -char *createString(char *); +/** + * \name Utilities + * + * Functions for performing helper tasks. + */ +/**@{*/ +void printInterpreterError(const char *, IdentifierNode *, ScopeObject *); +char *copyString(char *); +unsigned int isDecString(const char *); +unsigned int isHexString(const char *); +char *resolveIdentifierName(IdentifierNode *, ScopeObject *); +/**@}*/ + +/** + * \name Value object modifiers + * + * Functions for creating, copying, and deleting value objects. + */ +/**@{*/ ValueObject *createNilValueObject(void); ValueObject *createBooleanValueObject(int); ValueObject *createIntegerValueObject(int); ValueObject *createFloatValueObject(float); ValueObject *createStringValueObject(char *); ValueObject *createFunctionValueObject(FuncDefStmtNode *); +ValueObject *createArrayValueObject(ScopeObject *); ValueObject *copyValueObject(ValueObject *); void deleteValueObject(ValueObject *); -ReturnObject *createReturnObject(ReturnType, ValueObject *); -void deleteReturnObject(ReturnObject *); -char *resolveIdentifierName(IdentifierNode *, ScopeObject *); +/**@}*/ + +/** + * \name Scope object modifiers + * + * Functions for manipulating scope objects and their data. + */ +/**@{*/ ScopeObject *createScopeObject(ScopeObject *); void deleteScopeObject(ScopeObject *); -ValueObject *getScopeValue(ScopeObject *, IdentifierNode *); -ValueObject *getLocalScopeValue(ScopeObject *, IdentifierNode *); -ValueObject *createScopeValue(ScopeObject *, IdentifierNode *); -ValueObject *updateScopeValue(ScopeObject *, IdentifierNode *, ValueObject *); -void deleteScopeValue(ScopeObject *, IdentifierNode *); -unsigned int isNumString(const char *); -unsigned int isHexString(const char *); -ValueObject *castBooleanExplicit(ValueObject *, ScopeObject *); -ValueObject *castIntegerExplicit(ValueObject *, ScopeObject *); -ValueObject *castFloatExplicit(ValueObject *, ScopeObject *); -ValueObject *castStringExplicit(ValueObject *, ScopeObject *); +ValueObject *createScopeValue(ScopeObject *, ScopeObject *, IdentifierNode *); +ValueObject *updateScopeValue(ScopeObject *, ScopeObject *, IdentifierNode *, ValueObject *); +ValueObject *getScopeValue(ScopeObject *, ScopeObject *, IdentifierNode *); +ValueObject *getScopeValueArray(ScopeObject *, ScopeObject *, IdentifierNode *); +ValueObject *getScopeValueLocal(ScopeObject *, ScopeObject *, IdentifierNode *); +ScopeObject *getScopeObject(ScopeObject *, ScopeObject *, IdentifierNode *); +void deleteScopeValue(ScopeObject *, ScopeObject *, IdentifierNode *); +/**@}*/ + +/** + * \name Return object modifiers + * + * Functions for creating and deleting return objects. + */ +/**@{*/ +ReturnObject *createReturnObject(ReturnType, ValueObject *); +void deleteReturnObject(ReturnObject *); +/**@}*/ + +/** + * \name Casts + * + * Functions for performing casts between different types of values. + */ +/**@{*/ ValueObject *castBooleanImplicit(ValueObject *, ScopeObject *); ValueObject *castIntegerImplicit(ValueObject *, ScopeObject *); ValueObject *castFloatImplicit(ValueObject *, ScopeObject *); ValueObject *castStringImplicit(ValueObject *, ScopeObject *); +ValueObject *castBooleanExplicit(ValueObject *, ScopeObject *); +ValueObject *castIntegerExplicit(ValueObject *, ScopeObject *); +ValueObject *castFloatExplicit(ValueObject *, ScopeObject *); +ValueObject *castStringExplicit(ValueObject *, ScopeObject *); +/**@}*/ + +/** + * \name Node interpreters + * + * Functions for interpreting basic parse tree nodes. + */ +/**@{*/ ValueObject *interpretExprNode(ExprNode *, ScopeObject *); ReturnObject *interpretStmtNode(StmtNode *, ScopeObject *); ReturnObject *interpretStmtNodeList(StmtNodeList *, ScopeObject *); ReturnObject *interpretBlockNode(BlockNode *, ScopeObject *); int interpretMainNode(MainNode *); +/**@}*/ +/** + * \name Expression interpreters + * + * Functions for interpreting expression parse tree nodes. + */ +/**@{*/ ValueObject *interpretImpVarExprNode(ExprNode *, ScopeObject *); ValueObject *interpretCastExprNode(ExprNode *, ScopeObject *); ValueObject *interpretFuncCallExprNode(ExprNode *, ScopeObject *); ValueObject *interpretIdentifierExprNode(ExprNode *, ScopeObject *); ValueObject *interpretConstantExprNode(ExprNode *, ScopeObject *); +/**@}*/ +/** + * \name Operation interpreters + * + * Functions for interpreting operation parse tree nodes. + */ +/**@{*/ ValueObject *interpretNotOpExprNode(OpExprNode *, ScopeObject *); ValueObject *interpretArithOpExprNode(OpExprNode *, ScopeObject *); ValueObject *interpretBoolOpExprNode(OpExprNode *, ScopeObject *); ValueObject *interpretEqualityOpExprNode(OpExprNode *, ScopeObject *); ValueObject *interpretConcatOpExprNode(OpExprNode *, ScopeObject *); ValueObject *interpretOpExprNode(ExprNode *, ScopeObject *); +/**@}*/ +/** + * \name Statement interpreters + * + * Functions for interpreting statement parse tree nodes. + */ +/**@{*/ ReturnObject *interpretCastStmtNode(StmtNode *, ScopeObject *); ReturnObject *interpretPrintStmtNode(StmtNode *, ScopeObject *); ReturnObject *interpretInputStmtNode(StmtNode *, ScopeObject *); @@ -153,7 +249,14 @@ ReturnObject *interpretLoopStmtNode(StmtNode *, ScopeObject *); ReturnObject *interpretDeallocationStmtNode(StmtNode *, ScopeObject *); ReturnObject *interpretFuncDefStmtNode(StmtNode *, ScopeObject *); ReturnObject *interpretExprStmtNode(StmtNode *, ScopeObject *); +/**@}*/ +/** + * \name Arithmetic operations (integer-integer) + * + * Functions for performing integer-integer operations on values. + */ +/**@{*/ ValueObject *opAddIntegerInteger(ValueObject *, ValueObject *); ValueObject *opSubIntegerInteger(ValueObject *, ValueObject *); ValueObject *opMultIntegerInteger(ValueObject *, ValueObject *); @@ -161,7 +264,14 @@ ValueObject *opDivIntegerInteger(ValueObject *, ValueObject *); ValueObject *opMaxIntegerInteger(ValueObject *, ValueObject *); ValueObject *opMinIntegerInteger(ValueObject *, ValueObject *); ValueObject *opModIntegerInteger(ValueObject *, ValueObject *); +/**@}*/ +/** + * \name Arithmetic operations (integer-float) + * + * Functions for performing integer-float operations on values. + */ +/**@{*/ ValueObject *opAddIntegerFloat(ValueObject *, ValueObject *); ValueObject *opSubIntegerFloat(ValueObject *, ValueObject *); ValueObject *opMultIntegerFloat(ValueObject *, ValueObject *); @@ -169,7 +279,14 @@ ValueObject *opDivIntegerFloat(ValueObject *, ValueObject *); ValueObject *opMaxIntegerFloat(ValueObject *, ValueObject *); ValueObject *opMinIntegerFloat(ValueObject *, ValueObject *); ValueObject *opModIntegerFloat(ValueObject *, ValueObject *); +/**@}*/ +/** + * \name Arithmetic operations (float-integer) + * + * Functions for performing float-integer operations on values. + */ +/**@{*/ ValueObject *opAddFloatInteger(ValueObject *, ValueObject *); ValueObject *opSubFloatInteger(ValueObject *, ValueObject *); ValueObject *opMultFloatInteger(ValueObject *, ValueObject *); @@ -177,7 +294,14 @@ ValueObject *opDivFloatInteger(ValueObject *, ValueObject *); ValueObject *opMaxFloatInteger(ValueObject *, ValueObject *); ValueObject *opMinFloatInteger(ValueObject *, ValueObject *); ValueObject *opModFloatInteger(ValueObject *, ValueObject *); +/**@}*/ +/** + * \name Arithmetic operations (float-float) + * + * Functions for performing float-float operations on values. + */ +/**@{*/ ValueObject *opAddFloatFloat(ValueObject *, ValueObject *); ValueObject *opSubFloatFloat(ValueObject *, ValueObject *); ValueObject *opMultFloatFloat(ValueObject *, ValueObject *); @@ -185,26 +309,76 @@ ValueObject *opDivFloatFloat(ValueObject *, ValueObject *); ValueObject *opMaxFloatFloat(ValueObject *, ValueObject *); ValueObject *opMinFloatFloat(ValueObject *, ValueObject *); ValueObject *opModFloatFloat(ValueObject *, ValueObject *); +/**@}*/ +/** + * \name Equality operations (boolean-boolean) + * + * Functions for performing boolean-boolean operations on values. + */ +/**@{*/ ValueObject *opEqBooleanBoolean(ValueObject *, ValueObject *); ValueObject *opNeqBooleanBoolean(ValueObject *, ValueObject *); +/**@}*/ +/** + * \name Equality operations (integer-integer) + * + * Functions for performing integer-integer operations on values. + */ +/**@{*/ ValueObject *opEqIntegerInteger(ValueObject *, ValueObject *); ValueObject *opNeqIntegerInteger(ValueObject *, ValueObject *); +/**@}*/ +/** + * \name Equality operations (integer-float) + * + * Functions for performing integer-float operations on values. + */ +/**@{*/ ValueObject *opEqIntegerFloat(ValueObject *, ValueObject *); ValueObject *opNeqIntegerFloat(ValueObject *, ValueObject *); +/**@}*/ +/** + * \name Equality operations (float-integer) + * + * Functions for performing float-integer operations on values. + */ +/**@{*/ ValueObject *opEqFloatInteger(ValueObject *, ValueObject *); ValueObject *opNeqFloatInteger(ValueObject *, ValueObject *); +/**@}*/ +/** + * \name Equality operations (float-float) + * + * Functions for performing float-float operations on values. + */ +/**@{*/ ValueObject *opEqFloatFloat(ValueObject *, ValueObject *); ValueObject *opNeqFloatFloat(ValueObject *, ValueObject *); +/**@}*/ +/** + * \name Equality operations (string-string) + * + * Functions for performing string-string operations on values. + */ +/**@{*/ ValueObject *opEqStringString(ValueObject *, ValueObject *); ValueObject *opNeqStringString(ValueObject *, ValueObject *); +/**@}*/ +/** + * \name Equality operations (nil-nil) + * + * Functions for performing nil-nil operations on values. + */ +/**@{*/ ValueObject *opEqNilNil(ValueObject *, ValueObject *); ValueObject *opNeqNilNil(ValueObject *, ValueObject *); +/**@}*/ #endif /* __INTERPRETER_H__ */ diff --git a/lci.png b/lci.png new file mode 100644 index 0000000..e831184 Binary files /dev/null and b/lci.png differ diff --git a/lexer.c b/lexer.c index e582248..4ea93cf 100644 --- a/lexer.c +++ b/lexer.c @@ -1,15 +1,19 @@ #include "lexer.h" -/** Creates a Lexeme structure. - * - * \return A pointer to a Lexeme structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteLexeme(Lexeme *) */ -Lexeme *createLexeme(char *image, /**< [in] An array of characters that describe the lexeme. */ - const char *fname, /**< [in] A pointer to the name of the file containing the lexeme. */ - unsigned int line) /**< [in] The line number from the source file that the lexeme occurred on. */ +/** + * Creates a lexeme. + * + * \param [in] image The string that identifies the lexeme. + * + * \param [in] fname The name of the file containing the lexeme. + * + * \param [in] line The line number the lexeme occurred on. + * + * \return A new lexeme with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +Lexeme *createLexeme(char *image, const char *fname, unsigned int line) { Lexeme *ret = malloc(sizeof(Lexeme)); if (!ret) { @@ -23,8 +27,11 @@ Lexeme *createLexeme(char *image, /**< [in] An array of characters that de return NULL; } strcpy(ret->image, image); - /** \note fname is not copied because it would only one copy is stored - * for all Lexeme structures that share it. */ + /** + * \note \a fname is not copied because it only one copy is stored for + * all lexemes from the same file. This is simply to avoid large + * numbers of lexemes storing duplicate file name strings. + */ ret->fname = fname; ret->line = line; #ifdef DEBUG @@ -33,29 +40,29 @@ Lexeme *createLexeme(char *image, /**< [in] An array of characters that de return ret; } -/** Deletes a Lexeme structure. - * - * \pre \a lexeme points to a Lexeme structure created by createLexeme(char *, const char *, unsigned int). - * - * \post The memory at \a lexeme and all of its elements will be freed. - * - * \see createLexeme(char *, const char *, unsigned int) */ +/** + * Deletes a lexeme. + * + * \param [in,out] lexeme The lexeme to delete. + */ void deleteLexeme(Lexeme *lexeme) { if (!lexeme) return; free(lexeme->image); - /** \note We do not free (*lex)->fname because it is shared between many - * Lexeme structures and is free'd by whoever created them. */ + /** + * \note We do not free the file name because it is shared between many + * lexemes and is freed by whomever created the file name string. + */ free(lexeme); } -/** Creates a LexemeList structure. - * - * \return A pointer to a LexemeList structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteLexemeList(LexemeList *) */ +/** + * Creates a list of lexemes. + * + * \return An empty lexeme list. + * + * \retval NULL Memory allocation failed. + */ LexemeList *createLexemeList(void) { LexemeList *p = malloc(sizeof(LexemeList)); @@ -68,20 +75,21 @@ LexemeList *createLexemeList(void) return p; } -/** Adds a Lexeme structure to a LexemeList structure. - * - * \pre \a list was created by createLexemeList(void). - * \pre \a lexeme was created by createLexeme(char *, const char *, unsigned int). - * - * \post \a lexeme will be added on to the end of \a list and the size of - * \a list will be updated accordingly. - * - * \return A pointer to the added Lexeme structure (will be the same as - * \a lexeme). - * - * \retval NULL realloc was unable to allocate memory. */ -Lexeme *addLexeme(LexemeList *list, /**< [in,out] A pointer to the LexemeList structure to add \a lex to. */ - Lexeme *lexeme) /**< [in] A pointer to the Lexeme structure to add to \a list. */ +/** + * Adds a lexeme to a list of lexemes. + * + * \param [in,out] list The list of lexemes to add \a lexeme to. + * + * \param [in] lexeme The lexeme to add to \a list. + * + * \post \a lexeme will be added to the end of \a list and the size of \a list + * will be updated. + * + * \return A pointer to the added lexeme (will be the same as \a lexeme). + * + * \retval NULL Memory allocation failed. + */ +Lexeme *addLexeme(LexemeList *list, Lexeme *lexeme) { unsigned int newsize; void *mem = NULL; @@ -98,16 +106,14 @@ Lexeme *addLexeme(LexemeList *list, /**< [in,out] A pointer to the LexemeList st return lexeme; } -/** Deletes a LexemeList structure. - * - * \pre \a list was created by createLexemeList(void) and contains - * items added by addLexeme(LexemeList *, Lexeme *). - * - * \post The memory at \a list and any of its associated members will be - * freed. - * - * \see createLexemeList(void) */ -void deleteLexemeList(LexemeList *list) /**< [in,out] A pointer to the LexemeList structure to delete. */ +/** + * Deletes a list of lexemes. + * + * \param [in,out] list The lexeme list to delete. + * + * \post The memory at \a list and all of its members will be freed. + */ +void deleteLexemeList(LexemeList *list) { unsigned int n; if (!list) return; @@ -117,37 +123,39 @@ void deleteLexemeList(LexemeList *list) /**< [in,out] A pointer to the LexemeLis free(list); } -/** Scans through a character buffer, removing unecessary characters and - * generating lexemes. Lexemes are separated by whitespace (but newline - * characters are kept as their own lexeme). String literals are handled a - * bit differently: starting at the first quotation character, characters are - * collected until either an unescaped quotation character is read (that is, a - * quotation character not preceeded by a colon which itself is not proceeded - * by a colon) or a newline or carriage return character is read, whichever - * comes first. This handles the odd case of strings such as "::" which print - * out a single colon. Also handled are the effects of commas, ellipses, and - * bangs (!). - * - * \pre \a size is the number of characters starting at the memory location - * pointed to by \a buffer. - * - * \return A pointer to a LexemeList structure. */ -LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to tokenize. */ - unsigned int size, /**< [in] The number of characters in \a buffer. */ - const char *fname) /**< [in] An array of characters representing the name of the file used to read \a buffer. */ +/** + * Scans a buffer, removing unnecessary characters and grouping characters into + * lexemes. Lexemes are strings of characters separated by whitespace (although + * newline characters are considered separate lexemes). String literals are + * handled a bit differently: Starting at the first quotation character, + * characters are collected until either a non-escaped quotation character is + * read (i.e., a quotation character not preceded by a colon which itself is not + * preceded by a colon) or a newline or carriage return character is read, + * whichever comes first. This handles the odd (but possible) case of strings + * such as "::" which print out a single colon. Also handled are the effects of + * commas, ellipses, bangs (!), and array accesses ('Z). + * + * \param [in] buffer The characters to turn into lexemes. + * + * \param [in] size The number of characters in \a buffer. + * + * \param [in] fname The name of the file \a buffer was read from. + * + * \return A list of lexemes created from the contents of \a buffer. + */ +LexemeList *scanBuffer(const char *buffer, unsigned int size, const char *fname) { const char *start = buffer; LexemeList *list = NULL; unsigned int line = 1; - Lexeme *lex = NULL; list = createLexemeList(); if (!list) return NULL; while (start < buffer + size) { char *temp = NULL; - size_t len = 1; + unsigned int len = 1; /* Comma (,) is a soft newline */ if (*start == ',') { - lex = createLexeme("\n", fname, line); + Lexeme *lex = createLexeme("\n", fname, line); if (!lex) { deleteLexemeList(list); return NULL; @@ -162,7 +170,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t } /* Bang (!) is its own lexeme */ if (*start == '!') { - lex = createLexeme("!", fname, line); + Lexeme *lex = createLexeme("!", fname, line); if (!lex) { deleteLexemeList(list); return NULL; @@ -175,6 +183,21 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t start++; continue; } + /* Apostrophe Z ('Z) is its own lexeme */ + if (!strncmp(start, "'Z", 2)) { + Lexeme *lex = createLexeme("'Z", fname, line); + if (!lex) { + deleteLexemeList(list); + return NULL; + } + if (!addLexeme(list, lex)) { + deleteLexeme(lex); + deleteLexemeList(list); + return NULL; + } + start += 2; + continue; + } /* Skip over leading whitespace */ while (isspace(*start)) { unsigned int newline = 0; @@ -187,7 +210,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t newline = 1; } if (newline) { - lex = createLexeme("\n", fname, line); + Lexeme *lex = createLexeme("\n", fname, line); if (!lex) { deleteLexemeList(list); return NULL; @@ -213,7 +236,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t /* Make sure next line is not empty */ while (*test && isspace(*test)) { if (*test == '\r' || *test == '\n') { - fprintf(stderr, "%s:%u: a line with continuation may not be followed by an empty line\n", fname, line); + fprintf(stderr, "%s:%d: a line with continuation may not be followed by an empty line\n", fname, line); deleteLexemeList(list); return NULL; } @@ -240,7 +263,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t start++; if (start == buffer || *start == ',' || *start == '\r' || *start == '\n') continue; - fprintf(stderr, "%s:%u: multiple line comment may not appear on the same line as code\n", fname, line); + fprintf(stderr, "%s:%d: multiple line comment may not appear on the same line as code\n", fname, line); deleteLexemeList(list); return NULL; } @@ -269,9 +292,10 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t if (start[len] && !isspace(start[len]) && *(start + len) != ',' && *(start + len) != '!' + && strncmp(start + len, "'Z", 2) && strncmp(start + len, "...", 3) && strncmp(start + len, "\xE2\x80\xA6", 3)) { - fprintf(stderr, "%s:%u: expected token delimiter after string literal\n", fname, line); + fprintf(stderr, "%s:%d: expected token delimiter after string literal\n", fname, line); deleteLexemeList(list); return NULL; } @@ -281,6 +305,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t while (start[len] && !isspace(start[len]) && *(start + len) != ',' && *(start + len) != '!' + && strncmp(start + len, "'Z", 2) && strncmp(start + len, "...", 3) && strncmp(start + len, "\xE2\x80\xA6", 3)) len++; @@ -293,7 +318,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t } strncpy(temp, start, len); temp[len] = '\0'; - lex = createLexeme(temp, fname, line); + Lexeme *lex = createLexeme(temp, fname, line); if (!lex) { free(temp); deleteLexemeList(list); @@ -309,7 +334,7 @@ LexemeList *scanBuffer(const char *buffer, /**< [in] An array of characters to t start += len; } /* Create an end-of-file lexeme */ - lex = createLexeme("$", fname, line); + Lexeme *lex = createLexeme("$", fname, line); if (!lex) { deleteLexemeList(list); return NULL; diff --git a/lexer.h b/lexer.h index c0e7ef7..4e5877b 100644 --- a/lexer.h +++ b/lexer.h @@ -1,14 +1,16 @@ -/** Structures and functions for separating a character buffer into lexemes. The - * lexer reads through a buffer of characters (themselves typically read from - * standard input), strips whitespace, and breaks them up into logical atoms of - * character strings which, in turn, may be passed on to later processes (such - * as a tokenizer). - * - * \file lexer.h - * - * \author Justin J. Meza - * - * \date 2010 */ +/** + * Structures and functions for separating a character buffer into lexemes -- + * groups of characters. The lexer reads through a buffer of characters + * (themselves typically read from standard input), strips whitespace, and + * breaks them up into logical atoms of character strings which, in turn, may be + * passed on to later processes (such as a tokenizer). + * + * \file lexer.h + * + * \author Justin J. Meza + * + * \date 2010-2011 + */ #ifndef __LEXER_H__ #define __LEXER_H__ @@ -20,36 +22,44 @@ #undef DEBUG -/** Stores a lexeme. A lexeme is the smallest unit of contiguous characters, - * namely, it has been stripped of surrounding whitespace. - * - * \note This structure does not have any list structure to hold groups of it. - * Instead, pointers to arrays of these structures are employed to allow - * for easier tokenizing. - * - * \see createLexeme(char *, unsigned int) */ +/** + * Stores a lexeme. A lexeme is a group of contiguous characters, stripped of + * surrounding whitespace or other lexemes. + */ typedef struct { - char *image; /**< An array of characters that describe the lexeme. */ - const char *fname; /**< A pointer to the name of the file containing the lexeme. */ - unsigned int line; /**< The line number from the source file that the lexeme occurred on. */ + char *image; /**< The string that identifies the lexeme. */ + const char *fname; /**< The name of the file containing the lexeme. */ + unsigned int line; /**< The line number the lexeme occurred on. */ } Lexeme; -/** Stores a list of lexemes. This structure allows sets of lexemes to be - * grouped together. - * - * \see createLexemeList(void) - * \see addLexeme(LexemeList *, Lexeme *) - * \see deleteLexemeList(LexemeList *) */ +/** + * Stores a list of lexemes. + */ typedef struct { - unsigned int num; /**< The number of Lexeme structures stored. */ - Lexeme **lexemes; /**< A pointer to the array of Lexeme structures. */ + unsigned int num; /**< The number of lexemes stored. */ + Lexeme **lexemes; /**< The array of stored lexemes. */ } LexemeList; +/** + * \name Lexeme modifiers + * + * Functions for performing helper tasks. + */ +/**@{*/ Lexeme *createLexeme(char *, const char *, unsigned int); void deleteLexeme(Lexeme *); LexemeList *createLexemeList(void); Lexeme *addLexeme(LexemeList *, Lexeme*); void deleteLexemeList(LexemeList *); +/**@}*/ + +/** + * \name Buffer lexer + * + * Generates lexemes from a character buffer. + */ +/**@{*/ LexemeList *scanBuffer(const char *, unsigned int, const char *); +/**@}*/ #endif /* __LEXER_H__ */ diff --git a/main.c b/main.c index c084fab..a7a280d 100644 --- a/main.c +++ b/main.c @@ -3,7 +3,7 @@ * \section license License * * lci - a LOLCODE interpreter written in C. - * Copyright (C) 2010 Justin J. Meza + * Copyright (C) 2010-2011 Justin J. Meza * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/parser.c b/parser.c index 7d992f8..76f6653 100644 --- a/parser.c +++ b/parser.c @@ -13,16 +13,16 @@ void debug(const char *info) } #endif -/** Creates a MainNode structure. - * - * \pre \a block was created by createBlockNode(StmtNodeList *). - * - * \return A pointer to a MainNode structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteMainNode(MainNode *) */ -MainNode *createMainNode(BlockNode *block) /**< [in] A pointer to the block of code to execute first. */ +/** + * Creates the main code block of a program. + * + * \param [in] block The first code block to execute. + * + * \return A pointer to the main code block with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +MainNode *createMainNode(BlockNode *block) { MainNode *p = malloc(sizeof(MainNode)); if (!p) { @@ -33,32 +33,30 @@ MainNode *createMainNode(BlockNode *block) /**< [in] A pointer to the block of c return p; } -/** Deletes a MainNode structure. - * - * \pre \a node was created by createMainNode(BlockNode *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createMainNode(BlockNode *) */ -void deleteMainNode(MainNode *node) /**< [in,out] A pointer to the MainNode structure to be deleted. */ +/** + * Deletes the main code block of a program. + * + * \param [in,out] node The main code block to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteMainNode(MainNode *node) { if (!node) return; deleteBlockNode(node->block); free(node); } -/** Creates a BlockNode structure. - * - * \pre \a stmts was created by createStmtNodeList(void) and contains contents - * added by addStmtNode(StmtNodeList *, StmtNode *). - * - * \return A pointer to a BlockNode structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteBlockNode(BlockNode *) */ -BlockNode *createBlockNode(StmtNodeList *stmts) /**< [in] A pointer to the list of statements which comprise the block of code. */ +/** + * Creates a code block. + * + * \param [in] stmts The list of statements which comprise the code block. + * + * \return A pointer to the code block with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +BlockNode *createBlockNode(StmtNodeList *stmts) { BlockNode *p = malloc(sizeof(BlockNode)); if (!p) { @@ -69,28 +67,27 @@ BlockNode *createBlockNode(StmtNodeList *stmts) /**< [in] A pointer to the list return p; } -/** Deletes a BlockNode structure. - * - * \pre \a node was created by createBlockNode(StmtNodeList *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createBlockNode(StmtNodeList *) */ -void deleteBlockNode(BlockNode *node) /**< [in,out] A pointer to the BlockNode structure to be deleted. */ +/** + * Deletes a code block. + * + * \param [in,out] node The code block to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteBlockNode(BlockNode *node) { if (!node) return; deleteStmtNodeList(node->stmts); free(node); } -/** Creates a BlockNodeList structure. - * - * \return A pointer to a BlockNodeList structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteBlockNodeList(BlockNodeList *) */ +/** + * Creates an empty code block list. + * + * \return A pointer to an empty code block list. + * + * \retval NULL Memory allocation failed. + */ BlockNodeList *createBlockNodeList(void) { BlockNodeList *p = malloc(sizeof(BlockNodeList)); @@ -103,21 +100,21 @@ BlockNodeList *createBlockNodeList(void) return p; } -/** Adds a BlockNode structure to a BlockNodeList structure. - * - * \pre \a list was created by createBlockNodeList(void). - * \pre \a node was created by createBlockNode(StmtNodeList *). - * - * \post \a node will be added on to the end of \a list and the size of - * \a list will be updated accordingly. - * - * \retval 0 realloc was unable to allocate memory. - * \retval 1 \a node was added to \a list. - * - * \see createBlockNodeList(void) - * \see deleteBlockNodeList(BlockNodeList *) */ -int addBlockNode(BlockNodeList *list, /**< [in,out] A pointer to the BlockNodeList structure to add \a node to. */ - BlockNode *node) /**< [in] A pointer to the BlockNode structure to add to \a list. */ +/** + * Adds a code block to a list. + * + * \param [in,out] list The code block list to add \a node to. + * + * \param [in] node The code block to add to \a list. + * + * \post \a node will be added to \a list and its size will be updated. + * + * \retval 0 Memory allocation failed. + * + * \retval 1 \a node was added to \a list. + */ +int addBlockNode(BlockNodeList *list, + BlockNode *node) { unsigned int newsize = list->num + 1; void *mem = realloc(list->blocks, sizeof(BlockNode *) * newsize); @@ -131,16 +128,14 @@ int addBlockNode(BlockNodeList *list, /**< [in,out] A pointer to the BlockNodeL return 1; } -/** Deletes a BlockNodeList structure. - * - * \pre \a list was created by createBlockNodeList(void) and contains items - * added by addBlockNode(BlockNodeList *, BlockNode *). - * - * \post The memory at \a list and any of its associated members will be - * freed. - * - * \see createBlockNodeList(void) */ -void deleteBlockNodeList(BlockNodeList *list) /**< [in,out] A pointer to the BlockNodeList structure to delete. */ +/** + * Deletes a code block list. + * + * \param [in,out] list The code block list to delete. + * + * \post The memory at \a list and all of its members will be freed. + */ +void deleteBlockNodeList(BlockNodeList *list) { unsigned int n; if (!list) return; @@ -150,15 +145,17 @@ void deleteBlockNodeList(BlockNodeList *list) /**< [in,out] A pointer to the Blo free(list); } -/** Creates a boolean type ConstantNode structure. - * - * \return A pointer to a boolean type ConstantNode structure with value - * \c 0 if \a data equals 0 and \c 1 otherwise. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteConstantNode(ConstantNode *) */ -ConstantNode *createBooleanConstantNode(int data) /**< [in] The constant boolean data. */ +/** + * Creates a boolean constant. + * + * \param [in] data The boolean constant value. + * + * \return A pointer to a boolean constant which will be FALSE if \a data is \c + * 0 and TRUE otherwise. + * + * \retval NULL Memory allocation failed. + */ +ConstantNode *createBooleanConstantNode(int data) { ConstantNode *p = malloc(sizeof(ConstantNode)); if (!p) { @@ -170,14 +167,16 @@ ConstantNode *createBooleanConstantNode(int data) /**< [in] The constant boolean return p; } -/** Creates an integer type ConstantNode structure. - * - * \return A pointer to an integer type ConstantNode storing the desired value. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteConstantNode(ConstantNode *) */ -ConstantNode *createIntegerConstantNode(int data) /**< [in] The constant integer data. */ +/** + * Creates an integer constant. + * + * \param [in] data The integer constant value. + * + * \return A pointer to an integer constant whose value is \a data. + * + * \retval NULL Memory allocation failed. + */ +ConstantNode *createIntegerConstantNode(int data) { ConstantNode *p = malloc(sizeof(ConstantNode)); if (!p) { @@ -189,15 +188,16 @@ ConstantNode *createIntegerConstantNode(int data) /**< [in] The constant integer return p; } -/** Creates a floating point decimal type ConstantNode structure. - * - * \return A pointer to a floating point decimal type ConstantNode storing the - * desired value. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteConstantNode(ConstantNode *) */ -ConstantNode *createFloatConstantNode(float data) /**< [in] The constant floating point decimal data. */ +/** + * Creates a float constant. + * + * \param [in] data The float constant value. + * + * \return A pointer to a float constant whose value is \a data. + * + * \retval NULL Memory allocation failed. + */ +ConstantNode *createFloatConstantNode(float data) { ConstantNode *p = malloc(sizeof(ConstantNode)); if (!p) { @@ -209,14 +209,16 @@ ConstantNode *createFloatConstantNode(float data) /**< [in] The constant floatin return p; } -/** Creates a string type ConstantNode structure. - * - * \return A pointer to a string type ConstantNode storing the desired value. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteConstantNode(ConstantNode *) */ -ConstantNode *createStringConstantNode(char *data) /**< [in] The constant character string data. */ +/** + * Creates a string constant. + * + * \param [in] data The string constant value. + * + * \return A pointer to the string constant whose value is \a data. + * + * \retval NULL Memory allocation failed. + */ +ConstantNode *createStringConstantNode(char *data) { ConstantNode *p = malloc(sizeof(ConstantNode)); if (!p) { @@ -228,37 +230,42 @@ ConstantNode *createStringConstantNode(char *data) /**< [in] The constant charac return p; } -/** Deletes a ConstantNode structure. - * - * \pre \a node was created by either createBooleanConstantNode(int), createIntegerConstantNode(int), - * createFloatConstantNode(float), or createStringConstantNode(char *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createBooleanConstantNode(int) - * \see createIntegerConstantNode(int) - * \see createFloatConstantNode(float) - * \see createStringConstantNode(char *) */ -void deleteConstantNode(ConstantNode *node) /**< [in,out] A pointer to the ConstantNode structure to be deleted. */ +/** + * Deletes a constant. + * + * \param [in,out] node The constant to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteConstantNode(ConstantNode *node) { if (!node) return; if (node->type == CT_STRING) free(node->data.s); free(node); } -/** Creates an IdentifierNode structure. - * - * \return A pointer to an IdentifierNode structure with the desired - * properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteIdentifierNode(IdentifierNode *) */ -IdentifierNode *createIdentifierNode(IdentifierType type, /**< [in] The type of IdentifierNode stored in \a id. */ - void *id, /**< [in] A pointer to the stored identifier data. */ - const char *fname, /**< [in] A pointer to the name of the file containing the identifier. */ - unsigned int line) /**< [in] The line number from the source file that the identifier occurred on. */ +/** + * Creates an indentifier. + * + * \param [in] type The type of the identifier \a id. + * + * \param [in] id The identifier data. + * + * \param [in] slot An optional slot to index. + * + * \param [in] fname The file containing the identifier. + * + * \param [in] line The line the identifier occurred on. + * + * \return A pointer to the identifier with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +IdentifierNode *createIdentifierNode(IdentifierType type, + void *id, + IdentifierNode *slot, + const char *fname, + unsigned int line) { IdentifierNode *p = malloc(sizeof(IdentifierNode)); if (!p) { @@ -267,6 +274,7 @@ IdentifierNode *createIdentifierNode(IdentifierType type, /**< [in] The type of } p->type = type; p->id = id; + p->slot = slot; if (fname) { p->fname = malloc(sizeof(char) * (strlen(fname) + 1)); strcpy(p->fname, fname); @@ -278,15 +286,14 @@ IdentifierNode *createIdentifierNode(IdentifierType type, /**< [in] The type of return p; } -/** Deletes an IdentifierNode structure. - * - * \pre \a node was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createIdentifierNode(IdentifierType, void *, const char *, unsigned int) */ -void deleteIdentifierNode(IdentifierNode *node) /**< [in,out] A pointer to the IdentifierNode structure to be deleted. */ +/** + * Deletes an identifier. + * + * \param [in,out] node The identifier to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteIdentifierNode(IdentifierNode *node) { if (!node) return; switch (node->type) { @@ -302,18 +309,18 @@ void deleteIdentifierNode(IdentifierNode *node) /**< [in,out] A pointer to the I fprintf(stderr, "Unable to delete unknown identifier type\n"); break; } + if (node->slot) deleteIdentifierNode(node->slot); if (node->fname) free(node->fname); free(node); } -/** Creates an IdentifierNodeList structure. - * - * \return A pointer to a IdentifierNodeList structure with the desired - * properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteIdentifierNodeList(IdentifierNodeList *) */ +/** + * Creates an identifier list. + * + * \return A pointer to an identifier list. + * + * \retval NULL Memory allocation failed. + */ IdentifierNodeList *createIdentifierNodeList(void) { IdentifierNodeList *p = malloc(sizeof(IdentifierNodeList)); @@ -326,21 +333,22 @@ IdentifierNodeList *createIdentifierNodeList(void) return p; } -/** Adds an IdentifierNode structure to an IdentifierNodeList structure. - * - * \pre \a list was created by createIdentifierNodeList(void). - * \pre \a node was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * - * \post \a node will be added on to the end of \a list and the size of - * \a list will be updated accordingly. - * - * \retval 0 realloc was unable to allocate memory. - * \retval 1 \a node was added to \a list. - * - * \see createIdentifierNodeList(void) - * \see deleteIdentifierNodeList(IdentifierNodeList *) */ -int addIdentifierNode(IdentifierNodeList *list, /**< [in,out] A pointer to the IdentifierNodeList structure to add \a node to. */ - IdentifierNode *node) /**< [in] A pointer to the IdentifierNode structure to add to \a list. */ +/** + * Adds an identifier to a list. + * + * \param [in,out] list The list of identifiers to add \a node to. + * + * \param [in] node The identifier to add to \a list. + * + * \post \a token will be added to the end of \a list and the size of \a list + * will be updated. + * + * \retval 0 Memory allocation failed. + * + * \retval 1 \a node was added to \a list. + */ +int addIdentifierNode(IdentifierNodeList *list, + IdentifierNode *node) { unsigned int newsize = list->num + 1; void *mem = realloc(list->ids, sizeof(IdentifierNode *) * newsize); @@ -354,16 +362,14 @@ int addIdentifierNode(IdentifierNodeList *list, /**< [in,out] A pointer to the return 1; } -/** Deletes an IdentifierNodeList structure. - * - * \pre \a list was created by createIdentifierNodeList(void) and contains - * items added by addIdentifierNode(IdentifierNodeList *, IdentifierNode *). - * - * \post The memory at \a list and any of its associated members will be - * freed. - * - * \see createIdentifierNodeList(void) */ -void deleteIdentifierNodeList(IdentifierNodeList *list) /**< [in,out] A pointer to the IdentifierNodeList structure to delete. */ +/** + * Deletes an identifier list. + * + * \param [in,out] list The list of identifiers to delete. + * + * \post The memory at \a list and all of its members will be freed. + */ +void deleteIdentifierNodeList(IdentifierNodeList *list) { unsigned int n; if (!list) return; @@ -373,14 +379,16 @@ void deleteIdentifierNodeList(IdentifierNodeList *list) /**< [in,out] A pointer free(list); } -/** Creates a TypeNode structure. - * - * \return A pointer to a TypeNode structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteTypeNode(TypeNode *) */ -TypeNode *createTypeNode(ConstantType type) /**< [in] The type of value. */ +/** + * Creates a type. + * + * \param [in] type The type to create. + * + * \return A pointer to a new type with the desired properties. + * + * \retval NULL Memory allocatin failed. + */ +TypeNode *createTypeNode(ConstantType type) { TypeNode *p = malloc(sizeof(TypeNode)); if (!p) { @@ -391,43 +399,32 @@ TypeNode *createTypeNode(ConstantType type) /**< [in] The type of value. */ return p; } -/** Deletes a TypeNode structure. - * - * \pre \a node was created by createTypeNode(ConstantType). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createTypeNode(ConstantType) */ -void deleteTypeNode(TypeNode *node) /**< [in,out] A pointer to the TypeNode structure to be deleted. */ +/** + * Deletes a type. + * + * \param [in,out] node The type to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteTypeNode(TypeNode *node) { if (!node) return; free(node); } -/** Creates a StmtNode structure. - * - * \pre \a stmt contains a structure created corresponding to \a type: - * - ST_CAST: createCastStmtNode(IdentifierNode *, TypeNode *) - * - ST_PRINT: createPrintStmtNode(ExprNodeList *, int) - * - ST_INPUT: createInputStmtNode(IdentifierNode *) - * - ST_ASSIGNMENT: createAssignmentStmtNode(IdentifierNode *, ExprNode *) - * - ST_DECLARATION: createDeclarationStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, TypeNode *) - * - ST_IFTHENELSE: createIfThenElseStmtNode(BlockNode *, BlockNode *, ExprNodeList *, BlockNodeList *) - * - ST_SWITCH: createSwitchStmtNode(ExprNodeList *, BlockNodeList *, BlockNode *) - * - ST_BREAK: no structure needed, use \c NULL - * - ST_RETURN: createReturnStmtNode(ExprNode *) - * - ST_LOOP: createLoopStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, ExprNode *, BlockNode *) - * - ST_FUNCDEF: createFuncDefStmtNode(IdentifierNode *, IdentifierNode *, IdentifierNodeList *, BlockNode *) - * - ST_EXPR: createExprNode(ExprType, void *) - * - * \return A pointer to a StmtNode structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteStmtNode(StmtNode *) */ -StmtNode *createStmtNode(StmtType type, /**< [in] The type of statement stored in \a node. */ - void *stmt) /**< [in] A pointer to the particular statement structure. */ +/** + * Creates a statement. + * + * \param [in] type The type of statement. + * + * \param [in] stmt The statement data. + * + * \return A pointer to a statement with the desired properties. + * + * \retval NULL malloc was unable to allocate memory. + */ +StmtNode *createStmtNode(StmtType type, + void *stmt) { StmtNode *p = malloc(sizeof(StmtNode)); if (!p) { @@ -439,15 +436,14 @@ StmtNode *createStmtNode(StmtType type, /**< [in] The type of statement stored i return p; } -/** Deletes a StmtNode structure. - * - * \pre \a node was created by createStmtNode(StmtType, void *). - * - * \post The memory at \a stmt and any of its associated members will be - * freed. - * - * \see createStmtNode(StmtType, void *) */ -void deleteStmtNode(StmtNode *node) /**< [in, out] A pointer to the StmtNode structure to be deleted. */ +/** + * Deletes a statement. + * + * \param [in,out] node The statement to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteStmtNode(StmtNode *node) { if (!node) return; switch (node->type) { @@ -520,13 +516,13 @@ void deleteStmtNode(StmtNode *node) /**< [in, out] A pointer to the StmtNode str free(node); } -/** Creates a StmtNodeList structure. - * - * \return A pointer to a StmtNodeList structure with no elements. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteStmtNodeList(StmtNodeList *) */ +/** + * Creates an empty statement list. + * + * \return A pointer to an empty statement list. + * + * \retval NULL Memory allocation failed. + */ StmtNodeList *createStmtNodeList(void) { StmtNodeList *p = malloc(sizeof(StmtNodeList)); @@ -539,21 +535,21 @@ StmtNodeList *createStmtNodeList(void) return p; } -/** Adds a StmtNode to a StmtNodeList structure. - * - * \pre \a list was created by createStmtNodeList(void). - * \pre \a node was created by createStmtNode(StmtType, void *). - * - * \post \a node will be added on to the end of \a list and the size of - * \a list will be updated accordingly. - * - * \retval 0 malloc was unable to allocate memory. - * \retval 1 \a node was added to \a list. - * - * \see createStmtNodeList(void) - * \see deleteStmtNodeList(StmtNodeList *) */ -int addStmtNode(StmtNodeList *list, /**< [in,out] A pointer to the StmtNodeList structure to add \a node to. */ - StmtNode *node) /**< [in] A pointer to the StmtNode structure to add to \a list. */ +/** + * Adds a statement to a list. + * + * \param [in,out] list The statement list to add \a node to. + * + * \param [in] node The statement to add to \a list. + * + * \post \a node will be added to \a list and its size will be updated. + * + * \retval 0 Memory allocation failed. + * + * \retval 1 \a node was added to \a list. + */ +int addStmtNode(StmtNodeList *list, + StmtNode *node) { unsigned int newsize = list->num + 1; void *mem = realloc(list->stmts, sizeof(StmtNode *) * newsize); @@ -567,16 +563,14 @@ int addStmtNode(StmtNodeList *list, /**< [in,out] A pointer to the StmtNodeList return 1; } -/** Deletes a StmtNodeList structure. - * - * \pre \a list was created by createStmtNodeList(void) and contains items added - * by addStmtNode(StmtNodeList *, StmtNode *). - * - * \post The memory at \a list and any of its associated members will be - * freed. - * - * \see createStmtNodeList(void) */ -void deleteStmtNodeList(StmtNodeList *list) /**< [in,out] A pointer to the StmtNodeList structure to delete. */ +/** + * Deletes a statement list. + * + * \param [in,out] list The statement list to delete. + * + * \post The memory at \a list and all of its members will be freed. + */ +void deleteStmtNodeList(StmtNodeList *list) { unsigned int n; if (!list) return; @@ -586,18 +580,19 @@ void deleteStmtNodeList(StmtNodeList *list) /**< [in,out] A pointer to the StmtN free(list); } -/** Creates a CastStmtNode structure. - * - * \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * \pre \a newtype was created by createTypeNode(ConstantType). - * - * \return A pointer to a CastStmtNode structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteCastStmtNode(CastStmtNode *) */ -CastStmtNode *createCastStmtNode(IdentifierNode *target, /**< [in] A pointer to the name of the variable whose type is to be changed to \a newtype. */ - TypeNode *newtype) /**< [in] A pointer to the type to change \a target to. */ +/** + * Creates a cast statement. + * + * \param [in] target The variable to cast to \a newtype. + * + * \param [in] newtype The type to cast \a target to. + * + * \return A pointer to a cast statement with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +CastStmtNode *createCastStmtNode(IdentifierNode *target, + TypeNode *newtype) { CastStmtNode *p = malloc(sizeof(CastStmtNode)); if (!p) { @@ -609,15 +604,14 @@ CastStmtNode *createCastStmtNode(IdentifierNode *target, /**< [in] A pointer to return p; } -/** Deletes a CastStmtNode structure. - * - * \pre \a node was created by createCastStmtNode(IdentifierNode *, TypeNode *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createCastStmtNode(IdentifierNode *, TypeNode *) */ -void deleteCastStmtNode(CastStmtNode *node) /**< [in,out] A pointer to the CastStmtNode structure to be deleted. */ +/** + * Deletes a cast statement. + * + * \param [in,out] node The cast statement to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteCastStmtNode(CastStmtNode *node) { if (!node) return; deleteIdentifierNode(node->target); @@ -625,18 +619,19 @@ void deleteCastStmtNode(CastStmtNode *node) /**< [in,out] A pointer to the CastS free(node); } -/** Creates a PrintStmtNode structure. - * - * \pre \a args was created by createExprNodeList(void) and contains items - * added by addExprNode(ExprNodeList *, ExprNode *). - * - * \return A pointer to a PrintStmtNode structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deletePrintStmtNode(PrintStmtNode *) */ -PrintStmtNode *createPrintStmtNode(ExprNodeList *args, /**< [in] A pointer to the list of expressions to evaluate and print. */ - int nonl) /**< [in] Denotes an ending newline should be surpressed if not \c 0 and printed if \c 0. */ +/** + * Creates a print statement. + * + * \param [in] args The expressions to print. + * + * \param [in] nonl Whether an ending newline should be surpressed. + * + * \return A pointer to the print statement with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +PrintStmtNode *createPrintStmtNode(ExprNodeList *args, + int nonl) { PrintStmtNode *p = malloc(sizeof(PrintStmtNode)); if (!p) { @@ -648,31 +643,30 @@ PrintStmtNode *createPrintStmtNode(ExprNodeList *args, /**< [in] A pointer to th return p; } -/** Deletes a PrintStmtNode structure. - * - * \pre \a node was created by createPrintStmtNode(ExprNodeList *, int). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createPrintStmtNode(ExprNodeList *, int) */ -void deletePrintStmtNode(PrintStmtNode *node) /**< [in,out] A pointer to the PrintStmtNode structure to be deleted. */ +/** + * Deletes a print statement. + * + * \param [in,out] node The print statement to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deletePrintStmtNode(PrintStmtNode *node) { if (!node) return; deleteExprNodeList(node->args); free(node); } -/** Creates an InputStmtNode structure. - * - * \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * - * \return A pointer to an InputStmtNode structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteInputStmtNode(InputStmtNode *) */ -InputStmtNode *createInputStmtNode(IdentifierNode *target) /**< [in] A pointer to the name of the variable to store the input in. */ +/** + * Creates an input statement. + * + * \param [in] target The variable to store input in. + * + * \return A pointer to an input statement with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +InputStmtNode *createInputStmtNode(IdentifierNode *target) { InputStmtNode *p = malloc(sizeof(InputStmtNode)); if (!p) { @@ -683,34 +677,33 @@ InputStmtNode *createInputStmtNode(IdentifierNode *target) /**< [in] A pointer t return p; } -/** Deletes an InputStmtNode structure. - * - * \pre \a node was created by createInputStmtNode(IdentifierNode *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createInputStmtNode(IdentifierNode *) */ -void deleteInputStmtNode(InputStmtNode *node) /**< [in,out] A pointer to the InputStmtNode structure to be deleted. */ +/** + * Deletes an input statement. + * + * \param [in,out] node The input statement to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteInputStmtNode(InputStmtNode *node) { if (!node) return; deleteIdentifierNode(node->target); free(node); } -/** Creates an AssignmentStmtNode structure. - * - * \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * \pre \a expr was created by createExprNode(ExprType, void *). - * - * \return A pointer to an AssignmentStmtNode structure with the desired - * properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteAssignmentStmtNode(AssignmentStmtNode *) */ -AssignmentStmtNode *createAssignmentStmtNode(IdentifierNode *target, /**< [in] A pointer to the name of the variable to store the evaluated contents of a \a expr into. */ - ExprNode *expr) /**< [in] A pointer to the expression to evaluate and store in \a target. */ +/** + * Creates an assignment statement. + * + * \param [in] target The variable to store \a expr in. + * + * \param [in] expr The expression to store in \a target. + * + * \return A pointer to an assignment statement with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +AssignmentStmtNode *createAssignmentStmtNode(IdentifierNode *target, + ExprNode *expr) { AssignmentStmtNode *p = malloc(sizeof(AssignmentStmtNode)); if (!p) { @@ -722,15 +715,14 @@ AssignmentStmtNode *createAssignmentStmtNode(IdentifierNode *target, /**< [in] A return p; } -/** Deletes an AssignmentStmtNode structure. - * - * \pre \a node was created by createAssignmentStmtNode(IdentifierNode *, ExprNode *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createAssignmentStmtNode(IdentifierNode *, ExprNode *) */ -void deleteAssignmentStmtNode(AssignmentStmtNode *node) /**< [in,out] A pointer to the AssignmentStmtNode structure to be deleted. */ +/** + * Deletes an assignment statement. + * + * \param [in,out] node The assignment statement to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteAssignmentStmtNode(AssignmentStmtNode *node) { if (!node) return; deleteIdentifierNode(node->target); @@ -738,22 +730,25 @@ void deleteAssignmentStmtNode(AssignmentStmtNode *node) /**< [in,out] A pointer free(node); } -/** Creates a DeclarationStmtNode structure. - * - * \pre \a scope was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * \pre \a expr was created by createExprNode(ExprType, void *). - * - * \return A pointer to a DeclarationStmtNode structure with the desired - * properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteDeclarationStmtNode(DeclarationStmtNode *) */ -DeclarationStmtNode *createDeclarationStmtNode(IdentifierNode *scope, /**< [in] A pointer to the scope to create the variable in. */ - IdentifierNode *target, /**< [in] A pointer to the name of the variable to create. */ - ExprNode *expr, /**< [in] An optional pointer to the expression to initialize \a target to. */ - TypeNode *type) /**< [in] An optional pointer to the type to initialize \a target to. */ +/** + * Creates a declaration statement. + * + * \param [in] scope The scope to create the variable in. + * + * \param [in] target The variable to create. + * + * \param [in] expr An optional expression to initialize \a target to. + * + * \param [in] type An optional type to initialize \a target to. + * + * \return A pointer to a declaration statement with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +DeclarationStmtNode *createDeclarationStmtNode(IdentifierNode *scope, + IdentifierNode *target, + ExprNode *expr, + TypeNode *type) { DeclarationStmtNode *p = malloc(sizeof(DeclarationStmtNode)); if (!p) { @@ -767,15 +762,14 @@ DeclarationStmtNode *createDeclarationStmtNode(IdentifierNode *scope, /**< [in] return p; } -/** Deletes a DeclarationStmtNode structure. - * - * \pre \a node was created by createDeclarationStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, TypeNode *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createDeclarationStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, TypeNode *) */ -void deleteDeclarationStmtNode(DeclarationStmtNode *node) /**< [in,out] A pointer to the DeclarationStmtNode structure to be deleted. */ +/** + * Deletes a declaration statement. + * + * \param [in,out] node The declaration statement to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteDeclarationStmtNode(DeclarationStmtNode *node) { if (!node) return; deleteIdentifierNode(node->scope); @@ -785,25 +779,29 @@ void deleteDeclarationStmtNode(DeclarationStmtNode *node) /**< [in,out] A pointe free(node); } -/** Creates an IfThenElseStmtNode structure. - * - * \pre \a yes was created by createBlockNode(StmtNodeList *). - * \pre \a no was created by createBlockNode(StmtNodeList *). - * \pre \a guards was created by createExprNodeList(void) and contains items - * added by addExprNode(ExprNodeList *, ExprNode *). - * \pre \a blocks was created by createBlockNodeList(void) and contains items - * added by addBlockNode(BlockNodeList *, BlockNode *). - * - * \return A pointer to a IfThenElseStmtNode structure with the desired - * properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteIfThenElseStmtNode(IfThenElseStmtNode *) */ -IfThenElseStmtNode *createIfThenElseStmtNode(BlockNode *yes, /**< [in] A pointer to the block of code to execute if the \ref impvar "implicit variable" casts to \c false. */ - BlockNode *no, /**< [in] A pointer to the block of code to execute if the \ref impvar "implicit variable" casts to \c false \b and the evaluations of all of the \a guards cast to \c false. */ - ExprNodeList *guards, /**< [in] A pointer to the expressions to test if the \ref impvar "implicit variable" casts to \c false. */ - BlockNodeList *blocks) /**< [in] A pointer to the respective blocks of code to execute if one of the evaluated \a guards casts to \c true. */ +/** + * Creates an if/then/else statement. + * + * \param [in] yes The code block to execute if the \ref impvar "implicit + * variable" is \c true. + * + * \param [in] no The code block to execute if the \ref impvar "implicit + * variable" is \c false and all \a guards are \c false. + * + * \param [in] guards The expressions to test if the \ref impvar "implicit + * variable" is \c false. + * + * \param [in] blocks The code blocks to execute if the respective guard is \c + * true. + * + * \return A pointer to the if/then/else statement with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +IfThenElseStmtNode *createIfThenElseStmtNode(BlockNode *yes, + BlockNode *no, + ExprNodeList *guards, + BlockNodeList *blocks) { IfThenElseStmtNode *p = malloc(sizeof(IfThenElseStmtNode)); if (!p) { @@ -817,15 +815,14 @@ IfThenElseStmtNode *createIfThenElseStmtNode(BlockNode *yes, /**< [in] A return p; } -/** Deletes a IfThenElseStmtNode structure. - * - * \pre \a node was created by createIfThenElseStmtNode(BlockNode *, BlockNode *, ExprNodeList *, BlockNodeList *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createIfThenElseStmtNode(BlockNode *, BlockNode *, ExprNodeList *, BlockNodeList *) */ -void deleteIfThenElseStmtNode(IfThenElseStmtNode *node) /**< [in,out] A pointer to the IfThenElseStmtNode structure to be deleted. */ +/** + * Deletes an if/then/else statement. + * + * \param [in,out] node The if/then/else statement to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteIfThenElseStmtNode(IfThenElseStmtNode *node) { if (!node) return; deleteBlockNode(node->yes); @@ -835,22 +832,25 @@ void deleteIfThenElseStmtNode(IfThenElseStmtNode *node) /**< [in,out] A pointer free(node); } -/** Creates a SwitchStmtNode structure. - * - * \pre \a guards was created by createExprNodeList(void) and contains items - * added by addExprNode(ExprNodeList *, ExprNode *). - * \pre \a blocks was created by createBlockNodeList(void) and contains items - * added by addBlockNode(BlockNodeList *, BlockNode *). - * \pre \a def was created by createBlockNode(StmtNodeList *). - * - * \return A pointer to a SwitchStmtNode structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteSwitchStmtNode(SwitchStmtNode *) */ -SwitchStmtNode *createSwitchStmtNode(ExprNodeList *guards, /**< [in] A pointer to the expressions to evaluate and compare to the \ref impvar "implicit variable". */ - BlockNodeList *blocks, /**< [in] A pointer to the respective blocks of code to execute if one of the \a guards matches the \ref impvar "implicit variable". */ - BlockNode *def) /**< [in] A pointer to the default block of code to execute if none of the \a guards match the \ref impvar "implicit variable". */ +/** + * Creates a switch statement. + * + * \param [in] guards The expressions to compare the the \ref impvar "implicit + * variable". + * + * \param [in] blocks The code blocks to execute if a respective guard matches + * the \ref impvar "implicit variable". + * + * \param [in] def The default code block to execute if none of the \a guards + * match the \ref impvar "implicit variable". + * + * \return A pointer to a switch statement with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +SwitchStmtNode *createSwitchStmtNode(ExprNodeList *guards, + BlockNodeList *blocks, + BlockNode *def) { SwitchStmtNode *p = malloc(sizeof(SwitchStmtNode)); if (!p) { @@ -863,15 +863,14 @@ SwitchStmtNode *createSwitchStmtNode(ExprNodeList *guards, /**< [in] A pointer return p; } -/** Deletes a SwitchStmtNode structure. - * - * \pre \a node was created by createSwitchStmtNode(ExprNodeList *, BlockNodeList *, BlockNode *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createSwitchStmtNode(ExprNodeList *, BlockNodeList *, BlockNode *) */ -void deleteSwitchStmtNode(SwitchStmtNode *node) /**< [in,out] A pointer to the SwitchStmtNode structure to be deleted. */ +/** + * Deletes a switch statement. + * + * \param [in,out] node The switch statement to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteSwitchStmtNode(SwitchStmtNode *node) { if (!node) return; deleteExprNodeList(node->guards); @@ -880,16 +879,16 @@ void deleteSwitchStmtNode(SwitchStmtNode *node) /**< [in,out] A pointer to the S free(node); } -/** Creates a ReturnStmtNode structure. - * - * \pre \a value was created by createExprNode(ExprType, void *). - * - * \return A pointer to a ReturnStmtNode structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteReturnStmtNode(ReturnStmtNode *) */ -ReturnStmtNode *createReturnStmtNode(ExprNode *value) /**< [in] A pointer to the value to return. */ +/** + * Creates a return statement. + * + * \param [in] value The return value. + * + * \return A pointer to a return statement of the desired properties. + * + * \retval NULL Memory allocation failed. + */ +ReturnStmtNode *createReturnStmtNode(ExprNode *value) { ReturnStmtNode *p = malloc(sizeof(ReturnStmtNode)); if (!p) { @@ -900,39 +899,42 @@ ReturnStmtNode *createReturnStmtNode(ExprNode *value) /**< [in] A pointer to the return p; } -/** Deletes a ReturnStmtNode structure. - * - * \pre \a node was created by createReturnStmtNode(ExprNode *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createReturnStmtNode(ExprNode *) */ -void deleteReturnStmtNode(ReturnStmtNode *node) /**< [in,out] A pointer to the ReturnStmtNode structure to be deleted. */ +/** + * Deletes a return statement. + * + * \param [in,out] node The return statement to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteReturnStmtNode(ReturnStmtNode *node) { if (!node) return; deleteExprNode(node->value); free(node); } -/** Creates a LoopStmtNode structure. - * - * \pre \a name was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * \pre \a var was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * \pre \a guard was created by createExprNode(ExprType, void *). - * \pre \a update was created by createExprNode(ExprType, void *). - * \pre \a body was created by createBlockNode(StmtNodeList *). - * - * \return A pointer to a LoopStmtNode structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteLoopStmtNode(LoopStmtNode *) */ -LoopStmtNode *createLoopStmtNode(IdentifierNode *name, /**< [in] A pointer to the name of the loop. */ - IdentifierNode *var, /**< [in] A pointer to the name of the variable to be updated by \a update. */ - ExprNode *guard, /**< [in] A pointer to the expression to determine if the loop will continue. */ - ExprNode *update, /**< [in] A pointer to the expression to evaluate to update \a var. */ - BlockNode *body) /**< [in] A pointer to the block of code to be executed with each iteration of the loop. */ +/** + * Creates a loop statement. + * + * \param [in] name The name of the loop. + * + * \param [in] var The induction variable. + * + * \param [in] guard The expression to determine if the loop continues. + * + * \param [in] update The expression to update \a var using. + * + * \param [in] body The code block to execute with each loop iteration. + * + * \return A pointer to a loop statement with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +LoopStmtNode *createLoopStmtNode(IdentifierNode *name, + IdentifierNode *var, + ExprNode *guard, + ExprNode *update, + BlockNode *body) { LoopStmtNode *p = malloc(sizeof(LoopStmtNode)); if (!p) { @@ -947,15 +949,14 @@ LoopStmtNode *createLoopStmtNode(IdentifierNode *name, /**< [in] A pointer to th return p; } -/** Deletes a LoopStmtNode structure. - * - * \pre \a node was created by createLoopStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, ExprNode *, BlockNode *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createLoopStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, ExprNode *, BlockNode *) */ -void deleteLoopStmtNode(LoopStmtNode *node) /**< [in,out] A pointer to the LoopStmtNode structure to be deleted. */ +/** + * Deletes a loop statement. + * + * \param [in,out] node The loop statement to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteLoopStmtNode(LoopStmtNode *node) { if (!node) return; deleteIdentifierNode(node->name); @@ -966,17 +967,16 @@ void deleteLoopStmtNode(LoopStmtNode *node) /**< [in,out] A pointer to the LoopS free(node); } -/** Creates a DeallocationStmtNode structure. - * - * \pre \a target was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * - * \return A pointer to a DeallocationStmtNode structure with the desired - * properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteDeallocationStmtNode(DeallocationStmtNode *) */ -DeallocationStmtNode *createDeallocationStmtNode(IdentifierNode *target) /**< [in] A pointer to the name of the variable. */ +/** + * Creates a deallocation statement. + * + * \param [in] target The variable to deallocate. + * + * \return A pointer to a deallocation statement with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +DeallocationStmtNode *createDeallocationStmtNode(IdentifierNode *target) { DeallocationStmtNode *p = malloc(sizeof(DeallocationStmtNode)); if (!p) { @@ -987,39 +987,40 @@ DeallocationStmtNode *createDeallocationStmtNode(IdentifierNode *target) /**< [i return p; } -/** Deletes a DeallocationStmtNode structure. - * - * \pre \a node was created by createDeallocationStmtNode(IdentifierNode *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createDeallocationStmtNode(IdentifierNode *) */ -void deleteDeallocationStmtNode(DeallocationStmtNode *node) /**< [in,out] A pointer to the DeallocationStmtNode structure to be deleted. */ +/** + * Deletes a deallocation statement. + * + * \param [in,out] node The deallocation statement to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteDeallocationStmtNode(DeallocationStmtNode *node) { if (!node) return; deleteIdentifierNode(node->target); free(node); } -/** Creates a FuncDefStmtNode structure. - * - * \pre \a scope was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * \pre \a name was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * \pre \a args was created by createIdentifierNodeList(void) and contains - * items added by addIdentifierNode(IdentifierNodeList *, IdentifierNode *). - * \pre \a body was created by createBlockNode(StmtNodeList *). - * - * \return A pointer to a FuncDefStmtNode structure with the desired - * properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteFuncDefStmtNode(FuncDefStmtNode *) */ -FuncDefStmtNode *createFuncDefStmtNode(IdentifierNode *scope, /**< [in] A pointer to the scope to define the function in. */ - IdentifierNode *name, /**< [in] A pointer to the name of the function. */ - IdentifierNodeList *args, /**< [in] A pointer to an array of the names of the arguments of the function. */ - BlockNode *body) /**< [in] A pointer to the block of code defined by the function. */ +/** + * Creates a function definition statement. + * + * \param [in] scope The scope to define the function in. + * + * \param [in] name The name of the function. + * + * \param [in] args The function arguments names. + * + * \param [in] body The function's code block. + * + * \return A pointer to a function definition statement with the desired + * properties. + * + * \retval NULL Memory allocation failed. + */ +FuncDefStmtNode *createFuncDefStmtNode(IdentifierNode *scope, + IdentifierNode *name, + IdentifierNodeList *args, + BlockNode *body) { FuncDefStmtNode *p = malloc(sizeof(FuncDefStmtNode)); if (!p) { @@ -1033,15 +1034,14 @@ FuncDefStmtNode *createFuncDefStmtNode(IdentifierNode *scope, /**< [in] A poi return p; } -/** Deletes a FuncDefStmtNode structure. - * - * \pre \a node was created by createFuncDefStmtNode(IdentifierNode *, IdentifierNode *, IdentifierNodeList *, BlockNode *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createFuncDefStmtNode(IdentifierNode *, IdentifierNode *, IdentifierNodeList *, BlockNode *) */ -void deleteFuncDefStmtNode(FuncDefStmtNode *node) /**< [in,out] A pointer to the FuncDefStmtNode structure to be deleted. */ +/** + * Deletes a function definition statement. + * + * \param [in,out] node The function definition statement to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteFuncDefStmtNode(FuncDefStmtNode *node) { if (!node) return; deleteIdentifierNode(node->scope); @@ -1051,24 +1051,19 @@ void deleteFuncDefStmtNode(FuncDefStmtNode *node) /**< [in,out] A pointer to the free(node); } -/** Creates an ExprNode structure. - * - * \pre \a expr contains a structure created corresponding to \a type: - * - ET_CAST: createCastExprNode(ExprNode *, TypeNode *) - * - ET_CONSTANT: createBooleanConstantNode(int), createIntegerConstantNode(int), - * createFloatConstantNode(float), or createStringConstantNode(char *) - * - ET_IDENTIFIER: createIdentifierNode(IdentifierType, void *, const char *, unsigned int) - * - ET_FUNCCALL: createFuncCallExprNode(IdentifierNode *, IdentifierNode *, ExprNodeList *) - * - ET_OP: createOpExprNode(OpType, ExprNodeList *) - * - ET_IMPVAR: (for the \ref impvar "implicit variable") no structure needed, use \c NULL - * - * \return A pointer to an ExprNode structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteExprNode(ExprNode *) */ -ExprNode *createExprNode(ExprType type, /**< [in] The type of expression stored in \a expr. */ - void *expr) /**< [in] A pointer to the particular expression structure. */ +/** + * Creates an expression. + * + * \param [in] type The type of expression. + * + * \param [in] expr The expression data. + * + * \return A pointer to an expression with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +ExprNode *createExprNode(ExprType type, + void *expr) { ExprNode *p = malloc(sizeof(ExprNode)); if (!p) { @@ -1080,15 +1075,14 @@ ExprNode *createExprNode(ExprType type, /**< [in] The type of expression stored return p; } -/** Deletes an ExprNode structure. - * - * \pre \a node was created by createExprNode(ExprType, void *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createExprNode(ExprType, void *) */ -void deleteExprNode(ExprNode *node) /**< [in,out] A pointer to the ExprNode structure to be deleted. */ +/** + * Deletes an expression. + * + * \param [in,out] node The expression to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteExprNode(ExprNode *node) { if (!node) return; switch (node->type) { @@ -1116,13 +1110,13 @@ void deleteExprNode(ExprNode *node) /**< [in,out] A pointer to the ExprNode stru free(node); } -/** Creates an ExprNodeList structure. - * - * \return A pointer to an ExprNodeList structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteExprNodeList(ExprNodeList *) */ +/** + * Creates an empty expression list. + * + * \return A pointer to an empty expression list. + * + * \retval NULL Memory allocation failed. + */ ExprNodeList *createExprNodeList(void) { ExprNodeList *p = malloc(sizeof(ExprNodeList)); @@ -1135,21 +1129,21 @@ ExprNodeList *createExprNodeList(void) return p; } -/** Adds an ExprNode structure to an ExprNodeList structure. - * - * \pre \a list was created by createExprNodeList(void). - * \pre \a node was created by createExprNode(ExprType, void *). - * - * \post \a node will be added on to the end of \a list and the size of - * \a list will be updated accordingly. - * - * \retval 0 realloc was unable to allocate memory. - * \retval 1 \a node was added to \a list. - * - * \see createExprNodeList(void) - * \see deleteExprNodeList(ExprNodeList *) */ -int addExprNode(ExprNodeList *list, /**< [in,out] A pointer to the ExprNodeList structure to add \a node to. */ - ExprNode *node) /**< [in] A pointer to the ExprNode structure to add to \a list. */ +/** + * Adds an expression to a list. + * + * \param [in,out] list The expression list to add \a node to. + * + * \param [in] node The expression to add to \a list. + * + * \post \a node will be added to \a list and its size will be updated. + * + * \retval 0 Memory allocation failed. + * + * \retval 1 \a node was added to \a list. + */ +int addExprNode(ExprNodeList *list, + ExprNode *node) { unsigned int newsize = list->num + 1; void *mem = realloc(list->exprs, sizeof(ExprNode *) * newsize); @@ -1163,16 +1157,14 @@ int addExprNode(ExprNodeList *list, /**< [in,out] A pointer to the ExprNodeList return 1; } -/** Deletes an ExprNodeList structure. - * - * \pre \a list was created by createExprNodeList(void) and contains items - * added by addExprNode(ExprNodeList *, ExprNode *). - * - * \post The memory at \a list and any of its associated members will be - * freed. - * - * \see createExprNodeList(void) */ -void deleteExprNodeList(ExprNodeList *list) /**< [in,out] A pointer to the ExprNodeList structure to delete. */ +/** + * Deletes an expression list. + * + * \param [in,out] list The expression list to delete. + * + * \post The memory at \a list and all of its members will be freed. + */ +void deleteExprNodeList(ExprNodeList *list) { unsigned int n; if (!list) return; @@ -1182,18 +1174,19 @@ void deleteExprNodeList(ExprNodeList *list) /**< [in,out] A pointer to the ExprN free(list); } -/** Creates a CastExprNode structure. - * - * \pre \a target was created by createExprNode(ExprType, void *). - * \pre \a newtype was created by createTypeNode(ConstantType). - * - * \return A pointer to a CastExprNode structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteCastExprNode(CastExprNode *) */ -CastExprNode *createCastExprNode(ExprNode *target, /**< [in] A pointer to the expression to cast. */ - TypeNode *newtype) /**< [in] A pointer to the type to cast the copy of \a target to. */ +/** + * Creates a cast expression. + * + * \param [in] target The expression to cast. + * + * \param [in] newtype The type to cast \a target to. + * + * \return A pointer to a cast expression with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +CastExprNode *createCastExprNode(ExprNode *target, + TypeNode *newtype) { CastExprNode *p = malloc(sizeof(CastExprNode)); if (!p) { @@ -1205,15 +1198,14 @@ CastExprNode *createCastExprNode(ExprNode *target, /**< [in] A pointer to the e return p; } -/** Deletes a CastExprNode structure. - * - * \pre \a node was created by createCastExprNode(ExprNode *, TypeNode *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createCastExprNode(ExprNode *, TypeNode *) */ -void deleteCastExprNode(CastExprNode *node) /**< [in,out] A pointer to the CastExprNode structure to be deleted. */ +/** + * Deletes a cast expression. + * + * \param [in,out] node The cast expression to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteCastExprNode(CastExprNode *node) { if (!node) return; deleteExprNode(node->target); @@ -1221,22 +1213,22 @@ void deleteCastExprNode(CastExprNode *node) /**< [in,out] A pointer to the CastE free(node); } -/** Creates a FuncCallExprNode structure. - * - * \pre \a scope was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * \pre \a name was created by createIdentifierNode(IdentifierType, void *, const char *, unsigned int). - * \pre \a args was created by createIdentifierNodeList(void) and contains - * items added by addIdentifierNode(IdentifierNodeList *, IdentifierNode *). - * - * \return A pointer to a FuncCallExprNode structure with the desired - * properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteFuncCallExprNode(FuncCallExprNode *) */ -FuncCallExprNode *createFuncCallExprNode(IdentifierNode *scope, /**< [in] A pointer to the scope the function is defined in. */ - IdentifierNode *name, /**< [in] A pointer to the name of the function. */ - ExprNodeList *args) /**< [in] A pointer to a list of ExprNode structure arguments supplied to the function definition. */ +/** + * Creates a function call expression. + * + * \param [in] scope The scope to lookup the function in. + * + * \param [in] name The name of the function. + * + * \param [in] args The arguments to supply the function. + * + * \return A pointer to a function call expression with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +FuncCallExprNode *createFuncCallExprNode(IdentifierNode *scope, + IdentifierNode *name, + ExprNodeList *args) { FuncCallExprNode *p = malloc(sizeof(FuncCallExprNode)); if (!p) { @@ -1249,15 +1241,14 @@ FuncCallExprNode *createFuncCallExprNode(IdentifierNode *scope, /**< [in] A poin return p; } -/** Deletes a FuncCallExprNode structure. - * - * \pre \a node was created by createFuncCallExprNode(IdentifierNode *, IdentifierNode *, ExprNodeList *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createFuncCallExprNode(IdentifierNode *, IdentifierNode *, ExprNodeList *) */ -void deleteFuncCallExprNode(FuncCallExprNode *node) /**< [in,out] A pointer to the FuncCallExprNode structure to be deleted. */ +/** + * Deletes a function call expression. + * + * \param [in,out] node The function call expression to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteFuncCallExprNode(FuncCallExprNode *node) { if (!node) return; deleteIdentifierNode(node->scope); @@ -1266,18 +1257,19 @@ void deleteFuncCallExprNode(FuncCallExprNode *node) /**< [in,out] A pointer to t free(node); } -/** Creates an OpExprNode structure. - * - * \pre \a args was created by createExprNodeList(void) and contains items - * added by addExprNode(ExprNodeList *, ExprNode *). - * - * \return A pointer to an OpExprNode structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteOpExprNode(OpExprNode *) */ -OpExprNode *createOpExprNode(OpType type, /**< [in] The type of operation to perform on \a args. */ - ExprNodeList *args) /**< [in] A pointer to the arguments to perform the operation on. */ +/** + * Creates an operation expression. + * + * \param [in] type The type of operation to perform. + * + * \param [in] args The operands. + * + * \return A pointer to an operation expression with the desired properties. + * + * \retval NULL Memroy allocation failed. + */ +OpExprNode *createOpExprNode(OpType type, + ExprNodeList *args) { OpExprNode *p = malloc(sizeof(OpExprNode)); if (!p) { @@ -1289,43 +1281,37 @@ OpExprNode *createOpExprNode(OpType type, /**< [in] The type of operation return p; } -/** Deletes an OpExprNode structure. - * - * \pre \a node was created by createOpExprNode(OpType, ExprNodeList *). - * - * \post The memory at \a node and any of its associated members will be - * freed. - * - * \see createOpExprNode(OpType, ExprNodeList *) */ -void deleteOpExprNode(OpExprNode *node) /**< [in,out] A pointer to the OpExprNode structure to be deleted. */ +/** + * Deletes an operation expression. + * + * \param [in,out] node The operation expression to delete. + * + * \post The memory at \a node and all of its members will be freed. + */ +void deleteOpExprNode(OpExprNode *node) { if (!node) return; deleteExprNodeList(node->args); free(node); } -/** Checks if the token pointed to by \a tokenp matches \a token and if it does, - * advances the token pointer to the next token in the array. - * - * \note Unlike peekToken(Token ***, TokenType) and nextToken(Token ***, TokenType), this - * function \b does modify \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post If the token pointed to by \a tokenp does not match \a token, - * \a tokenp will point to the same token as when the function was - * called. - * \post If the token pointed to by \a tokenp matches \a token, \a tokenp will - * point to the next token \b after the one matched. - * - * \retval 0 The token does not match \a token. - * \retval 1 The token matches \a token. - * - * \see peekToken(Token ***, TokenType) - * \see nextToken(Token ***, TokenType) */ -int acceptToken(Token ***tokenp, /**< [in,out] A pointer to the position of the next token to parse in an array of Token structures. */ - TokenType token) /**< [in] The type of token to match. */ +/** + * Checks if a type of token is at a position in a token list, and if so, + * advances the position. + * + * \param [in,out] tokenp The position in a token list to check. + * + * \param [in] token The type of token to check for. + * + * \post If the type of \a tokenp is not \a token, \a tokenp will remain + * unchanged, else, it will point to the token after the one matched. + * + * \retval 0 The type of \a tokenp is \a token. + * + * \retval 1 The type of \a tokenp is not \a token. + */ +int acceptToken(Token ***tokenp, + TokenType token) { Token **tokens = *tokenp; if ((*tokens)->type != token) return 0; @@ -1334,84 +1320,78 @@ int acceptToken(Token ***tokenp, /**< [in,out] A pointer to the position of the return 1; } -/** Checks if the token pointed to by \a tokenp matches \a token. - * - * \note Unlike acceptToken(Token ***, TokenType), this function does not - * modify \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the same token as when the function was - * called. - * - * \retval 0 The token does not match \a token. - * \retval 1 The token matches \a token. - * - * \see acceptToken(Token ***, TokenType) - * \see nextToken(Token ***, TokenType) */ -int peekToken(Token ***tokenp, /**< [in] A pointer to the position of the next token to parse in an array of Token structures. */ - TokenType token) /**< [in] The type of token to match. */ +/** + * Checks if a type of token is at a position in a token list. + * + * \param [in] tokenp The position in a token list to check. + * + * \param [in] token The type of token to check for. + * + * \post \a tokenp will remain unchanged. + * + * \retval 0 The type of \a tokenp is \a token. + * + * \retval 1 The type of \a tokenp is not \a token. + */ +int peekToken(Token ***tokenp, + TokenType token) { Token **tokens = *tokenp; if ((*tokens)->type != token) return 0; return 1; } -/** Checks if the token \b after the one pointed to by \a tokenp matches - * \a token. - * - * \note Unlike acceptToken(Token ***, TokenType), this function does not - * modify \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the same token as when the function was - * called. - * - * \retval 0 The next token does not match \a token. - * \retval 1 The next token matches \a token. - * - * \see acceptToken(Token ***, TokenType) - * \see peekToken(Token ***, TokenType) */ -int nextToken(Token ***tokenp, /**< [in] A pointer to the position of the next token to parse in an array of Token structures. */ - TokenType token) /**< [in] The type of token to match. */ +/** + * Checks if a type of token is after a position in a token list. + * + * \param [in] tokenp The position in a token list to check after. + * + * \param [in] token The type of token to check for. + * + * \post \a tokenp will remain unchanged. + * + * \retval 0 The type of the token after \a tokenp is \a token. + * + * \retval 1 The type of the token after \a tokenp is not \a token. + */ +int nextToken(Token ***tokenp, + TokenType token) { Token **tokens = *tokenp; if ((*(tokens + 1))->type != token) return 0; return 1; } -/** Prints an error message of the form "LINE: INFO before: NEXT.\n", where LINE - * is the line the next token appears on, INFO is \a info and NEXT is the image - * of the next token. - * - * \pre \a tokens was created by tokenizeLexemes(LexemeList *). */ -void error(const char *info, /**< [in] The array of characters to print. */ - Token **tokens) /**< [in] A pointer to an array of tokens to parse. */ +/** + * Prints an error message of the form "FILE:LINE: INFO before: NEXT.\n", where + * LINE is the line the head of \a tokens appears on, INFO is \a info, and NEXT + * is the image of the head of \a tokens. + * + * \param [in] info The information to print. + * + * \param [in] tokens The tokens being parsed when the error occurred. + */ +void error(const char *info, + Token **tokens) { - fprintf(stderr, "%s:%u: %s at: %s\n", (*tokens)->fname, (*tokens)->line, info, (*tokens)->image); + fprintf(stderr, "%s:%u: %s at: %s\n", + (*tokens)->fname, + (*tokens)->line, + info, + (*tokens)->image); } -/** Parses a set of tokens into a ConstantNode structure. Parsing begins at the - * token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated ConstantNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseTypeNode(Token ***) - * \see parseIdentifierNode(Token ***) - * \see parseExprNode(Token ***) - * \see parseStmtNode(Token ***) - * \see parseBlockNode(Token ***) - * \see parseMainNode(Token **) */ +/** + * Parses tokens into a constant. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a constant. + * + * \retval NULL Unable to parse. + */ ConstantNode *parseConstantNode(Token ***tokenp) { ConstantNode *ret = NULL; @@ -1520,25 +1500,18 @@ parseConstantNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into a TypeNode structure. Parsing begins at the - * token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated ExprNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseConstantNode(Token ***) - * \see parseIdentifierNode(Token ***) - * \see parseExprNode(Token ***) - * \see parseStmtNode(Token ***) - * \see parseBlockNode(Token ***) - * \see parseMainNode(Token **) */ -TypeNode *parseTypeNode(Token ***tokenp) /**< [in,out] A pointer to the position of the next token to parse. */ +/** + * Parses tokens into a type. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a type. + * + * \retval NULL Unable to parse. + */ +TypeNode *parseTypeNode(Token ***tokenp) { TypeNode *ret = NULL; @@ -1589,6 +1562,14 @@ TypeNode *parseTypeNode(Token ***tokenp) /**< [in,out] A pointer to the position ret = createTypeNode(CT_STRING); if (!ret) goto parseTypeNodeAbort; } + /* Associative array */ + else if (acceptToken(&tokens, TT_BUKKIT)) { +#ifdef DEBUG + debug("CT_ARRAY"); +#endif + ret = createTypeNode(CT_ARRAY); + if (!ret) goto parseTypeNodeAbort; + } else { error("expected type", tokens); } @@ -1610,26 +1591,25 @@ parseTypeNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into an IdentifierNode structure. Parsing begins at - * the token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated ExprNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseConstantNode(Token ***) - * \see parseTypeNode(Token ***) - * \see parseExprNode(Token ***) - * \see parseStmtNode(Token ***) - * \see parseBlockNode(Token ***) - * \see parseMainNode(Token **) */ -IdentifierNode *parseIdentifierNode(Token ***tokenp) /**< [in,out] A pointer to the position of the next token to parse. */ +/** + * Parses tokens into an identifier. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to an identifier. + * + * \retval NULL Unable to parse. + */ +IdentifierNode *parseIdentifierNode(Token ***tokenp) { + IdentifierType type; + void *data = NULL; + IdentifierNode *slot = NULL; + const char *fname = NULL; + unsigned int line; + /* For direct identifier */ char *temp = NULL; @@ -1646,8 +1626,12 @@ IdentifierNode *parseIdentifierNode(Token ***tokenp) /**< [in,out] A pointer to shiftout(); #endif + fname = (*tokens)->fname; + line = (*tokens)->line; + /* Direct identifier */ if (peekToken(&tokens, TT_IDENTIFIER)) { + type = IT_DIRECT; #ifdef DEBUG debug("IT_DIRECT"); #endif @@ -1655,10 +1639,7 @@ IdentifierNode *parseIdentifierNode(Token ***tokenp) /**< [in,out] A pointer to temp = malloc(sizeof(char) * (strlen((*tokens)->image) + 1)); if (!temp) goto parseIdentifierNodeAbort; strcpy(temp, (*tokens)->image); - - /* Create the new IdentifierNode structure */ - ret = createIdentifierNode(IT_DIRECT, temp, (*tokens)->fname, (*tokens)->line); - if (!ret) goto parseIdentifierNodeAbort; + data = temp; /* This should succeed; it was checked for above */ status = acceptToken(&tokens, TT_IDENTIFIER); @@ -1668,25 +1649,33 @@ IdentifierNode *parseIdentifierNode(Token ***tokenp) /**< [in,out] A pointer to } } else if (acceptToken(&tokens, TT_SRS)) { + type = IT_INDIRECT; #ifdef DEBUG debug("IT_INDIRECT"); #endif /* Parse the expression representing the identifier */ expr = parseExprNode(&tokens); if (!expr) goto parseIdentifierNodeAbort; - - /* Create the new IdentifierNode structure */ - ret = createIdentifierNode(IT_INDIRECT, expr, (*tokens)->fname, (*tokens)->line); - if (!ret) goto parseIdentifierNodeAbort; + data = expr; } else { error("expected identifier", tokens); } + /* Check if there is a slot access */ + if (acceptToken(&tokens, TT_APOSTROPHEZ)) { + slot = parseIdentifierNode(&tokens); + if (!slot) goto parseIdentifierNodeAbort; + } + #ifdef DEBUG shiftin(); #endif + /* Create the new IdentifierNode structure */ + ret = createIdentifierNode(type, data, slot, fname, line); + if (!ret) goto parseIdentifierNodeAbort; + /* Since we're successful, update the token stream */ *tokenp = tokens; @@ -1702,27 +1691,24 @@ parseIdentifierNodeAbort: /* Exception handling */ /* For direct identifier */ if (temp) free(temp); + + if (slot) deleteIdentifierNode(slot); } return NULL; } -/** Parses a set of tokens into an ExprNode structure containing a CastExprNode - * structure. Parsing begins at the token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated ExprNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseConstantExprNode(Token ***) - * \see parseIdentifierExprNode(Token ***) - * \see parseFuncCallExprNode(Token ***) - * \see parseOpExprNode(Token ***) */ +/** + * Parses tokens into a cast expression. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a cast expression. + * + * \retval NULL Unable to parse. + */ ExprNode *parseCastExprNode(Token ***tokenp) { ExprNode *target = NULL; @@ -1782,22 +1768,17 @@ parseCastExprNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into an ExprNode structure containing a ConstantExprNode - * structure. Parsing begins at the token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated ExprNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastExprNode(Token ***) - * \see parseIdentifierExprNode(Token ***) - * \see parseFuncCallExprNode(Token ***) - * \see parseOpExprNode(Token ***) */ +/** + * Parses tokens into a constant expression. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a constant expression. + * + * \retval NULL Unable to parse. + */ ExprNode *parseConstantExprNode(Token ***tokenp) { ConstantNode *node = NULL; @@ -1834,23 +1815,17 @@ parseConstantExprNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into an ExprNode structure containing an - * IdentifierExprNode structure. Parsing begins at the token pointed to by - * \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated ExprNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastExprNode(Token ***) - * \see parseConstantExprNode(Token ***) - * \see parseFuncCallExprNode(Token ***) - * \see parseOpExprNode(Token ***) */ +/** + * Parses tokens into an identifier expression. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to an identifier expression. + * + * \retval NULL Unable to parse. + */ ExprNode *parseIdentifierExprNode(Token ***tokenp) { IdentifierNode *node = NULL; @@ -1887,23 +1862,17 @@ parseIdentifierExprNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into an ExprNode structure containing a - * FuncCallExprNode structure. Parsing begins at the token pointed to by - * \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated ExprNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastExprNode(Token ***) - * \see parseConstantExprNode(Token ***) - * \see parseIdentifierExprNode(Token ***) - * \see parseOpExprNode(Token ***) */ +/** + * Parses tokens into a function call expression. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a Tokenp will point to the next unparsed token. + * + * \return A pointer to a function call expression. + * + * \retval NULL Unable to parse. + */ ExprNode *parseFuncCallExprNode(Token ***tokenp) { IdentifierNode *scope = NULL; @@ -1999,23 +1968,17 @@ parseFuncCallExprNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into an ExprNode structure containing an OpExprNode - * structure. Parsing begins at the token pointed to by - * \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated ExprNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastExprNode(Token ***) - * \see parseConstantExprNode(Token ***) - * \see parseFuncCallExprNode(Token ***) - * \see parseOpExprNode(Token ***) */ +/** + * Parses tokens into an operation expression. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a operation expression. + * + * \retval NULL Unable to parse. + */ ExprNode *parseOpExprNode(Token ***tokenp) { enum ArityType { @@ -2237,25 +2200,18 @@ parseOpExprNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into an ExprNode structure. Parsing begins at the - * token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated ExprNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseConstantNode(Token ***) - * \see parseTypeNode(Token ***) - * \see parseIdentifierNode(Token ***) - * \see parseStmtNode(Token ***) - * \see parseBlockNode(Token ***) - * \see parseMainNode(Token **) */ -ExprNode *parseExprNode(Token ***tokenp) /**< [in,out] A pointer to the position of the next token to parse. */ +/** + * Parses tokens into an expression. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to an expression. + * + * \retval NULL Unable to parse. + */ +ExprNode *parseExprNode(Token ***tokenp) { Token **tokens = *tokenp; ExprNode *ret = NULL; @@ -2264,8 +2220,32 @@ ExprNode *parseExprNode(Token ***tokenp) /**< [in,out] A pointer to the position shiftout(); #endif + /* Parse context-sensitive expressions */ + if (peekToken(&tokens, TT_IDENTIFIER) + || peekToken(&tokens, TT_SRS)) { + IdentifierNode *id = NULL; + + /* Remove the identifier from the token stream */ + /** \todo This works, but it also prints out the debug + * information as if it was parsed which can be confusing + * to see. Fix it to not print this out. */ + id = parseIdentifierNode(&tokens); + if (!id) return NULL; + + /* We do not need to hold onto it */ + deleteIdentifierNode(id); + + /* Function call (must come before identifier) */ + if (peekToken(&tokens, TT_IZ)) { + ret = parseFuncCallExprNode(tokenp); + } + /* Identifier */ + else { + ret = parseIdentifierExprNode(tokenp); + } + } /* Cast */ - if (peekToken(&tokens, TT_MAEK)) { + else if (peekToken(&tokens, TT_MAEK)) { ret = parseCastExprNode(tokenp); } /* Constant value */ @@ -2274,15 +2254,6 @@ ExprNode *parseExprNode(Token ***tokenp) /**< [in,out] A pointer to the position || peekToken(&tokens, TT_FLOAT) || peekToken(&tokens, TT_STRING)) ret = parseConstantExprNode(tokenp); - /* Function call (must come before identifier) */ - else if (nextToken(&tokens, TT_IZ)) { - ret = parseFuncCallExprNode(tokenp); - } - /* Identifier */ - else if (peekToken(&tokens, TT_IDENTIFIER) - || peekToken(&tokens, TT_SRS)) { - ret = parseIdentifierExprNode(tokenp); - } /* Operation */ else if (peekToken(&tokens, TT_SUMOF) || peekToken(&tokens, TT_DIFFOF) @@ -2326,29 +2297,17 @@ ExprNode *parseExprNode(Token ***tokenp) /**< [in,out] A pointer to the position return ret; } -/** Parses a set of tokens into a StmtNode structure containing a CastStmtNode - * structure. Parsing begins at the token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated StmtNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parsePrintStmtNode(Token ***) - * \see parseInputStmtNode(Token ***) - * \see parseAssignmentStmtNode(Token ***) - * \see parseDeclarationStmtNode(Token ***) - * \see parseIfThenElseStmtNode(Token ***) - * \see parseSwitchStmtNode(Token ***) - * \see parseBreakStmtNode(Token ***) - * \see parseReturnStmtNode(Token ***) - * \see parseLoopStmtNode(Token ***) - * \see parseDeallocationStmtNode(Token ***) - * \see parseFuncDefStmtNode(Token ***) */ +/** + * Parses tokens into a cast statement. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a cast statement. + * + * \retval NULL Unable to parse. + */ StmtNode *parseCastStmtNode(Token ***tokenp) { IdentifierNode *target = NULL; @@ -2412,29 +2371,17 @@ parseCastStmtNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into a StmtNode structure containing a PrintStmtNode - * structure. Parsing begins at the token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated StmtNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastStmtNode(Token ***) - * \see parseInputStmtNode(Token ***) - * \see parseAssignmentStmtNode(Token ***) - * \see parseDeclarationStmtNode(Token ***) - * \see parseIfThenElseStmtNode(Token ***) - * \see parseSwitchStmtNode(Token ***) - * \see parseBreakStmtNode(Token ***) - * \see parseReturnStmtNode(Token ***) - * \see parseLoopStmtNode(Token ***) - * \see parseDeallocationStmtNode(Token ***) - * \see parseFuncDefStmtNode(Token ***) */ +/** + * Parses tokens into a print statement. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a print statement. + * + * \retval NULL Unable to parse. + */ StmtNode *parsePrintStmtNode(Token ***tokenp) { ExprNode *arg = NULL; @@ -2512,29 +2459,17 @@ parsePrintStmtNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into a StmtNode structure containing an InputStmtNode - * structure. Parsing begins at the token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated StmtNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastStmtNode(Token ***) - * \see parsePrintStmtNode(Token ***) - * \see parseAssignmentStmtNode(Token ***) - * \see parseDeclarationStmtNode(Token ***) - * \see parseIfThenElseStmtNode(Token ***) - * \see parseSwitchStmtNode(Token ***) - * \see parseBreakStmtNode(Token ***) - * \see parseReturnStmtNode(Token ***) - * \see parseLoopStmtNode(Token ***) - * \see parseDeallocationStmtNode(Token ***) - * \see parseFuncDefStmtNode(Token ***) */ +/** + * Parses tokens into an input statement. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to an input statement. + * + * \retval NULL Unable to parse. + */ StmtNode *parseInputStmtNode(Token ***tokenp) { IdentifierNode *target = NULL; @@ -2592,30 +2527,17 @@ parseInputStmtNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into a StmtNode structure containing an - * AssignmentStmtNode structure. Parsing begins at the token pointed to by - * \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated StmtNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastStmtNode(Token ***) - * \see parsePrintStmtNode(Token ***) - * \see parseInputStmtNode(Token ***) - * \see parseDeclarationStmtNode(Token ***) - * \see parseIfThenElseStmtNode(Token ***) - * \see parseSwitchStmtNode(Token ***) - * \see parseBreakStmtNode(Token ***) - * \see parseReturnStmtNode(Token ***) - * \see parseLoopStmtNode(Token ***) - * \see parseDeallocationStmtNode(Token ***) - * \see parseFuncDefStmtNode(Token ***) */ +/** + * Parses tokens into an assignment statement. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to an assignment statement. + * + * \retval NULL unable to parse. + */ StmtNode *parseAssignmentStmtNode(Token ***tokenp) { IdentifierNode *target = NULL; @@ -2678,30 +2600,17 @@ parseAssignmentStmtNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into a StmtNode structure containing a - * DeclarationStmtNode structure. Parsing begins at the token pointed to by - * \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated StmtNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastStmtNode(Token ***) - * \see parsePrintStmtNode(Token ***) - * \see parseInputStmtNode(Token ***) - * \see parseAssignmentStmtNode(Token ***) - * \see parseIfThenElseStmtNode(Token ***) - * \see parseSwitchStmtNode(Token ***) - * \see parseBreakStmtNode(Token ***) - * \see parseReturnStmtNode(Token ***) - * \see parseLoopStmtNode(Token ***) - * \see parseDeallocationStmtNode(Token ***) - * \see parseFuncDefStmtNode(Token ***) */ +/** + * Parses tokens into a declaration statement. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a declaration statement. + * + * \retval NULL Unable to parse. + */ StmtNode *parseDeclarationStmtNode(Token ***tokenp) { IdentifierNode *scope = NULL; @@ -2781,30 +2690,17 @@ parseDeclarationStmtNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into a StmtNode structure containing an - * IfThenElseStmtNode structure. Parsing begins at the token pointed to by - * \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated StmtNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastStmtNode(Token ***) - * \see parsePrintStmtNode(Token ***) - * \see parseInputStmtNode(Token ***) - * \see parseAssignmentStmtNode(Token ***) - * \see parseDeclarationStmtNode(Token ***) - * \see parseSwitchStmtNode(Token ***) - * \see parseBreakStmtNode(Token ***) - * \see parseReturnStmtNode(Token ***) - * \see parseLoopStmtNode(Token ***) - * \see parseDeallocationStmtNode(Token ***) - * \see parseFuncDefStmtNode(Token ***) */ +/** + * Parses tokens into an if/then/else statement. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to an if/then/else statement. + * + * \retval NULL Unable to parse. + */ StmtNode *parseIfThenElseStmtNode(Token ***tokenp) { BlockNode *yes = NULL; @@ -2947,29 +2843,17 @@ parseIfThenElseStmtNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into a StmtNode structure containing a SwitchStmtNode - * structure. Parsing begins at the token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated StmtNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastStmtNode(Token ***) - * \see parsePrintStmtNode(Token ***) - * \see parseInputStmtNode(Token ***) - * \see parseAssignmentStmtNode(Token ***) - * \see parseDeclarationStmtNode(Token ***) - * \see parseIfThenElseStmtNode(Token ***) - * \see parseBreakStmtNode(Token ***) - * \see parseReturnStmtNode(Token ***) - * \see parseLoopStmtNode(Token ***) - * \see parseDeallocationStmtNode(Token ***) - * \see parseFuncDefStmtNode(Token ***) */ +/** + * Parses tokens into a switch statement. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a switch statement. + * + * \retval NULL Unable to parse. + */ StmtNode *parseSwitchStmtNode(Token ***tokenp) { ExprNodeList *guards = NULL; @@ -3133,30 +3017,17 @@ parseSwitchStmtNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into a StmtNode structure representing a break - * statement. Parsing begins at the token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated StmtNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastStmtNode(Token ***) - * \see parsePrintStmtNode(Token ***) - * \see parseInputStmtNode(Token ***) - * \see parseAssignmentStmtNode(Token ***) - * \see parseDeclarationStmtNode(Token ***) - * \see parseIfThenElseStmtNode(Token ***) - * \see parseSwitchStmtNode(Token ***) - * \see parseReturnStmtNode(Token ***) - * \see parseLoopStmtNode(Token ***) - * \see parseDeallocationStmtNode(Token ***) - * \see parseFuncDefStmtNode(Token ***) - * \see parseExprNode(Token ***) */ +/** + * Parses tokens into a break statement. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a break statement. + * + * \retval NULL Unable to parse. + */ StmtNode *parseBreakStmtNode(Token ***tokenp) { StmtNode *ret = NULL; @@ -3199,29 +3070,17 @@ parseBreakStmtNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into a StmtNode structure containing a ReturnStmtNode - * structure. Parsing begins at the token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated StmtNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastStmtNode(Token ***) - * \see parsePrintStmtNode(Token ***) - * \see parseInputStmtNode(Token ***) - * \see parseAssignmentStmtNode(Token ***) - * \see parseDeclarationStmtNode(Token ***) - * \see parseIfThenElseStmtNode(Token ***) - * \see parseSwitchStmtNode(Token ***) - * \see parseBreakStmtNode(Token ***) - * \see parseLoopStmtNode(Token ***) - * \see parseDeallocationStmtNode(Token ***) - * \see parseFuncDefStmtNode(Token ***) */ +/** + * Parses tokens into a return statement. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a return statement. + * + * \retval NULL Unable to parse. + */ StmtNode *parseReturnStmtNode(Token ***tokenp) { ExprNode *value = NULL; @@ -3278,29 +3137,17 @@ parseReturnStmtNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into a StmtNode structure containing a LoopStmtNode - * structure. Parsing begins at the token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated StmtNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastStmtNode(Token ***) - * \see parsePrintStmtNode(Token ***) - * \see parseInputStmtNode(Token ***) - * \see parseAssignmentStmtNode(Token ***) - * \see parseDeclarationStmtNode(Token ***) - * \see parseIfThenElseStmtNode(Token ***) - * \see parseSwitchStmtNode(Token ***) - * \see parseBreakStmtNode(Token ***) - * \see parseReturnStmtNode(Token ***) - * \see parseDeallocationStmtNode(Token ***) - * \see parseFuncDefStmtNode(Token ***) */ +/** + * Parses tokens into a loop statement. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a loop statement. + * + * \retval NULL Unable to parse. + */ StmtNode *parseLoopStmtNode(Token ***tokenp) { IdentifierNode *name1 = NULL; @@ -3400,7 +3247,7 @@ StmtNode *parseLoopStmtNode(Token ***tokenp) id = malloc(sizeof(char) * (strlen(var->id) + 1)); if (!id) goto parseLoopStmtNodeAbort; strcpy(id, var->id); - varcopy = createIdentifierNode(IT_DIRECT, id, var->fname, var->line); + varcopy = createIdentifierNode(IT_DIRECT, id, NULL, var->fname, var->line); if (!varcopy) goto parseLoopStmtNodeAbort; id = NULL; @@ -3489,7 +3336,7 @@ StmtNode *parseLoopStmtNode(Token ***tokenp) id = malloc(sizeof(char) * (strlen(temp->id) + 1)); if (!id) goto parseLoopStmtNodeAbort; strcpy(id, temp->id); - var = createIdentifierNode(IT_DIRECT, id, temp->fname, temp->line); + var = createIdentifierNode(IT_DIRECT, id, NULL, temp->fname, temp->line); if (!var) goto parseLoopStmtNodeAbort; id = NULL; @@ -3609,6 +3456,7 @@ parseLoopStmtNodeAbort: /* Exception handling */ if (ret) deleteStmtNode(ret); else if (stmt) deleteLoopStmtNode(stmt); else { + /** \todo Need to adjust this to properly clean up nested objects. */ if (name2) deleteIdentifierNode(name2); if (def) deleteFuncDefStmtNode(def); if (body) deleteBlockNode(body); @@ -3640,30 +3488,17 @@ parseLoopStmtNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into a StmtNode structure containing a - * DeallocationStmtNode structure. Parsing begins at the token pointed to by - * \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated StmtNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastStmtNode(Token ***) - * \see parsePrintStmtNode(Token ***) - * \see parseInputStmtNode(Token ***) - * \see parseAssignmentStmtNode(Token ***) - * \see parseDeclarationStmtNode(Token ***) - * \see parseIfThenElseStmtNode(Token ***) - * \see parseSwitchStmtNode(Token ***) - * \see parseBreakStmtNode(Token ***) - * \see parseReturnStmtNode(Token ***) - * \see parseLoopStmtNode(Token ***) - * \see parseFuncDefStmtNode(Token ***) */ +/** + * Parses tokens into a deallocation statement. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a deallocation statement. + * + * \retval NULL Unable to parse. + */ StmtNode *parseDeallocationStmtNode(Token ***tokenp) { IdentifierNode *target = NULL; @@ -3721,30 +3556,17 @@ parseDeallocationStmtNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into a StmtNode structure containing a - * FuncDefStmtNode structure. Parsing begins at the token pointed to by - * \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated StmtNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseCastStmtNode(Token ***) - * \see parsePrintStmtNode(Token ***) - * \see parseInputStmtNode(Token ***) - * \see parseAssignmentStmtNode(Token ***) - * \see parseDeclarationStmtNode(Token ***) - * \see parseIfThenElseStmtNode(Token ***) - * \see parseSwitchStmtNode(Token ***) - * \see parseBreakStmtNode(Token ***) - * \see parseReturnStmtNode(Token ***) - * \see parseLoopStmtNode(Token ***) - * \see parseDeallocationStmtNode(Token ***) */ +/** + * Parses tokens into a function definition statement. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a function definition statement. + * + * \retval NULL Unable to parse. + */ StmtNode *parseFuncDefStmtNode(Token ***tokenp) { IdentifierNode *scope = NULL; @@ -3860,25 +3682,18 @@ parseFuncDefStmtNodeAbort: /* Exception handling */ return NULL; } -/** Parses a set of tokens into a StmtNode structure. Parsing begins at the - * token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated StmtNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseConstantNode(Token ***) - * \see parseTypeNode(Token ***) - * \see parseIdentifierNode(Token ***) - * \see parseExprNode(Token ***) - * \see parseBlockNode(Token ***) - * \see parseMainNode(Token **) */ -StmtNode *parseStmtNode(Token ***tokenp) /**< [in,out] A pointer to the position of the next token to parse. */ +/** + * Parses tokens into a statement. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a statement. + * + * \retval NULL Unable to parse. + */ +StmtNode *parseStmtNode(Token ***tokenp) { StmtNode *ret = NULL; ExprNode *expr = NULL; @@ -3896,6 +3711,9 @@ StmtNode *parseStmtNode(Token ***tokenp) /**< [in,out] A pointer to the position IdentifierNode *id = NULL; /* Remove the identifier from the token stream */ + /** \todo This works, but it also prints out the debug + * information as if it was parsed which can be confusing + * to see. Fix it to not print this out. */ id = parseIdentifierNode(&tokens); if (!id) return NULL; @@ -3923,14 +3741,14 @@ StmtNode *parseStmtNode(Token ***tokenp) /**< [in,out] A pointer to the position /* Reset state and continue parsing */ tokens = *tokenp; - /* Parse the expression */ - expr = parseExprNode(&tokens); - if (!expr) return NULL; - #ifdef DEBUG debug("ST_EXPR"); #endif + /* Parse the expression */ + expr = parseExprNode(&tokens); + if (!expr) return NULL; + /* The expression should appear on its own line */ if (!acceptToken(&tokens, TT_NEWLINE)) { error("expected end of expression", tokens); @@ -4018,25 +3836,18 @@ StmtNode *parseStmtNode(Token ***tokenp) /**< [in,out] A pointer to the position return ret; } -/** Parses a set of tokens into a BlockNode structure. Parsing begins at the - * token pointed to by \a tokenp. - * - * \pre \a tokenp points to a position in an array of tokens created by - * tokenizeLexemes(LexemeList *). - * - * \post \a tokenp will point to the next \b unparsed token in the array. - * - * \return A pointer to the generated BlockNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseConstantNode(Token ***) - * \see parseTypeNode(Token ***) - * \see parseIdentifierNode(Token ***) - * \see parseExprNode(Token ***) - * \see parseStmtNode(Token ***) - * \see parseMainNode(Token **) */ -BlockNode *parseBlockNode(Token ***tokenp) /**< [in,out] A pointer to the position of the next token to parse. */ +/** + * Parses tokens into a code block. + * + * \param [in] tokenp The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a code block. + * + * \retval NULL Unable to parse. + */ +BlockNode *parseBlockNode(Token ***tokenp) { StmtNodeList *stmts = NULL; StmtNode *stmt = NULL; @@ -4099,23 +3910,18 @@ parseBlockNodeAbort: /* Exception handling */ return NULL; } -/** Parses \a tokens into a MainNode structure, an intermediary form to be - * passed along to a later stage of processing such as, for example, an - * interpreter. - * - * \pre \a tokens was created by tokenizeLexemes(LexemeList *). - * - * \return A pointer to the generated MainNode structure. - * - * \retval NULL An error occurred during parsing. - * - * \see parseConstantNode(Token ***) - * \see parseTypeNode(Token ***) - * \see parseIdentifierNode(Token ***) - * \see parseExprNode(Token ***) - * \see parseStmtNode(Token ***) - * \see parseBlockNode(Token ***) */ -MainNode *parseMainNode(Token **tokens) /**< [in] A pointer to an array of tokens to parse. */ +/** + * Parses tokens into a main code block. + * + * \param [in] tokens The position in a token list to start parsing at. + * + * \post \a tokenp will point to the next unparsed token. + * + * \return A pointer to a main node block. + * + * \retval NULL Unable to parse. + */ +MainNode *parseMainNode(Token **tokens) { BlockNode *block = NULL; MainNode *_main = NULL; diff --git a/parser.h b/parser.h index 6c17620..6d9e1da 100644 --- a/parser.h +++ b/parser.h @@ -1,172 +1,194 @@ -/** Structures and functions for parsing tokens into a parse tree. The parser - * reads through a series of tokens (generated by the tokenizer) and adds - * semantic meaning to them by forming them into a parse tree which can, in - * turn, be passed on to later processes (such as an interpreter). - * - * \file parser.h - * - * \author Justin J. Meza - * - * \date 2010 */ +/** + * Structures and functions for parsing tokens to a parse tree. The parser + * reads through a list of tokens (generated by the tokenizer) and adds semantic + * meaning to them by forming them into a parse tree which can then be passed on + * to later stages (such as the interpreter). + * + * \file parser.h + * + * \author Justin J. Meza + * + * \date 2010-2011 + */ -/** \page impvar The Implicit Variable - * - * The implicit variable in LOLCODE is denoted by the keyword \c IT and stores - * a copy of the result of the most recently evaluated expression statement, - * that is, an expression all by itself on a line. (See - * http://lolcode.com/specs/1.2#conditionals for an example.) */ +/** + * \page impvar The Implicit Variable + * + * The implicit variable in LOLCODE is denoted by the keyword \c IT and stores a + * copy of the result of the most recently evaluated expression statement (an + * expression all by itself on a line). (See + * http://lolcode.com/specs/1.2#conditionals for an example.) + */ -/** \page lolebnf The LOLCODE EBNF - * Presented below is the EBNF (see http://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_Form) - * for LOLCODE that \c lci parses. Note that by this stage, the scanner has: - * - already removed any whitespace between tokens, - * - added in and truncated newline tokens at logical line breaks, and - * - added an end-of-file (\c $) token. - * - * \section progebnf Program Structure - * - * These production rules dictate the overall form of the program. - * - * \par - * MainNode ::= \c TT_HAI \a version \c TT_NEWLINE BlockNode \c $ - * - * \par - * BlockNode ::= StmtNode * - * - * \section typesebnf Types - * - * These production rules specify some general types of parse structures. - * - * \par - * ConstantNode ::= Boolean | Integer | Float | String - * - * \par - * IdentifierNode ::= Identifier | \c TT_SRS ExprNode - * - * \par - * TypeNode ::= \c TT_NOOB | \c TT_TROOF | \c TT_NUMBR | \c TT_NUMBAR | \c TT_YARN - * - * \section stmtebnf Statements - * - * These production rules specify the types of statements formed. - * - * \par - * StmtNode ::= CastStmtNode | PrintStmtNode | InputStmtNode | AssignmentStmtNode | DeclarationStmtNode | IfThenElseStmtNode | SwitchStmtNode | BreakStmt | ReturnStmtNode | LoopStmtNode | DeallocationStmtNode | FuncDefStmtNode | ExprStmt - * - * \par - * CastStmtNode ::= IdentifierNode \c TT_ISNOWA TypeNode \c TT_NEWLINE - * - * \par - * PrintStmtNode ::= \c TT_VISIBLE ExprNodeList \c TT_BANG ? TT_NEWLINE - * - * \par - * InputStmtNode ::= \c TT_GIMMEH IdentifierNode TT_NEWLINE - * - * \par - * AssignmentStmtNode ::= IdentifierNode \c TT_R ExprNode \c TT_NEWLINE - * - * \par - * DeclarationStmtNode ::= IdentifierNode \c TT_HASA IdentifierNode Initialization ? \c TT_NEWLINE - * - * \par - * Initialization ::= \c TT_ITZ ExprNode | \c TT_ITZA TypeNode - * - * \par - * IfThenElseStmtNode ::= \c TT_ORLY \c TT_NEWLINE \c TT_YARLY \c TT_NEWLINE BlockNode ElseIf * Else ? \c TT_OIC \c TT_NEWLINE - * - * \par - * ElseIf ::= \c TT_MEBBE ExprNode \c TT_NEWLINE BlockNode - * - * \par - * Else ::= \c TT_NOWAI \c TT_NEWLINE BlockNode - * - * \par - * SwitchStmtNode ::= \c TT_WTF \c TT_NEWLINE Case + DefaultCase ? \c TT_OIC \c TT_NEWLINE - * - * \par - * Case ::= \c TT_OMG ExprNode \c TT_NEWLINE BlockNode - * - * \par - * DefaultCase ::= \c TT_OMGWTF \c TT_NEWLINE BlockNode - * - * \par - * BreakStmt ::= \c TT_GTFO \c TT_NEWLINE - * - * \par - * ReturnStmtNode ::= \c TT_FOUNDYR ExprNode \c TT_NEWLINE - * - * \par - * LoopStmtNode ::= \c TT_IMINYR IdentifierNode LoopUpdate ? LoopGuard ? \c TT_NEWLINE BlockNode \c TT_IMOUTTAYR IdentifierNode \c TT_NEWLINE - * - * \par - * LoopUpdate ::= LoopUpdateOp \c TT_YR IdentifierNode - * - * \par - * LoopUpdateOp ::= \c TT_UPPIN | \c TT_NERFIN | UnaryFunction - * - * \par - * UnaryFunction ::= The name of a previously defined unary function. - * - * \par - * LoopGuard ::= \c TT_TIL ExprNode | \c TT_WILE ExprNode - * - * \par - * DeallocationStmtNode ::= IdentifierNode \c TT_RNOOB - * - * \par - * FuncDefStmtNode ::= \c TT_HOWIZ IdentifierNode IdentifierNode FunctionArgs ? \c TT_NEWLINE BlockNode \c TT_IFUSAYSO \c TT_NEWLINE - * - * \par - * FunctionArgs ::= \c TT_YR IdentifierNode FunctionArg * - * - * \par - * FunctionArg ::= \c TT_ANYR IdentifierNode - * - * \par - * ExprStmt ::= ExprNode \c TT_NEWLINE - * - * \section exprebnf Expressions - * - * These production rules specify the types of expressions formed. - * - * \par - * ExprNode ::= CastExprNode | ConstantNode | IdentifierNode | FuncCallExprNode | OpExprNode | ImplicitVariable - * - * \par - * CastExprNode ::= \c TT_MAEK ExprNode \c TT_A TypeNode - * - * \par - * FuncCallExprNode ::= IdentifierNode \c TT_IZ IdentifierNode FunctionArgs ? TT_MKAY - * - * \par - * OpExprNode ::= UnaryOp | BinaryOp | NaryOp - * - * \par - * UnaryOp ::= UnaryOpType ExprNode - * - * \par - * UnaryOpType ::= \c TT_NOT - * - * \par - * BinaryOp ::= BinaryOpType ExprNode \c TT_AN ? ExprNode - * - * \par - * BinaryOpType ::= \c TT_SUMOF | \c TT_DIFFOF | \c TT_PRODUKTOF | \c TT_QUOSHUNTOF | \c TT_MODOF | \c BIGGROF | \c SMALLROF | \c TT_BOTHOF | \c TT_EITHEROF | \c TT_WONOF - * - * \par - * NaryOp ::= NaryOpType NaryOpArgs \c TT_MKAY - * - * \par - * NaryOpType ::= \c TT_ALLOF | \c TT_ANYOF | \c TT_SMOOSH - * - * \par - * NaryOpArgs ::= ExprNode NaryOpArg + - * - * \par - * NaryOpArg ::= \c TT_AN ? ExprNode - * - * \par - * ImplicitVariable ::= \c TT_IT */ +/** + * \page lolebnf The LOLCODE EBNF + * + * Presented below is the EBNF (see + * http://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_Form) for the + * LOLCODE language that \c lci parses. Note that by this stage, the scanner + * has: + * - already removed any whitespace between tokens, + * - added in and truncated newline tokens at logical line breaks, and + * - added an end-of-file (\c $) token. + * + * \section progebnf Program Structure + * + * These production rules dictate the overall form of the program. + * + * \par + * MainNode ::= \c TT_HAI \a version \c TT_NEWLINE BlockNode \c $ + * + * \par + * BlockNode ::= StmtNode * + * + * \section typesebnf Types + * + * These production rules specify some general types of parse structures. + * + * \par + * ConstantNode ::= Boolean | Integer | Float | String + * + * \par + * IdentifierNode ::= Identifier | \c TT_SRS ExprNode + * + * \par + * TypeNode ::= \c TT_NOOB | \c TT_TROOF | \c TT_NUMBR | \c TT_NUMBAR | \c + * TT_YARN + * + * \section stmtebnf Statements + * + * These production rules specify the types of statements formed. + * + * \par + * StmtNode ::= CastStmtNode | PrintStmtNode | InputStmtNode | + * AssignmentStmtNode | DeclarationStmtNode | IfThenElseStmtNode | + * SwitchStmtNode | BreakStmt | ReturnStmtNode | LoopStmtNode | + * DeallocationStmtNode | FuncDefStmtNode | ExprStmt + * + * \par + * CastStmtNode ::= IdentifierNode \c TT_ISNOWA TypeNode \c TT_NEWLINE + * + * \par + * PrintStmtNode ::= \c TT_VISIBLE ExprNodeList \c TT_BANG ? TT_NEWLINE + * + * \par + * InputStmtNode ::= \c TT_GIMMEH IdentifierNode TT_NEWLINE + * + * \par + * AssignmentStmtNode ::= IdentifierNode \c TT_R ExprNode \c TT_NEWLINE + * + * \par + * DeclarationStmtNode ::= IdentifierNode \c TT_HASA IdentifierNode + * Initialization ? \c TT_NEWLINE + * + * \par + * Initialization ::= \c TT_ITZ ExprNode | \c TT_ITZA TypeNode + * + * \par + * IfThenElseStmtNode ::= \c TT_ORLY \c TT_NEWLINE \c TT_YARLY \c TT_NEWLINE + * BlockNode ElseIf * Else ? \c TT_OIC \c TT_NEWLINE + * + * \par + * ElseIf ::= \c TT_MEBBE ExprNode \c TT_NEWLINE BlockNode + * + * \par + * Else ::= \c TT_NOWAI \c TT_NEWLINE BlockNode + * + * \par + * SwitchStmtNode ::= \c TT_WTF \c TT_NEWLINE Case + DefaultCase ? \c TT_OIC \c + * TT_NEWLINE + * + * \par + * Case ::= \c TT_OMG ExprNode \c TT_NEWLINE BlockNode + * + * \par + * DefaultCase ::= \c TT_OMGWTF \c TT_NEWLINE BlockNode + * + * \par + * BreakStmt ::= \c TT_GTFO \c TT_NEWLINE + * + * \par + * ReturnStmtNode ::= \c TT_FOUNDYR ExprNode \c TT_NEWLINE + * + * \par + * LoopStmtNode ::= \c TT_IMINYR IdentifierNode LoopUpdate ? LoopGuard ? \c + * TT_NEWLINE BlockNode \c TT_IMOUTTAYR IdentifierNode \c TT_NEWLINE + * + * \par + * LoopUpdate ::= LoopUpdateOp \c TT_YR IdentifierNode + * + * \par + * LoopUpdateOp ::= \c TT_UPPIN | \c TT_NERFIN | UnaryFunction + * + * \par + * UnaryFunction ::= The name of a previously defined unary function. + * + * \par + * LoopGuard ::= \c TT_TIL ExprNode | \c TT_WILE ExprNode + * + * \par + * DeallocationStmtNode ::= IdentifierNode \c TT_RNOOB + * + * \par + * FuncDefStmtNode ::= \c TT_HOWIZ IdentifierNode IdentifierNode FunctionArgs ? + * \c TT_NEWLINE BlockNode \c TT_IFUSAYSO \c TT_NEWLINE + * + * \par + * FunctionArgs ::= \c TT_YR IdentifierNode FunctionArg * + * + * \par + * FunctionArg ::= \c TT_ANYR IdentifierNode + * + * \par + * ExprStmt ::= ExprNode \c TT_NEWLINE + * + * \section exprebnf Expressions + * + * These production rules specify the types of expressions formed. + * + * \par + * ExprNode ::= CastExprNode | ConstantNode | IdentifierNode | FuncCallExprNode + * | OpExprNode | ImplicitVariable + * + * \par + * CastExprNode ::= \c TT_MAEK ExprNode \c TT_A TypeNode + * + * \par + * FuncCallExprNode ::= IdentifierNode \c TT_IZ IdentifierNode FunctionArgs ? + * TT_MKAY + * + * \par + * OpExprNode ::= UnaryOp | BinaryOp | NaryOp + * + * \par + * UnaryOp ::= UnaryOpType ExprNode + * + * \par + * UnaryOpType ::= \c TT_NOT + * + * \par + * BinaryOp ::= BinaryOpType ExprNode \c TT_AN ? ExprNode + * + * \par + * BinaryOpType ::= \c TT_SUMOF | \c TT_DIFFOF | \c TT_PRODUKTOF | \c + * TT_QUOSHUNTOF | \c TT_MODOF | \c BIGGROF | \c SMALLROF | \c TT_BOTHOF | \c + * TT_EITHEROF | \c TT_WONOF + * + * \par + * NaryOp ::= NaryOpType NaryOpArgs \c TT_MKAY + * + * \par + * NaryOpType ::= \c TT_ALLOF | \c TT_ANYOF | \c TT_SMOOSH + * + * \par + * NaryOpArgs ::= ExprNode NaryOpArg + + * + * \par + * NaryOpArg ::= \c TT_AN ? ExprNode + * + * \par + * ImplicitVariable ::= \c TT_IT + */ #ifndef __PARSER_H__ #define __PARSER_H__ @@ -181,326 +203,292 @@ #undef DEBUG -/** Denotes the type of statement a StmtNode stores. */ +/** + * Represents a statement type. + */ typedef enum { - ST_CAST, /**< A CastStmtNode structure. */ - ST_PRINT, /**< A PrintStmtNode structure. */ - ST_INPUT, /**< An InputStmtNode structure. */ - ST_ASSIGNMENT, /**< An AssignmentStmtNode structure. */ - ST_DECLARATION, /**< A DeclarationStmtNode structure. */ - ST_IFTHENELSE, /**< An IfThenElseStmtNode structure. */ - ST_SWITCH, /**< A SwitchStmtNode structure. */ - ST_BREAK, /**< A break statement (no structure is needed for this type of statement). */ - ST_RETURN, /**< A ReturnStmtNode structure. */ - ST_LOOP, /**< A LoopStmtNode structure. */ - ST_DEALLOCATION, /**< A DeallocationStmtNode structure. */ - ST_FUNCDEF, /**< A FuncDefStmtNode structure. */ - ST_EXPR /**< An ExprNode structure. */ + ST_CAST, /**< Cast statement. */ + ST_PRINT, /**< Print statement. */ + ST_INPUT, /**< Input statement. */ + ST_ASSIGNMENT, /**< Assignment statement. */ + ST_DECLARATION, /**< Declaration statement. */ + ST_IFTHENELSE, /**< If/then/else statement. */ + ST_SWITCH, /**< Switch statement. */ + ST_BREAK, /**< Break statement. */ + ST_RETURN, /**< Return statement. */ + ST_LOOP, /**< Loop statement. */ + ST_DEALLOCATION, /**< Deallocation statement. */ + ST_FUNCDEF, /**< Function definition statement. */ + ST_EXPR /**< Expression statement. */ } StmtType; -/** Stores a statement. A statement is a unit of code which can be executed by - * itself and may possibly cause side-effects to occur. - * - * \see createStmtNode(StmtType, void *) - * \see deleteStmtNode(StmtNode *) */ +/** + * Stores statement data. + */ typedef struct { - StmtType type; /**< The type of statement stored in \a node. */ - void *stmt; /**< A pointer to the particular statement structure. */ + StmtType type; /**< The type of statement in \a node. */ + void *stmt; /**< The statement. */ } StmtNode; -/** Stores a list of statements. This structure allows sets of statements to be - * grouped together. - * - * \see createStmtNodeList(void) - * \see addStmtNode(StmtNodeList *, StmtNode *) - * \see deleteStmtNodeList(StmtNodeList *) */ +/** + * Stores a list of statements. + */ typedef struct { - unsigned int num; /**< The number of StmtNode structures stored. */ - StmtNode **stmts; /**< A pointer to the array of StmtNode structures. */ + unsigned int num; /**< The number of statements. */ + StmtNode **stmts; /**< The array of statements. */ } StmtNodeList; -/** Denotes the type of expression an ExprNode stores. */ +/** + * Represents an expression type. + */ typedef enum { - ET_CAST, /**< A CastExprNode structure. */ - ET_CONSTANT, /**< A ConstantNode structure. */ - ET_IDENTIFIER, /**< An IdentifierNode structure. */ - ET_FUNCCALL, /**< A FuncCallExprNode structure. */ - ET_OP, /**< An OpExprNode structure. */ - ET_IMPVAR /**< An \ref impvar "implicit variable" (no structure is needed for this type of expression). */ + ET_CAST, /**< Cast expression. */ + ET_CONSTANT, /**< Constant expression. */ + ET_IDENTIFIER, /**< Identifier expression. */ + ET_FUNCCALL, /**< Function call expression. */ + ET_OP, /**< Operation expression. */ + ET_IMPVAR /**< \ref impvar "Implicit variable". */ } ExprType; -/** Stores an expression. An expression is a unit of code which evaluates to - * some value and typically does not cause side-effects to occur. - * - * \see createExprNode(ExprType, void *) - * \see deleteExprNode(ExprNode *) */ +/** + * Stores an expression. + */ typedef struct { - ExprType type; /**< The type of expression stored in \a expr. */ - void *expr; /**< A pointer to the particular expression structure. */ + ExprType type; /**< The type of expression in \a expr. */ + void *expr; /**< The expression. */ } ExprNode; -/** Stores a list of expressions. This structure allows sets of expressions to - * be grouped together. - * - * \see createExprNodeList(void) - * \see addExprNode(ExprNodeList *, ExprNode *) - * \see deleteExprNodeList(ExprNodeList *) */ +/** + * Stores a list of expressions. + */ typedef struct { - unsigned int num; /**< The number of ExprNode structures stored. */ - ExprNode **exprs; /**< A pointer to an array of ExprNode structures. */ + unsigned int num; /**< The number of expressions. */ + ExprNode **exprs; /**< The array of statements. */ } ExprNodeList; -/** Denotes the type of identifier an IdentifierNode is. */ +/** + * Represents an identifier type. + */ typedef enum { - IT_DIRECT, /**< A direct IdentifierNode structure. */ - IT_INDIRECT /**< An indirect IdentifierNode structure. */ + IT_DIRECT, /**< Direct identifier. */ + IT_INDIRECT /**< Indirect identifier. */ } IdentifierType; -/** Stores an identifier. An identifier either directly or indirectly names - * particular variable. - * - * \see createIdentifierNode(IdentifierType, void *) - * \see deleteIdentifierNode(IdentifierNode *) */ -typedef struct { - IdentifierType type; /**< The type of identifier stored in \a id. */ - void *id; /**< The identifier data stored. */ - char *fname; /**< A pointer to the name of the file containing the identifier. */ - unsigned int line; /**< The line number from the source file that the identifier occurred on. */ +/** + * Stores an identifier. + */ +typedef struct identifiernode { + IdentifierType type; /**< The type of identifier in \a id. */ + void *id; /**< The identifier. */ + char *fname; /**< The original file name. */ + unsigned int line; /**< The original line number. */ + struct identifiernode *slot; /**< The slot to access. */ } IdentifierNode; -/** Stores a list of identifiers. This structure allows sets of identifiers - * to be grouped together. - * - * \see createIdentifierNodeList(void) - * \see addIdentifierNode(IdentifierNodeList *, IdentifierNode *) - * \see deleteIdentifierNodeList(IdentifierNodeList *) */ +/** + * Stores a list of identifiers. + */ typedef struct { - unsigned int num; /**< The number of IdentifierNode structures stored. */ - IdentifierNode **ids; /**< A pointer to the array of IdentifierNode structures. */ + unsigned int num; /**< The number of identifiers. */ + IdentifierNode **ids; /**< The array of identifiers. */ } IdentifierNodeList; -/** Stores a a block of code. A block of code consists of a set of statements. - * - * \see createBlockNode(StmtNodeList *) - * \see deleteBlockNode(BlockNode *) */ +/** + * Stores a code block. + */ typedef struct { - StmtNodeList *stmts; /**< A pointer to the list of statements which comprise the block of code. */ + StmtNodeList *stmts; /**< The list of statements in the block. */ } BlockNode; -/** Stores a list of blocks of code. This structure allows sets of blocks of - * code to be grouped together. - * - * \see createBlockNodeList(void) - * \see addBlockNode(BlockNodeList *, BlockNode *) - * \see deleteBlockNodeList(BlockNodeList *) */ +/** + * Stores a list of code blocks. + */ typedef struct { - unsigned int num; /**< The number of BlockNode structures stored. */ - BlockNode **blocks; /**< A pointer to an array of BlockNode structures. */ + unsigned int num; /**< The number of code blocks. */ + BlockNode **blocks; /**< The array of code blocks. */ } BlockNodeList; -/** Denotes the type of a constant. */ +/** + * Represents a constant type. + */ typedef enum { - CT_INTEGER, /**< An integer value. */ - CT_FLOAT, /**< A floating point decimal value. */ - CT_BOOLEAN, /**< A true/false value. */ - CT_STRING, /**< A character string value. */ - CT_NIL /**< Represents no value. */ + CT_INTEGER, /**< Integer constant. */ + CT_FLOAT, /**< Decimal constant. */ + CT_BOOLEAN, /**< Boolean constant. */ + CT_STRING, /**< String constant. */ + CT_NIL, /**< Nil constant. */ + CT_ARRAY /**< Array constant. */ } ConstantType; -/** Stores the data associated with a ConstantNode structure. */ +/** + * Stores constant data. + */ typedef union { int i; /**< Integer data. */ - float f; /**< Floating point data. */ - char *s; /**< Character string data. */ + float f; /**< Decimal data. */ + char *s; /**< String data. */ } ConstantData; -/** Stores a constant value. A constant value evaluates to its contents, - * depending on its \a type. - * - * \see createBooleanConstantNode(int) - * \see createIntegerConstantNode(int) - * \see createFloatConstantNode(float) - * \see createStringConstantNode(char *) - * \see deleteConstantNode(ConstantNode *) */ +/** + * Stores a constant. + */ typedef struct { - ConstantType type; /**< The type of the constant. */ - ConstantData data; /**< The stored data of type \a type. */ + ConstantType type; /**< The type of constant in \a data. */ + ConstantData data; /**< The constant. */ } ConstantNode; -/** Stores a function definition statement. A function definition statement - * defines the prototype and contents of a function. - * - * \see createFuncDefStmtNode(IdentifierNode *, IdentifierNode *, IdentifierNodeList *, BlockNode *) - * \see deleteFuncDefStmtNode(FuncDefStmtNode *) */ +/** + * Stores a function definition statement. + */ typedef struct { - IdentifierNode *scope; /**< A pointer to the scope to define the function in. */ - IdentifierNode *name; /**< A pointer to the name of the function. */ - IdentifierNodeList *args; /**< A pointer to a list of the names of the arguments of the function. */ - BlockNode *body; /**< A pointer to the block of code defined by the function. */ + IdentifierNode *scope; /**< The scope of the function. */ + IdentifierNode *name; /**< The name of the function. */ + IdentifierNodeList *args; /**< The names of the function arguments. */ + BlockNode *body; /**< The body of the function. */ } FuncDefStmtNode; -/** Stores the main block of code a program executes. This structure could be - * accomplished using only a BlockNode instead, but its logical importance to - * program control flow (namely, it is the first portion of code executed) - * merits its own structure. - * - * \see createMainNode(BlockNode *) - * \see deleteMainNode(MainNode *) */ +/** + * Stores the main code block of a program. + * + * \note This could be represented with just a BlockNode, but it seems + * significant enough to merit its own structure. + */ typedef struct { - BlockNode *block; /**< A pointer to the block of code to execute first. */ + BlockNode *block; /**< The first block of code to execute. */ } MainNode; -/** Stores a variable type. - * - * \see createTypeNode(ConstantType) - * \see deleteTypeNode(TypeNode *) */ +/** + * Stores a variable type. + */ typedef struct { - ConstantType type; /**< The type of the variable. */ + ConstantType type; /**< The type variable. */ } TypeNode; -/** Stores a cast statement. A cast statement changes the type of a variable - * identified by \a target to the type given by \a newtype. - * - * \see createCastStmtNode(IdentifierNode *, TypeNode *) - * \see deleteCastStmtNode(CastStmtNode *) */ +/** + * Stores a cast statement. This statement changes the type of a variable. + */ typedef struct { - IdentifierNode *target; /**< A pointer to the name of the variable whose type is to be changed to \a newtype. */ - TypeNode *newtype; /**< A pointer to the type to change \a target to. */ + IdentifierNode *target; /**< The name of the variable to cast. */ + TypeNode *newtype; /**< The type to cast \a target to. */ } CastStmtNode; -/** Stores a print statement. A print statement prints its arguments to some - * output device (by default standard output). - * - * \see createPrintStmtNode(ExprNodeList *, int) - * \see deletePrintStmtNode(PrintStmtNode *) */ +/** + * Stores a print statement. This statement prints a list of expressions with + * an optional newline. + */ typedef struct { - ExprNodeList *args; /**< A pointer to the list of expressions to evaluate and print. */ - int nonl; /**< Denotes an ending newline should be surpressed if not \c 0 and printed if \c 0. */ + ExprNodeList *args; /**< The expressions to print. */ + int nonl; /**< Whether to print an ending newline. */ } PrintStmtNode; -/** Stores an input statement. An input statement accepts a line of input from - * the use on an input device (by default standard input) and stores it in a - * variable. - * - * \see createInputStmtNode(IdentifierNode *) - * \see deleteInputStmtNode(InputStmtNode *) */ +/** + * Stores an input statement. This statement accepts input from the user and + * stores it in a variable. + */ typedef struct { - IdentifierNode *target; /**< A pointer to the name of the variable to store the input in. */ + IdentifierNode *target; /**< The variable to store the input in. */ } InputStmtNode; -/** Stores an assignment statement. An assignment statement updates the value - * of a variable, \a target, to the result of an expression, \a expr. - * - * \see createAssignmentStmtNode(IdentifierNode *, ExprNode *) - * \see deleteAssignmentStmtNode(AssignmentStmtNode *) */ +/** + * Stores an assignment statement. This statement stores an evaluated + * expression in a variable. + */ typedef struct { - IdentifierNode *target; /**< A pointer to the name of the variable to store the evaluated contents of \a expr into. */ - ExprNode *expr; /**< A pointer to the expression to evaluate and store in \a target. */ + IdentifierNode *target; /**< The variable to store \a expr in. */ + ExprNode *expr; /**< The expression to store. */ } AssignmentStmtNode; -/** Stores a declaration statement. A declaration statement creates a new - * variable named by \a target, optionally initializing it to the evaluated - * contents of \a expr. \a scope determines which level of scope the variable - * is to be created in. - * - * \note \a expr and \a type are mutually exclusive. If both are non-NULL, - * results are undefined. - * - * \see createDeclarationStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *) - * \see deleteDeclarationStmtNode(DeclarationStmtNode *) */ +/** + * Stores a declaration statement. This statement creates a new variable in a + * given scope and optionally initializes it to an expression. + * + * \note Either provide \a expr OR \a type. If both are provided, the result is + * undefined. + */ typedef struct { - IdentifierNode *scope; /**< A pointer to the scope to create the variable in. */ - IdentifierNode *target; /**< A pointer to the name of the variable to create. */ - ExprNode *expr; /**< An optional pointer to the expression to initialize \a target to. */ - TypeNode *type; /**< An optional pointer to the type to initialize \a target to. */ + IdentifierNode *scope; /**< The scope to create the variable in. */ + IdentifierNode *target; /**< The name of the variable to create. */ + ExprNode *expr; /**< An optional initialization expression. */ + TypeNode *type; /**< An optional initialization type. */ } DeclarationStmtNode; -/** Stores an if/then/else statement. A conditional statement checks the value - * of the \ref impvar "implicit variable" and executes \a yes if it casts to \c - * true. If the value of the \ref impvar "implicit variable" casts to \c - * false, each of the optional expressions in \a guards is evaluated and if it - * casts to true, the corresponding block in \a blocks is executes. If the - * value of the \ref impvar "implicit variable" casts to false \b and all of - * the guards cast to false, the contents of \a no is executed. - * - * \see createIfThenElseStmtNode(BlockNode *, BlockNode *, ExprNodeList *, BlockNodeList *) - * \see deleteIfThenElseStmtNode(IfThenElseStmtNode *) */ +/** + * Stores an if/then/else statement. This statement checks the value of the + * \ref impvar "implicit variable" and executes the \c yes block if it can be + * cast to true. Else, the \c guards are evaluated and the corresponding code + * in one of the \c blocks is executed. Finally, if none of these things occur, + * the \c no block is executed. + */ typedef struct { - BlockNode *yes; /**< A pointer to the block of code to execute if the \ref impvar "implicit variable" casts to false. */ - BlockNode *no; /**< A pointer to the block of code to execute if the \ref impvar "implicit variable" casts to false \b and the evaluations of all of the \a guards cast to false. */ - ExprNodeList *guards; /**< A pointer to the expressions to test if the \ref impvar "implicit variable" casts to false. */ - BlockNodeList *blocks; /**< A pointer to the respective blocks of code to execute if one of the evaluated \a guards casts to true. */ + BlockNode *yes; /**< The code to execute if \c IT is true. */ + BlockNode *no; /**< The code to execute if nothing else does. */ + ExprNodeList *guards; /**< The guards for the \c blocks. */ + BlockNodeList *blocks; /**< The code to execute if a guard is true. */ } IfThenElseStmtNode; -/** Stores a switch statement. A switch statement compares the value of the - * \ref impvar "implicit variable" to each of the \a guards and executes the - * respective block of code in \a blocks if they match. If no matches are - * found between the \ref impvar "implicit variable" and one of the \a guards, - * the optional default block of code, \a def, is executed. - * - * \see createSwitchStmtNode(ExprNodeList *, BlockNodeList *, BlockNode *) - * \see deleteSwitchStmtNode(SwitchStmtNode *) */ +/** + * Stores a switch statement. This statement compares the value of the \ref + * impvar "implicit variable" to each of the \a guards and executes the + * respective block of code in \a blocks if they match. If no matches are + * found, the optional default block of code, \a def, is executed. + */ typedef struct { - ExprNodeList *guards; /**< A pointer to the expressions to evaluate and compare to the \ref impvar "implicit variable". */ - BlockNodeList *blocks; /**< A pointer to the respective blocks of code to execute if one of the \a guards matches the \ref impvar "implicit variable". */ - BlockNode *def; /**< A pointer to the default block of code to execute if none of the \a guards match the \ref impvar "implicit variable". */ + ExprNodeList *guards; /**< The expressions to evaluate. */ + BlockNodeList *blocks; /**< The blocks of code to execute. */ + BlockNode *def; /**< An optional default block of code. */ } SwitchStmtNode; -/** Stores a return statement. A return statement signals that the current - * function is to be returned from with value \a value. - * - * \see createReturnStmtNode(ExprNode *) - * \see deleteReturnStmtNode(ReturnStmtNode *) */ +/** + * Stores a return statement. This statement signals that control should be + * returned to the caller with a status value. + */ typedef struct { - ExprNode *value; /**< A pointer to the value to return. */ + ExprNode *value; /**< The value to return. */ } ReturnStmtNode; -/** Stores a loop statement. A loop statement repeatedly executes its \a body - * while \a guard evaluates to true, executing \a update at the end of each - * cycle. - * - * \see createLoopStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, ExprNode *, BlockNode *) - * \see deleteLoopStmtNode(LoopStmtNode *) */ +/** + * Stores a loop statement. This statement repeatedly executes its \a body + * while \a guard evaluates to true, executing \a update at the end of each + * cycle. + */ typedef struct { - IdentifierNode *name; /**< A pointer to the name of the loop. */ - IdentifierNode *var; /**< A pointer to the name of the variable to be updated by \a update. */ - ExprNode *guard; /**< A pointer to the expression to determine if the loop will continue. */ - ExprNode *update; /**< A pointer to the expression to evaluate to update \a var. */ - BlockNode *body; /**< A pointer to the block of code to be executed with each iteration of the loop. */ + IdentifierNode *name; /**< The name of the loop. */ + IdentifierNode *var; /**< The variable to be updated. */ + ExprNode *guard; /**< The expression to determine continuation. */ + ExprNode *update; /**< The expression to update \a var with. */ + BlockNode *body; /**< The code to execute at each iteration. */ } LoopStmtNode; -/** Deallocates a variable. This means freeing the memory and structures used - * by the variable. - * - * \see createDeallocationStmtNode(IdentifierNode *) - * \see deleteDeallocationStmtNode(DeallocationStmtNode *) */ +/** + * Stores a deallocation statement. This statement releases the resources used + * by a variable. + */ typedef struct { - IdentifierNode *target; /**< A pointer to the name of the variable. */ + IdentifierNode *target; /**< The variable to deallocate. */ } DeallocationStmtNode; -/** Stores a cast expression. A cast expression evaluates an expression and - * casts it to a particular type. - * - * \see createCastExprNode(ExprNode *, TypeNode *) - * \see deleteCastExprNode(CastExprNode *) */ +/** + * Stores a cast expression. This expression evaluates an expression and casts + * its value to a particular type. + */ typedef struct { - ExprNode *target; /**< A pointer to the expression to cast. */ - TypeNode *newtype; /**< A pointer to the type to cast the copy of \a target to. */ + ExprNode *target; /**< The expression to cast. */ + TypeNode *newtype; /**< The type to cast \a target to. */ } CastExprNode; -/** Stores a function call expression. A function call expression evaluates to - * the return value of the function defined in \a def called with the arguments - * listed in \a args. - * - * \see createFuncCallExprNode(IdentifierNode *, IdentifierNode *, ExprNodeList *) - * \see deleteFuncCallExprNode(FuncCallExprNode *) */ +/** + * Stores a function call expression. This expression calls a named function + * and evaluates to the return value of that function. + */ typedef struct { - IdentifierNode *scope; /**< A pointer to the scope the function is defined in. */ - IdentifierNode *name; /**< A pointer to the name of the function. */ - ExprNodeList *args; /**< A pointer to a list of ExprNode structure arguments to be supplied to the function. */ + IdentifierNode *scope; /**< The scope to call the function in. */ + IdentifierNode *name; /**< The name of the function to call. */ + ExprNodeList *args; /**< The arguments to supply the function. */ } FuncCallExprNode; -/** Denotes the type of operation an OpExprNode performs. */ +/** + * Represents the type of operation an OpExprNode performs. + */ typedef enum { OP_ADD, /**< Addition. */ OP_SUB, /**< Subtraction. */ @@ -521,91 +509,246 @@ typedef enum { OP_CAT /**< String concatenation. */ } OpType; -/** Stores an operation expression. An operation expression evaluates to - * the result of the operation performed on its arguments. - * - * \see createOpExprNode(OpType, ExprNodeList *) - * \see deleteOpExprNode(OpExprNode *) */ +/** + * Stores an operation expression. This expression applies an operator to its + * arguments. + */ typedef struct { - OpType type; /**< The type of operation to perform on \a args. */ - ExprNodeList *args; /**< A pointer to the arguments to perform the operation on. */ + OpType type; /**< The type of operation to perform. */ + ExprNodeList *args; /**< The arguments to perform the operation on. */ } OpExprNode; +/** + * \name MainNode modifiers + * + * Functions for creating and deleting MainNodes. + */ +/**@{*/ MainNode *createMainNode(BlockNode *); void deleteMainNode(MainNode *); +/**@}*/ +/** + * \name BlockNode modifiers + * + * Functions for creating and deleting single or multiple BlockNodes. + */ +/**@{*/ BlockNode *createBlockNode(StmtNodeList *); void deleteBlockNode(BlockNode *); BlockNodeList *createBlockNodeList(void); int addBlockNode(BlockNodeList *, BlockNode *); void deleteBlockNodeList(BlockNodeList *); +/**@}*/ -IdentifierNode *createIdentifierNode(IdentifierType, void *, const char *, unsigned int); +/** + * \name IdentifierNode modifiers + * + * Functions for creating and deleting single or multiple IdentifierNodes. + */ +/**@{*/ +IdentifierNode *createIdentifierNode(IdentifierType, void *, IdentifierNode *, const char *, unsigned int); void deleteIdentifierNode(IdentifierNode *); +IdentifierNodeList *createIdentifierNodeList(void); +int addIdentifierNode(IdentifierNodeList *, IdentifierNode *); +void deleteIdentifierNodeList(IdentifierNodeList *); +/**@}*/ + +/** + * \name TypeNode modifiers + * + * Functions for creating and deleting TypeNodes. + */ +/**@{*/ TypeNode *createTypeNode(ConstantType); void deleteTypeNode(TypeNode *); +/**@}*/ +/** + * \name StmtNode modifiers + * + * Functions for creating and deleting single or multiple of StmtNodes. + */ +/**@{*/ StmtNode *createStmtNode(StmtType, void *); void deleteStmtNode(StmtNode *); StmtNodeList *createStmtNodeList(void); int addStmtNode(StmtNodeList *, StmtNode *); void deleteStmtNodeList(StmtNodeList *); +/**@}*/ +/** + * \name CastStmtNode modifiers + * + * Functions for creating and deleting CastStmtNodes. + */ +/**@{*/ CastStmtNode *createCastStmtNode(IdentifierNode *, TypeNode *); void deleteCastStmtNode(CastStmtNode *); +/**@}*/ +/** + * \name PrintStmtNode modifiers + * + * Functions for creating and deleting PrintStmtNodes. + */ +/**@{*/ PrintStmtNode *createPrintStmtNode(ExprNodeList *, int); void deletePrintStmtNode(PrintStmtNode *); +/**@}*/ +/** + * \name InputStmtNode modifiers + * + * Functions for creating and deleting InputStmtNodes. + */ +/**@{*/ InputStmtNode *createInputStmtNode(IdentifierNode *); void deleteInputStmtNode(InputStmtNode *); +/**@}*/ +/** + * \name AssignmentStmtNode modifiers + * + * Functions for creating and deleting AssignmentStmtNodes. + */ +/**@{*/ AssignmentStmtNode *createAssignmentStmtNode(IdentifierNode *, ExprNode *); void deleteAssignmentStmtNode(AssignmentStmtNode *); +/**@}*/ +/** + * \name DeclarationStmtNode modifiers + * + * Functions for creating and deleting DeclarationStmtNodes. + */ +/**@{*/ DeclarationStmtNode *createDeclarationStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, TypeNode *); void deleteDeclarationStmtNode(DeclarationStmtNode *); +/**@}*/ +/** + * \name IfThenElseStmtNode modifiers + * + * Functions for creating and deleting IfThenElseStmtNodes. + */ +/**@{*/ IfThenElseStmtNode *createIfThenElseStmtNode(BlockNode *, BlockNode *, ExprNodeList *, BlockNodeList *); void deleteIfThenElseStmtNode(IfThenElseStmtNode *); +/**@}*/ +/** + * \name SwitchStmtNode modifiers + * + * Functions for creating and deleting SwitchStmtNodes. + */ +/**@{*/ SwitchStmtNode *createSwitchStmtNode(ExprNodeList *, BlockNodeList *, BlockNode *); void deleteSwitchStmtNode(SwitchStmtNode *); +/**@}*/ +/** + * \name ReturnStmtNode modifiers + * + * Functions for creating and deleting ReturnStmtNodes. + */ +/**@{*/ ReturnStmtNode *createReturnStmtNode(ExprNode *); void deleteReturnStmtNode(ReturnStmtNode *); +/**@}*/ +/** + * \name LoopStmtNode modifiers + * + * Functions for creating and deleting LoopStmtNodes. + */ +/**@{*/ LoopStmtNode *createLoopStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, ExprNode *, BlockNode *); void deleteLoopStmtNode(LoopStmtNode *); +/**@}*/ +/** + * \name DeallocationStmtNode modifiers + * + * Functions for creating and deleting DeallocationStmtNodes. + */ +/**@{*/ DeallocationStmtNode *createDeallocationStmtNode(IdentifierNode *); void deleteDeallocationStmtNode(DeallocationStmtNode *); +/**@}*/ +/** + * \name FuncDefStmtNode modifiers + * + * Functions for creating and deleting FuncDefStmtNodes. + */ +/**@{*/ FuncDefStmtNode *createFuncDefStmtNode(IdentifierNode *, IdentifierNode *, IdentifierNodeList *, BlockNode *); void deleteFuncDefStmtNode(FuncDefStmtNode *); +/**@}*/ +/** + * \name ExprNode modifiers + * + * Functions for creating and deleting single or multiple ExprNodes. + */ +/**@{*/ ExprNode *createExprNode(ExprType, void *); void deleteExprNode(ExprNode *); ExprNodeList *createExprNodeList(void); int addExprNode(ExprNodeList *, ExprNode *); void deleteExprNodeList(ExprNodeList *); +/**@}*/ +/** + * \name CastExprNode modifiers + * + * Functions for creating and deleting CastExprNodes. + */ +/**@{*/ CastExprNode *createCastExprNode(ExprNode *, TypeNode *); void deleteCastExprNode(CastExprNode *); +/**@}*/ +/** + * \name FuncCallExprNode modifiers + * + * Functions for creating and deleting FuncCallExprNodes. + */ +/**@{*/ FuncCallExprNode *createFuncCallExprNode(IdentifierNode *, IdentifierNode *, ExprNodeList *); void deleteFuncCallExprNode(FuncCallExprNode *); +/**@}*/ +/** + * \name OpExprNode modifiers + * + * Functions for creating and deleting OpExprNodes. + */ +/**@{*/ OpExprNode *createOpExprNode(OpType, ExprNodeList *); void deleteOpExprNode(OpExprNode *); +/**@}*/ +/** + * \name Utilities + * + * Functions for performing helper tasks. + */ +/**@{*/ int acceptToken(Token ***, TokenType); int peekToken(Token ***, TokenType); int nextToken(Token ***, TokenType); - void error(const char *, Token **); +/**@}*/ +/** + * \name Parsing functions + * + * Functions for parsing a stream of tokens. + */ +/**@{*/ ConstantNode *parseConstantNode(Token ***); TypeNode *parseTypeNode(Token ***); IdentifierNode *parseIdentifierNode(Token ***); @@ -613,13 +756,11 @@ ExprNode *parseExprNode(Token ***); StmtNode *parseStmtNode(Token ***); BlockNode *parseBlockNode(Token ***); MainNode *parseMainNode(Token **); - ExprNode *parseCastExprNode(Token ***); ExprNode *parseConstantExprNode(Token ***); ExprNode *parseIdentifierExprNode(Token ***); ExprNode *parseFuncCallExprNode(Token ***); ExprNode *parseOpExprNode(Token ***); - StmtNode *parseCastStmtNode(Token ***); StmtNode *parsePrintStmtNode(Token ***); StmtNode *parseInputStmtNode(Token ***); @@ -632,15 +773,19 @@ StmtNode *parseReturnStmtNode(Token ***); StmtNode *parseLoopStmtNode(Token ***); StmtNode *parseDeallocationStmtNode(Token ***); StmtNode *parseFuncDefStmtNode(Token ***); +/**@}*/ +/** + * \name ConstantNode modifiers + * + * Functions for creating and deleting ConstantNode. + */ +/**@{*/ ConstantNode *createBooleanConstantNode(int); ConstantNode *createIntegerConstantNode(int); ConstantNode *createFloatConstantNode(float); ConstantNode *createStringConstantNode(char *); void deleteConstantNode(ConstantNode *); - -IdentifierNodeList *createIdentifierNodeList(void); -int addIdentifierNode(IdentifierNodeList *, IdentifierNode *); -void deleteIdentifierNodeList(IdentifierNodeList *); +/**@}*/ #endif /* __PARSER_H__ */ diff --git a/test/testDir.sh b/test/testDir.sh index a166041..602ab1e 100755 --- a/test/testDir.sh +++ b/test/testDir.sh @@ -20,6 +20,6 @@ done # Remove options, leave arguments shift $((OPTIND - 1)) -find $2 -name *.lol | sort | xargs -n 1 ./testFile.sh$OPTS $1 && echo "Passed all tests!" && exit 0 +find $2 -name *.lol | sort -t'/' -n -k1 -k2 -k3 -k4 -k5 -k6 -k7 -k8 -k9 -k10 | xargs -n 1 ./testFile.sh$OPTS $1 && echo "Passed all tests!" && exit 0 exit 1 diff --git a/test/testFile.sh b/test/testFile.sh index 8eb9ea8..5e9ce36 100755 --- a/test/testFile.sh +++ b/test/testFile.sh @@ -61,7 +61,7 @@ then test ! $QUIET && printf "Found output file ($OUTFILE)!\n" fi # Run the test - TMPFILE=$(mktemp) && test ! $QUIET && printf "Using temporary output file ($TMPFILE)...\n" + TMPFILE=$(mktemp /tmp/temp.XXXX) && test ! $QUIET && printf "Using temporary output file ($TMPFILE)...\n" eval "$MEMCHK $PROGRAM $TESTFILE $IN > $TMPFILE" RESULT=$? # Check that program exited normally diff --git a/tokenizer.c b/tokenizer.c index e1dbf79..afd2ebe 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -12,6 +12,7 @@ static const char *keywords[] = { "NUMBAR", /* TT_NUMBAR */ "TROOF", /* TT_TROOF */ "YARN", /* TT_YARN */ + "BUKKIT", /* TT_BUKKIT */ "", /* TT_EOF */ "", /* TT_NEWLINE */ "HAI", /* TT_HAI */ @@ -67,23 +68,27 @@ static const char *keywords[] = { "IF U SAY SO", /* TT_IFUSAYSO */ "FOUND YR", /* TT_FOUNDYR */ "SRS", /* TT_SRS */ + "'Z", /* TT_APOSTROPHEZ */ + "BUKKIT", /* TT_BUKKIT */ "" /* TT_ENDOFTOKENS */ }; -/** Checks if a string of characters follows the format for an integer. - * Specifically, it checks if the string of characters matches the regular - * expression: [-]?[1-9][0-9]* | 0 - * - * \retval 0 The string of characters is not an integer. - * \retval 1 The string of characters is an integer. - * - * \see isFloat(const char *) - * \see isString(const char *) - * \see isIdentifier(const char *) */ -int isInteger(const char *image) /**< [in] The string of characters to compare. */ +/** + * Checks if a string follows the format for an integer. Specifically, it + * checks if the string matches the regular expression: (-?[1-9][0-9]*|0). + * + * \param [in] image The string to check. + * + * \retval 0 \a image does not match the pattern for an integer. + * + * \retval 1 \a image matches the pattern for an integer. + */ +int isInteger(const char *image) { const char *cur = image; - if (*cur == '-' || (isdigit(*cur) && *cur != '0') || (*cur == '0' && *(cur + 1) == '\0')) { + if (*cur == '-' + || (isdigit(*cur) && *cur != '0') + || (*cur == '0' && *(cur + 1) == '\0')) { cur++; while (isdigit(*cur)) cur++; if (*cur == '\0') return 1; @@ -91,17 +96,17 @@ int isInteger(const char *image) /**< [in] The string of characters to compare. return 0; } -/** Checks if a string of characters follows the format for a floating - * point decimal. Specifically, it checks if the string of characters matches - * the regular expression: [-]?[0-9].[0-9]* - * - * \retval 0 The string of characters is not a floating point decimal. - * \retval 1 The string of characters is a floating point decimal. - * - * \see isInteger(const char *) - * \see isString(const char *) - * \see isIdentifier(const char *) */ -int isFloat(const char *image) /**< [in] The string of characters to compare. */ +/** + * Checks if a string follows the format for a decimal. Specifically, it checks + * if the string matches the regular expression: (-?[0-9].[0-9]*). + * + * \param [in] image The string to check. + * + * \retval 0 \a image does not match the pattern for a decimal. + * + * \retval 1 \a image matches the pattern for a decimal. + */ +int isFloat(const char *image) { const char *cur = image; if (*cur == '-' || isdigit(*cur)) { @@ -116,33 +121,33 @@ int isFloat(const char *image) /**< [in] The string of characters to compare. */ return 0; } -/** Checks if a string of characters follows the format for a string. - * Specifically, it checks if the string of characters begins and ends with a - * quote character. - * - * \retval 0 The string of characters is not a string. - * \retval 1 The string of characters is a string. - * - * \see isInteger(const char *) - * \see isFloat(const char *) - * \see isIdentifier(const char *) */ -int isString(const char *image) /**< [in] The string of characters to compare. */ +/** + * Checks if a string follows the format for a string literal. Specifically, it + * checks if the string matches the regular expression: (".*"). + * + * \param [in] image The string to check. + * + * \retval 0 \a image does not match the pattern for a string. + * + * \retval 1 \a image matches the pattern for a string. + */ +int isString(const char *image) { size_t len = strlen(image); return (len >= 2 && image[0] == '"' && image[len - 1] == '"'); } -/** Checks if a string of characters follows the format for an identifier. - * Specifically, it checks if the string of characters matches the regular - * expression: [a-zA-Z][a-zA-Z0-9_]* - * - * \retval 0 The string of characters is not an identifier. - * \retval 1 The string of characters is an identifier. - * - * \see isInteger(const char *) - * \see isFloat(const char *) - * \see isString(const char *) */ -int isIdentifier(const char *image) /**< [in] The string of characters to compare. */ +/** + * Checks if a string follows the format for an identifier. Specifically, it + * checks if the string matches the regular expression: ([a-zA-Z][a-zA-Z0-9_]*). + * + * \param image [in] The string to check. + * + * \retval 0 \a image does not match the pattern for an identifier. + * + * \retval 1 \a image matches the pattern for an identifier. + */ +int isIdentifier(const char *image) { const char *cur = image; /* First character must be alphabetic */ @@ -155,17 +160,25 @@ int isIdentifier(const char *image) /**< [in] The string of characters to compar return 1; } -/** Creates a Token structure. - * - * \return A pointer to a Token structure with the desired properties. - * - * \retval NULL malloc was unable to allocate memory. - * - * \see deleteToken(Token *) */ -Token *createToken(TokenType type, /**< [in] The type of token to create. */ - const char *image, /**< [in] The characters from the source file that represent the token. */ - const char *fname, /**< [in] A pointer to the name of the file containing the token. */ - unsigned int line) /**< [in] The line number from the source file that the token occurred on. */ +/** + * Creates a token. + * + * \param [in] type The type of token to create. + * + * \param [in] image The string that represents the token. + * + * \param [in] fname The name of the file containing the token. + * + * \param [in] line The number of the line containing the token. + * + * \return A pointer to a new token with the desired properties. + * + * \retval NULL Memory allocation failed. + */ +Token *createToken(TokenType type, + const char *image, + const char *fname, + unsigned int line) { Token *ret = malloc(sizeof(Token)); if (!ret) { @@ -180,20 +193,22 @@ Token *createToken(TokenType type, /**< [in] The type of token to create. */ return NULL; } strcpy(ret->image, image); - /** \note fname is not copied because it would only one copy is stored - * for all Token structures that share it. */ + /** + * \note fname is not copied because only one copy is stored for all + * Token structures that share it. + */ ret->fname = fname; ret->line = line; return ret; } -/** Deletes a Token structure. - * - * \pre \a token points to a Token structure created by createToken(TokenType, const char *, const char *, unsigned int). - * - * \post The memory at \a token and all of its elements will be freed. - * - * \see createToken(TokenType, const char *, const char *, unsigned int) */ +/** + * Deletes a token. + * + * \param [in,out] token The token to delete. + * + * \post The memory at \a token and all of its members will be freed. + */ void deleteToken(Token *token) { if (!token) return; @@ -201,22 +216,25 @@ void deleteToken(Token *token) free(token); } -/** Adds a Token to an array of Token structures. - * - * \note \a list may be NULL in which case a new list is created. - * - * \pre \a num is the number of elements in \a list. - * - * \post \a token will be added on to the end of \a list and the value at \a num - * will be updated accordingly. - * - * \retval 0 realloc was unable to allocate memory. - * \retval 1 \a node was added to \a list. - * - * \see deleteTokens(Token **) */ -int addToken(Token ***list, /**< [in,out] A pointer to a pointer to an array of Token structures to add the new Token onto. */ - unsigned int *num, /**< [in,out] A pointer to the number of elements in \a list. */ - Token *token) /**< [in] A pointer to the Token structure to add to \a list. */ +/** + * Adds a token to a list. + * + * \param [in,out] list The list of tokens to add \a token to. + * + * \param [in,out] num The number of tokens in \a list. + * + * \param [in] token The token to add to \a list. + * + * \post \a token will be added to the end of \a list and the size of \a list + * will be updated. + * + * \retval 0 Memory allocation failed. + * + * \retval 1 \a token was added to \a list. + */ +int addToken(Token ***list, + unsigned int *num, + Token *token) { unsigned int newsize = *num + 1; void *mem = realloc(*list, sizeof(Token *) * newsize); @@ -233,14 +251,14 @@ int addToken(Token ***list, /**< [in,out] A pointer to a pointer to an array return 1; } -/** Deletes an array of Token structures. - * - * \pre \a list was created by and contains items added by addToken(Token ***, unsigned int *, Token *). - * - * \post The memory at \a list and all of its elements will be freed. - * - * \see addToken(Token ***, unsigned int *, Token *) */ -void deleteTokens(Token **list) /**< [in,out] A pointer to an array of Token structures to be deleted. */ +/** + * Deletes a list of tokens. + * + * \param list [in,out] The list of tokens to delete. + * + * \post The memory at \a list and all of its members will be freed. + */ +void deleteTokens(Token **list) { Token **tok = list; while (*tok) { @@ -250,20 +268,28 @@ void deleteTokens(Token **list) /**< [in,out] A pointer to an array of Token str free(list); } -/** Tries to match a sequence of lexemes. Scans through \a lexemes starting at - * \a start and tries to match space-delimited lexemes from \a match. - * - * \pre \a lexemes was created by scanBuffer(const char *, unsigned int, const char *). - * - * \return The number of lexemes matched. */ -unsigned int acceptLexemes(LexemeList *lexemes, /**< [in] A pointer to a LexemeList structure to match lexemes from. */ - unsigned int start, /**< [in] The position within \a lexemes to start matching at. */ - const char *match) /**< [in] A pointer to a character array describing the sequence of lexemes to match. */ +/** + * Matches lexemes against a string. Traverses \a lexemes starting at \a start + * and compares lexeme images to space-delimited substrings from \a match. + * + * \param lexemes [in] The list of lexemes to match from. + * + * \param start [in] The index within \a lexemes to start matching at. + * + * \param match [in] A string of space-delimited substrings to match. + * + * \return The number of lexemes matched. + */ +unsigned int acceptLexemes(LexemeList *lexemes, + unsigned int start, + const char *match) { unsigned int offset = 0; unsigned int n; unsigned int i; - for (n = 0, i = 0; match[n] || lexemes->lexemes[start + offset]->image[i]; n++) { + for (n = 0, i = 0; + match[n] || lexemes->lexemes[start + offset]->image[i]; + n++) { if (match[n] == ' ') { offset++; i = 0; @@ -276,49 +302,59 @@ unsigned int acceptLexemes(LexemeList *lexemes, /**< [in] A pointer to a LexemeL return offset + 1; } -/** Checks if a sequence of lexemes is a keyword. \a lexemes is searched - * starting at \a start for keywords. If one is found, the appropriate Token - * structure is created and returned and the value of \a start is incremented - * by the number of lexemes matched minus one. - * - * \pre \a lexemes was created by scanBuffer(const char *, unsigned int, const char *). - * - * \post If a keyword is not found, \a start will be unmodified. Otherwise, - * \a start will be incremented by the number of lexemes matched minus - * one. - * - * \return A pointer to a newly created keyword Token structure. - * - * \retval NULL No keywords were matched or there was an error allocating - * memory. */ -Token *isKeyword(LexemeList *lexemes, /**< [in] A pointer to a LexemeList structure to search for keywords in. */ - unsigned int *start) /**< [in,out] A pointer to the position within \a lexemes to start checking at. */ +/** + * Checks if the next lexemes in a list comprise a keyword and, if so, generates + * a new token representing that keyword. Specifically, \a lexemes is searched, + * starting at \a start for keywords. If one is found, an appropriate token is + * created and returned and \a start is incremented by the number of lexemes + * matched minus one. + * + * \param lexemes [in] A list of lexemes to search for keywords in. + * + * \param start [in,out] The position within \a lexemes to begin searching for + * keywords. + * + * \post If a keyword is not found, \a start will not be modified. Otherwise, + * \a start will be incremented by the number of lexemes matched minus one. + * + * \return A pointer to the token containing the matched keyword. + * + * \retval NULL No keywords were found or there was an error allocating memory. + */ +Token *isKeyword(LexemeList *lexemes, + unsigned int *start) { Token *token = NULL; TokenType type; const char *fname = lexemes->lexemes[*start]->fname; unsigned int line = lexemes->lexemes[*start]->line; + /* For each keyword, */ for (type = 0; type != TT_ENDOFTOKENS; type++) { - unsigned int num = acceptLexemes(lexemes, *start, keywords[type]); + /* Check if the start of lexemes match */ + unsigned int num = acceptLexemes(lexemes, + *start, keywords[type]); if (!num) continue; + /* If so, create a new token for the keyword */ token = createToken(type, keywords[type], fname, line); + /* And advance the start */ *start += (num - 1); break; } return token; } -/** Converts a list of lexemes into tokens. Additionally parses the literal - * values of integers, floating point decimals, and strings. - * - * \pre \a list was created by scanBuffer(const char *, unsigned int, const char *). - * - * \return A pointer to an array of Token structures representing the tokenized - * form of the input lexeme stream. - * - * \retval NULL An unrecognized token was encountered or memory allocation - * failed. */ -Token **tokenizeLexemes(LexemeList *list) /**< [in] A pointer to a LexemeList structure to tokenize. */ +/** + * Converts a list of lexemes into tokens. Also parses integers, floats, and + * strings into tokens with semantic meaning. + * + * \param list [in] A list of lexemes to tokenize. + * + * \return A list of tokens generated from \a list. + * + * \retval NULL An unrecognized token was encounteres or memory allocation + * failed. + */ +Token **tokenizeLexemes(LexemeList *list) { void *mem = NULL; Token **ret = NULL; @@ -368,8 +404,8 @@ Token **tokenizeLexemes(LexemeList *list) /**< [in] A pointer to a LexemeList st continue; } /* Newline */ - /* Note that the spec is unclear as to whether a command *must* follow - * a comma. For now, we let commas end a line. */ + /* Note that the spec is unclear as to whether a command *must* + * follow a comma. For now, we let commas end a line. */ else if (!strcmp(image, "\n")) { /* Note that we ignore any initial newlines */ if (retsize < 1) { @@ -392,8 +428,8 @@ Token **tokenizeLexemes(LexemeList *list) /**< [in] A pointer to a LexemeList st else if ((token = isKeyword(list, &n))) { } /* Identifier */ - /* This must be placed after keyword parsing because most - * keywords look like identifiers. */ + /* This must be placed after keyword parsing or else most + * keywords would be tokenized as identifiers. */ else if (isIdentifier(image)) { token = createToken(TT_IDENTIFIER, image, fname, line); } diff --git a/tokenizer.h b/tokenizer.h index ab1e2f6..93ad823 100644 --- a/tokenizer.h +++ b/tokenizer.h @@ -1,14 +1,16 @@ -/** Structures and functions for grouping lexemes into tokens. The tokenizer - * reads through an array of lexemes (generated by the lexer) and groups them - * into tokens based on their structure. In addition, some lexemes with - * semantic meaning (such as integers, floats, strings, and booleans) will have - * their values extracted and stored. - * - * \file tokenizer.h - * - * \author Justin J. Meza - * - * \date 2010 */ +/** + * Structures and functions for grouping lexemes into tokens. The tokenizer + * reads through an array of lexemes (generated by the lexer) and groups them + * into tokens based on their structure. In addition, some lexemes with + * semantic meaning (such as integers, floats, strings, and booleans) will have + * their values extracted and stored. + * + * \file tokenizer.h + * + * \author Justin J. Meza + * + * \date 2010-2011 + */ #ifndef __TOKENIZER_H__ #define __TOKENIZER_H__ @@ -21,107 +23,138 @@ #undef DEBUG -/** Denotes the type of token present. All of the token type names are - * self-explainatory and correspond to either the semantic type of token data - * (in the case of TT_INTEGER, TT_FLOAT, TT_STRING, or TT_IDENTIFIER) or the - * lexemes which make up the particular token. - * - * \note Remember to update the keywords array with the token image. */ +/** + * Represents a token type. All of the token type names correspond to either + * the semantic type of token data or the lexemes which make up the particular + * token. + * + * \note Remember to update the keywords array (in the tokens C file) with the + * token image. + */ typedef enum { - TT_INTEGER, - TT_FLOAT, - TT_STRING, - TT_IDENTIFIER, - TT_BOOLEAN, - TT_IT, - TT_NOOB, - TT_NUMBR, - TT_NUMBAR, - TT_TROOF, - TT_YARN, - TT_EOF, - TT_NEWLINE, - TT_HAI, - TT_KTHXBYE, - TT_HASA, - TT_ITZA, - TT_ITZ, - TT_RNOOB, - TT_R, - TT_ANYR, - TT_AN, - TT_SUMOF, - TT_DIFFOF, - TT_PRODUKTOF, - TT_QUOSHUNTOF, - TT_MODOF, - TT_BIGGROF, - TT_SMALLROF, - TT_BOTHOF, - TT_EITHEROF, - TT_WONOF, - TT_NOT, - TT_MKAY, - TT_ALLOF, - TT_ANYOF, - TT_BOTHSAEM, - TT_DIFFRINT, - TT_MAEK, - TT_A, - TT_ISNOWA, - TT_VISIBLE, - TT_SMOOSH, - TT_BANG, - TT_GIMMEH, - TT_ORLY, - TT_YARLY, - TT_MEBBE, - TT_NOWAI, - TT_OIC, - TT_WTF, - TT_OMG, - TT_OMGWTF, - TT_GTFO, - TT_IMINYR, - TT_UPPIN, - TT_NERFIN, - TT_YR, - TT_TIL, - TT_WILE, - TT_IMOUTTAYR, - TT_HOWIZ, - TT_IZ, - TT_IFUSAYSO, - TT_FOUNDYR, - TT_SRS, - TT_ENDOFTOKENS + TT_INTEGER, /**< Integer literal. */ + TT_FLOAT, /**< Decimal literal. */ + TT_STRING, /**< String literal. */ + TT_IDENTIFIER, /**< Identifier literal. */ + TT_BOOLEAN, /**< Boolean literal. */ + TT_IT, /**< \ref impvar "Implicit variable". */ + TT_NOOB, /**< Nil keyword. */ + TT_NUMBR, /**< Integer keyword. */ + TT_NUMBAR, /**< Decimal keyword. */ + TT_TROOF, /**< Boolean keyword. */ + TT_YARN, /**< String keyword. */ + TT_BUKKIT, /**< Array. */ + TT_EOF, /**< End of file. */ + TT_NEWLINE, /**< Newline. */ + TT_HAI, /**< Beginning of main block. */ + TT_KTHXBYE, /**< End of main block. */ + TT_HASA, /**< Variable declaration. */ + TT_ITZA, /**< Variable type initialization. */ + TT_ITZ, /**< Variable value initialization. */ + TT_RNOOB, /**< Deallocation. */ + TT_R, /**< Assignment. */ + TT_ANYR, /**< User-defined function argument separator. */ + TT_AN, /**< Built-in function argument separator. */ + TT_SUMOF, /**< Addition. */ + TT_DIFFOF, /**< Subtraction. */ + TT_PRODUKTOF, /**< Multiplication. */ + TT_QUOSHUNTOF, /**< Division. */ + TT_MODOF, /**< Modulo. */ + TT_BIGGROF, /**< Greater than. */ + TT_SMALLROF, /**< Less than. */ + TT_BOTHOF, /**< Logical AND. */ + TT_EITHEROF, /**< Logical OR. */ + TT_WONOF, /**< Logical XOR. */ + TT_NOT, /**< Logical NOT. */ + TT_MKAY, /**< Infinite arity argument delimiter. */ + TT_ALLOF, /**< Infinite arity logical AND. */ + TT_ANYOF, /**< Infinite arity logical OR. */ + TT_BOTHSAEM, /**< Equality. */ + TT_DIFFRINT, /**< Inequality. */ + TT_MAEK, /**< Cast. */ + TT_A, /**< Cast target separator. */ + TT_ISNOWA, /**< In-place cast. */ + TT_VISIBLE, /**< Print. */ + TT_SMOOSH, /**< String concatenation. */ + TT_BANG, /**< Exclamation point (!) */ + TT_GIMMEH, /**< Input. */ + TT_ORLY, /**< Conditional. */ + TT_YARLY, /**< True branch. */ + TT_MEBBE, /**< Else branch. */ + TT_NOWAI, /**< False branch. */ + TT_OIC, /**< Conditional and switch delimiter. */ + TT_WTF, /**< Switch. */ + TT_OMG, /**< Case. */ + TT_OMGWTF, /**< Default case. */ + TT_GTFO, /**< Break or return without value. */ + TT_IMINYR, /**< Loop beginning. */ + TT_UPPIN, /**< Auto increment loop variable. */ + TT_NERFIN, /**< Auto decrement loop variable. */ + TT_YR, /**< Function name delimiter. */ + TT_TIL, /**< Do until. */ + TT_WILE, /**< Do while. */ + TT_IMOUTTAYR, /**< Loop ending. */ + TT_HOWIZ, /**< Function definition beginning. */ + TT_IZ, /**< Function scope delimiter. */ + TT_IFUSAYSO, /**< Function definition end. */ + TT_FOUNDYR, /**< Return with value. */ + TT_SRS, /**< Indirect variable access. */ + TT_APOSTROPHEZ, /**< Array slot access ('Z). */ + TT_ENDOFTOKENS /**< The end of this enum -- don't move it! */ } TokenType; -/** Stores the data associated with a Token structure. */ +/** + * Stores token data with semantic meaning. + */ typedef union { int i; /**< Integer data. */ - float f; /**< Floating point data. */ + float f; /**< Decimal data. */ } TokenData; -/** Stores a token and any value parsed by the tokenizer. */ +/** + * Stores a token type and any parsed values. + */ typedef struct { TokenType type; /**< The type of token. */ TokenData data; /**< The stored data of type \a type. */ - char *image; /**< The array of characters from the lexer which correspond to the token. */ - const char *fname; /**< A pointer to the name of the file containing the token. */ - unsigned int line; /**< The line number from the source file that the token occurred on. */ + char *image; /**< The characters that comprise the token. */ + const char *fname; /**< The name of the file containing the token. */ + unsigned int line; /**< The line number the token was on. */ } Token; +/** + * \name Utilities + * + * Functions for performing helper tasks. + */ +/**@{*/ int isInteger(const char *); int isFloat(const char *); int isString(const char *); int isIdentifier(const char *); +Token *isKeyword(LexemeList *, unsigned int *); +/**@}*/ + +/** + * \name Token modifiers + * + * Functions for creating and deleting tokens. + */ +/**@{*/ Token *createToken(TokenType, const char *, const char *, unsigned int); void deleteToken(Token *); int addToken(Token ***, unsigned int *, Token*); void deleteTokens(Token **); unsigned int acceptLexemes(LexemeList *, unsigned int, const char *); -Token *isKeyword(LexemeList *, unsigned int *); +/**@}*/ + +/** + * \name Lexeme tokenizer + * + * Generates tokens from lexemes. + */ +/**@{*/ Token **tokenizeLexemes(LexemeList *); +/**@}*/ #endif /* __TOKENIZER_H__ */ diff --git a/unicode.c b/unicode.c index a9b8369..bfc022f 100644 --- a/unicode.c +++ b/unicode.c @@ -36860,15 +36860,22 @@ static const long codepoints[] = { #define NUM_UNICODE 18426 -/** Performs a binary search on an array of strings. - * - * \return The index of the matching entry, if found. - * - * \retval -1 The entry does not exist in the array. */ -int binarySearch(const char **strings, /**< [in] A pointer to an array of character strings to search through. */ - int start, /**< [in] The start of the range to search through. */ - int end, /**< [in] The end of the range to search through. */ - const char *find) /**< [in] The entry to search for. */ +/** + * Performs a binary search on an array of strings. + * + * \param [in] strings The array of string to search. + * \param [in] start The index to start searching at. + * \param [in] end The index to end searching at. + * \param [in] find The string to search for. + * + * \return The index of the matching string, if found. + * + * \retval -1 The string was not found in the array. + */ +int binarySearch(const char **strings, + int start, + int end, + const char *find) { int midpoint; int cmp; @@ -36884,12 +36891,16 @@ int binarySearch(const char **strings, /**< [in] A pointer to an array of charac return -1; } -/** Converts a Unicode normative name to a Unicode code point. - * - * \return The Unicode code point corresponding to the given Unicode name. - * - * \retval -1 An invalid Unicode normative name was supplied. */ -long convertNormativeNameToCodePoint(const char *name) /**< [in] A pointer to a string of characters representing the Unicode normative name desired. */ +/** + * Converts a Unicode normative name to a Unicode code point. + * + * \param [in] name The Unicode normative name to convert. + * + * \return The Unicode code point corresponding to \a name. + * + * \retval -1 An invalid Unicode normative name was supplied. + */ +long convertNormativeNameToCodePoint(const char *name) { int index = binarySearch(names, 0, NUM_UNICODE - 1, name); if (index < 0) { @@ -36900,14 +36911,18 @@ long convertNormativeNameToCodePoint(const char *name) /**< [in] A pointer to a return codepoints[index]; } -/** Converts the bits in a long integer representing a Unicode code point to a - * series of one or more bytes representing a UTF-8 character. - * - * \return The number of characters in the converted multi-byte character. - * - * \retval 0 An invalid Unicode code point was supplied. */ -size_t convertCodePointToUTF8(unsigned long codepoint, /**< [in] The Unicode code point to convert to UTF-8. */ - char *out) /**< [out] A pointer to the location to store the resulting UTF-8 bytes. */ +/** + * Converts a Unicode code point to a UTF-8 character. + * + * \param [in] codepoint The Unicode code point to convert to UTF-8. + * \param [out] out A pointer to the location to store the UTF-8 character. + * + * \return The length of the converted multi-byte UTF-8 character. + * + * \retval 0 An invalid Unicode code point was supplied. + */ +size_t convertCodePointToUTF8(unsigned long codepoint, + char *out) { /* Out of range */ if (codepoint > 0x10FFFF) { diff --git a/unicode.h b/unicode.h index a092379..aed38a2 100644 --- a/unicode.h +++ b/unicode.h @@ -1,11 +1,13 @@ -/** Data and functions for converting from Unicode normative names to - * code points. - * - * \file unicode.h - * - * \author Justin J. Meza - * - * \date 2010 */ +/** + * Data and functions for converting from Unicode normative names to Unicode + * code points. + * + * \file unicode.h + * + * \author Justin J. Meza + * + * \date 2010-2011 + */ #ifndef __UNICODE_H__ #define __UNICODE_H__