Added basic array functionality and cleaned up documentation.

This commit is contained in:
Justin J. Meza 2011-06-14 23:54:12 -07:00
parent 977e3dfde5
commit a6ef5811e8
17 changed files with 5218 additions and 4813 deletions

418
Doxyfile
View File

@ -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
@ -31,14 +31,27 @@ PROJECT_NAME = lci
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER =
PROJECT_NUMBER = 0.10.0
# 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
@ -57,7 +70,7 @@ CREATE_SUBDIRS = NO
# 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,
# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
OUTPUT_LANGUAGE = English
@ -86,7 +99,17 @@ REPEAT_BRIEF = YES
# "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
@ -126,7 +149,7 @@ STRIP_FROM_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
# (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
@ -137,7 +160,7 @@ SHORT_NAMES = NO
# 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
@ -159,7 +182,7 @@ MULTILINE_CPP_IS_BRIEF = NO
# 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
@ -207,14 +230,15 @@ OPTIMIZE_FOR_FORTRAN = NO
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 =
@ -222,7 +246,7 @@ EXTENSION_MAPPING =
# 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
# func(std::string) {}). This also makes the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
BUILTIN_STL_SUPPORT = NO
@ -240,12 +264,12 @@ 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
# 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
@ -270,7 +294,7 @@ SUBGROUPING = YES
# 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.
@ -278,10 +302,10 @@ TYPEDEF_HIDES_STRUCT = YES
# 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.
# 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 rougly double the
# 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
@ -297,7 +321,7 @@ SYMBOL_CACHE_SIZE = 0
# 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
# will be included in the documentation.
@ -326,7 +350,7 @@ EXTRACT_LOCAL_METHODS = NO
# 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.
# anonymous namespaces are hidden.
EXTRACT_ANON_NSPACES = NO
@ -372,7 +396,7 @@ INTERNAL_DOCS = NO
# 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
@ -384,7 +408,13 @@ HIDE_SCOPE_NAMES = NO
# 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 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.
@ -396,16 +426,22 @@ INLINE_INFO = YES
# 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
# 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
@ -425,6 +461,15 @@ SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
# 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.
@ -455,10 +500,10 @@ GENERATE_DEPRECATEDLIST= YES
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 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 defines in the
# 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.
@ -483,8 +528,7 @@ SHOW_DIRECTORIES = NO
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
# 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
@ -499,12 +543,12 @@ SHOW_NAMESPACES = YES
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 =
@ -536,13 +580,13 @@ WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be abled to get warnings for
# 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
@ -568,7 +612,7 @@ WARN_LOGFILE =
# 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
@ -582,10 +626,42 @@ INPUT_ENCODING = UTF-8
# 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
# *.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.
@ -600,7 +676,7 @@ RECURSIVE = NO
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
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
EXCLUDE_SYMLINKS = NO
@ -611,7 +687,7 @@ EXCLUDE_SYMLINKS = NO
# 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
@ -632,7 +708,7 @@ EXAMPLE_PATH =
# 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
@ -652,20 +728,17 @@ IMAGE_PATH =
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> 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
# to standard output. If FILTER_PATTERNS is specified, this tag will be
# ignored.
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:
# 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.
# 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 =
@ -675,6 +748,14 @@ FILTER_PATTERNS =
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
#---------------------------------------------------------------------------
@ -712,10 +793,9 @@ 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.
# 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
@ -729,7 +809,7 @@ USE_HTAGS = NO
# 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
@ -739,7 +819,7 @@ VERBATIM_HEADERS = NO
# 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
@ -787,11 +867,6 @@ HTML_HEADER =
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
@ -801,6 +876,37 @@ HTML_TIMESTAMP = NO
HTML_STYLESHEET =
# 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.
@ -823,7 +929,8 @@ HTML_DYNAMIC_SECTIONS = NO
# 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.
# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
# for more information.
GENERATE_DOCSET = NO
@ -841,6 +948,16 @@ DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
# 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)
@ -885,10 +1002,10 @@ BINARY_TOC = NO
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
@ -902,7 +1019,7 @@ QCH_FILE =
# 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
@ -910,20 +1027,24 @@ QHP_NAMESPACE =
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 =
# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see
# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
# Qt Help Project / Custom Filters</a>.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's
# filter section matches.
# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
# Qt Help Project / Filter Attributes</a>.
QHP_SECT_FILTER_ATTRS =
@ -934,14 +1055,33 @@ QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
# 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])
# 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
@ -966,6 +1106,11 @@ USE_INLINE_TREES = NO
TREEVIEW_WIDTH = 250
# 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
@ -974,13 +1119,54 @@ TREEVIEW_WIDTH = 250
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
#---------------------------------------------------------------------------
@ -988,7 +1174,7 @@ SEARCHENGINE = YES
# 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
@ -998,6 +1184,9 @@ 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.
# 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
@ -1014,10 +1203,10 @@ MAKEINDEX_CMD_NAME = makeindex
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
# 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
# packages that should be included in the LaTeX output.
@ -1057,7 +1246,10 @@ LATEX_BATCHMODE = NO
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
@ -1197,10 +1389,8 @@ GENERATE_PERLMOD = NO
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
# 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.
@ -1267,15 +1457,15 @@ 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.
# 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 =
# 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.
# 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
@ -1287,10 +1477,8 @@ SKIP_FUNCTION_MACROS = YES
# 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
@ -1331,9 +1519,8 @@ PERL_PATH = /usr/bin/perl
# 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.
# 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
@ -1359,16 +1546,23 @@ HIDE_UNDOC_RELATIONS = YES
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,
# 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 default size is 10pt.
@ -1443,7 +1637,7 @@ CALL_GRAPH = NO
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.
# will generate a graphical hierarchy of all classes instead of a textual one.
GRAPHICAL_HIERARCHY = YES
@ -1455,7 +1649,7 @@ GRAPHICAL_HIERARCHY = YES
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
# generated by dot. Possible values are png, svg, gif or svg.
# If left blank png will be used.
DOT_IMAGE_FORMAT = png
@ -1471,6 +1665,12 @@ DOT_PATH =
DOTFILE_DIRS =
# 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

