#+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 *** [[http://www.nhplace.com/kent/Papers/cl-untold-story.html][Common Lisp: The Untold Story]] *** Theorem Proving Systems * [[http://pvs.csl.sri.com/index.shtml][PVS]] * [[http://www.cs.utexas.edu/users/moore/acl2/][ACL2]] *** Command Line Parsers Discussed a simple Python command line parser inspired by some of the early examples in the book [[http://www.amazon.com/Lisp-Small-Pieces-Christian-Queinnec/dp/0521545668][Lisp in Small Pieces]] -- see appendix. An even simpler command line parser was discussed, with possible functional variations -- also see appendix. *** [[http://www.clozure.com/clozurecl.html][Clozure]] *** JavaScript * [[http://nodejs.org/][node.js]] * [[http://underscorejs.org/][underscore.js]] #+latex: \newpage ** Appendix *** References * [[http://www.torfree.net/][Toronto Free Net]] * [[http://bentobox.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) #+end_src #+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 #+end_src |