#
# Required version of omake
#
OMakeVersion(0.9.4, 0.9.4)

########################################################################
# Copyright (C) 2003-2004 Jason Hickey and Mojave Group
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this file, to deal in the File without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the File, and to permit persons to whom the File
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the File.
#
# THE FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# FILE OR THE USE OR OTHER DEALINGS IN THE FILE.

########################################################################
# This file defines the Pervasives module--the standard module
# open to every program.  This is a bootstrap file.  The syntax
# here is mainly normal, but it is assumed that the basic classes
# are empty at this point.  You never need to assume this again.
#
class Pervasives

########################################################################
# \begin{doc}
#
# \section{The Pervasives Object}
#
# The \verb+Pervasives+ object is the toplevel object that is opened
# to all programs.  In addition to the builtin functions that have
# been mentioned, it includes the following objects.
#
# \subsection{Object}
#
# Parent objects: none.
#
# The \verb+Object+ object is a generic object.
# It provides the following fields:
#
# \begin{itemize}
# \item \verb+$(o.object-length)+: the number of fields and methods in the object.
# \item \verb+$(o.object-mem <var>)+: returns \verb+true+ iff the \verb+<var>+ is a field
#    or method of the object.
# \item \verb+$(o.object-add <var>, <value>)+: adds the field to the object,
#    returning a new object.
# \item \verb+$(o.object-find <var>)+: fetches the field or method from the object;
#    it is equivalent to \verb+$(o.<var>)+, but the variable can be non-constant.
# \item \verb+$(o.object-map <fun>)+: maps a function over the object.  The function
#    should take two arguments; the first is a field name, the second is the
#    value of that field.  The result is a new object constructed from the
#    values returned by the function.
# \item \verb+o.object-foreach+: the \verb+foreach+ form is equivalent to \verb+map+,
#    but with altered syntax.
#
#    \begin{verbatim}
#    o.foreach(<var1>, <var2>)
#       <body>
#    \end{verbatim}
#
#    For example, the following function prints all the fields of an
#    object \verb+o+.
#
#    \begin{verbatim}
#    PrintObject(o) =
#       o.foreach(v, x)
#          println($(v) = $(x)
#    \end{verbatim}
#
#    The \verb+export+ form is valid in a \verb+foreach+ body.  The following
#    function collects just the field names of an object.
#
#    \begin{verbatim}
#    FieldNames(o) =
#       names =
#       o.foreach(v, x)
#          names += $(v)
#          export
#       return $(names)
#    \end{verbatim}
# \end{itemize}
# \end{doc}
#
Object. +=
   class Object

   object-length() =
      return $(obj-length $(this))

   object-mem(v) =
      return $(obj-mem $(this), $(v))

   object-add(v, x) =
      return $(obj-add $(this), $(v), $(x))

   object-find(v) =
      return $(obj-find $(this), $(v))

   object-map(f) =
      return $(obj-map $(this), $(f))

   object-foreach(body, v, x) =
      return $(obj-map $(this), $(v), $(x), $(body))

#
# The runtime doesn't know to include the Object module, so do it now.
#
extends $(Object)

########################################################################
# \begin{doc}
# \subsection{Number}
#
# Parent objects: \verb+Object+.
#
# The \verb+Number+ object is the parent object for integers
# and floating-point numbers.
# \end{doc}
#
Number. +=
   class Number
   extends $(Object)

#
# \begin{doc}
# \subsection{Int}
#
# Parent objects: \verb+Number+.
#
# The \verb+Int+ object represents integer values.
# \end{doc}
#
Int. +=
   class Int
   extends $(Number)

#
# \begin{doc}
# \subsection{Int}
#
# Parent objects: \verb+Number+.
#
# The \verb+Float+ object represents floating-point numbers.
# \end{doc}
#
Float. +=
   class Float
   extends $(Number)