View File

@ -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)

10
README
View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
/** Structures and functions for interpreting a parse tree. The interpreter
/**
* 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.
@ -7,7 +8,8 @@
*
* \author Justin J. Meza
*
* \date 2010 */
* \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. */
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__ */

BIN
lci.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

157
lexer.c
View File

@ -1,15 +1,19 @@
#include "lexer.h"
/** Creates a Lexeme structure.
/**
* Creates a lexeme.
*
* \return A pointer to a Lexeme structure with the desired properties.
* \param [in] image The string that identifies the lexeme.
*
* \retval NULL malloc was unable to allocate memory.
* \param [in] fname The name of the file containing the lexeme.
*
* \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. */
* \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.
/**
* Deletes a lexeme.
*
* \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) */
* \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.
/**
* Creates a list of lexemes.
*
* \return A pointer to a LexemeList structure with the desired properties.
* \return An empty lexeme list.
*
* \retval NULL malloc was unable to allocate memory.
*
* \see deleteLexemeList(LexemeList *) */
* \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.
/**
* Adds a lexeme to a list of lexemes.
*
* \pre \a list was created by createLexemeList(void).
* \pre \a lexeme was created by createLexeme(char *, const char *, unsigned int).
* \param [in,out] list The list of lexemes to add \a lexeme to.
*
* \post \a lexeme will be added on to the end of \a list and the size of
* \a list will be updated accordingly.
* \param [in] lexeme The lexeme to add to \a list.
*
* \return A pointer to the added Lexeme structure (will be the same as
* \a lexeme).
* \post \a lexeme will be added to the end of \a list and the size of \a list
* will be updated.
*
* \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. */
* \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.
/**
* Deletes a list of lexemes.
*
* \pre \a list was created by createLexemeList(void) and contains
* items added by addLexeme(LexemeList *, Lexeme *).
* \param [in,out] list The lexeme list to delete.
*
* \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. */
* \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 (!).
/**
* 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).
*
* \pre \a size is the number of characters starting at the memory location
* pointed to by \a buffer.
* \param [in] buffer The characters to turn into lexemes.
*
* \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. */
* \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;

60
lexer.h
View File

@ -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).
/**
* 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 */
* \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__ */

2
main.c
View File

@ -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

1702
parser.c

File diff suppressed because it is too large Load Diff

679
parser.h
View File

