123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- import cPickle as pickle
- import os
- import sys
- from grammar_compiler_visitor import GrammarCompilerVisitor
- from hutnparser import Parser, Tree
- from meta_grammar import Grammar
- from cached_exception import CachedException
- global parsers
- parsers = {}
- def read(filename):
- with open(filename, 'r') as f:
- return f.read()
- def do_parse(inputfile, grammarfile):
- new_grammar = True
- picklefile = grammarfile + ".pickle"
- if grammarfile not in parsers:
- try:
- if os.path.getmtime(picklefile) > os.path.getmtime(grammarfile):
- # Pickle is more recent than grammarfile, so use it
- grammar = pickle.load(open(picklefile, 'rb'))
- new_grammar = False
- else:
- # Will be catched immediately
- raise Exception("Pickle is invalid!")
- except:
- result = parser = Parser(Grammar(), hide_implicit = True).parse(read(grammarfile))
- if result['status'] != Parser.Constants.Success:
- print 'not a valid grammar!'
- print result
- tree = result['tree']
- visitor = GrammarCompilerVisitor()
- structure = visitor.visit(tree)
- grammar = Grammar()
- grammar.rules = structure['rules']
- grammar.tokens = structure['tokens']
- pickle.dump(grammar, open(picklefile, 'wb'), pickle.HIGHEST_PROTOCOL)
- parsers[grammarfile] = grammar
- else:
- new_grammar = False
- grammar = parsers[grammarfile]
- picklefile = inputfile + ".pickle"
- try:
- if new_grammar:
- # Stop anyway, as the grammar is new
- raise Exception()
- if os.path.getmtime(picklefile) > os.path.getmtime(inputfile):
- # Pickle is more recent than inputfile, so use it
- result = pickle.load(open(picklefile, 'rb'))
- else:
- # Inputfile has changed
- raise Exception()
- except:
- result = Parser(grammar, line_position = True).parse(read(inputfile))
- if result['status'] != Parser.Constants.Success:
- msg = "%s:%s:%s: %s" % (inputfile, result["line"], result["column"], result["text"])
- raise Exception(msg)
- pickle.dump(result, open(picklefile, 'wb'), pickle.HIGHEST_PROTOCOL)
- return result
- def find_file(filename, include_paths):
- import os.path
- include_paths = ["."] + \
- [os.path.abspath(os.path.dirname(working_file))] + \
- [os.path.abspath("%s/../includes/" % (os.path.dirname(os.path.abspath(__file__))))] + \
- include_paths + \
- []
- attempts = []
- for include in include_paths:
- testfile = include + os.sep + filename
- if os.path.isfile(os.path.abspath(testfile)):
- return os.path.abspath(testfile)
- else:
- attempts.append(os.path.abspath(testfile))
- else:
- raise Exception("Could not resolve file %s. Tried: %s" % (filename, attempts))
- def do_compile(inputfile, grammarfile, visitors=[], include_paths = []):
- import os.path
- global working_file
- working_file = os.path.abspath(inputfile)
- result = do_parse(inputfile, grammarfile)
- error = result["status"] != Parser.Constants.Success
- if error:
- msg = "%s:%s:%s: %s" % (inputfile, result["line"], result["column"], result["text"])
- raise Exception(msg)
- else:
- for child in result["tree"].tail:
- child.inputfile = inputfile
- included = set()
- while True:
- for i, v in enumerate(result["tree"].tail):
- if v.head == "include":
- # Expand this node
- for j in v.tail:
- if j.head == "STRVALUE":
- f = str(j.tail[0])[1:-1]
- if f in included:
- subtree = []
- else:
- name = str(j.tail[0])[1:-1]
- subtree = do_parse(find_file(name, include_paths), grammarfile)["tree"].tail
- if subtree is None:
- raise Exception("Parsing error for included file %s" % find_file(name, include_paths))
- for t in subtree:
- t.inputfile = name
- included.add(f)
- # Found the string value, so break from the inner for ("searching for element")
- break
- # Merge all nodes in
- before = result["tree"].tail[:i]
- after = result["tree"].tail[i+1:]
- result["tree"].tail = before + subtree + after
- # Found an include node, but to prevent corruption of the tree, we need to start over again, so break from the outer for loop
- break
- else:
- # The outer for finally finished, so there were no includes remaining, thus terminate the infinite while loop
- break
- result["tree"].fix_tracability(inputfile)
- for visitor in visitors:
- visitor.visit(result["tree"])
- if visitors:
- return visitors[-1].dump()
- def main(input_file, grammar_file, mode, args=[], symbols=None):
- from prettyprint_visitor import PrettyPrintVisitor
- from prettyprint_visitor import PrintVisitor
- from semantics_visitor import SemanticsVisitor
- from bootstrap_visitor import BootstrapVisitor
- from primitives_visitor import PrimitivesVisitor
- from primitives_object_visitor import PrimitivesObjectVisitor
- from constructors_visitor import ConstructorsVisitor
- from constructors_object_visitor import ConstructorsObjectVisitor
- from model_visitor import ModelVisitor
- from model_object_visitor import ModelObjectVisitor
- modes = {
- "N" : [],
- "P" : [PrintVisitor],
- "PP" : [PrettyPrintVisitor],
- "S" : [SemanticsVisitor],
- "PS" : [SemanticsVisitor, PrimitivesVisitor],
- "PO" : [SemanticsVisitor, PrimitivesObjectVisitor],
- "BS" : [SemanticsVisitor, BootstrapVisitor],
- "CS" : [SemanticsVisitor, ConstructorsVisitor],
- "CO" : [SemanticsVisitor, ConstructorsObjectVisitor],
- "M" : [ModelVisitor],
- "MO" : [ModelObjectVisitor],
- }
- try:
- visitors = [v(args) for v in modes[mode]]
- result = do_compile(input_file, grammar_file, visitors)
- if symbols is not None and mode == "BS":
- symbols.update(visitors[-1].object_symbols)
- except CachedException:
- return True
- return result
- if __name__ == "__main__":
- if len(sys.argv) <= 2:
- print("Invocation: ")
- print(" %s input_file grammar_file mode [mode_params]*" % sys.argv[0])
- sys.exit(1)
- else:
- value = main(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4:])
- if value is not None:
- print(value)
|