""" A Python script for combining GF with the semantics construction in MMT. """ import subprocess import requests import sys import os import time LOCATION_MMT_JAR = '/home/jfs/mmt/systems/MMT/deploy/mmt.jar' # GF_BIN = 'gf' # works if gf is in path GF_BIN = '/usr/bin/gf' MMT_PORT = '8080' GF_CATEGORY = 'S' # category for parsing MMT_ARCHIVE = 'Teaching/lbs1920' SEMANTICS_VIEW = 'http://mathhub.info/Teaching/lbs1920/assignment3/A3SemanticsConstruction' GF_CONCRETE_FILE = '/home/jfs/mmt/content/MathHub/Teaching/lbs1920/source/assignment3/Assignment3Eng.gf' # the following files have to be relative to the source directory in the MMT archive GF_ABSTRACT_FILES = ['assignment3/Assignment3.gf'] MMT_FILES = ['assignment3/assignment3.mmt'] # Basically a unique string that will never show up in the output (hopefully) COMMAND_SEPARATOR = "COMMAND_SEPARATOR===??!<>239'_" class GfRepl(object): def __init__(self, gf_bin = GF_BIN): self.pipe = os.pipe() # (read, write) self.gfproc = subprocess.Popen((gf_bin, '--run'), stdin = subprocess.PIPE, stderr = self.pipe[1], stdout = self.pipe[1]) self.commandcounter = 0 self.infile = os.fdopen(self.pipe[0]) # catch any initial messages sep = self.__writeSeparator() self.gfproc.stdin.flush() self.initialOutput = self.__getOutput(sep) def __writeCmd(self, cmd): if not cmd.endswith('\n'): cmd += '\n' self.gfproc.stdin.write(str.encode(cmd)) self.commandcounter += 1 def __writeSeparator(self): sep = COMMAND_SEPARATOR + str(self.commandcounter) self.gfproc.stdin.write(str.encode(f"ps \"{sep}\"\n")) return sep def __getOutput(self, sep): """ read lines until sep found """ output = "" for line in self.infile: if line.rstrip() == sep: return output output += line def handleLine(self, cmd): """ forwards a command to the GF Repl and returns the output """ self.__writeCmd(cmd) sep = self.__writeSeparator() self.gfproc.stdin.flush() return self.__getOutput(sep) printIndented = lambda s : print(' ' + s.replace(os.linesep, os.linesep + ' ')) # START MMT SERVER extensions = ['extension info.kwarc.mmt.glf.GlfConstructServer', 'extension info.kwarc.mmt.glf.GlfBuildServer'] mmt_proc = subprocess.Popen( ['java', '-jar', LOCATION_MMT_JAR, '-w', ' ; '.join(extensions) + ' ; server on ' + MMT_PORT]) print(('java', '-jar', LOCATION_MMT_JAR, '-w', '"' + ' ; '.join(extensions) + ' ; server on ' + MMT_PORT + '"')) # INITIALIZE GF REPL gfrepl = GfRepl(GF_BIN) print(f'Importing "{GF_CONCRETE_FILE}" into GF') r = gfrepl.handleLine('import ' + GF_CONCRETE_FILE) printIndented(r) def jsonPost(url, json): response = requests.post(url, json=json) try: return response.json() except: print("ERROR: FAILED TO PARSE RESPONSE AS JSON!") print("RESPONSE:") print(response.text) sys.exit(1) import time print("Sleeping a little to give MMT time to start-up the server...") time.sleep(2) # BUILD MMT FILES AND IMPORT ABSTRACT GRAMMAR INTO MMT build_url = 'http://localhost:' + MMT_PORT + '/:glf-build' buildrequests = [{'archive' : MMT_ARCHIVE, 'file' : f} for f in GF_ABSTRACT_FILES + MMT_FILES] for br in buildrequests: print('Trying to build ' + br['file']) resp = jsonPost(build_url, br) print(' ' + str(resp)) # START THE MAIN LOOP print('DONE') print('You may now enter sentences.') construct_url = 'http://localhost:' + MMT_PORT + '/:glf-construct' while True: sentence = input('> ') gfresponse = gfrepl.handleLine('parse -cat=' + GF_CATEGORY + ' "' + sentence.replace('"', '\\"') + '"').strip() printIndented(gfresponse) if gfresponse.startswith("The parser failed at token") or gfresponse == "The sentence is not complete": continue parsetrees = gfresponse.splitlines() request = {'semanticsView' : SEMANTICS_VIEW, 'ASTs' : parsetrees} r = jsonPost(construct_url, request) print(os.linesep.join(r))