@ -1,24 +1,32 @@
/** 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).
/**
* 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 */
* \date 2010-2011
*/
/** \page impvar The Implicit Variable
/**
* \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.) */
* 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:
/**
* \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.
@ -44,14 +52,18 @@
* IdentifierNode ::= Identifier | \c TT_SRS ExprNode
*
* \par
* TypeNode ::= \c TT_NOOB | \c TT_TROOF | \c TT_NUMBR | \c TT_NUMBAR | \c TT_YARN
* 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
* StmtNode ::= CastStmtNode | PrintStmtNode | InputStmtNode |
* AssignmentStmtNode | DeclarationStmtNode | IfThenElseStmtNode |
* SwitchStmtNode | BreakStmt | ReturnStmtNode | LoopStmtNode |
* DeallocationStmtNode | FuncDefStmtNode | ExprStmt
*
* \par
* CastStmtNode ::= IdentifierNode \c TT_ISNOWA TypeNode \c TT_NEWLINE
@ -66,13 +78,15 @@
* AssignmentStmtNode ::= IdentifierNode \c TT_R ExprNode \c TT_NEWLINE
*
* \par
* DeclarationStmtNode ::= IdentifierNode \c TT_HASA IdentifierNode Initialization ? \c TT_NEWLINE
* 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
* 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
@ -81,7 +95,8 @@
* Else ::= \c TT_NOWAI \c TT_NEWLINE BlockNode
*
* \par
* SwitchStmtNode ::= \c TT_WTF \c TT_NEWLINE Case + DefaultCase ? \c TT_OIC \c TT_NEWLINE
* 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
@ -96,7 +111,8 @@
* 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
* 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
@ -114,7 +130,8 @@
* DeallocationStmtNode ::= IdentifierNode \c TT_RNOOB
*
* \par
* FuncDefStmtNode ::= \c TT_HOWIZ IdentifierNode IdentifierNode FunctionArgs ? \c TT_NEWLINE BlockNode \c TT_IFUSAYSO \c TT_NEWLINE
* FuncDefStmtNode ::= \c TT_HOWIZ IdentifierNode IdentifierNode FunctionArgs ?
* \c TT_NEWLINE BlockNode \c TT_IFUSAYSO \c TT_NEWLINE
*
* \par
* FunctionArgs ::= \c TT_YR IdentifierNode FunctionArg *
@ -130,13 +147,15 @@
* These production rules specify the types of expressions formed.
*
* \par
* ExprNode ::= CastExprNode | ConstantNode | IdentifierNode | FuncCallExprNode | OpExprNode | ImplicitVariable
* 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
* FuncCallExprNode ::= IdentifierNode \c TT_IZ IdentifierNode FunctionArgs ?
* TT_MKAY
*
* \par
* OpExprNode ::= UnaryOp | BinaryOp | NaryOp
@ -151,7 +170,9 @@
* 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
* 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
@ -166,7 +187,8 @@
* NaryOpArg ::= \c TT_AN ? ExprNode
*
* \par
* ImplicitVariable ::= \c TT_IT */
* 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.
/**
* Stores the main code block of a program.
*
* \see createMainNode(BlockNode *)
* \see deleteMainNode(MainNode *) */
* \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.
/**
* Stores a declaration statement. This statement creates a new variable in a
* given scope and optionally initializes it to an expression.
*
* \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 *) */
* \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
/**
* 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 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 *) */
* 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
/**
* 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.
*
* \see createLoopStmtNode(IdentifierNode *, IdentifierNode *, ExprNode *, ExprNode *, BlockNode *)
* \see deleteLoopStmtNode(LoopStmtNode *) */
*/
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__ */

View File

@ -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

View File

@ -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

View File

