From: PASCALE NOYRET Date: Fri, 26 Jan 2024 12:04:30 +0000 (+0100) Subject: sauvegarde 26 janvier X-Git-Tag: V_demo_28_mars_2024~46 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=ebf9a139f3c0ffa121db615a04736990b26d4fff;p=tools%2Feficas.git sauvegarde 26 janvier --- diff --git a/Accas/IO/__init__.py b/Accas/IO/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/Accas/IO/convert/CMakeLists.txt b/Accas/IO/convert/CMakeLists.txt new file mode 100644 index 00000000..0e12f7a0 --- /dev/null +++ b/Accas/IO/convert/CMakeLists.txt @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# CONFIGURATION MANAGEMENT OF EDF VERSION +# ====================================================================== +# COPYRIGHT (C) 1991 - 2024 EDF R&D WWW.CODE-ASTER.ORG +# THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY +# IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY +# THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR +# (AT YOUR OPTION) ANY LATER VERSION. +# +# THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT +# WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF +# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU +# GENERAL PUBLIC LICENSE FOR MORE DETAILS. +# +# YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE +# ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, +# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. +# +# +# ====================================================================== + +install ( FILES __init__.py parseur_python.py convert_python.py convert_TELEMAC.py + convert_map.py + DESTINATION ${CMAKE_INSTALL_PREFIX}/convert + ) + + + + +### Local Variables: +### mode: cmake +### End: diff --git a/Accas/IO/convert/__init__.py b/Accas/IO/convert/__init__.py new file mode 100644 index 00000000..2bc11929 --- /dev/null +++ b/Accas/IO/convert/__init__.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2007-2024 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +""" + This package contains all input format converters + into objects understandable by EFICAS. + + These converters are implemented in the form of plugins +""" +import os +from Accas.IO import pluginloader +currentDir = os.path.abspath(os.path.dirname(__file__)) +plugins = pluginloader.PluginLoader(currentDir) diff --git a/Accas/IO/convert/convert_TELEMAC.py b/Accas/IO/convert/convert_TELEMAC.py new file mode 100644 index 00000000..da93b15b --- /dev/null +++ b/Accas/IO/convert/convert_TELEMAC.py @@ -0,0 +1,557 @@ +# Copyright (C) 2007-2024 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +import re +from Accas.extensions.eficas_translation import tr + +# import traceback +# traceback.print_stack() + +""" +this module contains the parser to read .cas files +convert them in python +""" + +from Accas.IO.convert.convert_python import Pythonparser + +pattern_comment_slash = re.compile(r"^\s*/") +pattern_comment_slash_vide = re.compile(r"^\s*/\s*$") +pattern_comment_tiret = re.compile(r"^\s*/-*/*$") +pattern_eta = re.compile(r".*&ETA.*") +pattern_fin = re.compile(r".*&FIN.*") +pattern_oui = re.compile(r"^\s*(oui|OUI|YES|yes|TRUE|true|vrai|VRAI)\s*$") +pattern_non = re.compile(r"^\s*(non|NON|NO|no|FALSE|false|faux|FAUX)\s*$") +pattern_blanc = re.compile(r"^\s*$") +pattern_listeVide = re.compile(r"^\s*'\s*'\s*$") +pattern_commence_par_quote = re.compile(r'^\s*[\'"].*') +pattern_finit_par_virgule_ou_affect = re.compile(r"^.*(,|;|=|:)\s*$") + +pattern_ligne = re.compile(r"^\s*(?P[^=:]*)\s*[:=]\s*(?P.*)$") + +pattern_variables = re.compile( + r"^\s*(?PC_VSM_PRINTOUT_SELECTION|COUPLAGE AVEC|COUPLING WITH|VARIABLES FOR GRAPHIC PRINTOUTS|VARIABLES POUR LES SORTIES GRAPHIQUES|VARIABLES TO BE PRINTED|VARIABLES A IMPRIMER|VARIABLES FOR 3D GRAPHIC PRINTOUTS|VARIABLES POUR LES SORTIES GRAPHIQUES 3D|VARIABLES POUR LES SORTIES GRAPHIQUES 2D|VARIABLES FOR 2D GRAPHIC PRINTOUTS)\s*[:=]\s*(?P[']?)(?P[A-Za-z]+(\d*|\*)([,;][A-Za-z]+(\d*|\*))*)\s*(?P=quote)(?P.*)$" +) + +# Attention aux listes de flottants +pattern_liste = re.compile( + r"^\s*(?P[+-.\w]+(\s*;\s*[+-.\w]+)+)\s*(?P.*)$" +) +pattern_liste_texte = re.compile( + r"^\s*(?P('.*(';\s*))+('.*'\s*)?)(?P.*)$" +) +pattern_flottant = re.compile( + r"^\s*(?P[+-]?((\d+(\.\d*)?)|(\.\d+))([dDeE][+-]?\d+)?)\s*(?P.*)$" +) +pattern_texteQuote = re.compile(r"^\s*(?P'[^']+(''[^']+)*')\s*(?P.*)$") +pattern_texteSimple = re.compile(r"(?P(^|\s)\s*[\w\.-]+)\s*(?P.*)$") +pattern_texteVide = re.compile(r"^\s*(?P'')\s*(?P.*)$") + +pattern_ContientDouble = re.compile(r"^.*''.*$") + +# le pattern texte reconnait +# nom1 nom 2 : ou = chaine entre ' +# avec eventuellement des quotes au milieu par exemple +# TITRE = 'TELEMAC 2D : GOUTTE D''EAU DANS UN BASSIN$' +# m.group("texte") va rendre 'TELEMAC 2D : GOUTTE D''EAU DANS UN BASSIN$' + + +# Si le code n est pas Telemac +# try : +# from enum_Telemac2d_auto import self.TelemacdicoEn +# except : +# pass + +from Accas.extensions import localisation + + +def entryPoint(): + """ + Return a dictionary containing the description needed to load the plugin + """ + return {"name": "TELEMAC", "factory": TELEMACparser} + + +class TELEMACparser(Pythonparser): + """ + This converter works like Pythonparser, except that it also initializes all + model variables to None in order to avoid Python syntax errors when loading + a file with a different or inexistent definition of variables. + """ + + def convert(self, outformat, appliEficas=None): + from Accas import A_BLOC, A_FACT, A_SIMP + + try: + self.dicoCasToCata = appliEficas.readercata.dicoCasToCata + except: + self.dicoCasToCata = {} + print("pas de dicoCasToCata") + self.dicoInverse = appliEficas.readercata.dicoInverse + self.dicoMC = appliEficas.readercata.dicoMC + self.ordreDesCommandes = appliEficas.readercata.ordreDesCommandes + try: + self.TelemacdicoEn = appliEficas.readercata.TelemacdicoEn + except: + self.TelemacdicoEn = {} + print("pas de TelemacdicoEn") + try: + self.DicoEnumCasFrToEnumCasEn = ( + appliEficas.readercata.DicoEnumCasFrToEnumCasEn + ) + except: + self.DicoEnumCasFrToEnumCasEn = {} + print("pas de DicoEnumCasFrToEnumCasEn") + + if appliEficas.langue == "fr": + # from enum_Telemac2d_auto import DicoEnumCasFrToEnumCasEn + for k in self.DicoEnumCasFrToEnumCasEn: + self.TelemacdicoEn[k] = self.DicoEnumCasFrToEnumCasEn[k] + + text = "" + self.dictSimp = {} + + l_lignes_texte_all = self.text.split("\n") + l_lignes_texte = [] + listeComment = [] + dicoComment = {} + dicoCommentSimp = {} + dicoCommentMC = {} + texteComment = "" + debut = True + trouveComment = 0 + for l in l_lignes_texte_all: + if pattern_eta.match(l): + continue + if pattern_fin.match(l): + continue + if pattern_blanc.match(l): + continue + + if not (pattern_comment_slash.match(l)): + l_lignes_texte.append(l) + if trouveComment: + if debut: + dicoComment["debut"] = texteComment + else: + dicoComment[l] = texteComment + trouveComment = 0 + texteComment = "" + if debut: + debut = False + + if pattern_comment_slash.match(l): + # if pattern_comment_slash_vide.match(l) : continue + if pattern_comment_tiret.match(l): + continue + texteComment += l.replace("/", "", 1) + texteComment += "\n" + trouveComment = 1 + + if texteComment != "": + dicoComment["fin"] = texteComment + + l_lignes = [] + i = 0 + while i < len(l_lignes_texte): + ligne = l_lignes_texte[i] + i = i + 1 + if not (pattern_finit_par_virgule_ou_affect.match(ligne)): + l_lignes.append(ligne) + continue + nouvelle_ligne = ligne + while i < len(l_lignes_texte): + ligne_traitee = l_lignes_texte[i] + i = i + 1 + nouvelle_ligne += ligne_traitee + if not (pattern_finit_par_virgule_ou_affect.match(ligne_traitee)): + l_lignes.append(nouvelle_ligne) + break + + for ligne in l_lignes: + if pattern_comment_slash.match(ligne): + continue + # PN : deja teste + # if pattern_eta.match(ligne) : continue + # if pattern_fin.match(ligne) : continue + # if pattern_blanc.match(ligne) : continue + + finLigne = ligne + while finLigne != "": + if pattern_comment_slash.match(finLigne): + finLigne = "" + continue + valeur = "" + if pattern_variables.match(finLigne): + m = pattern_variables.match(finLigne) + simpCas = self.traiteIdent(m.group("ident")) + if simpCas in ["COUPLING WITH", "COUPLAGE AVEC"]: + if "," in m.group("valeur"): + valeur = m.group("valeur").split(",") + else: + valeur = m.group("valeur").split(";") + else: + valeur = m.group("valeur") + finLigne = m.group("reste") + self.dictSimp[simpCas] = valeur + continue + + m = pattern_ligne.match(finLigne) + if m == None: + # print( "________________________________________________") + print("pb avec ****", finLigne, "**** dans ", ligne) + # print( "________________________________________________") + break + + simpCas = self.traiteIdent(m.group("ident")) + if not simpCas: + finLigne = m.group("reste") + continue + + finLigne = m.group("reste") + # attention, l ordre des if est important + if pattern_liste.match(finLigne): + m = pattern_liste.match(finLigne) + elif pattern_liste_texte.match(finLigne): + m = pattern_liste_texte.match(finLigne) + elif pattern_texteQuote.match(finLigne): + m = pattern_texteQuote.match(finLigne) + elif pattern_flottant.match(finLigne): + m = pattern_flottant.match(finLigne) + elif pattern_texteVide.match(finLigne): + m = pattern_texteVide.match(finLigne) + elif pattern_texteSimple.match(finLigne): + m = pattern_texteSimple.match(finLigne) + else: + # print ("________________________________________________") + print("pb avec ****", finLigne, "**** dans ", ligne) + print("non match") + # print ("________________________________________________") + break + + valeur = m.group("valeur") + if pattern_blanc.match(valeur): + valeur = None + + if pattern_flottant.match(finLigne): + valeur = re.sub("d", "e", valeur) + valeur = re.sub("D", "E", valeur) + + if pattern_liste.match(finLigne) or pattern_liste_texte.match(finLigne): + valeur = valeur.split(";") + + finLigne = m.group("reste") + self.dictSimp[simpCas] = valeur + + if ligne in dicoComment.keys(): + dicoCommentSimp[simpCas] = dicoComment[ligne] + + if "TITLE" not in self.dictSimp: + import os + + # self.dictSimp['TITLE']=os.path.basename(self.filename) + + dicoParMC = {} + for simp in self.dictSimp: + if simp in TELEMACparser.__dict__: + TELEMACparser.__dict__[simp]( + self, + ) + + for simp in self.dictSimp: + if simp not in self.dicoInverse: + # print ( "************") + print("pb avec dans dicoInverse", simp, "------") + print("dicoInverse", sorted(self.dicoInverse.keys())) + # print ("************") + continue + listeGenea = self.dicoInverse[simp] + listeGeneaReverse = [] + for u, v in listeGenea: + if isinstance(v, A_BLOC.BLOC): + continue + listeGeneaReverse.append(u) + listeGeneaReverse.reverse() + dicoTravail = dicoParMC + i = 0 + if simp in dicoCommentSimp: + MC = listeGeneaReverse[0] + if MC in dicoCommentMC: + dicoCommentMC[MC] + dicoCommentSimp[simp] + else: + dicoCommentMC[MC] = dicoCommentSimp[simp] + while i < len(listeGeneaReverse[0:-1]): + mot = listeGeneaReverse[i] + i = i + 1 + if mot not in dicoTravail: + dicoTravail[mot] = {} + dicoTravail = dicoTravail[mot] + dicoTravail[simp] = self.dictSimp[simp] + + self.textePy = "" + listeMC = self.tri(list(dicoParMC.keys())) + for k in listeMC: + if k in dicoCommentMC: + commentaire = "COMMENTAIRE(" + repr(dicoCommentMC[k]) + ")\n" + self.textePy += commentaire + self.textePy += str(k) + "(" + self.traiteMC(dicoParMC[k]) + self.textePy += ");\n" + + # ne sert plus + # appliEficas.listeTelemac=self.dictSimp + appliEficas.listeTelemac = {} + if "debut" in dicoComment: + commentaire = "COMMENTAIRE(" + repr(dicoComment["debut"]) + ")\n" + self.textePy = commentaire + self.textePy + if "fin" in dicoComment: + commentaire = "COMMENTAIRE(" + repr(dicoComment["fin"]) + ")\n" + self.textePy = self.textePy + commentaire + + # print (self.textePy) + return self.textePy + + # ---------------------------------------- + def traiteIdent(self, ident): + # enleve les espaces de part et autre + # traduit du langage Telemac vers le langage Catalogue + # ---------------------------------------- + while ident[-1] == " " or ident[-1] == "\t": + ident = ident[0:-1] + while ident[0] == " " or ident[0] == "\t": + ident = ident[1:] + try: + identCata = self.dicoCasToCata[ident] + except: + print("---> ", "pb mot clef pour", ident) + identCata = None + return identCata + + def traiteMC(self, dico): + from Accas import A_BLOC, A_FACT, A_SIMP + + for k in dico: + valeur = dico[k] + if k not in self.dicoMC: + kA = self.dicoFrancaisAnglais[k] + else: + kA = k + obj = self.dicoMC[kA] + if isinstance(obj, A_FACT.FACT): + self.convertFACT(obj, kA, valeur) + elif isinstance(obj, A_BLOC.BLOC): + self.convertBLOC(obj, kA, valeur) + elif isinstance(obj, A_SIMP.SIMP): + self.convertSIMP(obj, kA, valeur) + else: + print( + "%%%%%%%%%%%\n", "pb conversion type pour", k, obj, "\n%%%%%%%%%%%" + ) + + def convertFACT(self, obj, nom, valeur): + # traitement LIQUID_BOUNDARIES + if nom in TELEMACparser.__dict__: + TELEMACparser.__dict__[nom]( + self, + ) + return + self.textePy += nom + "=_F( " + self.traiteMC(valeur) + self.textePy += "),\n" + + def convertBLOC(self, obj, nom, valeur): + print("ANOMALIE _________ BLOC ") + print(nom) + + def convertSIMP(self, obj, nom, valeur): + # print ('in convertSIMP', nom,valeur) + # if nom in ("PRESCRIBED_FLOWRATES", "PRESCRIBED_VELOCITIES", "PRESCRIBED_ELEVATIONS" ): return + if obj.max == 1: + if hasattr(obj.type[0], "ntuple"): + lval = [] + for v in valeur: + try: + v = eval(v, {}) + except: + pass + lval.append(v) + self.textePy += nom + "=" + str(lval) + "," + return + if "TXM" in obj.type: + if pattern_ContientDouble.match(str(valeur)): + valeur = re.sub("''", "''", str(valeur)) + self.textePy += nom + "=" + str(valeur) + "," + return + valeur = str(valeur) + + # ceinture et bretelle si les re sont correctes -) + while valeur[-1] == " " or valeur[-1] == "\t": + valeur = valeur[0:-1] + while valeur[0] == " " or valeur[0] == "\t": + valeur = valeur[1:] + + # Pour les enum + try: + valeur = eval(valeur, {}) + except: + pass + + if nom in self.TelemacdicoEn: + try: + valeur = self.TelemacdicoEn[nom][valeur] + self.textePy += nom + "= '" + str(valeur) + "'," + return + except: + pass + + if ( + obj.into != [] + and obj.into != None + and not ("R" in obj.type) + and not ("I" in obj.type) + ): + for possible in obj.into: + try: + if possible.upper() == valeur.upper(): + valeur = possible + break + v = valeur[0].upper() + valeur[1:].lower() + v2 = tr(v) + if possible.upper() == v2.upper(): + valeur = possible + break + except: + if valeur != None: + print( + "pb avec le type de ", + obj.nom, + obj.type, + "et la valeur ", + valeur, + ) + + if ( + "Fichier" in obj.type + or "TXM" in obj.type + or "Repertoire" in obj.type + or "FichierOuRepertoire" in obj.type + ): + valeur = str(valeur) + if valeur == "" or valeur == " ": + self.textePy += nom + "= '" + str(valeur) + "' ," + return + while valeur[-1] == " ": + valeur = valeur[0:-1] + while valeur[0] == " ": + valeur = valeur[1:] + self.textePy += nom + "= '" + str(valeur) + "' ," + return + + if bool in obj.type: + if valeur == True: + self.textePy += nom + "= True," + elif valeur == False: + self.textePy += nom + "= False," + elif pattern_oui.match(valeur): + self.textePy += nom + "= True," + elif pattern_non.match(valeur): + self.textePy += nom + "= False," + else: + self.textePy += nom + "= None," + return + self.textePy += nom + "=" + str(valeur) + "," + + else: + if valeur == () or valeur == [] or pattern_listeVide.match(str(valeur)): + self.textePy += nom + "= None," + return + + # les 4 lignes suivantes sont probablement inutiles + while valeur[-1] == " " or valeur[-1] == "'": + valeur = valeur[0:-1] + while valeur[0] == " " or valeur[-0] == "'": + valeur = valeur[1:] + oldValeur = valeur + if isinstance(valeur, str): + if ";" in valeur: + valeur = valeur.split(";") + else: + valeur = valeur.split(",") + + if len(valeur) < 2 and pattern_flottant.match(oldValeur): + # Attention : on attend une liste mais on a une seule valeur! + try: + oldValeur = eval(oldValeur, {}) + except: + pass + if nom in self.TelemacdicoEn: + v = self.TelemacdicoEn[nom][oldValeur] + self.textePy += nom + "= ('" + str(v) + "',)," + else: + self.textePy += nom + "= (" + str(oldValeur) + ",)," + return + + # Cas des liste de booléen + if bool in obj.type: + values = [] + for val in valeur: + if val == True or pattern_oui.match(val) or val == "True": + values.append("True") + elif val == False or pattern_non.match(val) or val == "False": + values.append("False") + else: + values.append("None") + self.textePy += nom + "= [" + ",".join(values) + "]," + return + + if valeur == None: + return + newVal = [] + for v in valeur: + try: + v = eval(v, {}) + except: + pass + if nom in self.TelemacdicoEn: + try: + v = self.TelemacdicoEn[nom][v] + except: + pass + newVal.append(v) + self.textePy += nom + "=" + str(newVal) + "," + + def tri(self, listeIn): + if len(listeIn) == 1: + return listeIn + if self.ordreDesCommandes == None: + return listeIn + listeOut = [ + listeIn[0], + ] + for k in listeIn[1:]: + # k=str(self.dicoFrancaisAnglais[kF]) + ordreK = self.ordreDesCommandes.index(k) + i = 0 + while i < len(listeOut): + # ordreI=self.ordreDesCommandes.index(self.dicoFrancaisAnglais[listeOut[i]]) + ordreI = self.ordreDesCommandes.index(listeOut[i]) + if ordreK < ordreI: + break + i = i + 1 + # listeOut.insert(i,kF) + listeOut.insert(i, k) + return listeOut diff --git a/Accas/IO/convert/convert_UQPython.py b/Accas/IO/convert/convert_UQPython.py new file mode 100644 index 00000000..817d2ef6 --- /dev/null +++ b/Accas/IO/convert/convert_UQPython.py @@ -0,0 +1,92 @@ +# Copyright (C) 2007-2022 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from Accas.extensions.eficas_translation import tr + +# import traceback +# traceback.print_stack() + +from Accas.IO.convert.convert_python import Pythonparser + + +def entryPoint(): + """ + Return a dictionary containing the description needed to load the plugin + """ + return {"name": "pythonUQ", "factory": pythonUQParser} + + +class pythonUQParser(Pythonparser): + """ + This converter works like Pythonparser, except that it also initializes all + links between deterministic and probabilistic variables + """ + + def convert(self, outformat, appliEficas=None): + text = Pythonparser.convert(self, outformat, appliEficas) + return text + + def traitementApresLoad(self, jdc): + debug = 0 + if debug: + print("traitementApresLoad") + etapeIncertitude = jdc.getEtapesByName("ExpressionIncertitude") + if etapeIncertitude == []: + return + + incertitudeInput = etapeIncertitude[0].getChildOrChildInBloc("Input") + self.lesVariablesInput = incertitudeInput[0].getChildOrChildInBloc( + "VariableProbabiliste" + ) + for mc in self.lesVariablesInput: + # if debug : print (mc,'mc') + mcVDPath = mc.getChild("MCPath").valeur + if debug: + print(mcVDPath) + # a modifier lorsque le MCPath comprendra le nom des OPERs + if not (mcVDPath): + mc.parent.suppentite(mc) + break # on admet ici que le . comm n est pas valide + mcModelVariable = mc.getChild("ModelVariable") + mcModelVariable.definition.addInto(mcModelVariable.valeur) + # try : + # mcObjectName=mc.getChild('ObjectName') + # mcObjectName.changeStatut('f') + # except : + # pass + mcCherche = jdc.getObjetByMCPath(mcVDPath) + if not (mcCherche): + mc.parent.suppentite(mc) + break # on admet ici que le . comm n est pas valide + if debug: + print(mcCherche) + if mc.nature == "MCFACT": + mc[0].variableDeterministe = mcCherche + mcCherche.variableProbabiliste = mc[0] + else: + mc.variableDeterministe = mcCherche + mcCherche.variableProbabiliste = mc[0] + mcCherche.definition.siValide = mcCherche.changeValeursRefUQ + mcCherche.associeVariableUQ = True + itemConsigne = mc.getChild("Consigne") + itemConsigne.setValeur( + "la valeur entrée pour {} est {}".format( + mcCherche.nom, mcCherche.valeur + ) + ) diff --git a/Accas/IO/convert/convert_XML.py b/Accas/IO/convert/convert_XML.py new file mode 100644 index 00000000..18a55b14 --- /dev/null +++ b/Accas/IO/convert/convert_XML.py @@ -0,0 +1,76 @@ +# Copyright (C) 2007-2024 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +import re +from Accas.extensions.eficas_translation import tr + +# import traceback +# traceback.print_stack() + +from Accas.extensions import localisation +from Accas.processing import P_CR +from Accas.IO.convert.convert_UQPython import pythonUQParser + + +def entryPoint(): + """ + Return a dictionary containing the description needed to load the plugin + """ + return {"name": "xml", "factory": XMLparser} + + +class XMLparser: + """ + This converter works like Pythonparser, except that it reads XML file + """ + + def __init__(self, cr=None): + # print("dans XML convert") + self.text = "" + if cr: + self.cr = cr + else: + self.cr = P_CR.CR( + debut="CR convertisseur format XML", fin="fin CR format XML" + ) + + def readfile(self, filename): + self.filename = filename + try: + with open(filename) as fd: + self.text = fd.read() + except: + self.cr.exception(tr("Impossible d'ouvrir le fichier %s", str(filename))) + self.cr.fatal(tr("Impossible d'ouvrir le fichier %s", str(filename))) + return + + def convert(self, outformat, appliEficas=None): + # ici on ne fait rien + # on le fera a la creation du JDC + try: + return self.text + except Exception as e: + # Erreur lors de la conversion + l = traceback.format_exception( + sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2] + ) + self.cr.exception( + tr("Impossible de convertir le fichier XML\n %s", "".join(l)) + ) + return "" diff --git a/Accas/IO/convert/convert_dico.py b/Accas/IO/convert/convert_dico.py new file mode 100644 index 00000000..a92609ef --- /dev/null +++ b/Accas/IO/convert/convert_dico.py @@ -0,0 +1,90 @@ +# Copyright (C) 2007-2024 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from Accas.IO.convert.convert_python import Pythonparser +from Accas.processing import P_CR + + +def entryPoint(): + """ + Return a dictionary containing the description needed to load the plugin + """ + return {"name": "dico", "factory": Dicoparser} + + +class Dicoparser(Pythonparser): + """ + This converter initializes model variable from a python dictionnary + """ + + def __init__(self, cr=None): + # Si l'objet compte-rendu n'est pas fourni, on utilise le + # compte-rendu standard + self.text = "" + self.textePy = "" + if cr: + self.cr = cr + else: + self.cr = P_CR.CR( + debut="CR convertisseur format dico", fin="fin CR format dico" + ) + + def readfile(self, filename): + self.filename = filename + try: + with open(filename) as fd: + self.text = fd.read() + except: + self.cr.exception(tr("Impossible d'ouvrir le fichier %s", str(filename))) + self.cr.fatal(tr("Impossible d'ouvrir le fichier %s", str(filename))) + return + + def convert(self, outformat, appli=None): + monTexteDico = {} + exec(self.text, globals(), monTexteDico) + if len(monTexteDico.keys()) != 1: + self.cr.exception(tr("Impossible de traiter le fichier %s", str(filename))) + self.cr.fatal(tr("Impossible de traiter le fichier %s", str(filename))) + return + self.textePy = "" + monDico = monTexteDico[monTexteDico.keys()[0]] + for commande in monDico: + valeurs = monDico[commande] + if valeurs.has_key("NomDeLaSdCommande"): + # cas d un oper + self.textePy += valeurs["NomDeLaSdCommande"] + " = " + commande + "(" + del valeurs["NomDeLaSdCommande"] + else: + self.textePy += commande + "(" + for mot in valeurs: + if isinstance(valeurs[mot], dict): + self.traiteMCFact(mot, valeurs[mot]) + else: + self.textePy += mot + " = " + str(valeurs[mot]) + "," + self.textePy += ");\n" # fin de la commande + return self.textePy + + def traiteMCFact(self, mot, valeurs): + self.textePy += mot + "=_F(" + for mot in valeurs: + if isinstance(valeurs[mot], dict): + self.traiteMCFact(mot, valeurs[mot]) + else: + self.textePy += mot + " = " + str(valeurs[mot]) + "," + self.textePy += ")," diff --git a/Accas/IO/convert/convert_python.py b/Accas/IO/convert/convert_python.py new file mode 100644 index 00000000..499e938a --- /dev/null +++ b/Accas/IO/convert/convert_python.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2007-2024 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +""" + Ce module contient le plugin convertisseur de fichier + au format python pour EFICAS. + + Un plugin convertisseur doit fournir deux attributs de classe : + extensions et formats et deux methodes : readfile,convert. + + L'attribut de classe extensions est une liste d'extensions + de fichiers preconisees pour ce type de format. Cette information + est seulement indicative. + + L'attribut de classe formats est une liste de formats de sortie + supportes par le convertisseur. Les formats possibles sont : + eval, dict ou exec. + Le format eval est un texte source Python qui peut etre evalue. Le + resultat de l'evaluation est un objet Python quelconque. + Le format dict est un dictionnaire Python. + Le format exec est un texte source Python qui peut etre execute. + + La methode readfile a pour fonction de lire un fichier dont le + nom est passe en argument de la fonction. + - convertisseur.readfile(nom_fichier) + + La methode convert a pour fonction de convertir le fichier + prealablement lu dans un objet du format passe en argument. + - objet=convertisseur.convert(outformat) + + Ce convertisseur supporte le format de sortie exec + +""" + +import sys, traceback +from builtins import str +from builtins import object + +from .parseur_python import PARSEUR_PYTHON +from Accas.processing import P_CR +from Accas.extensions.eficas_translation import tr +from Accas.extensions.eficas_exception import EficasException + + +def entryPoint(): + """ + Retourne les informations necessaires pour le chargeur de plugins + Ces informations sont retournees dans un dictionnaire + """ + return { + # Le nom du plugin + "name": "python", + # La factory pour creer une instance du plugin + "factory": Pythonparser, + } + + +class Pythonparser(object): + """ + Ce convertisseur lit un fichier au format python avec la + methode readfile : convertisseur.readfile(nom_fichier) + et retourne le texte au format outformat avec la + methode convertisseur.convert(outformat) + + Ses caracteristiques principales sont exposees dans 2 attributs + de classe : + - extensions : qui donne une liste d'extensions de fichier preconisees + - formats : qui donne une liste de formats de sortie supportes + """ + + # Les extensions de fichier preconisees + extensions = (".py",) + # Les formats de sortie supportes (eval dict ou exec) + # Le format exec est du python executable (commande exec) converti avec PARSEUR_PYTHON + # Le format execnoparseur est du python executable (commande exec) non converti + formats = ("exec", "execnoparseur") + + def __init__(self, cr=None): + # Si l'objet compte-rendu n'est pas fourni, on utilise le + # compte-rendu standard + self.text = "" + if cr: + self.cr = cr + else: + self.cr = P_CR.CR( + debut="CR convertisseur format python", fin="fin CR format python" + ) + + def readfile(self, filename): + self.filename = filename + try: + with open(filename) as fd: + self.text = fd.read() + except: + self.cr.exception(tr("Impossible d'ouvrir le fichier %s", str(filename))) + self.cr.fatal(tr("Impossible d'ouvrir le fichier %s", str(filename))) + return + + def convert(self, outformat, appliEficas=None): + if outformat == "exec": + try: + # import cProfile, pstats, StringIO + # pr = cProfile.Profile() + # pr.enable() + l = PARSEUR_PYTHON(self.text).getTexte(appliEficas) + + # pr.disable() + # s = StringIO.StringIO() + # sortby = 'cumulative' + # ps = pstats.Stats(pr, stream=s).sort_stats(sortby) + # ps.print_stats() + # print (s.getValue()) + + return l + except EficasException: + # Erreur lors de la conversion + l = traceback.format_exception( + sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2] + ) + self.cr.exception( + tr( + "Impossible de convertir le fichier Python qui doit contenir des erreurs.\n\ + On retourne le fichier non converti. Prevenir la maintenance.\n\n %s", + "".join(l), + ) + ) + # On retourne neanmoins le source initial non converti (au cas ou) + return self.text + elif outformat == "execnoparseur": + return self.text + else: + raise EficasException(tr("Format de sortie : %s, non supporte", outformat)) + return None diff --git a/Accas/IO/convert/old/Parserv5/Makefile b/Accas/IO/convert/old/Parserv5/Makefile new file mode 100644 index 00000000..d75ca643 --- /dev/null +++ b/Accas/IO/convert/old/Parserv5/Makefile @@ -0,0 +1,2 @@ +tables.py:tables.tag + python Translate.py -force tables.tag diff --git a/Accas/IO/convert/old/Parserv5/README b/Accas/IO/convert/old/Parserv5/README new file mode 100644 index 00000000..57294e33 --- /dev/null +++ b/Accas/IO/convert/old/Parserv5/README @@ -0,0 +1,3 @@ +Pour mettre à jour le parser de fichier au format Asterv5, il faut +recompiler le fichier tables.tag en faisant : + make diff --git a/Accas/IO/convert/old/Parserv5/Translate.py b/Accas/IO/convert/old/Parserv5/Translate.py new file mode 100644 index 00000000..016113de --- /dev/null +++ b/Accas/IO/convert/old/Parserv5/Translate.py @@ -0,0 +1,2498 @@ +# -*- coding: utf-8 -*- +# CONFIGURATION MANAGEMENT OF EDF VERSION +# ====================================================================== +# COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG +# THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY +# IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY +# THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR +# (AT YOUR OPTION) ANY LATER VERSION. +# +# THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT +# WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF +# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU +# GENERAL PUBLIC LICENSE FOR MORE DETAILS. +# +# YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE +# ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, +# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. +# +# +# ====================================================================== + +#!/bin/env python -d +#!/tools/net/app/Python-1.5.2/bin/python1.5 + +"""Translate - a first attempt at parsing my little language + +Usage: Translate [switches] [] + + -stdout -- write to standard output instead of a file + -force -- write to the even if it already + exists (overwrite any existing file) + + -import -- import tag table from Translate_tags.py, + instead of using the internal table + + -compare -- compare the imported and internal tag tables + (development option!) + + -test -- use our internal test data and write to stdout + -pytag -- use the interpreted tagging engine + -debug -- if -pytag, enable its debugger + -diag -- enable general debugging + Beware that this currently also writes line + numbers to the start of each line in the output, + so it doesn't emit legal Python... + + -help -- show this text + -history -- show the module history + -version -- show the module version + +If is not specified, will be used with its extension +replaced by ".py". +""" + +__author__ = """Tibs (Tony J Ibbs) +tony@lsl.co.uk or tibs@tibsnjoan.demon.co.uk or tibs@bigfoot.com +http://www.tibsnjoan.demon.co.uk/ +""" +__version__ = "0.3 (tiepin) of 1999-11-15" +__history__ = """\ +Originally created 1999-08-13 + +First released version is 0.2 (bootstrap)/1999-09-09, which gave +an idea of how the thing would work, and nearly did. + +Second released version is 0.3 (tiepin)/1999-11-15, which is sufficient +to allow the parser used within this utility to be written in the little +language, translated and then used as such. +""" + +import sys +import os +import string + +# ............................................................ +# How we want to work things - this is fudge for me in initial development +if os.name == "posix": + # Unix at work + DEFAULT_DEBUG = 0 + DEFAULT_PYTAG = 0 +else: + # Windows 95 at home + TEXTTOOLS_PATH = "C:\\Program Files\\Python" + PYTAG_PATH = "C:\\Program Files\\Python\\TextTools\\Examples" + DEFAULT_DEBUG = 0 + DEFAULT_PYTAG = 0 + + if TEXTTOOLS_PATH not in sys.path: + print "Adding",TEXTTOOLS_PATH + sys.path.append(TEXTTOOLS_PATH) + + if PYTAG_PATH not in sys.path: + print "Adding",PYTAG_PATH + sys.path.append(PYTAG_PATH) +# ............................................................ + +# Import the TextTools themselves +# - I'm not personally too keen on import *, but it seems to be +# the recommended thing, so I'll leave it for now... +try: + from TextTools import * +except: + from mx.TextTools import * + #from TextTools.Constants.TagTables import * + #from TextTools.Constants.Sets import * + + +# ------------------------------------------------------------ +# Useful little constants for unpicking the parsed tuples +OBJECT = 0 +LEFT = 1 +RIGHT = 2 +SUBLIST = 3 + +# We want to align inline comments when possible - so this is +# the column at which we will try to place their "#" marks... +COMMENT_COLUMN = 40 + +# Are we (generally) debugging? +DEBUGGING = 0 + +# Do we want a comma after the last tuple (or item) in a table? +WANT_LAST_COMMA = 1 + + +# ------------------------------------------------------------ +def define_tagtable(): + """Returns our tag table, if we're not importing it.""" + + # We are not, initially, going to try for anything very sophisticated + # - just something that will get us bootstrapped, so that I can use the + # "little language" to write more sophisticated stuff (without having + # to worry about dropped commas between tuples, and so on!) + + + # Whitespace is always useful + t_whitespace = (None,AllIn,' \t') + t_opt_whitespace = t_whitespace + (+1,) + + # Comments are fairly simple + t_comment = ('comment',Table, + ((None,Is,'#'), + (None,AllNotIn,'\n\r',MatchOk)) + ) + + # We care about the "content" of the indentation at the start of a line, + # but note that it is optional + t_indent = ('indent',AllIn,' \t') + t_indentation = t_indent + (+1,) # zero indentation doesn't show + + # A string is text within single or double quotes + # (of course, this is an oversimplification, because we should also + # deal with things like "This is a \"substring\"", and it would be + # nice to be able to cope with triple-quoted strings too, but it + # will do for a start) + + # Major bug - doesn't recognised zero length strings... + # (since "AllNotIn" must match at least one character) + t_string = ('str',Table, + ((None,Is,"'",+3,+1), + ('text',AllNotIn,"'"), + (None,Is,"'",MatchFail,MatchOk), + (None,Is,'"'), + ('text',AllNotIn,'"'), + (None,Is,'"'), + )) + + # An integer is a series of digits... + t_integer = ('int',AllIn,number) + + t_signed_integer = ('signed_int',Table, + (('sign',Is,"+",+1,+2), + ('sign',Is,"-",+1,+1), + t_integer + )) + + # Remember to be careful to specify the LONGEST possible match first, + # so that we try for "IsIn" before we try for "Is" (because "IsIn" + # would *match* "Is", leaving us with a spurious "In" hanging around...) + t_operation = ('op',Table, + (('op',Word,"AllInSet", +1,MatchOk), + ('op',Word,"AllIn", +1,MatchOk), + ('op',Word,"AllNotIn", +1,MatchOk), + ('op',Word,"CallArg", +1,MatchOk), + ('op',Word,"Call", +1,MatchOk), + ('op',Word,"EOF", +1,MatchOk), + ('op',Word,"Fail", +1,MatchOk), + ('op',Word,"IsInSet", +1,MatchOk), + ('op',Word,"IsIn", +1,MatchOk), + ('op',Word,"IsNotIn", +1,MatchOk), + ('op',Word,"IsNot", +1,MatchOk), + ('op',Word,"Is", +1,MatchOk), + ('op',Word,"Jump", +1,MatchOk), + ('op',Word,"LoopControl",+1,MatchOk), + ('op',Word,"Loop", +1,MatchOk), + ('op',Word,"Move", +1,MatchOk), + ('op',Word,"NoWord", +1,MatchOk), # alias for WordStart + ('op',Word,"Skip", +1,MatchOk), + ('op',Word,"SubTableInList",+1,MatchOk), + ('op',Word,"SubTable", +1,MatchOk), + ('op',Word,"sFindWord", +1,MatchOk), + ('op',Word,"sWordStart", +1,MatchOk), + ('op',Word,"sWordEnd", +1,MatchOk), + ('op',Word,"TableInList",+1,MatchOk), + ('op',Word,"Table", +1,MatchOk), + ('op',Word,"WordStart", +1,MatchOk), + ('op',Word,"WordEnd", +1,MatchOk), + ('op',Word,"Word", MatchFail,MatchOk), + )) + + # Python keywords + t_keyword = ('keyword',Table, + ((None,Word,"and", +1,+28), + (None,Word,"assert", +1,+27), + (None,Word,"break", +1,+26), + (None,Word,"class", +1,+25), + (None,Word,"continue",+1,+24), + (None,Word,"def", +1,+23), + (None,Word,"del", +1,+22), + (None,Word,"elif", +1,+21), + (None,Word,"else", +1,+20), + (None,Word,"except", +1,+19), + (None,Word,"exec", +1,+18), + (None,Word,"finally", +1,+17), + (None,Word,"for", +1,+16), + (None,Word,"from", +1,+15), + (None,Word,"global", +1,+14), + (None,Word,"if", +1,+13), + (None,Word,"import", +1,+12), + (None,Word,"in", +1,+11), + (None,Word,"is", +1,+10), + (None,Word,"lambda", +1,+9), + (None,Word,"not", +1,+8), + (None,Word,"or", +1,+7), + (None,Word,"pass", +1,+6), + (None,Word,"print", +1,+5), + (None,Word,"raise", +1,+4), + (None,Word,"return", +1,+3), + (None,Word,"try", +1,+2), + (None,Word,"while", MatchFail,+1), + # In order to not recognise things like "in_THIS_CASE" + # we must check that the next character is not legitimate + # within an identifier + (None,IsIn,alpha+'_'+number,+1,MatchFail), + # If it wasn't another identifier character, we need to + # unread it so that it can be recognised as something else + # (so that, for instance, "else:" is seen as "else" followed + # by ":") + (None,Skip,-1) + )) + + # Do the same for mxText commands + t_mxkeyword = ('mxKeyword',Table, + (t_operation, + (None,IsIn,alpha+'_'+number,+1,MatchFail), + (None,Skip,-1) + )) + + # Traditional identifiers + t_identifier = ('identifier',Table, + (t_keyword + (+1,MatchFail), # don't allow Python keywords + t_mxkeyword + (+1,MatchFail), # don't allow mxText commands + (None,IsIn,alpha+'_'), # can't start with a digit + (None,AllIn,alpha+'_'+number,MatchOk)) + ) + + # We don't yet deal with the following with anything in parentheses, + # which means we can't handle functions or command lists, or other + # things which "look like" a tuple + t_argument = ('arg',Table, + (('arg',Word,"Here", +1,MatchOk), # EOF Here, Fail Here + ('arg',Word,"ToEOF", +1,MatchOk), # Move ToEOF + ('arg',Word,"To", +1,MatchOk), # Jump To + ('arg',Word,"ThisTable",+1,MatchOk), # [Sub]Table ThisTable + ('arg',Word,"back", +1,MatchOk), # Skip back + ('arg',Word,"Break", +1,MatchOk), # LoopControl Break + ('arg',Word,"Reset", +1,MatchOk), # LoopControl Reset + t_string + (+1,MatchOk), # e.g., Word "Fred" + t_signed_integer + (+1,MatchOk), # e.g., Skip -4, Move 3 + t_identifier # e.g., Table Fred + )) + + t_plus = ('plus',Table, + (t_opt_whitespace, + (None,Is,"+"), + t_opt_whitespace + )) + + # Arguments can contain "+" + t_plus_arg = ('plusarg',Table, + (t_argument, # start with a single argument + t_plus + (MatchOk,), # if we have a "+" + t_argument, # then we expect another argument + (None,Jump,To,-2), # then look for another "+" + )) + + # Match, for example: + # + t_label = ('label',Table, + ((None,Is,"<"), + t_identifier, + (None,Is,">") + )) + + # Targets for Jump and F:/T: + t_target = ('target',Table, + (('tgt',Word,"next", +1,MatchOk), + ('tgt',Word,"previous", +1,MatchOk), + ('tgt',Word,"repeat", +1,MatchOk), + ('tgt',Word,"MatchOk", +1,MatchOk), + ('tgt',Word,"MatchOK", +1,MatchOk), # For kindness sake + ('tgt',Word,"MatchFail",+1,MatchOk), + t_label + )) + + # A value is either an identifier, or a string, or an integer + t_value = ('val',Table, + (t_identifier +(+1,MatchOk), + t_string +(+1,MatchOk), + t_integer + )) + + # An assignment is (optionally) used in Tuple and Table definitions... + t_assignment = ('assignment',Table, + (t_value, + t_opt_whitespace, + (None,Is,'='), + )) + + # A common error when writing tuples is to miss off the "=" sign + # - the following is used in diagnosing that (see t_bad_tuple below) + # (it's useful to have something with identical structure to the + # "real thing") + t_bad_tagobj = ('tagobj',Table, + (t_string, + )) + + t_bad_assignment = ('assignment',Table, + (t_value, + )) + + # This is the line that starts the definition of a single tuple. + # For the moment, restrict what it gets assigned to to a simple identifier. + # Match, for example: + # Fred is: + t_tupleblock = ('tupleblock',Table, + (t_identifier, + t_whitespace, + (None,Word,"is:") + )) + + # This is the line that starts a new table or sub-table. + # For the moment, we only cope with full Tables. + # NOTE that this is used for the "outer" declaration of a tag table, + # and also for the "inner" declaration of an inner table or sub-table. + # The discrimination between these is done after initial parsing. + # Match, for example: + # 'keyword' = Table is: (inner) + # tagtable = Table is: (outer) + t_tableblock = ('tableblock',Table, + (t_assignment + (+2,+1), # left hand side is optional + t_opt_whitespace, + ('type',Word,"Table",+1,+2), # Either "Table" + ('type',Word,"SubTable"), # or "SubTable" is required + t_whitespace, # whitespace is required + (None,Word,"is:") # "is:" is required + )) + + # This is the line that starts an "if" block + # Match, for example: + # Is "Fred": + # controlsymbol: + t_ifblock = ('ifblock',Table, + (t_assignment + (+2,+1), # left hand side is optional + t_opt_whitespace, + t_operation + (+4,+1), + t_whitespace, + t_plus_arg, + (None,Is,":",MatchFail,MatchOk), + t_identifier, + (None,Is,":") + )) + + # Note that we don't allow spaces WITHIN our false and true thingies + + t_onfalse = ('onfalse',Table, + (t_whitespace, + (None,Word,"F:"), + t_target + )) + + t_ontrue = ('ontrue',Table, + (t_whitespace, + (None,Word,"T:"), + t_target + )) + + # Valid examples are things like: + # 'fred' = Is "xxx" F: T:MatchOk + # AllIn jim T: + # + # For the moment, we're not trying to recognise things in any detail + t_tuple = ('tuple',Table, + (t_assignment + (+2,+1), # left hand side is optional + t_opt_whitespace, + t_operation, # operation is required + t_whitespace, # for the moment, we always require space here + t_plus_arg, # argument is required + t_onfalse + (+1,+1), # F:target is optional + t_ontrue + (MatchOk,MatchOk) # T:target is also optional + )) + + # If the user has defined a "partial" tuple, they might use something + # of the form: + # match_fred F:MatchFalse T:MatchOk + t_tupleplus = ('tupleplus',Table, + (t_identifier, + t_onfalse + (+1,+1), # F:target is optional + t_ontrue + (MatchOk,MatchOk) # T:target is also optional + )) + + # Treat Jump To specially - for example: + # Jump To + # so that they don't have to do the less obvious "Jump To F: