Index: compile_rules.py ================================================================== --- compile_rules.py +++ compile_rules.py @@ -2,10 +2,11 @@ import re import traceback import json import compile_rules_js_convert as jsconv +import compile_rules_graph as crg dDEF = {} lFUNCTIONS = [] @@ -441,30 +442,24 @@ exit() # removing comments, zeroing empty lines, creating definitions, storing tests, merging rule lines print(" parsing rules...") global dDEF - lLine = [] lRuleLine = [] lTest = [] lOpt = [] + bGraph = False + lGraphRule = [] for i, sLine in enumerate(lRules, 1): if sLine.startswith('#END'): # arbitrary end printBookmark(0, "BREAK BY #END", i) break elif sLine.startswith("#"): # comment pass - elif sLine.startswith("@@@@"): - # rules graph call - m = re.match(r"@@@@GRAPH: *(\w+)@@@@", sLine.strip()) - if m: - #lRuleLine.append(["@GRAPHLINK", m.group(1)]) - printBookmark(1, "@GRAPH: " + m.group(1), i) - lRuleLine.append([i, "@@@@"+m.group(1)]) elif sLine.startswith("DEF:"): # definition m = re.match("DEF: +([a-zA-Z_][a-zA-Z_0-9]*) +(.+)$", sLine.strip()) if m: dDEF["{"+m.group(1)+"}"] = m.group(2) @@ -471,26 +466,42 @@ else: print("Error in definition: ", end="") print(sLine.strip()) elif sLine.startswith("TEST:"): # test - lTest.append("r{:<7}".format(i) + " " + sLine[5:].strip()) + lTest.append("{:<8}".format(i) + " " + sLine[5:].strip()) elif sLine.startswith("TODO:"): # todo pass elif sLine.startswith(("OPTGROUP/", "OPTSOFTWARE:", "OPT/", "OPTLANG/", "OPTDEFAULTUILANG:", "OPTLABEL/", "OPTPRIORITY/")): # options lOpt.append(sLine) - elif re.match("[  \t]*$", sLine): - # empty line - pass elif sLine.startswith("!!"): # bookmark m = re.match("!!+", sLine) nExMk = len(m.group(0)) if sLine[nExMk:].strip(): printBookmark(nExMk-2, sLine[nExMk:].strip(), i) + # Graph rules + elif sLine.startswith("@@@@GRAPH:"): + # rules graph call + m = re.match(r"@@@@GRAPH: *(\w+)", sLine.strip()) + if m: + printBookmark(1, "@GRAPH: " + m.group(1), i) + lRuleLine.append([i, "@@@@"+m.group(1)]) + bGraph = True + lGraphRule.append([i, sLine]) + bGraph = True + elif sLine.startswith("@@@@END_GRAPH"): + lGraphRule.append([i, sLine]) + bGraph = False + elif bGraph: + lGraphRule.append([i, sLine]) + # Regex rules + elif re.match("[  \t]*$", sLine): + # empty line + pass elif sLine.startswith((" ", "\t")): # rule (continuation) lRuleLine[-1][1] += " " + sLine.strip() else: # new rule @@ -561,14 +572,18 @@ print("Unnamed rules: " + str(nRULEWITHOUTNAME)) d = { "callables": sPyCallables, "callablesJS": sJSCallables, - "regex_gctests": sGCTests, - "regex_gctestsJS": sGCTestsJS, + "gctests": sGCTests, + "gctestsJS": sGCTestsJS, "paragraph_rules": mergeRulesByOption(lParagraphRules), "sentence_rules": mergeRulesByOption(lSentenceRules), "paragraph_rules_JS": jsconv.writeRulesToJSArray(mergeRulesByOption(lParagraphRulesJS)), "sentence_rules_JS": jsconv.writeRulesToJSArray(mergeRulesByOption(lSentenceRulesJS)) } d.update(dOptions) + + # compile graph rules + d2 = crg.make(lGraphRule, sLang, bJavaScript) + d.update(d2) return d Index: compile_rules_graph.py ================================================================== --- compile_rules_graph.py +++ compile_rules_graph.py @@ -1,14 +1,14 @@ # Create a Direct Acyclic Rule Graph (DARG) import re import traceback import json + import darg -dDEF = {} dACTIONS = {} dFUNCTIONS = {} def prepareFunction (s, bTokenValue=False): @@ -223,80 +223,40 @@ else: print("# Unknown action at line " + sIdAction) return None -def printBookmark (nLevel, sComment, nLine): - print(" {:>6}: {}".format(nLine, " " * nLevel + sComment)) - - -def make (spLang, sLang, bJavaScript): +def make (lRule, sLang, bJavaScript): "compile rules, returns a dictionary of values" # for clarity purpose, don’t create any file here - print("> read graph rules file...") - try: - lRules = open(spLang + "/rules_graph.grx", 'r', encoding="utf-8").readlines() - except: - print("Error. Rules file in project [" + sLang + "] not found.") - exit() - # removing comments, zeroing empty lines, creating definitions, storing tests, merging rule lines print(" parsing rules...") - global dDEF - lTest = [] lTokenLine = [] sActions = "" nPriority = 4 dAllGraph = {} sGraphName = "" - for i, sLine in enumerate(lRules, 1): + for i, sLine in lRule: sLine = sLine.rstrip() if "\t" in sLine: # tabulation not allowed print("Error. Tabulation at line: ", i) exit() - if sLine.startswith('#END'): - # arbitrary end - printBookmark(0, "BREAK BY #END", i) - break - elif sLine.startswith("#"): - # comments - pass - elif sLine.startswith("GRAPH_NAME: "): - # Graph name - m = re.match("GRAPH_NAME: +([a-zA-Z_][a-zA-Z_0-9]*)+", sLine.strip()) + elif sLine.startswith("@@@@GRAPH: "): + # rules graph call + m = re.match(r"@@@@GRAPH: *(\w+)", sLine.strip()) if m: sGraphName = m.group(1) if sGraphName in dAllGraph: print("Error. Group name " + sGraphName + " already exists.") exit() dAllGraph[sGraphName] = [] else: - print("Error. Graph name not found in", sLine.strip()) + print("Error. Graph name not found at line", i) exit() - elif sLine.startswith("DEF:"): - # definition - m = re.match("DEF: +([a-zA-Z_][a-zA-Z_0-9]*) +(.+)$", sLine.strip()) - if m: - dDEF["{"+m.group(1)+"}"] = m.group(2) - else: - print("Error in definition: ", end="") - print(sLine.strip()) - elif sLine.startswith("TEST:"): - # test - lTest.append("g{:<7}".format(i) + " " + sLine[5:].strip()) - elif sLine.startswith("TODO:"): - # todo - pass - elif sLine.startswith("!!"): - # bookmarks - m = re.search("^!!+", sLine) - nExMk = len(m.group(0)) - if sLine[nExMk:].strip(): - printBookmark(nExMk-2, sLine[nExMk:].strip(), i) elif sLine.startswith("__") and sLine.endswith("__"): # new rule group m = re.match("__(\\w+)(!\\d|)__", sLine) if m: sRuleName = m.group(1) @@ -318,24 +278,19 @@ dAllGraph[sGraphName].append((j, sRuleName, sTokenLine, sActions, nPriority)) lTokenLine.clear() sActions = "" sRuleName = "" nPriority = 4 - elif sLine.startswith((" <<-", " <<-")): + elif re.search(" +<<- ", sLine): # actions sActions += " " + sLine.strip() elif sLine.startswith((" ")): lTokenLine.append([i, sLine.strip()]) else: print("Unknown line:") print(sLine) - # tests - print(" list tests...") - sGCTests = "\n".join(lTest) - sGCTestsJS = '{ "aData2": ' + json.dumps(lTest, ensure_ascii=False) + " }\n" - # processing rules print(" preparing rules...") for sGraphName, lRuleLine in dAllGraph.items(): lPreparedRule = [] for i, sRuleGroup, sTokenLine, sActions, nPriority in lRuleLine: @@ -378,13 +333,9 @@ print(sActionName, aAction) # Result d = { "graph_callables": sPyCallables, - "graph_gctests": sGCTests, "rules_graphs": dAllGraph, "rules_actions": dACTIONS } - return d - - Index: make.py ================================================================== --- make.py +++ make.py @@ -17,11 +17,10 @@ from distutils import dir_util, file_util import dialog_bundled import compile_rules -import compile_rules_graph import helpers import lex_build sWarningMessage = "The content of this folder is generated by code and replaced at each build.\n" @@ -192,15 +191,12 @@ dVars = xConfig._sections['args'] dVars['locales'] = dVars["locales"].replace("_", "-") dVars['loc'] = str(dict([ [s, [s[0:2], s[3:5], ""]] for s in dVars["locales"].split(" ") ])) ## COMPILE RULES - dResultRegex = compile_rules.make(spLang, dVars['lang'], bJavaScript) - dVars.update(dResultRegex) - - dResultGraph = compile_rules_graph.make(spLang, dVars['lang'], bJavaScript) - dVars.update(dResultGraph) + dResult = compile_rules.make(spLang, dVars['lang'], bJavaScript) + dVars.update(dResult) ## READ GRAMMAR CHECKER PLUGINS print("PYTHON:") print("+ Plugins: ", end="") sCodePlugins = "" @@ -231,14 +227,11 @@ print() # TEST FILES with open("grammalecte/"+sLang+"/gc_test.txt", "w", encoding="utf-8", newline="\n") as hDstPy: hDstPy.write("# TESTS FOR LANG [" + sLang + "]\n\n") - hDstPy.write("# REGEX RULES\n\n") - hDstPy.write(dVars['regex_gctests']) - hDstPy.write("\n\n\n# GRAPH RULES\n\n") - hDstPy.write(dVars['graph_gctests']) + hDstPy.write(dVars['gctests']) hDstPy.write("\n") createOXT(spLang, dVars, xConfig._sections['oxt'], spLangPack, bInstallOXT) createServerOptions(sLang, dVars)