########################################################################
# \begin{doc}
# \subsection{Sequence}
#
# Parent objects: \verb+Object+.
#
# The \verb+Sequence+ object represents a generic object containing
# sequential elements.  It provides the following methods.
#
# \begin{itemize}
# \item \verb+$(s.length)+: the number of elements in the sequence.
# \item \verb+$(s.map <fun>)+: maps a function over the fields in the sequence.
#    The function
#    should take two arguments; the first is a field name, the second is the
#    value of that field.  The result is a new sequence constructed from the
#    values returned by the function.
# \item \verb+s.foreach+: the \verb+foreach+ form is equivalent to \verb+map+,
#    but with altered syntax.
#
#    \begin{verbatim}
#    s.foreach(<var1>, <var2>)
#       <body>
#    \end{verbatim}
#
#    For example, the following function prints all the elements of the sequence.
#
#    \begin{verbatim}
#    PrintSequence(s) =
#       s.foreach(x)
#          println(Elem = $(x))
#    \end{verbatim}
#
#    The \verb+export+ form is valid in a \verb+foreach+ body.  The following
#    function counts the number of zeros in the sequence.
#
#    \begin{verbatim}
#    Zeros(s) =
#       count = $(int 0)
#       s.foreach(v)
#          if $(equal $(v), 0)
#             count = $(add $(count), 1)
#             export
#          export
#       return $(count)
#    \end{verbatim}
# \end{itemize}
# \end{doc}
#
Sequence. +=
   class Sequence
   extends $(Object)

   length() =
      return $(sequence-length $(this))

   nth(i) =
      return $(sequence-nth $(this), $(i))

   rev() =
      return $(sequence-rev $(this))

   map(f) =
      return $(sequence-map $(f), $(this))

   foreach(body, v) =
      return $(sequence-map $(body), $(v), $(this))

#
# \begin{doc}
# \subsection{Array}
#
# Parent objects: \verb+Sequence+.
#
# The \verb+Array+ is a random-access sequence.
# It provides the following additional methods.
#
# \begin{itemize}
# \item \verb+$(s.nth <i>)+: returns element \verb+i+ of the sequence.
# \item \verb+$(s.rev <i>)+: returns the reversed sequence.
# \end{itemize}
#
# \end{doc}
#
Array. +=
   class Array
   extends $(Sequence)

#
# \begin{doc}
# \subsection{String}
#
# Parent objects: \verb+Array+.
#
# The \verb+String+ object provides the following methods.
# \begin{itemize}
# \end{doc}
#
String. +=
    class String
    extends $(Array)

    #
    # \begin{doc}
    # \item \verb+$(s.explode)+: returns an array of the characters in \verb+s+.
    # \end{doc}
    #
    explode() =
       return $(explode $(this))
#
# \begin{doc}
# \end{itemize}
# \end{doc}
#

#
# \begin{doc}
# \subsection{Map}
#
# Parent objects: \verb+Sequence+.
#
# A \verb+Map+ is a map from strings to values.  It provides the following
# methods.
#
# \begin{itemize}
# \item \verb+$(o.mem <var>)+: returns \verb+true+ iff the \verb+<var>+ is defined
#    in the map.
# \item \verb+$(o.add <var>, <value>)+: adds the field to the map,
#    returning a new map.
# \item \verb+$(o.find <var>)+: fetches the field from the map.
# \item \verb+$(o.map <fun>)+: maps a function over the map.  The function
#    should take two arguments; the first is a field name, the second is the
#    value of that field.  The result is a new object constructed from the
#    values returned by the function.
# \item \verb+o.foreach+: the \verb+foreach+ form is equivalent to \verb+map+,
#    but with altered syntax.
#
#    \begin{verbatim}
#    o.foreach(<var1>, <var2>)
#       <body>
#    \end{verbatim}
#
#    For example, the following function prints all the fields of an
#    object \verb+o+.
#
#    \begin{verbatim}
#    PrintObject(o) =
#       o.foreach(v, x)
#          println($(v) = $(x)
#    \end{verbatim}
#
#    The \verb+export+ form is valid in a \verb+foreach+ body.  The following
#    function collects just the field names of the map.
#
#    \begin{verbatim}
#    FieldNames(o) =
#       names =
#       o.foreach(v, x)
#          names += $(v)
#          export
#       return $(names)
#    \end{verbatim}
# \end{itemize}
# \end{doc}
#
Map. +=
    class Map
    extends $(Sequence)

    mem(v) =
        return $(map-mem $(this), $(v))

    add(v, x) =
        return $(map-add $(this), $(v), $(x))

    find(v) =
        return $(map-find $(this), $(v))

    map(f) =
        return $(map-map $(this), $(f))

    foreach(body, v, x) =
        return $(map-map $(this), $(v), $(x), $(body))