@ -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
/**
* 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).
*
* \retval 0 The string of characters is not an integer.
* \retval 1 The string of characters is an integer.
* \param [in] image The string to check.
*
* \see isFloat(const char *)
* \see isString(const char *)
* \see isIdentifier(const char *) */
int isInteger(const char *image) /**< [in] The string of characters to compare. */
* \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]*
/**
* Checks if a string follows the format for a decimal. Specifically, it checks
* if the string 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.
* \param [in] image The string to check.
*
* \see isInteger(const char *)
* \see isString(const char *)
* \see isIdentifier(const char *) */
int isFloat(const char *image) /**< [in] The string of characters to compare. */
* \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.
/**
* Checks if a string follows the format for a string literal. Specifically, it
* checks if the string matches the regular expression: (".*").
*
* \retval 0 The string of characters is not a string.
* \retval 1 The string of characters is a string.
* \param [in] image The string to check.
*
* \see isInteger(const char *)
* \see isFloat(const char *)
* \see isIdentifier(const char *) */
int isString(const char *image) /**< [in] The string of characters to compare. */
* \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_]*
/**
* 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_]*).
*
* \retval 0 The string of characters is not an identifier.
* \retval 1 The string of characters is an identifier.
* \param image [in] The string to check.
*
* \see isInteger(const char *)
* \see isFloat(const char *)
* \see isString(const char *) */
int isIdentifier(const char *image) /**< [in] The string of characters to compare. */
* \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.
/**
* Creates a token.
*
* \return A pointer to a Token structure with the desired properties.
* \param [in] type The type of token to create.
*
* \retval NULL malloc was unable to allocate memory.
* \param [in] image The string that represents the token.
*
* \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. */
* \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.
/**
* Deletes a token.
*
* \pre \a token points to a Token structure created by createToken(TokenType, const char *, const char *, unsigned int).
* \param [in,out] token The token to delete.
*
* \post The memory at \a token and all of its elements will be freed.
*
* \see createToken(TokenType, const char *, const char *, unsigned int) */
* \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.
/**
* Adds a token to a list.
*
* \note \a list may be NULL in which case a new list is created.
* \param [in,out] list The list of tokens to add \a token to.
*
* \pre \a num is the number of elements in \a list.
* \param [in,out] num The number of tokens 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.
* \param [in] token The token to add to \a list.
*
* \retval 0 realloc was unable to allocate memory.
* \retval 1 \a node was added to \a list.
* \post \a token will be added to the end of \a list and the size of \a list
* will be updated.
*
* \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. */
* \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.
/**
* Deletes a list of tokens.
*
* \pre \a list was created by and contains items added by addToken(Token ***, unsigned int *, Token *).
* \param list [in,out] The list of tokens to delete.
*
* \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. */
* \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.
/**
* Matches lexemes against a string. Traverses \a lexemes starting at \a start
* and compares lexeme images to space-delimited substrings from \a match.
*
* \pre \a lexemes was created by scanBuffer(const char *, unsigned int, const char *).
* \param lexemes [in] The list of lexemes to match from.
*
* \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. */
* \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.
/**
* 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.
*
* \pre \a lexemes was created by scanBuffer(const char *, unsigned int, const char *).
* \param lexemes [in] A list of lexemes to search for keywords in.
*
* \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.
* \param start [in,out] The position within \a lexemes to begin searching for
* keywords.
*
* \return A pointer to a newly created keyword Token structure.
* \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.
*
* \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. */
* \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.
/**
* Converts a list of lexemes into tokens. Also parses integers, floats, and
* strings into tokens with semantic meaning.
*
* \pre \a list was created by scanBuffer(const char *, unsigned int, const char *).
* \param list [in] A list of lexemes to tokenize.
*
* \return A pointer to an array of Token structures representing the tokenized
* form of the input lexeme stream.
* \return A list of tokens generated from \a list.
*
* \retval NULL An unrecognized token was encountered or memory allocation
* failed. */
Token **tokenizeLexemes(LexemeList *list) /**< [in] A pointer to a LexemeList structure to tokenize. */
* \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);
}

View File

@ -1,4 +1,5 @@
/** Structures and functions for grouping lexemes into tokens. The tokenizer
/**
* 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
@ -8,7 +9,8 @@
*
* \author Justin J. Meza
*
* \date 2010 */
* \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.
/**
* 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 with the token image. */
* \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__ */

View File

@ -36860,15 +36860,22 @@ static const long codepoints[] = {
#define NUM_UNICODE 18426
/** Performs a binary search on an array of strings.
/**
* Performs a binary search on an array of strings.
*
* \return The index of the matching entry, if found.
* \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.
*
* \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. */
* \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.
/**
* Converts a Unicode normative name to a Unicode code point.
*
* \return The Unicode code point corresponding to the given Unicode name.
* \param [in] name The Unicode normative name to convert.
*
* \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. */
* \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.
/**
* Converts a Unicode code point to a UTF-8 character.
*
* \return The number of characters in the converted multi-byte 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.
*
* \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. */
* \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) {

View File

@ -1,11 +1,13 @@
/** Data and functions for converting from Unicode normative names to
/**
* Data and functions for converting from Unicode normative names to Unicode
* code points.
*
* \file unicode.h
*
* \author Justin J. Meza
*
* \date 2010 */
* \date 2010-2011
*/
#ifndef __UNICODE_H__
#define __UNICODE_H__