Past Meetings‎ > ‎

Discussion Meeting (June 2012)

#+latex: \newpage
* Toronto Lisp Meeting 2012-06-05
** Present
   * Brian
   * Dann
   * Jos'h
   * Paul
   * Ravi
   * Sebastian

** Business
*** Shall we meet through summer?
    6 ayes, 0 nays

#+latex: \newpage
** Discussion
*** [[][Common Lisp: The Untold Story]]
*** Theorem Proving Systems
    * [[][PVS]]
    * [[][ACL2]]
*** Command Line Parsers
    Discussed a simple Python command line parser inspired by some of the
    early examples in the book [[][Lisp in Small Pieces]] -- see appendix. An
    even simpler command line parser was discussed, with possible
    functional variations -- also see appendix.
*** [[][Clozure]]
*** JavaScript
    * [[][node.js]]
    * [[][underscore.js]]

#+latex: \newpage
** Appendix
*** References
    * [[][Toronto Free Net]]
    * [[][Bento Box]]
#+latex: \newpage
*** Lisp in Small Pieces Inspired Parser
    In an attempt to make a somewhat readable example, actual
    functionality (the calc() function, etc.) has been elided. Comments
    provide more detail.
    #+begin_src python
      import sys, re
      # This provides a nice, self documenting help screen.
      def usage(g):
          print "Usage: %s [options]...\n" % sys.argv[0]
          print g[0]; print
          rows = [(" ".join(rule[0]), " ".join(rule[1:]), help)
                  for rule, help, action in g[1:]]
          fmt = "%%-%ds %%-%ds %%s" % (
              max([len(x[0]) for x in rows]),
              max([len(x[1]) for x in rows]))
          for row in sorted(rows): print fmt % row
          raise SystemExit
      # This dictionary describes the types recognized. Specify the type
      # name as a string and a compiled regexp that will match it.
      types = {"number": re.compile("^-?\d+$"),
               "pyname": re.compile("^[a-zA-Z_][a-zA-Z0-9_]+$"),
               "op":     re.compile("^[-+/*]$"),
               # Add more types here or in the calling program...
      # This list describes the program and the options it will take. The
      # first entry to the list is the program description. The remaining
      # entries are the specifications for each command line option. A
      # specification consists of a list containing a grammar, a help
      # message and an action. The action can be a function or a string to
      # exec. The grammar is a list, the first element describes the
      # alternatives for the option itself, and the remaining elements
      # describe the grammar required.
      grammar = ["This is a demonstration of the parser.",
                 (("-? -h --help".split(),), "Display help screen.", "usage(g)"),
                 (("-v --verbose".split(),), "Increase verbosity.",  "verbose += 1"),
                 (("-c calc".split(), "number", "op", "number"),
                  "Simple calculations.",
                  "print calc(tt[2], tt[1], tt[3])"),
                 # Add new entries here, or in the calling program...
      # The parse function applies the grammar rules
      # successively. Non-recursive.
      def parse(tt, g=None):
          while len(tt):
              for rule, help, action in g[1:]:
                  if len(rule) > len(tt): continue
                  if tt[0] not in rule[0]: continue
                  if None in [types[p].match(t) for p, t in zip(rule[1:], tt[1:])]:
                      print "ERROR: Syntax error after '%s'.\n" % tt[0]; usage(g)
                  elif callable(action): apply(action); tt = tt[len(rule):]; break
                  else: exec(action);                   tt = tt[len(rule):]; break
              else: print "ERROR: Unrecognized token '%s'.\n" % tt[0]; usage(g)
      # If this file is run standalone, then parse will be called against
      # the command line options. Otherwise it can be imported as a module.
      if "__main__" == __name__: verbose = 0; parse(sys.argv[1:], g)
#+latex: \newpage
*** Tiny Command Line Parser
    This is a very simple parser, not suitable for order dependant
    arguments, but easy to use and remember as a code idiom.
    #+begin_src python
      import sys
      args = sys.argv[1:]; args.reverse()
      hold = None
      for arg in args:
          if   arg in ("-?", "-h", "--help"): usage()
          elif arg in ("-v", "--verbose"): verbose += 1
          elif arg in ("-f", "--file"): file = hold
          else: hold = arg