########################################################################
# \begin{doc}
# \subsection{Fun}
#
# Parent objects: \verb+Object+.
#
# The \verb+Fun+ object provides the following methods.
# \begin{itemize}
# \item \verb+$(f.arity)+: the arity if the function.
# \end{itemize}
# \end{doc}
#
Fun. +=
   class Fun
   extends $(Object)

   arity() =
      return $(sequence-length $(this))

########################################################################
# \begin{doc}
# \subsection{Rule}
#
# Parent objects: \verb+Object+.
#
# The \verb+Rule+ object represents a build rule.
# It does not currently have any methods.
# \end{doc}
#
Rule. +=
   class Rule
   extends $(Object)

########################################################################
# \begin{doc}
# \subsection{Node}
#
# Parent objects: \verb+Object+.
#
# The \verb+Node+ object is the parent object for files and directories.
# It supports the following operations.
# \begin{itemize}
# \end{doc}
#
Node. +=
    class Node
    extends $(Object)

    #
    # \begin{doc}
    # \item \verb+$(node.stat)+: returns a \verb+stat+ object for the file.  If the
    # file is a symbolic link, the \verb+stat+ information is for the destination of
    # the link, not the link itself.
    #
    #
    # \item \verb+$(node.lstat)+: returns a \verb+stat+ object for the file or symbolic link.
    # \end{doc}
    #
    stat() =
       return $(public.stat $(this))

    lstat() =
       return $(public.lstat $(this))

    #
    # \begin{doc}
    # \item \verb+$(node.unlink)+: removes the file.
    # \item \verb+$(node.rename <file>)+: renames the file.
    # \item \verb+$(node.link <file>)+: creates a hard link \verb+<dst>+ to this file.
    # \item \verb+$(node.symlink <file>)+: create a symbolic link \verb+<dst>+ to this file.
    # \end{doc}
    #
    unlink() =
       return $(public.unlink $(this))

    rename(file) =
       return $(public.rename $(this), $(file))

    link(file) =
       return $(public.link $(this), $(file))

    symlink(file) =
       return $(public.symlink $(this), $(file))

    #
    # \begin{doc}
    # \item \verb+$(node.chmod <perm>)+: change the permission of this file.
    # \item \verb+$(node.chown <uid>, <gid>)+: change the owner and group id of this file.
    # \end{doc}
    #
    chmod(perm) =
       return $(public.chmod $(this), $(perm))

    chown(uid, gid) =
       return $(public.chown $(this), $(uid), $(gid))
#
# \begin{doc}
# \end{itemize}
# \end{doc}
#

#
# \begin{doc}
# \subsection{File}
#
# Parent objects: \verb+Node+.
#
# The file object represents the name of a file.
# \end{doc}
#
File. +=
    class File
    extends $(Node)

#
# \begin{doc}
# \subsection{Dir}
#
# Parent objects: \verb+Node+.
#
# The \verb+Dir+ object represents the name of a directory.
# \end{doc}
#
Dir. +=
    class Dir
    extends $(Node)

########################################################################
# \begin{doc}
# \subsection{Channel}
#
# Parent objects: \verb+Object+.
#
# A \verb+Channel+ is a generic IO channel.
# It provides the following methods.
# \begin{itemize}
# \end{doc}
Channel. +=
    class Channel
    extends $(Object)

    #
    # \begin{doc}
    # \item \verb+$(o.close)+: close the channel.
    # \end{doc}
    #
    close() =
       public.close($(this))
#
# \begin{doc}
# \end{itemize}
# \end{doc}
#

########################################################################
# \begin{doc}
# \subsection{InChannel}
#
# Parent objects: \verb+Channel+.
#
# A \verb+InChannel+ is an input channel.  The variable \verb+stdin+ is the
# standard input channel.
#
# It provides the following methods.
# \begin{itemize}
# \end{doc}
#
InChannel. +=
    class InChannel
    extends $(Channel)

    #
    # \begin{doc}
    # \item \verb+$(InChannel.open <file>)+: open a new input channel.
    # \end{doc}
    #
    open(file) =
       return $(public.fopen $(file), r)
#
# \begin{doc}
# \end{itemize}
# \end{doc}
#

########################################################################
# \begin{doc}
# \subsection{OutChannel}
#
# Parent object: \verb+Channel+.
#
# A \verb+OutChannel+ is an output channel.  The variables \verb+stdout+
# and \verb+stderr+ are the standard output and error channels.
#
# It provides the following methods.
# \begin{itemize}
# \end{doc}
#
OutChannel. +=
    class OutChannel
    extends $(Channel)

    #
    # \begin{doc}
    # \item \verb+$(OutChannel.open <file>)+: open a new output channel.
    # \end{doc}
    #
    open(file) =
       return $(public.fopen $(file), w)

    #
    # \begin{doc}
    # \item \verb+$(OutChannel.append <file>)+: opens a new output channel,
    # appending to the file.
    # \end{doc}
    #
    append(file) =
       return $(public.fopen $(file), a)

    #
    # \begin{doc}
    # \item \verb+$(c.flush)+: flush the output channel.
    # \end{doc}
    #
    flush() =
        return $(public.flush $(this))

    #
    # \begin{doc}
    # \item \verb+$(c.print <string>)+: print a string to the channel.
    # \end{doc}
    #
    print(s) =
        return $(public.fprint $(this), $(s))

    #
    # \begin{doc}
    # \item \verb+$(c.println <string>)+: print a string to the channel,
    # followed by a line terminator.
    # \end{doc}
    #
    println(s) =
        return $(public.fprintln $(this), $(s))
#
# \begin{doc}
# \end{itemize}
# \end{doc}
#

########################################################################
# \begin{doc}
# \subsection{Location}
#
# Parent objects: \verb+Location+.
#
# The \verb+Location+ object represents a location in a file.
# \end{doc}
#
Location. +=
    class Location
    extends $(Object)

########################################################################
# \begin{doc}
# \subsection{Position}
#
# Parent objects: \verb+Position+.
#
# The \verb+Position+ object represents a stack trace.
# \end{doc}
#
Position. +=
    class Position
    extends $(Object)

########################################################################
# \begin{doc}
# \subsection{Exception}
#
# Parent objects: \verb+Object+.
#
# The \verb+Exception+ object is used as the base object for exceptions.
# It has no fields.
# \end{doc}
#
Exception. +=
    class Exception
    extends $(Object)

#
# \begin{doc}
# \subsection{RuntimeException}
#
# Parent objects: \verb+Exception+.
#
# The \verb+RuntimeException+ object represents an exception from the
# runtime system.  It has the following fields.
#
# \begin{itemize}
# \item \verb+position+: a string representing the location where the
#    exception was raised.
# \item \verb+message+: a string containing the exception message.
# \end{itemize}
# \end{doc}
#
RuntimeException. +=
    class RuntimeException
    extends $(Exception)

    position = no position
    message = no message

########################################################################
# System objects.
#
Select. +=
   class Select
   extends $(Object)

Pipe. +=
   class Pipe
   extends $(Object)

Stat. +=
   class Stat
   extends $(Object)

