| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- #!/usr/bin/env python
- """
- Template of a pyBison parser file
- This is actually a working parser, but so
- minimal as to be totally useless. Refer to the
- '.on_someTarget()' rule handler in the class
- 'Parser' below for more info.
- You can do much worse than to copy this file
- somewhere, and tinker away to your heart's content.
- """
- import sys
- from bison import BisonParser, BisonNode
- # -------------------------------------------
- # Our own custom base class for all objects
- # which get inserted into the parse tree
- # -------------------------------------------
- class ParseNode(BisonNode):
- """
- This is the base class from which all your
- parse nodes are derived.
- Add methods to this class as you need them
- """
- def __init__(self, **kw):
- BisonNode.__init__(self, **kw)
- def __str__(self):
- """Customise as needed"""
- return "<%s instance at 0x%x>" % (self.__class__.__name__, hash(self))
- def __repr__(self):
- """Customise as needed"""
- return str(self)
- def dump(self, indent=0):
- """
- Dump out human-readable, indented parse tree
- Customise as needed - here, or in the node-specific subclasses
- """
- BisonNode.dump(self, indent) # alter as needed
- # ----------------------------------------------------
- # Now, we need to define a node class for each parse
- # target. (This is completely optional, but it can
- # turn out to be a PITA if you don't).
- # ----------------------------------------------------
- class someTarget_Node(ParseNode):
- """
- Holds a "someTarget" parse target and its components.
- """
- def __init__(self, **kw):
- ParseNode.__init__(self, **kw)
- def dump(self, indent=0):
- ParseNode.dump(self, indent)
- # ----------------------------------------------------
- # Now, at last, we get to the main Parser class itself
- # ----------------------------------------------------
- class Parser(BisonParser):
- """
- Describe your parser here
- """
- # basename of binary parser engine dynamic lib
- bisonEngineLibName = "template-engine"
- # ----------------------------------------------------------------
- # lexer tokens - these must match those in your lex script (below)
- # ----------------------------------------------------------------
- tokens = [ 'WORD' ]
- # ------------------------------
- # precedences
- # ------------------------------
- precedences = (
- #('left', ('aTarget1', 'aTarget2',..., 'aTargetn')),
- #('right', ('another_target1', 'another_target2',..., 'another_targetn')),
- )
- # ---------------------------------------------------------------
- # These methods are the python handlers for the bison targets.
- # (which get called by the bison code each time the corresponding
- # parse target is unambiguously reached)
- #
- # WARNING - don't touch the method docstrings unless you know what
- # you are doing - they are in bison rule syntax, and are passed
- # verbatim to bison to build the parser engine library.
- # ---------------------------------------------------------------
- # Declare the start target here (by name)
- start = "someTarget"
- def on_someTarget(self, target, option, names, values):
- """
- someTarget
- :
- | someTarget WORD
- """
- print "on_someTarget: %s %s" % (option, repr(values))
- node = someTarget_Node(target=target,
- option=option,
- names=names,
- values=values)
- return node
- # -----------------------------------------
- # raw lex script, verbatim here
- #
- # the script used here in this template is one which
- # breaks up the input stream into strings of
- # alphanumeric 'words' and discards everything else
- # -----------------------------------------
- lexscript = r"""
- %{
- #include <stdio.h>
- #include <string.h>
- #include "Python.h"
- #define YYSTYPE void *
- #include "tokens.h"
- int yylineno = 0;
- int yywrap() { return(1); }
- extern void *py_parser;
- extern void (*py_input)(PyObject *parser, char *buf, int *result, int max_size);
- #define returntoken(tok) yylval = PyString_FromString(strdup(yytext)); return (tok);
- #define YY_INPUT(buf,result,max_size) { (*py_input)(py_parser, buf, &result, max_size); }
- %}
- %%
- [a-zA-Z0-9\.]+ { returntoken(WORD); }
- [ \t\n] { /* ignore spaces/tabs/newlines */ }
- . { printf("unknown char %c ignored\n", yytext[0]); /* ignore bad chars */}
- %%
- //yywrap() { return(1); }
- """
- # -----------------------------------------
- # end raw lex script
- # -----------------------------------------
- # --------------------------------------------------
- # global functions to add in unit-testing our parser
- # (same as what gets generated by bison2py)
- # --------------------------------------------------
- def usage():
- print "%s: PyBison template parser" % sys.argv[0]
- print "Usage: %s [-k] [-v] [-d] [filename]" % sys.argv[0]
- print " -k Keep temporary files used in building parse engine lib"
- print " -v Enable verbose messages while parser is running"
- print " -d Enable garrulous debug messages from parser engine"
- print " filename path of a file to parse, defaults to stdin"
- def main(*args):
- """
- Unit-testing func
- """
- keepfiles = 0
- verbose = 0
- debug = 0
- filename = None
- for s in ["-h", "-help", "--h", "--help", "-?"]:
- if s in args:
- usage()
- sys.exit(0)
- if len(args) > 0:
- if "-k" in args:
- keepfiles = 1
- args.remove("-k")
- if "-v" in args:
- verbose = 1
- args.remove("-v")
- if "-d" in args:
- debug = 1
- args.remove("-d")
- if len(args) > 0:
- filename = args[0]
- p = Parser(verbose=verbose, keepfiles=keepfiles)
- if filename == None:
- print "(Reading from standard input - please type stuff)"
- tree = p.run(file=filename, debug=debug)
- return tree
- if __name__ == "__main__":
- main(*(sys.argv[1:]))
|