########################################################################
# The shell object.
#
# \begin{doc}
# \subsection{Shell}
#
# Parent objects: \verb+Object+.
#
# The \verb+Shell+ object contains the collection of builtin functions
# available as shell commands.
#
# You can define aliases by extending this object with additional methods.
# All methods in this class are called with one argument: a single array
# containing an argument list.
#
# \begin{itemize}
# \end{doc}
#
Shell. +=
   class Shell
   extends $(Object)

   #
   # \begin{doc}
   # \item \verb+echo+
   #
   # The \verb+echo+ function prints its arguments to the standard output channel.
   # \end{doc}
   #
   echo = $(echo)

   #
   # \begin{doc}
   # \item \verb+jobs+
   #
   # The \verb+jobs+ method prints the status of currently running commands.
   # \end{doc}
   #
   jobs = $(jobs)

   #
   # \begin{doc}
   # \item \verb+cd+
   #
   # The \verb+cd+ function changes the current directory.
   # Note that the current directory follows the usual scoping
   # rules.  For example, the following program lists the
   # files in the \verb+foo+ directory, but the current
   # directory is not changed.
   #
   # \begin{verbatim}
   #    section
   #       echo Listing files in the foo directory...
   #       cd foo
   #       ls
   #
   #    echo Listing files in the current directory...
   #    ls
   # \end{verbatim}
   # \end{doc}
   #
   cd = $(cd)

   #
   # \begin{doc}
   # \item \verb+bg+
   #
   # The \verb+bg+ method places a job in the background.
   # The job is resumed if it has been suspended.
   # \end{doc}
   #
   bg = $(bg)

   #
   # \begin{doc}
   # \item \verb+fg+
   #
   # The \verb+fg+ method brings a job to the foreground.
   # The job is resumed if it has been suspended.
   # \end{doc}
   #
   fg = $(fg)

   #
   # \begin{doc}
   # \item \verb+stop+
   #
   # The \verb+stop+ method suspends a running job.
   # \end{doc}
   #
   stop = $(stop)

   #
   # \begin{doc}
   # \item \verb+wait+
   #
   # The \verb+wait+ function waits for a running job to terminate.
   # It is not possible to wait for a suspended job.
   #
   # The job is not brought to the foreground.  If the \verb+wait+
   # is interrupted, the job continues to run in the background.
   # \end{doc}
   #
   wait = $(wait)

   #
   # \begin{doc}
   # \item \verb+kill+
   #
   # The \verb+kill+ function signal a job.
   #
   # \verb+kill [signal] <pid...>+.
   #
   # The signals are either numeric, or symbolic.
   # The symbolic signals are named as follows.
   #
   # ABRT, ALRM, HUP, ILL, KILL, QUIT, SEGV, TERM, USR1,
   # USR2, CHLD, STOP, TSTP, TTIN, TTOU, VTALRM, PROF.
   # \end{doc}
   #
   kill = $(kill)

   #
   # \begin{doc}
   # \item \verb+exit+
   #
   # The \verb+exit+ function terminates the current session.
   # \end{doc}
   #
   exit = $(exit)

   #
   # \begin{doc}
   # \item Win32 functions.
   #
   #     Win32 doesn't provide very many programs for scripting, except
   #     for the functions that are builtin to the DOS \verb+cmd.exe+.
   #     The following functions are defined on Win32 and only on Win32.
   #     On other systems, it is expected that these programs already
   #     exist.
   #
   # \begin{itemize}
   # \end{doc}
   #
   if $(equal $(OSTYPE), Win32)
       #
       # \begin{doc}
       # \item \verb+grep+
       #
       # \begin{verbatim}
       #    grep [-q] [-n] pattern files...
       # \end{verbatim}
       #
       # The \verb+grep+ function calls the \Prog{omake}
       # \verb+grep+ function.
       # \end{doc}
       #
       grep = $(grep)

       export
   #
   # \begin{doc}
   # \end{itemize}
   # \end{doc}
   #

   #
   # \begin{doc}
   # By default, \Prog{omake} uses internal versions of the following commands:
   # \verb+cp+, \verb+rm+, \verb+mkdir+, \verb+chmod+, \verb+ln+.
   # If you really want to use the standard system versions of these
   # commands, set the \verb+USE_SYSTEM_COMMANDS+ as one of the first
   # definitions in your \verb+OMakeroot+ file.
   #
   # \begin{itemize}
   # \end{doc}
   #
   if $(not $(defined USE_SYSTEM_COMMANDS))
       #
       # \begin{doc}
       # \item \verb+mkdir+
       #
       # \begin{verbatim}
       #     mkdir [-m <mode>] [-p] files
       # \end{verbatim}
       #
       # The \verb+mkdir+ function is used to create directories.
       # The -verb+-m+ option can be used to specify the permission
       # mode of the created directory.  If the \verb+-p+ option
       # is specified, the full path is created.
       # \end{doc}
       #
       mkdir = $(mkdir)

       #
       # \begin{doc}
       # \item \verb+cp+
       # \item \verb+mv+
       #
       # \begin{verbatim}
       #     cp [-f] [-i] [-v] src dst
       #     cp [-f] [-i] [-v] files dst
       #     mv [-f] [-i] [-v] src dst
       #     mv [-f] [-i] [-v] files dst
       # \end{verbatim}
       #
       # The \verb+cp+ function copies a \verb+src+ file to
       # a \verb+dst+ file, overwriting it if it already exists.
       # If more than one source file is specified, the final file
       # must be a directory, and the source files are copied
       # into the directory.
       #
       # \begin{itemize}
       # \item[-f] Copy files forcably, do not prompt.
       # \item[-i] Prompt before removing destination files.
       # \item[-v] Explain what is happening.
       # \end{itemize}
       # \end{doc}
       #
       cp = $(cp)
       mv = $(mv)

       #
       # \begin{doc}
       # \item \verb+rm+
       #
       # \begin{verbatim}
       #    rm [-f] [-i] [-v] [-r] files
       #    rmdir [-f] [-i] [-v] [-r] dirs
       # \end{verbatim}
       #
       # The \verb+rm+ function removes a set of files.
       # No warnings are issued if the files do not exist, or if
       # they cannot be removed.
       #
       # Options:
       # \begin{itemize}
       # \item[-f] Forcably remove files, do not prompt.
       # \item[-i] Prompt before removal.
       # \item[-v] Explain what is happening.
       # \item[-r] Remove contents of directories recursively.
       # \end{itemize}
       # \end{doc}
       #
       rm = $(rm)
       rmdir = $(rmdir)

       #
       # \begin{doc}
       # \item \verb+chmod+
       #
       # \begin{verbatim}
       #     chmod [-r] [-v] [-f] mode files
       # \end{verbatim}
       #
       # The \verb+chmod+ function changes the permissions on a set of
       # files or directories.  This function does nothing on Win32.
       # The \verb+mode+ may be specified as an octal number,
       # or in symbolic form \verb+[ugoa]*[+-=][rwxXstugo]+.
       # See the man page for \verb+chmod+ for details.
       #
       # Options:
       # \begin{itemize}
       # \item[-r] Change permissions of all files in a directory recursively.
       # \item[-v] Explain what is happening.
       # \item[-f] Continue on errors.
       # \end{itemize}
       # \end{doc}
       #
       chmod = $(chmod)

       export
   #
   # \begin{doc}
   # \end{itemize}
   # \end{doc}
   #

#
# \begin{doc}
# \end{itemize}
# \end{doc}
#

#
# These are all documented in Omake_builtin_io_fun.
#
Token. =
   class Token

   loc =
   name =
   value =

   unit(loc, name) =
      this.loc = $(loc)
      this.name = $(name)
      return $(this)

   pair(loc, name, value) =
      this.loc = $(loc)
      this.name = $(name)
      this.value = $(value)
      return $(this)

Lexer. +=
   class Lexer
   extends $(Object)

   #
   # For interpreting the rules
   #
   rule = $(lex-rule)

   #
   # To use a lexer, you would normally hand it a channel
   #
   from-channel(channel) =
      this.channel = $(channel)
      return $(this)

   lex() =
      return $(lex-engine $(this.channel))

   lex-channel(channel) =
      return $(lex-engine $(channel))

Parser. +=
   class Parser
   extends $(Object)

   #
   # For interpreting the rules
   #
   rule         = $(parse-rule)

   #
   # You must set the lexer
   #
   lexer =

   #
   # Start symbols
   #
   start        = $(parse-start)

   #
   # Precedence operations
   #
   left         = $(parse-left)
   right        = $(parse-right)
   nonassoc     = $(parse-nonassoc)

   #
   # Manipulating the current precedence level
   #
   prec-min     = .min
   prec-max     = .max
   current-prec = .min

   #
   # Build the parser
   #
   build        = $(parse-build)

   #
   # Main parsing function
   #
   parse(sym) =
      return $(parse-engine $(sym))

   parse-channel(sym, channel) =
      lexer = $(lexer.from-channel $(channel))
      return $(parse-engine $(sym))

   parse-file(sym, file) =
      channel = $(fopen $(file), r)
      lexer = $(lexer.from-channel $(channel))
      result = $(parse-engine $(sym))
      close($(channel))
      return $(result)

