Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Related Pages

compile.c

00001 /* 00002 * Copyright (C) 1997-2004 The CDG Team <cdg@nats.informatik.uni-hamburg.de> 00003 * 00004 * This file is free software; as a special exception the author gives 00005 * unlimited permission to copy and/or distribute it, with or without 00006 * modifications, as long as this notice is preserved. 00007 * 00008 * This program is distributed in the hope that it will be useful, but 00009 * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the 00010 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00011 * 00012 * Birth: 10.5.1 00013 */ 00014 00015 /* ------------------------------------------------------------------------- 00016 * @addtogroup Compiler Compiler - compile a constraint grammar 00017 * \author Michael Daum (see also AUTHORS and THANKS for more) 00018 * 00019 * $Id: compile.c,v 1.87 2004/10/04 14:36:12 micha Exp $ 00020 * 00021 * This module implements a compiler in order to translate constraints into C code. 00022 * @{ 00023 */ 00024 00025 /* -- INCLUDES ---------------------------------------------------------- */ 00026 #include <config.h> 00027 #include <unistd.h> 00028 #include <time.h> 00029 #include <libgen.h> 00030 #include <stdio.h> 00031 #include <sys/stat.h> 00032 #include <pwd.h> 00033 #include <string.h> 00034 #include <assert.h> 00035 #include <dlfcn.h> 00036 #include <stdlib.h> 00037 #include <limits.h> 00038 #include <math.h> 00039 #include "cdg.h" 00040 #include "hook.h" 00041 #include "command.h" 00042 #include "input.h" 00043 #include "set.h" 00044 #include "timer.h" 00045 #include "constraintnet.h" 00046 #include "eval.h" 00047 00048 00049 /* -- MACROS -------------------------------------------------------------- */ 00050 #define INIT_GRAMMAR "initGrammar" /**< abbrev. */ 00051 #define FINIT_GRAMMAR "finitGrammar" /**< abbrev. */ 00052 00053 /* -- TYPE DEFINITIONS ---------------------------------------------------- */ 00054 00055 /* --------------------------------------------------------------------------- 00056 * definition of a \c CDG compiler object. 00057 */ 00058 typedef struct CompilerStruct { 00059 String ccFileName; /**< filename for C code */ 00060 FILE * ccFile; /**< filehandle of the file in ccFileName */ 00061 String objFileName; /**< filename for object code */ 00062 String soFileName; /**< filename for C dll grammar */ 00063 int indent; /**< current indentation level */ 00064 String indentString; /**< current indentation */ 00065 Vector indentStrings; /**< possible indentation */ 00066 Boolean needsIndent; /**< TRUE by comPrintln, FALSE by comPrint */ 00067 Vector directions; /**< collection of all defined directions */ 00068 Vector connexions; /**< collection of all defined connexions */ 00069 Constraint currentConstraint; /**< the constraint being currently translated */ 00070 Formula currentFormula; /**< the Formula being currently translated */ 00071 int maxValues; /**< max number of variables to eval all constraints */ 00072 int maxLookupStrings; /**< max number of Strings used in 'lookup' constraints */ 00073 Vector strings; /**< list of strings to allocated statically */ 00074 Boolean translateOnly; /**< if TRUE we dont compile+load a shared object */ 00075 } CompilerStruct; 00076 typedef struct CompilerStruct *Compiler; /**< type of a Compiler */ 00077 00078 /* --------------------------------------------------------------------------- 00079 * definition of a approver object. 00080 */ 00081 typedef struct { 00082 int noRounds; /**< no of times to eval all lv pairs */ 00083 Timer timer; /**< profiling */ 00084 unsigned long totalInterpretedUnaryTime; /**< profiling information */ 00085 unsigned long totalCompiledUnaryTime; /**< profiling information */ 00086 unsigned long totalInterpretedBinaryTime; /**< profiling information */ 00087 unsigned long totalCompiledBinaryTime; /**< profiling information */ 00088 } ApproverStruct; 00089 typedef ApproverStruct *Approver; /**< type of an Approver */ 00090 00091 /* --------------------------------------------------------------------------- 00092 * default make settings. 00093 * This structure bundles all the information that is needed to compile and 00094 * link a binary \c CDG grammar. This is called \c MakeInfo in according to 00095 * the normal place where such information is kept. 00096 */ 00097 typedef struct MakeInfoStruct { 00098 String cc; /**< CC */ 00099 String ld; /**< LD */ 00100 String cFlags; /**< CFLAGS */ 00101 String ldFlags; /**< LDFLAGS */ 00102 String ldLibs; /**< LDLIBS */ 00103 String includes; /**< INCLUDES */ 00104 } MakeInfoStruct; 00105 /** A Pointer to a MakeInfoStruct */ 00106 typedef struct MakeInfoStruct *MakeInfo; 00107 00108 /* --------------------------------------------------------------------------- 00109 * possible return types of formulas, predicates, functions, terms. 00110 */ 00111 typedef enum { 00112 RTBoolean = (1L << 0), /**< Boolean return type */ 00113 RTNumber = (1L << 1), /**< Number return type */ 00114 RTString = (1L << 2), /**< String return type */ 00115 RTAVNode = (1L << 3), /**< AVNode return type */ 00116 RTList = (1L << 4), /**< List return type */ 00117 RTConjunction = (1L << 5), /**< Conjunction return type */ 00118 RTDisjunction = (1L << 6), /**< Disjunction return type */ 00119 RTError = (1L << 7), /**< Syntax error "return type" */ 00120 RTLexemNode = (1L << 8), /**< LexemNode return type */ 00121 RTGraphemNode = (1L << 9), /**< GraphemNode return type */ 00122 RTNoError = (1L << 10), /**< indicate that no error is possible 00123 * in the returning function */ 00124 RTPeek = (1L << 11), /**< indicate a lexicon access 00125 * in the returning function */ 00126 RTLexemPosition = (1L << 12), /**< indicate the position where the 00127 * returning function is peeking 00128 * 0: modifier, 1: modifiee */ 00129 } ReturnType; 00130 00131 /* -- VARIABLES --------------------------------------------------------- */ 00132 static Compiler com; /**< this is allocated on every call to comCompile */ 00133 static MakeInfo makeInfo; /**< this is allocated once on comInitialize */ 00134 00135 /* -- FUNCTIONS --------------------------------------------------------- */ 00136 00137 /* main functions */ 00138 Boolean comTranslate(void); 00139 Boolean comMake(void); 00140 00141 /* constructor, destructor */ 00142 Compiler comNew(void); 00143 void comFree(Compiler); 00144 MakeInfo comMakeInfoNew(void); 00145 void comMakeInfoFree(MakeInfo); 00146 Approver comNewApprover(void); 00147 void comFreeApprover(Approver); 00148 00149 /* output helper */ 00150 void comIndent(void); 00151 void comOutdent(void); 00152 void comPrint(String, ...); 00153 void comPrintln(String, ...); 00154 void comWriteWarning(String, ...); 00155 void comWriteError(String, ...); 00156 void comWriteHeader(void); 00157 void comWriteDeclarations(void); 00158 void comWriteFunctions(void); 00159 void comWriteInitFunction(void); 00160 void comWriteFinitFunction(void); 00161 String comEscapeQuotes(String); 00162 00163 /* string registrator */ 00164 int comRegisterString(String); 00165 00166 /* stringifier */ 00167 String comDirectionToString(Direction); 00168 String comConnextionToString(Connexion); 00169 String comValueTypeToString(Value); 00170 String comFormulaTypeToString(Formula); 00171 String comTermTypeToString(Term); 00172 String comReturnTypeToString(ReturnType); 00173 00174 /* grammar analyzer */ 00175 void comAnalyzeGrammar(void); 00176 int comTermDepth(Term); 00177 int comFormulaDepth(Formula); 00178 int comConstraintDepth(Constraint); 00179 int comPredicateDepth(String, List); 00180 int comFunctionDepth(String, List); 00181 int comMaxLookupStrings(Constraint); 00182 int comMaxLookupStringsInFormula(Formula); 00183 int comMaxLookupStringsInTerm(Term); 00184 00185 /* type inference */ 00186 ReturnType comReturnTypeOfFormula(Formula); 00187 ReturnType comReturnTypeOfTerm(Term); 00188 ReturnType comReturnTypeOfFunction(String, List); 00189 ReturnType comReturnTypeOfPredicate(String, List); 00190 00191 /* translators */ 00192 void comTranslateUnaryConstraints(void); 00193 void comTranslateBinaryConstraints(void); 00194 void comTranslateConstraint(Constraint); 00195 void comTranslateFormula(Formula, int); 00196 void comTranslateTerm(Term, Boolean, Boolean, int); 00197 void comTranslatePredicate(String, List, int); 00198 void comTranslateFunction(String, List, int); 00199 void comTranslateLexicalAccess(Term); 00200 void comTranslateLexemNodeAccess(Term, int); 00201 void comTranslateMatch(List, int); 00202 void comTranslateMinMax(String, List, int); 00203 void comTranslateAbs(List, int); 00204 void comTranslateDistance(List, int); 00205 void comTranslateStartStop(String, List, int); 00206 void comTranslateGuard(String, List, int); 00207 void comTranslateExists(List); 00208 void comTranslateSubsumes(String, List, int); 00209 void comTranslateChunkHead(String, List, int); 00210 void comTranslateUnder(String, List, int); 00211 void comTranslateBetween(String, List, int); 00212 void comTranslateBottomPeek(Term, int); 00213 void comTranslateTopPeek(Term, int); 00214 void comTranslateArithmetics(Term, int); 00215 void comTranslateEquation(Formula, int); 00216 void comTranslateUnEquation(Formula, int); 00217 void comTranslatePrint(List, int); 00218 void comTranslateDirection(Formula); 00219 void comTranslateConnexion(Formula); 00220 void comTranslateString(Term, int); 00221 void comTranslateNumber(Term, int); 00222 void comTranslatePhrasequotes(List, int); 00223 void comTranslateLookup(List, int); 00224 void comTranslateQuotes(List, int); 00225 void comTranslateParens(List, int); 00226 void comTranslateParent(List, int); 00227 void comTranslatePts(List, int); 00228 void comTranslateHeight(List, int); 00229 void comTranslateIs(String, List, int); 00230 void comTranslateConnected(String, List, int); 00231 void comTranslateHas(String, List, int); 00232 00233 /* index finder */ 00234 int comIndexOfHierarchy(String); 00235 int comIndexOfConstraint(String); 00236 int comIndexOfVarInfo(VarInfo); 00237 00238 /* comparators */ 00239 Boolean comCompareNets(Approver, ConstraintNet, ConstraintNet); 00240 Boolean comCompareAllLvs(Approver, ConstraintNet, ConstraintNet); 00241 Boolean comCompareAllLvPairs(Approver, ConstraintNet net); 00242 LevelValue comFindComparableLv(ConstraintNet, LevelValue); 00243 Boolean comCompareLvs(LevelValue, LevelValue); 00244 Boolean comCompareWithContext(Approver, ConstraintNet net, List contextList); 00245 00246 /* ------------------------------------------------------------------------- 00247 * constructor for a Compiler 00248 */ 00249 Compiler comNew(void) 00250 { 00251 int i = 0; 00252 String indentString = 00253 strRegister(" "); 00254 00255 Compiler thisCom = (Compiler)memMalloc(sizeof(CompilerStruct)); 00256 00257 thisCom->ccFileName = NULL; 00258 thisCom->objFileName = NULL; 00259 thisCom->soFileName = NULL; 00260 thisCom->directions = vectorNew(5); 00261 thisCom->connexions = vectorNew(8); 00262 thisCom->indent = 0; 00263 thisCom->indentString = strRegister(""); 00264 thisCom->indentStrings = vectorNew(40); 00265 thisCom->needsIndent = TRUE; 00266 thisCom->currentConstraint = NULL; 00267 thisCom->strings = vectorNew(1000); 00268 thisCom->translateOnly = FALSE; 00269 00270 vectorAddElement(thisCom->directions, (Pointer)Left); 00271 vectorAddElement(thisCom->directions, (Pointer)Right); 00272 vectorAddElement(thisCom->directions, (Pointer)Nil); 00273 vectorAddElement(thisCom->directions, (Pointer)NonNil); 00274 vectorAddElement(thisCom->directions, (Pointer)AnyDir); 00275 00276 vectorAddElement(thisCom->connexions, (Pointer)Top); 00277 vectorAddElement(thisCom->connexions, (Pointer)Bottom); 00278 vectorAddElement(thisCom->connexions, (Pointer)Over); 00279 vectorAddElement(thisCom->connexions, (Pointer)Under); 00280 vectorAddElement(thisCom->connexions, (Pointer)None); 00281 vectorAddElement(thisCom->connexions, (Pointer)Inverse); 00282 vectorAddElement(thisCom->connexions, (Pointer)Identical); 00283 vectorAddElement(thisCom->connexions, (Pointer)AnyCon); 00284 00285 for (i = 0; i < vectorCapacity(thisCom->indentStrings) * 2 - 2; i+=2) { 00286 indentString[i] = 0; 00287 vectorAddElement(thisCom->indentStrings, strRegister(indentString)); 00288 indentString[i] = ' '; 00289 } 00290 00291 return thisCom; 00292 } 00293 00294 /* --------------------------------------------------------------------------- 00295 * destructor for a Compiler 00296 */ 00297 void comFree(Compiler thisCom) 00298 { 00299 int i; 00300 00301 if (thisCom == NULL) 00302 return; 00303 00304 for (i = 0; i < vectorSize(thisCom->indentStrings); i++) { 00305 cdgFreeString(vectorElement(thisCom->indentStrings, i)); 00306 } 00307 for (i = 0; i < vectorSize(thisCom->strings); i++) { 00308 cdgFreeString(vectorElement(thisCom->strings, i)); 00309 } 00310 vectorDelete(thisCom->indentStrings); 00311 vectorDelete(thisCom->strings); 00312 vectorDelete(thisCom->directions); 00313 vectorDelete(thisCom->connexions); 00314 00315 memFree(thisCom); 00316 } 00317 00318 /* --------------------------------------------------------------------------- 00319 * constructor for a MakeInfo 00320 */ 00321 MakeInfo comMakeInfoNew(void) 00322 { 00323 MakeInfo thisMakeInfo = (MakeInfo)memMalloc(sizeof(MakeInfoStruct)); 00324 00325 thisMakeInfo->cc = NULL; 00326 thisMakeInfo->ld = NULL; 00327 thisMakeInfo->cFlags = NULL; 00328 thisMakeInfo->ldFlags = NULL; 00329 thisMakeInfo->ldLibs = NULL; 00330 thisMakeInfo->includes = NULL; 00331 00332 return thisMakeInfo; 00333 } 00334 00335 /* --------------------------------------------------------------------------- 00336 * destructor of a MakeInfo 00337 */ 00338 void comMakeInfoFree(MakeInfo thisMakeInfo) 00339 { 00340 if (!thisMakeInfo) 00341 return; 00342 00343 cdgFreeString(thisMakeInfo->cc); 00344 cdgFreeString(thisMakeInfo->ld); 00345 cdgFreeString(thisMakeInfo->cFlags); 00346 cdgFreeString(thisMakeInfo->ldFlags); 00347 cdgFreeString(thisMakeInfo->ldLibs); 00348 cdgFreeString(thisMakeInfo->includes); 00349 memFree(thisMakeInfo); 00350 } 00351 00352 /* --------------------------------------------------------------------------- 00353 * increase indentation 00354 */ 00355 void comIndent(void) 00356 { 00357 com->indent++; 00358 com->indentString = vectorElement(com->indentStrings, 00359 min(vectorSize(com->indentStrings), com->indent)); 00360 } 00361 00362 /* --------------------------------------------------------------------------- 00363 * decrease indentation 00364 */ 00365 void comOutdent(void) 00366 { 00367 com->indent--; 00368 assert(com->indent >= 0); 00369 com->indentString = vectorElement(com->indentStrings, 00370 min(vectorSize(com->indentStrings), com->indent)); 00371 } 00372 00373 /* ---------------------------------------------------------------------- 00374 * grant a newline at the end 00375 */ 00376 void comPrintln(String format, ...) 00377 { 00378 va_list ap; 00379 00380 if (com->needsIndent) { 00381 fprintf(com->ccFile, "%s", com->indentString); 00382 } 00383 va_start(ap, format); 00384 vfprintf(com->ccFile, format, ap); 00385 va_end(ap); 00386 00387 fprintf(com->ccFile, "\n"); 00388 com->needsIndent = TRUE; 00389 } 00390 00391 /* ---------------------------------------------------------------------- 00392 * escape quotes in strings 00393 */ 00394 String comEscapeQuotes(String str) { 00395 String s = NULL, cp = NULL, rt = ""; 00396 00397 if (! strchr(str, '\"')) { 00398 return str; 00399 } 00400 00401 cp = strCopy(str); 00402 00403 /* escape all quotes */ 00404 while ((s = strchr(cp, '\"'))) { 00405 *s = '\0'; 00406 rt = strAppend(rt, strPrintf("%s\\\"", cp), NULL); 00407 cp = s + 1; 00408 } 00409 00410 rt = strAppend(rt, cp, NULL); 00411 00412 return rt; 00413 } 00414 00415 /* ---------------------------------------------------------------------- 00416 * write a preprocessor warning 00417 */ 00418 void comWriteWarning(String format, ...) 00419 { 00420 va_list ap; 00421 00422 fprintf(com->ccFile, "\n#warning \""); 00423 00424 va_start(ap, format); 00425 vfprintf(com->ccFile, format, ap); 00426 va_end(ap); 00427 00428 if (com->currentConstraint) { 00429 fprintf(com->ccFile, " in constraint `%s'", 00430 comEscapeQuotes(com->currentConstraint->id)); 00431 } 00432 00433 fprintf(com->ccFile, "\"\n"); 00434 com->needsIndent = TRUE; 00435 } 00436 00437 /* ---------------------------------------------------------------------- 00438 * write a preprocessor error 00439 */ 00440 void comWriteError(String format, ...) 00441 { 00442 va_list ap; 00443 00444 fprintf(com->ccFile, "\n#error \""); 00445 00446 va_start(ap, format); 00447 vfprintf(com->ccFile, format, ap); 00448 va_end(ap); 00449 00450 if (com->currentConstraint) { 00451 fprintf(com->ccFile, " in constraint `%s'", 00452 comEscapeQuotes(com->currentConstraint->id)); 00453 } 00454 00455 fprintf(com->ccFile, "\"\n"); 00456 com->needsIndent = TRUE; 00457 } 00458 00459 /* ---------------------------------------------------------------------- 00460 * no good c program without its own printf 00461 */ 00462 void comPrint(String format, ...) 00463 { 00464 va_list ap; 00465 00466 if (com->needsIndent) { 00467 fprintf(com->ccFile, "%s", com->indentString); 00468 } 00469 va_start(ap, format); 00470 vfprintf(com->ccFile, format, ap); 00471 va_end(ap); 00472 00473 com->needsIndent = FALSE; 00474 } 00475 00476 /* ---------------------------------------------------------------------- 00477 * string representation of a returntype 00478 */ 00479 String comReturnTypeToString(ReturnType returnType) 00480 { 00481 switch ((unsigned long) returnType) { 00482 case RTBoolean: return "RTBoolean"; 00483 case RTNumber: return "RTNumber"; 00484 case RTString: return "RTString"; 00485 case RTAVNode: return "RTAVNode"; 00486 case RTList: return "RTList"; 00487 case RTConjunction: return "RTConjunction"; 00488 case RTDisjunction: return "RTDisjunction"; 00489 case RTError: return "RTError"; 00490 case RTLexemNode: return "RTModifieeLexemNode"; 00491 case RTLexemNode | RTLexemPosition: return "RTModifierLexemNode"; 00492 case RTGraphemNode: return "RTGraphemNode"; 00493 case RTPeek: return "RTPeek"; 00494 00495 case RTBoolean | RTNoError: return "RTBoolean!"; 00496 case RTNumber | RTNoError: return "RTNumber!"; 00497 case RTString | RTNoError: return "RTString!"; 00498 case RTAVNode | RTNoError: return "RTAVNode!"; 00499 case RTList | RTNoError: return "RTList!"; 00500 case RTConjunction | RTNoError: return "RTConjunction!"; 00501 case RTDisjunction | RTNoError: return "RTDisjunction!"; 00502 case RTError | RTNoError: return "RTError!"; 00503 case RTLexemNode | RTNoError: return "RTModifieeLexemNode!"; 00504 case RTLexemNode | RTNoError | RTLexemPosition: return "RTModifierLexemNode!"; 00505 case RTGraphemNode | RTNoError: return "RTGraphemNode!"; 00506 case RTPeek | RTNoError: return "RTPeek!"; 00507 } 00508 return "horst"; 00509 } 00510 00511 /* ---------------------------------------------------------------------- 00512 * string representation of a term type 00513 */ 00514 String comTermTypeToString(Term term) 00515 { 00516 switch (term->type) { 00517 case TTTopPeek: return "TTTopPeek"; 00518 case TTBottomPeek: return "TTBottomPeek"; 00519 case TTLabel: return "TTLabel"; 00520 case TTLevel: return "TTLevel"; 00521 case TTAdd: return "TTAdd"; 00522 case TTSubtract: return "TTSubtract"; 00523 case TTMultiply: return "TTMultiply"; 00524 case TTDivide: return "TTDivide"; 00525 case TTFunction: return "TTFunction"; 00526 case TTString: return "TTString"; 00527 case TTNumber: return "TTNumber"; 00528 } 00529 return "horst"; 00530 } 00531 00532 /* ---------------------------------------------------------------------- 00533 * string representation of a formula type 00534 */ 00535 String comFormulaTypeToString(Formula formula) 00536 { 00537 switch (formula->type) { 00538 case FTEqual: return "FTEqual"; 00539 case FTGreater: return "FTGreater"; 00540 case FTLess: return "FTLess"; 00541 case FTGreaterEqual: return "FTGreaterEqual"; 00542 case FTLessEqual: return "FTLessEqual"; 00543 case FTNotEqual: return "FTNotEqual"; 00544 case FTConjunction: return "FTConjunction"; 00545 case FTDisjunction: return "FTDisjunction"; 00546 case FTImplication: return "FTImplication"; 00547 case FTBiimplication: return "FTBiimplication"; 00548 case FTPredicate: return "FTPredicate"; 00549 case FTNegation: return "FTNegation"; 00550 case FTConstant: return "FTConstant"; 00551 case FTConnexion: return "FTConnexion"; 00552 case FTDirection: return "FTDirection"; 00553 } 00554 return "horst"; 00555 } 00556 00557 /* ---------------------------------------------------------------------- 00558 * string representation of a value type 00559 */ 00560 String comValueTypeToString(Value value) 00561 { 00562 switch(value->type) { 00563 case VTNumber: return "VTNumber"; 00564 case VTString: return "VTString"; 00565 case VTAVNode: return "VTAVNode"; 00566 case VTList: return "VTList"; 00567 case VTConjunction: return "VTConjunction"; 00568 case VTDisjunction: return "VTDisjunction"; 00569 case VTError: return "VTError"; 00570 case VTLexemNode: return "VTLexemNode"; 00571 case VTGraphemNode: return "VTGraphemNode"; 00572 } 00573 return "horst"; 00574 } 00575 00576 /* ---------------------------------------------------------------------- 00577 * string representation of a connexion 00578 */ 00579 String comConnextionToString(Connexion connexion) 00580 { 00581 switch (connexion) { 00582 case Top: return "Top"; 00583 case Bottom: return "Bottom"; 00584 case Over: return "Over"; 00585 case Under: return "Under"; 00586 case None: return "None"; 00587 case Inverse: return "Inverse"; 00588 case Identical: return "Identical"; 00589 case AnyCon: return "AnyCon"; 00590 } 00591 return "horst"; 00592 } 00593 00594 /* ---------------------------------------------------------------------- 00595 * string representation of a direction 00596 */ 00597 String comDirectionToString(Direction direction) 00598 { 00599 switch (direction) { 00600 case Left: return "Left"; 00601 case Right: return "Right"; 00602 case Nil: return "Nil"; 00603 case NonNil: return "NonNil"; 00604 case AnyDir: return "AnyDir"; 00605 } 00606 return "horst"; 00607 } 00608 00609 /* ---------------------------------------------------------------------- 00610 * write header 00611 */ 00612 void comWriteHeader(void) 00613 { 00614 time_t now = time((time_t *)NULL); 00615 struct passwd *pwp = getpwuid(getuid()); 00616 00617 comPrintln("/*"); 00618 comPrintln(" * THIS IS A MACHINE GENERATED FILE. DO NOT CHANGE ANYTHING HERE SINCE"); 00619 comPrintln(" * IT WILL BE OVERWRITTEN NEXT TIME."); 00620 comPrintln(" *"); 00621 comPrintln(" * Compiled by %s (%s) on %s", 00622 pwp ? pwp->pw_name : "UNKNOWN", 00623 pwp ? pwp->pw_gecos : "UNKNOWN", 00624 ctime(&now)); 00625 00626 comPrintln(" */\n"); 00627 comPrintln("/* -- INCLUDES ------------------------------------------------ */"); 00628 comPrintln("#include <stdio.h>"); 00629 comPrintln("#include <string.h>"); 00630 comPrintln("#include <math.h>"); 00631 comPrintln("#include <assert.h>"); 00632 comPrintln("#include <blah.h>"); 00633 comPrintln("#include \"cdg.h\""); 00634 comPrintln("#include \"command.h\""); 00635 comPrintln("#include \"compile.h\""); 00636 comPrintln("#include \"lexemgraph.h\""); 00637 comPrintln("#include \"eval.h\""); 00638 comPrintln("#include \"input.h\""); 00639 comPrintln("#include \"levelvalue.h\""); 00640 comPrintln("#include \"hook.h\""); 00641 comPrintln("#include \"predicates.h\""); 00642 comPrintln("#include \"functions.h\""); 00643 comPrintln("#include \"parsing.h\""); 00644 comPrintln("#include \"chunker.h\""); 00645 } 00646 00647 /* ---------------------------------------------------------------------- 00648 * write declaration section 00649 */ 00650 void comWriteDeclarations(void) 00651 { 00652 int i; 00653 List l, m; 00654 Constraint constraint; 00655 00656 00657 comPrintln(""); 00658 comPrintln("/* -- VARIABLES ----------------------------------------------- */"); 00659 00660 if(com->maxValues) { 00661 comPrint("static ValueStruct "); 00662 } 00663 00664 for (i = 0; i < com->maxValues; i++) { 00665 comPrint("vs%d", i); 00666 if (i == com->maxValues - 1) { 00667 comPrintln(";"); 00668 } else if (i%12 == 11) { 00669 comPrintln(","); 00670 comPrint(" "); 00671 } else { 00672 comPrint(", "); 00673 } 00674 } 00675 00676 /* max lookup strings */ 00677 comPrintln("static String *lookupStrings;"); 00678 00679 /* hierarchies array */ 00680 comPrintln("typedef struct {"); 00681 comIndent(); 00682 comPrintln("String id;"); 00683 comPrintln("Hierarchy hierarchy;"); 00684 comOutdent(); 00685 comPrintln("} HierarchyStubStruct;"); 00686 comPrintln("typedef HierarchyStubStruct *HierarchyStub;"); 00687 comPrintln("static HierarchyStubStruct hierarchies[%d];", 00688 hashSize(inputCurrentGrammar->hierarchies)); 00689 comPrintln("static int maxHierachies = %d;", 00690 hashSize(inputCurrentGrammar->hierarchies)); 00691 00692 /* constraints array */ 00693 comPrintln("typedef struct {"); 00694 comIndent(); 00695 comPrintln("String id;"); 00696 comPrintln("Constraint constraint;"); 00697 comPrintln("BooleanFunction *cfunction;"); 00698 comOutdent(); 00699 comPrintln("} ConstraintStubStruct;"); 00700 comPrintln("static ConstraintStubStruct constraints[%d];", 00701 hashSize(inputCurrentGrammar->constraints)); 00702 comPrintln("typedef ConstraintStubStruct *ConstraintStub;"); 00703 comPrintln("static int maxConstraints = %d;", 00704 hashSize(inputCurrentGrammar->constraints)); 00705 00706 /* static globals */ 00707 comPrintln("static Hierarchy hierarchy;"); 00708 comPrintln("static String *strings;"); 00709 comPrintln("static int a __attribute__ ((unused)), b __attribute__ ((unused)), c __attribute__ ((unused)), d __attribute__ ((unused));"); 00710 comPrintln("static LevelValue lv __attribute__ ((unused));"); 00711 comPrintln("static Constraint constraint __attribute__ ((unused));"); 00712 comPrintln("static void *hasImplArgs[11] __attribute__ ((unused));"); 00713 comPrintln("static Boolean bool __attribute__ ((unused));"); 00714 comPrintln(""); 00715 00716 /* common forward declarations */ 00717 comPrintln("Boolean %s(Input);", INIT_GRAMMAR); 00718 comPrintln("void %s(Input);", FINIT_GRAMMAR); 00719 comPrintln(""); 00720 comPrintln("static HierarchyStub _findHierarchyStub(String id);"); 00721 comPrintln(""); 00722 comPrintln("static ValueType _matchList(String constraint, List candidates, String sort, Value result) __attribute__ ((unused));"); 00723 comPrintln("static ValueType _matchString(String constraint, String sortA, String sortB, Value result) __attribute__ ((unused));"); 00724 comPrintln("static Boolean _subsumes(String constraint, String sortA, String sortB) __attribute__ ((unused));"); 00725 comPrintln("static Boolean _compatible(String constraint, String sortA, String sortB) __attribute__ ((unused));"); 00726 comPrintln("static Hierarchy _findHierarchy(String id) __attribute__ ((unused));"); 00727 comPrintln("static Connexion _getConnextion(LevelValue, LevelValue) __attribute__ ((unused));"); 00728 comPrintln("static String _lookup(String hashtableName) __attribute__ ((unused));"); 00729 comPrintln("static Boolean _connected(int a, int b, int nrlevels, int levelno, LexemGraph lg, Vector context) __attribute__ ((unused));"); 00730 00731 /* forward declarations of all constraint c-functions */ 00732 comPrintln("/* forward declaration of unary constraints */"); 00733 m = hashListOfKeys(inputCurrentGrammar->constraints); 00734 for (l = m; l != NULL; l = listNext(l)) { 00735 constraint = hashGet(inputCurrentGrammar->constraints, listElement(l)); 00736 if (constraint->sig->arity == 1) { 00737 comPrintln("Boolean _evalConstraint_%d(LexemGraph, Vector context, LevelValue);", constraint->no); 00738 } 00739 } 00740 comPrintln("/* forward declaration of binary constraints */"); 00741 for (l = m; l != NULL; l = listNext(l)) { 00742 constraint = hashGet(inputCurrentGrammar->constraints, listElement(l)); 00743 if (constraint->sig->arity == 2) { 00744 comPrintln("Boolean _evalConstraint_%d(LexemGraph, Vector context, LevelValue, LevelValue);", constraint->no); 00745 } 00746 } 00747 listDelete(m); 00748 00749 comPrintln(""); 00750 } 00751 00752 /* ---------------------------------------------------------------------- 00753 * write helper functions 00754 */ 00755 void comWriteFunctions(void) 00756 { 00757 /* 00758 * _matchList 00759 */ 00760 comPrintln(""); 00761 comPrintln("/* ------------------------------------------------------------"); 00762 comPrintln(" * implement match(string, list, string), see funcMatch"); 00763 comPrintln(" * returns VTNumber or VTError"); 00764 comPrintln(" */"); 00765 comPrintln("static ValueType _matchList(String constraint, List candidates, String sort, Value result) "); 00766 comPrintln("{"); 00767 comIndent(); 00768 comPrintln("int a, b;"); 00769 comPrintln("List l;"); 00770 comPrintln("Value value;"); 00771 comPrintln(""); 00772 comPrintln("b = (int)hashGet(hierarchy->types, sort) - 1;"); 00773 comPrintln("if (b < 0) {"); 00774 comIndent(); 00775 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: 2nd type `%%s' not found in hierarchy `%%s' in `matchList' in constraint `%%s'\\n\"," 00776 "sort, hierarchy->id, constraint);"); 00777 comPrintln("return VTError;"); 00778 comOutdent(); 00779 comPrintln("}"); 00780 comPrintln(""); 00781 comPrintln("result->data.number = 0.0; result->type = VTNumber;"); 00782 comPrintln("for (l = candidates; l != NULL; l = listNext(listNext(l))) {"); 00783 comIndent(); 00784 comPrintln("value = (Value)listElement(l);"); 00785 comPrintln("a = (int)hashGet(hierarchy->types, value->data.string) - 1;"); 00786 comPrintln("if (a < 0) {"); 00787 comIndent(); 00788 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: type `%%s' not found in hierarchy `%%s' in `matchList' in constraint `%%s'\\n\"," 00789 "value->data.string, hierarchy->id, constraint);"); 00790 comPrintln("return VTError;"); 00791 comOutdent(); 00792 comPrintln("}"); 00793 comPrintln("if ((int)arrayElement(hierarchy->distance, a, b) >= 0) {"); 00794 comIndent(); 00795 comPrintln("result->data.number = ((Value)listElement(listNext(l)))->data.number;"); 00796 comPrintln("break;"); 00797 comOutdent(); 00798 comPrintln("}"); 00799 comOutdent(); 00800 comPrintln("}"); 00801 comPrintln("return VTNumber;"); 00802 comOutdent(); 00803 comPrintln("}"); 00804 comPrintln(""); 00805 00806 /* 00807 * _matchString 00808 */ 00809 comPrintln(""); 00810 comPrintln("/* ------------------------------------------------------------"); 00811 comPrintln(" * implement match(string, string, string), see funcMatch"); 00812 comPrintln(" * returns VTNumber or VTError"); 00813 comPrintln(" */"); 00814 comPrintln("static ValueType _matchString(String constraint, String sortA, String sortB, Value result)"); 00815 comPrintln("{"); 00816 comIndent(); 00817 comPrintln("int a, b;"); 00818 comPrintln(""); 00819 comPrintln("a = (int)hashGet(hierarchy->types, sortA) - 1;"); 00820 comPrintln("if (a < 0) {"); 00821 comIndent(); 00822 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: 1rst type `%%s' not found in hierarchy `%%s' in `matchString' in constraint `%%s'\\n\"," 00823 "sortA, hierarchy->id, constraint);"); 00824 comPrintln("return VTError;"); 00825 comOutdent(); 00826 comPrintln("}"); 00827 comPrintln(""); 00828 comPrintln("b = (int)hashGet(hierarchy->types, sortB) - 1;"); 00829 comPrintln("if (b < 0) {"); 00830 comIndent(); 00831 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: 2nd type `%%s' not found in hierarchy `%%s' in `matchString' in constraint `%%s'\\n\"," 00832 "sortB, hierarchy->id, constraint);"); 00833 comPrintln("return VTError;"); 00834 comOutdent(); 00835 comPrintln("}"); 00836 00837 comPrintln(""); 00838 comPrintln("result->data.number = ((int)arrayElement(hierarchy->distance, a, b) >= 0) ? 1.0 : 0.0;"); 00839 comPrintln("return VTNumber;"); 00840 comOutdent(); 00841 comPrintln("}"); 00842 comPrintln(""); 00843 00844 /* 00845 * _subsumes 00846 */ 00847 comPrintln(""); 00848 comPrintln("/* ------------------------------------------------------------"); 00849 comPrintln(" * implement subsumes(string, string, string), see predSubsumes"); 00850 comPrintln(" * returns VTNumber or VTError"); 00851 comPrintln(" */"); 00852 comPrintln("static Boolean _subsumes(String constraint, String sortA, String sortB)"); 00853 comPrintln("{"); 00854 comIndent(); 00855 comPrintln("int a, b;"); 00856 comPrintln(""); 00857 comPrintln("a = (int)hashGet(hierarchy->types, sortA) - 1;"); 00858 comPrintln("if (a < 0) {"); 00859 comIndent(); 00860 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: 1rst type `%%s' not found in hierarchy `%%s' in `subsumes' in constraint `%%s'\\n\"," 00861 "sortA, hierarchy->id, constraint);"); 00862 comPrintln("return FALSE;"); 00863 comOutdent(); 00864 comPrintln("}"); 00865 comPrintln(""); 00866 comPrintln("b = (int)hashGet(hierarchy->types, sortB) - 1;"); 00867 comPrintln("if (b < 0) {"); 00868 comIndent(); 00869 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: 2nd type `%%s' not found in hierarchy `%%s' in `subsumes' in constraint `%%s'\\n\"," 00870 "sortB, hierarchy->id, constraint);"); 00871 comPrintln("return FALSE;"); 00872 comOutdent(); 00873 comPrintln("}"); 00874 comPrintln("return ((int)arrayElement(hierarchy->distance, a, b) >= 0);"); 00875 comOutdent(); 00876 comPrintln("}"); 00877 comPrintln(""); 00878 00879 /* 00880 * _compatible 00881 */ 00882 comPrintln(""); 00883 comPrintln("/* ------------------------------------------------------------"); 00884 comPrintln(" * implement compatible(string, string, string), see predCompatible"); 00885 comPrintln(" * returns VTNumber or VTError"); 00886 comPrintln(" */"); 00887 comPrintln("static Boolean _compatible(String constraint, String sortA, String sortB)"); 00888 comPrintln("{"); 00889 comIndent(); 00890 comPrintln("int a, b;"); 00891 comPrintln(""); 00892 comPrintln("a = (int)hashGet(hierarchy->types, sortA) - 1;"); 00893 comPrintln("if (a < 0) {"); 00894 comIndent(); 00895 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: 1rst type `%%s' not found in hierarchy `%%s' in `compatible' in constraint `%%s'\\n\"," 00896 "sortA, hierarchy->id, constraint);"); 00897 comPrintln("return FALSE;"); 00898 comOutdent(); 00899 comPrintln("}"); 00900 comPrintln(""); 00901 comPrintln("b = (int)hashGet(hierarchy->types, sortB) - 1;"); 00902 comPrintln("if (b < 0) {"); 00903 comIndent(); 00904 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: 2nd type `%%s' not found in hierarchy `%%s' in `compatible' in constraint `%%s'\\n\"," 00905 "sortB, hierarchy->id, constraint);"); 00906 comPrintln("return FALSE;"); 00907 comOutdent(); 00908 comPrintln("}"); 00909 comPrintln("return (((int)arrayElement(hierarchy->distance, a, b) >= 0) ||"); 00910 comPrintln(" ((int)arrayElement(hierarchy->distance, b, a) >= 0));"); 00911 comOutdent(); 00912 comPrintln("}"); 00913 comPrintln(""); 00914 00915 /* 00916 * _findHierarchyStub 00917 */ 00918 comPrintln(""); 00919 comPrintln("/* ------------------------------------------------------------"); 00920 comPrintln(" * returns the named hierarchy stub, NULL if not found"); 00921 comPrintln(" */"); 00922 comPrintln("static HierarchyStub _findHierarchyStub(String id)"); 00923 comPrintln("{"); 00924 comIndent(); 00925 comPrintln("int i;"); 00926 comPrintln(""); 00927 comPrintln("for (i = 0; i < maxHierachies; i++) {"); 00928 comIndent(); 00929 comPrintln("if (strcmp(id, hierarchies[i].id) == 0) {"); 00930 comIndent(); 00931 comPrintln("return &hierarchies[i];"); 00932 comOutdent(); 00933 comPrintln("}"); 00934 comOutdent(); 00935 comPrintln("}"); 00936 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: hierarchy `%%s' not found in `findHierarchy'\\n\", id);"); 00937 comPrintln("return NULL;"); 00938 comOutdent(); 00939 comPrintln("}"); 00940 comPrintln(""); 00941 00942 /* 00943 * _findHierarchy 00944 */ 00945 comPrintln(""); 00946 comPrintln("/* ------------------------------------------------------------"); 00947 comPrintln(" * returns the named hierarchy, NULL if not found"); 00948 comPrintln(" */"); 00949 comPrintln("static Hierarchy _findHierarchy(String id)"); 00950 comPrintln("{"); 00951 comIndent(); 00952 comPrintln("HierarchyStub hierarchyStub = _findHierarchyStub(id);"); 00953 comPrintln("return hierarchyStub?hierarchyStub->hierarchy:NULL;"); 00954 comOutdent(); 00955 comPrintln("}"); 00956 comPrintln(""); 00957 00958 /* 00959 * _getConnextion 00960 */ 00961 comPrintln(""); 00962 comPrintln("/* ------------------------------------------------------------"); 00963 comPrintln(" * returns the connexion of two lvs and caches the result"); 00964 comPrintln(" */"); 00965 comPrintln("static Connexion _getConnextion(LevelValue lv1, LevelValue lv2)"); 00966 comPrintln("{"); 00967 comIndent(); 00968 comPrintln("static Connexion connexion;"); 00969 comPrintln("static LevelValue currentLv1 = NULL, currentLv2 = NULL;"); 00970 comPrintln("if (lv1 != currentLv1 || lv2 != currentLv2) {"); 00971 comIndent(); 00972 comPrintln("currentLv1 = lv1;"); 00973 comPrintln("currentLv2 = lv2;"); 00974 comPrintln("connexion = getCon(lv1, lv2);"); 00975 comOutdent(); 00976 comPrintln("}"); 00977 comPrintln("return connexion;"); 00978 comOutdent(); 00979 comPrintln("}"); 00980 comPrintln(""); 00981 00982 /* 00983 * _lookup 00984 */ 00985 comPrintln(""); 00986 comPrintln("/* ------------------------------------------------------------"); 00987 comPrintln(" * returns the string result of the hashtable lookup"); 00988 comPrintln(" */"); 00989 comPrintln("static String _lookup(String hashtableName)"); 00990 comPrintln("{"); 00991 comIndent(); 00992 comPrintln("Hashtable hashtable;"); 00993 comPrintln("Value result;"); 00994 comPrintln("String key = NULL;"); 00995 comPrintln("int i = 0;"); 00996 comPrintln(""); 00997 comPrintln("if (lookupStrings[0]) {"); 00998 comPrintln(" hashtable = hashGet(inputCurrentGrammar->maps, hashtableName);"); 00999 comPrintln(" if (hashtable) {"); 01000 comPrintln(" for (i = 0; lookupStrings[i]; i++) {"); 01001 #ifdef DEBUG_LOOKUP 01002 comPrintln(" cdgPrintf(CDG_DEBUG, \"LookupStrings[%%d] = %%s\\n\", i, lookupStrings[i]);"); 01003 #endif 01004 comPrintln(" key = key ? strAppend(key, strRegister(\":\"), lookupStrings[i], NULL) : lookupStrings[i] ;"); 01005 comPrintln(" }"); 01006 #ifdef DEBUG_LOOKUP 01007 comPrintln(" cdgPrintf(CDG_DEBUG, \"key = %%s\\n\", key);"); 01008 #endif 01009 comPrintln(" if ((result = hashGet(hashtable, key))) {"); 01010 #ifdef DEBUG_LOOKUP 01011 comPrintln(" cdgPrintf(CDG_DEBUG, \"Lookup result = %%s\\n\", result->data.string);"); 01012 #endif 01013 comPrintln(" return result->data.string;"); 01014 comPrintln(" }"); 01015 comPrintln(" }else {"); 01016 comPrintln(" cdgPrintf(CDG_WARNING, \"WARNING: Map %%s not found\\n\", hashtableName);"); 01017 comPrintln(" }"); 01018 comPrintln("}"); 01019 comPrintln("return strRegister(\"\");"); 01020 comOutdent(); 01021 comPrintln("}"); 01022 01023 /* 01024 * _connected 01025 */ 01026 comPrintln(""); 01027 comPrintln("/* ------------------------------------------------------------"); 01028 comPrintln(" * returns TRUE if a and b are part of the same tree"); 01029 comPrintln(" */"); 01030 comPrintln("static Boolean _connected(int a, int b, int nrlevels, int levelno, LexemGraph lg, Vector context)"); 01031 comPrintln("{"); 01032 comPrintln(" int count = 0, roota = -1, rootb = -1;"); 01033 comPrintln(" LevelValue lv;"); 01034 comPrintln(" int max = lg->max - lg->min;"); 01035 comPrintln(" "); 01036 comPrintln(" lv = vectorElement(context, nrlevels * a + levelno);"); 01037 comPrintln(" while(lv) {"); 01038 comPrintln(" if(!spec(lv->modifiee)) {"); 01039 comPrintln(" roota = lv->modifier->arc->from;"); 01040 comPrintln(" break;"); 01041 comPrintln(" }"); 01042 comPrintln(" else if(NONSPEC == lv->modifiee) {"); 01043 comPrintln(" return FALSE;"); 01044 comPrintln(" }"); 01045 comPrintln(" else if(count++ > max) {"); 01046 comPrintln(" roota = a;"); 01047 comPrintln(" break;"); 01048 comPrintln(" }"); 01049 comPrintln(" else {"); 01050 comPrintln(" lv = vectorElement(context, nrlevels * lv->modifiee->arc->from + levelno);"); 01051 comPrintln(" }"); 01052 comPrintln(" }"); 01053 comPrintln(" "); 01054 comPrintln(" count = 0;"); 01055 comPrintln(" lv = vectorElement(context, nrlevels * b + levelno);"); 01056 comPrintln(" while(lv) {"); 01057 comPrintln(" if(!spec(lv->modifiee)) {"); 01058 comPrintln(" rootb = lv->modifier->arc->from;"); 01059 comPrintln(" break;"); 01060 comPrintln(" }"); 01061 comPrintln(" else if(NONSPEC == lv->modifiee) {"); 01062 comPrintln(" return FALSE;"); 01063 comPrintln(" }"); 01064 comPrintln(" else if(count++ > max) {"); 01065 comPrintln(" rootb = b;"); 01066 comPrintln(" break;"); 01067 comPrintln(" }"); 01068 comPrintln(" else {"); 01069 comPrintln(" lv = vectorElement(context, nrlevels * lv->modifiee->arc->from + levelno);"); 01070 comPrintln(" }"); 01071 comPrintln(" }"); 01072 comPrintln(" "); 01073 comPrintln(" return roota == rootb;"); 01074 comPrintln("}"); 01075 01076 /* initGrammar and finitGrammar */ 01077 comWriteInitFunction(); 01078 comWriteFinitFunction(); 01079 assert(com->indent == 0); 01080 01081 } 01082 01083 /* ---------------------------------------------------------------------- 01084 * write the grammar finalization function 01085 */ 01086 void comWriteFinitFunction(void) 01087 { 01088 comPrintln("/* ------------------------------------------------------------"); 01089 comPrintln(" * finalize the dll grammar"); 01090 comPrintln(" */"); 01091 comPrintln("void %s(Input thisInput)", FINIT_GRAMMAR); 01092 comPrintln("{"); 01093 comIndent(); 01094 comPrintln("int i;"); 01095 comPrintln("Constraint constraint;"); 01096 comPrintln("HashIterator hi;"); 01097 01098 /* free the strings */ 01099 comPrintln("for (i = 0; i < %d; i++) {", vectorSize(com->strings)); 01100 comIndent(); 01101 comPrintln("cdgFreeString(strings[i]);"); 01102 comOutdent(); 01103 comPrintln("}"); 01104 comPrintln("memFree(strings);"); 01105 01106 /* reset unlink the c constraints */ 01107 comPrintln("hi = hashIteratorNew(thisInput->constraints);"); 01108 comPrintln("while (NULL != (constraint = (Constraint)hashIteratorNextValue(hi))) {"); 01109 comIndent(); 01110 comPrintln("constraint->cfunction = NULL;"); 01111 comOutdent(); 01112 comPrintln("}"); 01113 comPrintln("hashIteratorDelete(hi);"); 01114 01115 comOutdent(); 01116 comPrintln("}"); 01117 comPrintln(""); 01118 } 01119 /* ---------------------------------------------------------------------- 01120 * write the grammar initialization function 01121 */ 01122 void comWriteInitFunction(void) 01123 { 01124 Hierarchy hierarchy; 01125 Constraint constraint; 01126 int i; 01127 HashIterator hi; 01128 01129 comPrintln("/* ------------------------------------------------------------"); 01130 comPrintln(" * initialize the dll grammar"); 01131 comPrintln(" */"); 01132 comPrintln("Boolean %s(Input thisInput)", INIT_GRAMMAR); 01133 comPrintln("{"); 01134 comIndent(); 01135 comPrintln("int i;"); 01136 comPrintln("Hierarchy hierarchy = NULL;"); 01137 comPrintln("Constraint constraint = NULL;"); 01138 01139 /* remember the correct ids of the hierarchies */ 01140 for (i = 0, hi = hashIteratorNew(inputCurrentGrammar->hierarchies); 01141 NULL != (hierarchy = hashIteratorNextValue(hi)); 01142 i++) { 01143 comPrintln("hierarchies[%d].id = strRegister(\"%s\");", i, 01144 comEscapeQuotes(hierarchy->id)); 01145 comPrintln("hierarchies[%d].hierarchy = NULL;", i); 01146 } 01147 hashIteratorDelete(hi); 01148 comPrintln(""); 01149 01150 /* remember the correct ids of the constraints */ 01151 for (i = 0, hi = hashIteratorNew(inputCurrentGrammar->constraints); 01152 NULL != (constraint = hashIteratorNextValue(hi)); 01153 i++) { 01154 comPrintln("constraints[%d].id = strRegister(\"%s\");", i, 01155 comEscapeQuotes(constraint->id)); 01156 comPrintln("constraints[%d].constraint = NULL;", i); 01157 comPrintln("constraints[%d].cfunction = &_evalConstraint_%d;", i, constraint->no); 01158 } 01159 hashIteratorDelete(hi); 01160 comPrintln(""); 01161 01162 /* registration of static strings */ 01163 comPrintln("strings = (String *)memMalloc(sizeof(String) * %d);", 01164 vectorSize(com->strings)); 01165 for (i = 0; i < vectorSize(com->strings); i++) { 01166 String string = (String)vectorElement(com->strings, i); 01167 comPrintln("strings[%d] = strRegister(\"%s\");", i, comEscapeQuotes(string)); 01168 } 01169 01170 /* allocate memory for the lookup strings */ 01171 comPrintln("lookupStrings = (String *)memMalloc(sizeof(String) * %d);", 01172 (com->maxLookupStrings + 1)); 01173 01174 /* manual runtime linkage of the hierarchies */ 01175 comPrintln("for (i = 0; i < maxHierachies; i++) {"); 01176 comIndent(); 01177 comPrintln("if (! (hierarchy = (Hierarchy)findHierarchy(hierarchies[i].id))) {"); 01178 comIndent(); 01179 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: cannot find hierarchy `%%s'\\n\", hierarchies[i].id);"); 01180 comPrintln("return FALSE;"); 01181 comOutdent(); 01182 comPrintln("}"); 01183 01184 comPrintln("hierarchies[i].hierarchy = hierarchy;"); 01185 comOutdent(); 01186 comPrintln("}"); 01187 01188 /* manual runtime linkage of the constraints */ 01189 comPrintln("for(i = 0; i < maxConstraints; i++) {"); 01190 comIndent(); 01191 comPrintln("if (! (constraint = (Constraint)hashGet(thisInput->constraints, constraints[i].id))) {"); 01192 comIndent(); 01193 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: cannot find constraint `%%s'\\n\", constraints[i].id);"); 01194 comPrintln("return FALSE;"); 01195 comOutdent(); 01196 comPrintln("}"); 01197 01198 comPrintln("constraints[i].constraint = constraint;"); 01199 comPrintln("if (constraint->cfunction != NULL)"); 01200 comIndent(); 01201 comPrintln("cdgPrintf(CDG_WARNING, \"WARNING: constraint `%%s' has already been compiled\\n\", constraint->id);"); 01202 comOutdent(); 01203 comPrintln("constraint->cfunction = constraints[i].cfunction;"); 01204 comOutdent(); 01205 comPrintln("}"); 01206 01207 comPrintln("return TRUE;"); 01208 01209 comOutdent(); 01210 comPrintln("}"); 01211 comPrintln(""); 01212 } 01213 01214 /* ---------------------------------------------------------------------- 01215 * get the index of a hierarchy 01216 */ 01217 int comIndexOfHierarchy(String id) 01218 { 01219 int i; 01220 Hierarchy hierarchy; 01221 HashIterator hi; 01222 01223 for (i = 0, hi = hashIteratorNew(inputCurrentGrammar->hierarchies); 01224 NULL != (hierarchy = hashIteratorNextValue(hi)); 01225 i++) { 01226 if (strcmp(hierarchy->id, id) == 0) { 01227 return i; 01228 } 01229 } 01230 01231 comWriteError("unknown hierarchy `%s'", id); 01232 return -1; 01233 } 01234 01235 /* ---------------------------------------------------------------------- 01236 * get the index of a constraint 01237 */ 01238 int comIndexOfConstraint(String id) 01239 { 01240 int i; 01241 Constraint constraint; 01242 HashIterator hi; 01243 01244 for (i = 0, hi = hashIteratorNew(inputCurrentGrammar->constraints); 01245 NULL != (constraint = hashIteratorNextValue(hi)); 01246 i++) { 01247 if (strcmp(constraint->id, id) == 0) { 01248 return i; 01249 } 01250 } 01251 01252 comWriteError("unknown constraint `%s'", id); 01253 return -1; 01254 } 01255 01256 /* ---------------------------------------------------------------------- 01257 * get index of assigned variable 01258 */ 01259 int comIndexOfVarInfo(VarInfo varInfo) 01260 { 01261 int index = listIndex(com->currentConstraint->vars, varInfo); 01262 01263 assert(index > 0); 01264 01265 return index; 01266 } 01267 01268 /* ---------------------------------------------------------------------- 01269 * register a string to be allocated statically later 01270 * returns the index in strings 01271 */ 01272 int comRegisterString(String string) 01273 { 01274 int i; 01275 String oldString; 01276 String newString = strRegister(string); 01277 01278 01279 for (i = 0; i < vectorSize(com->strings); i++) { 01280 oldString = (String)vectorElement(com->strings, i); 01281 if (oldString == newString) { 01282 return i; 01283 } 01284 } 01285 01286 return vectorAddElement(com->strings, newString); 01287 } 01288 01289 /* ---------------------------------------------------------------------- 01290 * translate a ^id and \@id 01291 */ 01292 void comTranslateLexemNodeAccess(Term term, int tmpIndex) 01293 { 01294 String position = "horst"; 01295 String pathItem; 01296 01297 /* used in parent() */ 01298 if (term->type == TTFunction) { 01299 comPrint("((LexemNode)vs%d.data.lexemnode)", tmpIndex); 01300 return; 01301 } 01302 01303 /* security checks */ 01304 if (term->type == TTBottomPeek) { 01305 position = "modifier"; 01306 } else if (term->type == TTTopPeek) { 01307 position = "modifiee"; 01308 } 01309 else { /* never reach */ 01310 comWriteError("comTranslateLexemNodeAccess called with invalid term argument"); 01311 return; 01312 } 01313 01314 pathItem = (String) listElement(term->data.peek.path); 01315 if (strcmp("id", pathItem) != 0) { 01316 comWriteError("comTranslateLemNodeAccess called with invalid path item `%s'", 01317 pathItem); 01318 return; 01319 } 01320 01321 comPrint("lv%d->%s", 01322 comIndexOfVarInfo(term->data.peek.varinfo), position); 01323 } 01324 01325 /* ---------------------------------------------------------------------- 01326 * translate a lexical access 01327 */ 01328 void comTranslateLexicalAccess(Term term) 01329 { 01330 String position = "horst"; 01331 String pathItem; 01332 01333 /* security checks */ 01334 if (term->type == TTBottomPeek) { 01335 position = "modifier"; 01336 } else if (term->type == TTTopPeek) { 01337 position = "modifiee"; 01338 } else { /* never reach */ 01339 comWriteError("comTranslateLexicalAccess called with invalid term argument"); 01340 return; 01341 } 01342 01343 pathItem = (String) listElement(term->data.peek.path); 01344 if (strcmp("id", pathItem) == 0 || 01345 strcmp("from", pathItem) == 0 || 01346 strcmp("to", pathItem) == 0 || 01347 strcmp("word", pathItem) == 0) { 01348 comWriteError("comTranslateLexicalAccess called with invalid path item `%s'", 01349 pathItem); 01350 return; 01351 } 01352 01353 comPrint("lv%d->%s->lexem->values[%d/*%s*/]", 01354 comIndexOfVarInfo(term->data.peek.varinfo), 01355 position, term->data.peek.pathindex, sprintPath(term->data.peek.path)); 01356 } 01357 01358 /* ---------------------------------------------------------------------- 01359 * translate a function to c code 01360 */ 01361 void comTranslateFunction(String functor, List args, int tmpIndex) 01362 { 01363 comPrintln("( /* %s */ ", functor); 01364 comIndent(); 01365 01366 /* distance */ 01367 if (strcmp("distance", functor) == 0) { 01368 comTranslateDistance(args, tmpIndex); 01369 } 01370 01371 /* abs */ 01372 else if (strcmp("abs", functor) == 0) { 01373 comTranslateAbs(args, tmpIndex); 01374 } 01375 01376 /* min, max */ 01377 else if (strcmp("min", functor) == 0 || 01378 strcmp("max", functor) == 0) { 01379 comTranslateMinMax(functor, args, tmpIndex); 01380 } 01381 01382 /* match */ 01383 else if (strcmp("match", functor) == 0) { 01384 comTranslateMatch(args, tmpIndex); 01385 } 01386 01387 /* phrasequotes */ 01388 else if (strcmp("phrasequotes", functor) == 0) { 01389 comTranslatePhrasequotes(args, tmpIndex); 01390 } 01391 01392 /* lookup */ 01393 else if (strcmp("lookup", functor) == 0) { 01394 comTranslateLookup(args, tmpIndex); 01395 } 01396 01397 /* quotes */ 01398 else if (strcmp("quotes", functor) == 0) { 01399 comTranslateQuotes(args, tmpIndex); 01400 } 01401 01402 /* parens */ 01403 else if (strcmp("parens", functor) == 0) { 01404 comTranslateParens(args, tmpIndex); 01405 } 01406 01407 /* parent */ 01408 else if (strcmp("parent", functor) == 0) { 01409 comTranslateParent(args, tmpIndex); 01410 } 01411 01412 /* pts */ 01413 else if (strcmp("pts", functor) == 0) { 01414 comTranslatePts(args, tmpIndex); 01415 } 01416 01417 /* height */ 01418 else if (strcmp("height", functor) == 0) { 01419 comTranslateHeight(args, tmpIndex); 01420 } 01421 01422 /* never reach */ 01423 else { 01424 comWriteError("compile.c:%d: unknown function `%s'", __LINE__, functor); 01425 } 01426 01427 01428 comOutdent(); 01429 comPrint(")"); 01430 } 01431 01432 /* ---------------------------------------------------------------------- 01433 * translate the distance function 01434 */ 01435 void comTranslateDistance(List args, int tmpIndex) 01436 { 01437 Term term1 = (Term)listNthElement(args, 1); 01438 Term term2 = (Term)listNthElement(args, 2); 01439 ReturnType returnType1 = comReturnTypeOfTerm(term1) & ~RTNoError; 01440 ReturnType returnType2 = comReturnTypeOfTerm(term2) & ~RTNoError; 01441 01442 comTranslateTerm(term1, FALSE, TRUE, tmpIndex); 01443 comTranslateTerm(term2, FALSE, TRUE, tmpIndex+1); 01444 01445 switch(returnType1 & ~RTLexemPosition) { 01446 case RTLexemNode: 01447 comPrint("("); 01448 if (returnType1 & RTLexemPosition) { 01449 comPrint("("); 01450 comTranslateLexemNodeAccess(term1, tmpIndex); 01451 comPrintln(" == NULL) ? (vs%d.data.number = 0.0):", tmpIndex); 01452 } 01453 switch(returnType2 & ~RTLexemPosition) { 01454 case RTLexemNode: 01455 comPrint("("); 01456 if (returnType2 & RTLexemPosition) { 01457 comPrint("("); 01458 comTranslateLexemNodeAccess(term2, tmpIndex); 01459 comPrintln(" == NULL) ? (vs%d.data.number = 0.0):", tmpIndex); 01460 } 01461 comPrint("(vs%d.data.number = lgDistanceOfNodes(lg, ", tmpIndex); 01462 comTranslateLexemNodeAccess(term1, tmpIndex); 01463 comPrint(", "); 01464 comTranslateLexemNodeAccess(term2, tmpIndex); 01465 comPrintln(")))),"); 01466 comPrintln("(vs%d.type = VTNumber)", tmpIndex); 01467 break; 01468 default: /* never reach */ 01469 comWriteError("illegal return type `%s' in `distance'", 01470 comReturnTypeToString(returnType2)); 01471 } 01472 break; 01473 default: /* never reach */ 01474 comWriteError("illegal return type `%s' in `distance'", 01475 comReturnTypeToString(returnType1)); 01476 } 01477 } 01478 01479 /* ---------------------------------------------------------------------- 01480 * translate the abs function 01481 */ 01482 void comTranslateAbs(List args, int tmpIndex) 01483 { 01484 Term term = (Term)listElement(args); 01485 ReturnType returnType = comReturnTypeOfTerm(term); 01486 01487 comTranslateTerm(term, FALSE, TRUE, tmpIndex); 01488 returnType &= ~RTNoError; 01489 switch(returnType) { 01490 case RTPeek: 01491 comPrintln(" != VTNumber?", tmpIndex); 01492 comPrintln("(cdgPrintf(CDG_ERROR, \"ERROR: type mismatch in `abs'\"), vs%d.type = VTError) :", 01493 tmpIndex); 01494 comPrint("((vs%d.data.number = fabs(", tmpIndex); 01495 comTranslateLexicalAccess(term); 01496 comPrintln("->data.number)), vs%d.type = VTNumber))", tmpIndex); 01497 break; 01498 case RTNumber: 01499 comPrint("((vs%d.data.number = fabs(", tmpIndex); 01500 comTranslateNumber(term, tmpIndex); 01501 comPrintln(")), vs%d.type = VTNumber)", tmpIndex); 01502 break; 01503 default: /* never reach */ 01504 comWriteError("illegal return type `%s' in `abs'", 01505 comReturnTypeToString(returnType)); 01506 } 01507 } 01508 01509 /* ---------------------------------------------------------------------- 01510 * translate the phrasequotes function 01511 */ 01512 void comTranslatePhrasequotes(List args, int tmpIndex) 01513 { 01514 Term term = (Term)listElement(args); 01515 ReturnType returnType = comReturnTypeOfTerm(term); 01516 01517 /* top peek */ 01518 comPrint("(! "); 01519 comTranslateLexemNodeAccess(term, tmpIndex); 01520 if (returnType & RTLexemPosition) { 01521 comPrint(" || "); 01522 comTranslateLexemNodeAccess(term, tmpIndex); 01523 comPrint(" == NONSPEC"); 01524 } 01525 comPrintln(") ?"); 01526 comPrintln("cdgPrintf(CDG_ERROR,\"ERROR: argument of 'phrasequotes' isn't a lexem node\"), (vs%d.type = VTError) :", tmpIndex); 01527 comPrint("(vs%d.data.number = ", tmpIndex); 01528 comTranslateLexemNodeAccess(term, tmpIndex); 01529 comPrint("->arc->phraseQuotes), ("); 01530 comPrint("vs%d.type = VTNumber)", tmpIndex); 01531 } 01532 01533 /* ---------------------------------------------------------------------- 01534 * translate the lookup function 01535 */ 01536 void comTranslateLookup(List args, int tmpIndex) 01537 { 01538 List l; 01539 ReturnType returnType; 01540 Term term; 01541 int i = 0; 01542 Hashtable hashtable; 01543 String hashtableName; 01544 01545 term = (Term)listElement(args); 01546 returnType = comReturnTypeOfTerm(term) & ~RTNoError; 01547 hashtableName = term->data.string; 01548 01549 /* find map */ 01550 if ((hashtable = (hashGet(inputCurrentGrammar->maps, hashtableName)))) { 01551 for (l = listNext(args); l; l = listNext(l)) { 01552 term = (Term)listElement(l); 01553 returnType = comReturnTypeOfTerm(term) & ~RTNoError; 01554 01555 comPrintln("(lookupStrings[%d] = (", i++); 01556 comTranslateTerm(term, FALSE, FALSE, tmpIndex); 01557 if (returnType & RTString) { 01558 if (term->type != TTString) { 01559 comPrintln("!= VTString ?"); 01560 comPrintln("(cdgPrintf(CDG_WARNING, \"WARNING: Type Mismatch (arg %d) in lookup in constraint %s\\n\"), NULL) :", 01561 i + 1, comEscapeQuotes(com->currentConstraint->id)); 01562 } 01563 comTranslateString(term, tmpIndex); 01564 } 01565 if (returnType & RTPeek) { 01566 comPrintln("!= VTString ?"); 01567 comPrintln("(cdgPrintf(CDG_WARNING, \"WARNING: Type Mismatch (arg %d) in lookup in constraint %s\\n\"), NULL) :", 01568 i + 1, comEscapeQuotes(com->currentConstraint->id)); 01569 comTranslateLexicalAccess(term); 01570 comPrint("->data.string"); 01571 } 01572 comPrintln(")),"); 01573 } 01574 01575 comPrintln("(lookupStrings[%d] = NULL),", i); 01576 comPrintln("(vs%d.data.string = _lookup(\"%s\"))", tmpIndex, hashtableName); 01577 } else { 01578 comPrintln("vs%d.data.string = strRegister(\"\"), vs%d.type = VTString", 01579 tmpIndex, tmpIndex); 01580 } 01581 } 01582 01583 /* ---------------------------------------------------------------------- 01584 * translate the quotes function 01585 */ 01586 void comTranslateQuotes(List args, int tmpIndex) 01587 { 01588 Term term = (Term)listElement(args); 01589 ReturnType returnType = comReturnTypeOfTerm(term); 01590 01591 comPrint("! "); 01592 comTranslateLexemNodeAccess(term, tmpIndex); 01593 if (returnType & RTLexemPosition) { 01594 comPrint(" || "); 01595 comTranslateLexemNodeAccess(term, tmpIndex); 01596 comPrint(" == NONSPEC"); 01597 } 01598 comPrintln(" ?"); 01599 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: argument of function 'quotes' isn't a lexem node \"),"); 01600 comPrintln("(vs%d.type = VTError) :", tmpIndex); 01601 comPrint("(vs%d.data.number = ", tmpIndex); 01602 comTranslateLexemNodeAccess(term, tmpIndex); 01603 comPrintln("->arc->quotes),"); 01604 comPrintln("(vs%d.type = VTNumber)"); 01605 } 01606 01607 /* ---------------------------------------------------------------------- 01608 * translate the parens function 01609 */ 01610 void comTranslateParens(List args, int tmpIndex) 01611 { 01612 Term term = (Term)listElement(args); 01613 ReturnType returnType = comReturnTypeOfTerm(term); 01614 01615 comPrint("! "); 01616 comTranslateLexemNodeAccess(term, tmpIndex); 01617 if (returnType & RTLexemPosition) { 01618 comPrint(" || "); 01619 comTranslateLexemNodeAccess(term, tmpIndex); 01620 comPrint(" == NONSPEC"); 01621 } 01622 comPrintln(" ?"); 01623 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: argument of function 'parens' isn't a lexem node \"),"); 01624 comPrintln("(vs%d.type = VTError) :", tmpIndex); 01625 comPrint("(vs%d.data.number = ", tmpIndex); 01626 comTranslateLexemNodeAccess(term, tmpIndex); 01627 comPrintln("->arc->parens),"); 01628 comPrintln("(vs%d.type = VTNumber)"); 01629 } 01630 01631 /* ---------------------------------------------------------------------- 01632 * translate the parent function 01633 */ 01634 void comTranslateParent(List args, int tmpIndex) 01635 { 01636 Term term = (Term) listElement(args); 01637 ReturnType returnType = comReturnTypeOfTerm(term); 01638 int nrlevels = inputCurrentGrammar->noOfLevels; 01639 VarInfo vi = listElement(com->currentConstraint->vars); 01640 01641 comPrint("! "); 01642 comTranslateLexemNodeAccess(term, tmpIndex); 01643 if (returnType & RTLexemPosition) { 01644 comPrint(" || "); 01645 comTranslateLexemNodeAccess(term, tmpIndex); 01646 comPrint(" == NONSPEC"); 01647 } 01648 comPrintln(" ?"); 01649 comPrintln("(cdgPrintf(CDG_ERROR, \"ERROR: argument of function 'parent' isn't a lexem node \"),"); 01650 comPrintln("(vs%d.type = VTError)) :", tmpIndex); 01651 01652 comPrint("((vs%d.data.lexemnode = (struct LexemNodeStruct *)", tmpIndex); 01653 comPrint("((LevelValue)vectorElement(context, %d * ", nrlevels); 01654 comTranslateLexemNodeAccess(term, tmpIndex); 01655 comPrint("->arc->from + %d))->modifiee),", vi->level->no); 01656 comPrintln("(vs%d.type = VTLexemNode))"); 01657 } 01658 01659 /* ---------------------------------------------------------------------- 01660 * translate the pts function 01661 */ 01662 void comTranslatePts(List args, int tmpIndex) 01663 { 01664 Term term = (Term)listElement(args); 01665 01666 comPrint("! "); 01667 comTranslateLexemNodeAccess(term, tmpIndex); 01668 comPrintln(" ?"); 01669 comPrintln("cdgPrintf(CDG_ERROR, \"ERROR: argument of function 'quotes' isn't a lexem node \"),"); 01670 comPrintln("(vs%d.type = VTError) :", tmpIndex); 01671 comPrint("(vs%d.data.number = ", tmpIndex); 01672 comTranslateLexemNodeAccess(term, tmpIndex); 01673 comPrintln("->tagscore),"); 01674 comPrintln("(vs%d.type = VTNumber)"); 01675 01676 } 01677 01678 /* ---------------------------------------------------------------------- 01679 * translate the `height' function 01680 */ 01681 void comTranslateHeight(List args, int tmpIndex) 01682 { 01683 Term term = (Term) listElement(args); 01684 Level level; 01685 01686 if (NULL == (level = findLevel(term->data.peek.varinfo->levelname))) { 01687 comWriteError("ERROR: level `%s' not found!", term->data.peek.varinfo->levelname); 01688 return; 01689 } 01690 01691 comPrint("! "); 01692 comTranslateLexemNodeAccess(term, tmpIndex); 01693 comPrintln(" ?"); 01694 comPrintln("(cdgPrintf(CDG_ERROR, \"ERROR: argument of function 'height' isn't a lexem node \"),"); 01695 comPrintln("(vs%d.type = VTError)) :", tmpIndex); 01696 comPrint("((vs%d.data.number = ", tmpIndex); 01697 01698 comPrint("funcHeightImpl("); 01699 comTranslateLexemNodeAccess(term, tmpIndex); 01700 comPrint(", %d, lg, context)),", level->no); 01701 comPrintln("(vs%d.type = VTNumber))"); 01702 01703 } 01704 01705 /* ---------------------------------------------------------------------- 01706 * translate the min and max function 01707 */ 01708 void comTranslateMinMax(String functor, List args, int tmpIndex) 01709 { 01710 List l; 01711 Boolean isFirst = TRUE; 01712 Term term = (Term)listElement(args); 01713 Term lastTerm; 01714 ReturnType returnType = comReturnTypeOfTerm(term) & ~RTNoError; 01715 int lastTmpIndex; 01716 01717 comTranslateTerm(term, FALSE, TRUE, tmpIndex); 01718 01719 /* peek return type */ 01720 if (returnType == RTPeek) { 01721 comPrintln(" != VTNumber ?"); 01722 comPrintln("(cdgPrintf(CDG_ERROR,\"ERROR: 1rst argument of `%s' isn't numerical\"),", functor); 01723 comPrintln("(vs%d.type == VTError)) :", tmpIndex); 01724 } 01725 01726 comPrintln("(vs%d.type = VTNumber, ", tmpIndex); 01727 01728 /* loop thru all argument terms */ 01729 lastTmpIndex = tmpIndex; 01730 for (l = listNext(args); l != NULL; l = listNext(l)) { 01731 lastTerm = term; 01732 term = (Term)listElement(l); 01733 returnType = comReturnTypeOfTerm(term) & ~RTNoError; 01734 if (isFirst) { 01735 isFirst = FALSE; 01736 } else { 01737 comPrintln(","); 01738 } 01739 comTranslateTerm(term, FALSE, TRUE, tmpIndex+1); 01740 01741 /* peek return type */ 01742 if (returnType == RTPeek) { 01743 comPrintln(" != VTNumber ?"); 01744 comPrintln("(cdgPrintf(CDG_ERROR,\"ERROR: 1rst argument of `%s' isn't numerical\"),", functor); 01745 comPrintln("(vs%d.type == VTError)) :", tmpIndex); 01746 } 01747 /* granted to be RTNumber */ 01748 comPrint("(vs%d.data.number = %s(", tmpIndex, functor); 01749 comTranslateNumber(lastTerm, lastTmpIndex); 01750 comPrint(", "); 01751 comTranslateNumber(term, tmpIndex+1); 01752 comPrintln("))"); 01753 01754 lastTmpIndex = tmpIndex+1; 01755 } 01756 01757 comPrintln(")"); 01758 } 01759 01760 /* ---------------------------------------------------------------------- 01761 * translate the match function 01762 */ 01763 void comTranslateMatch(List args, int tmpIndex) 01764 { 01765 int i; 01766 Term term = (Term)listNthElement(args, 1); 01767 Term termA = (Term)listNthElement(args, 2); 01768 Term termB = (Term)listNthElement(args, 3); 01769 ReturnType returnType1 = comReturnTypeOfTerm(term) & ~RTNoError; 01770 ReturnType returnType2 = comReturnTypeOfTerm(termA) & ~RTNoError; 01771 ReturnType returnType3 = comReturnTypeOfTerm(termB) & ~RTNoError; 01772 01773 if (term->type != TTString) { 01774 comTranslateTerm(term, FALSE, TRUE, tmpIndex); 01775 } 01776 01777 /* check the hierarchy */ 01778 if (returnType1 == RTString) { 01779 01780 /* extra rule for static strings */ 01781 if (term->type == TTString) { 01782 Hierarchy hierarchy = 01783 hashGet(inputCurrentGrammar->hierarchies, term->data.string); 01784 if (!hierarchy) { 01785 comWriteError("hierarchy `%s' not found"); 01786 } else { 01787 i = comIndexOfHierarchy(hierarchy->id); 01788 comPrintln("(hierarchy = hierarchies[%d].hierarchy),", i); 01789 } 01790 } 01791 01792 /* its a string but not provided staticaly */ 01793 else { 01794 comPrint("(hierarchy = _findHierarchy("); 01795 comTranslateString(term, tmpIndex); 01796 comPrintln(")),"); 01797 comPrintln("(hierarchy == NULL)?"); 01798 comPrintln("(vs%d.type = VTError) :", tmpIndex); 01799 } 01800 } 01801 01802 /* hierarchy lexically encoded */ 01803 else if (returnType1 == RTPeek) { 01804 comPrintln(" != VTString ?", tmpIndex); 01805 comPrint("(cdgPrintf(CDG_ERROR, \"ERROR: type mismatch of 1rst argument in `match'\\n\"), "); 01806 comPrintln("(vs%d.type = VTError)) :", tmpIndex); 01807 comPrint("(hierarchy = _findHierarchy("); 01808 comTranslateLexicalAccess(term); 01809 comPrintln("->data.string)),", tmpIndex); 01810 comPrintln("(hierarchy == NULL)?"); 01811 comPrintln("(vs%d.type = VTError) :", tmpIndex); 01812 } 01813 01814 /* hierarchy unknown at compile time */ 01815 else { 01816 comPrintln("((vs%d.type != VTString)?", tmpIndex); 01817 comPrint("(cdgPrintf(CDG_ERROR, \"ERROR: type mismatch of 1rst argument in `match'\\n\"), "); 01818 comPrintln("(vs%d.type = VTError)) :", tmpIndex); 01819 comPrint("(hierarchy = _findHierarchy("); 01820 comTranslateString(term, tmpIndex); 01821 comPrintln("))),"); 01822 comPrintln("(hierarchy == NULL)?"); 01823 comPrintln("(vs%d.type = VTError) :", tmpIndex); 01824 } 01825 01826 01827 /* check termB */ 01828 if (returnType3 & RTPeek) { 01829 01830 comTranslateTerm(termB, FALSE, TRUE, tmpIndex+1); 01831 comPrintln(" != VTString ? (vs%d.type = VTError) :", tmpIndex); 01832 01833 comTranslateTerm(termA, FALSE, TRUE, tmpIndex); 01834 /* check termA */ 01835 if (returnType2 == RTPeek) { 01836 comPrintln(" != VTString ?"); 01837 comPrint("(("); 01838 comTranslateLexicalAccess(termA); 01839 comPrintln("->type != VTList)? (vs%d.type = VTError):", tmpIndex); 01840 comPrint("(vs%d.type = _matchList(\"%s\", ", tmpIndex, comEscapeQuotes(com->currentConstraint->id)); 01841 comTranslateLexicalAccess(termA); 01842 comPrint("->data.list, "); 01843 comTranslateLexicalAccess(termB); 01844 comPrintln("->data.string, &vs%d))) :", tmpIndex); 01845 comPrint("(vs%d.type = _matchString(\"%s\", ", tmpIndex, comEscapeQuotes(com->currentConstraint->id)); 01846 comTranslateLexicalAccess(termA); 01847 comPrint("->data.string, "); 01848 comTranslateLexicalAccess(termB); 01849 comPrintln("->data.string, &vs%d))", tmpIndex); 01850 } else if (returnType2 == RTString) { 01851 comPrint("(vs%d.type = _matchString(\"%s\", ", 01852 tmpIndex, comEscapeQuotes(com->currentConstraint->id)); 01853 comTranslateString(termA, tmpIndex); 01854 comPrint(", "); 01855 comTranslateLexicalAccess(termB); 01856 comPrintln("->data.string, &vs%d))", tmpIndex); 01857 } else if (returnType2 == RTList) { /* not detected, but hey */ 01858 comPrint("(vs%d.type = _matchList(\"%s\", vs%d.data.list, ", 01859 tmpIndex, comEscapeQuotes(com->currentConstraint->id), tmpIndex); 01860 comTranslateLexicalAccess(termB); 01861 comPrintln("->data.string, &vs%d))", tmpIndex); 01862 } 01863 } 01864 01865 if (returnType3 & RTString) { 01866 comTranslateTerm(termA, FALSE, TRUE, tmpIndex); 01867 /* check termA */ 01868 if (returnType2 == RTPeek) { 01869 comPrintln(" != VTString ?"); 01870 comPrint("(("); 01871 comTranslateLexicalAccess(termA); 01872 comPrintln("->type != VTList)? (vs%d.type = VTError):", tmpIndex); 01873 comPrint("(vs%d.type = _matchList(\"%s\", ", tmpIndex, comEscapeQuotes(com->currentConstraint->id)); 01874 comTranslateLexicalAccess(termA); 01875 comPrint("->data.list, "); 01876 comTranslateString(termB, tmpIndex+1); 01877 comPrintln(", &vs%d))) :", tmpIndex); 01878 comPrint("(vs%d.type = _matchString(\"%s\", ", tmpIndex, comEscapeQuotes(com->currentConstraint->id)); 01879 comTranslateLexicalAccess(termA); 01880 comPrint("->data.string, "); 01881 comTranslateString(termB, tmpIndex+1); 01882 comPrintln(", &vs%d))", tmpIndex); 01883 } else if (returnType2 == RTString) { 01884 comPrint("(vs%d.type = _matchString(\"%s\", ", 01885 tmpIndex, comEscapeQuotes(com->currentConstraint->id)); 01886 comTranslateString(termA, tmpIndex); 01887 comPrint(", "); 01888 comTranslateString(termB, tmpIndex+1); 01889 comPrintln(", &vs%d))", tmpIndex); 01890 } else if (returnType2 == RTList) { /* not detected, but hey */ 01891 comPrint("(vs%d.type = _matchList(\"%s\", vs%d.data.list, ", 01892 tmpIndex, comEscapeQuotes(com->currentConstraint->id), tmpIndex); 01893 comTranslateString(termB, tmpIndex+1); 01894 comPrintln(", &vs%d))", tmpIndex); 01895 } 01896 } 01897 } 01898 01899 /* ---------------------------------------------------------------------- 01900 * translate a number access 01901 */ 01902 void comTranslateNumber(Term term, int tmpIndex) 01903 { 01904 switch(term->type) { 01905 case TTNumber: 01906 comPrint("%g", term->data.number); 01907 break; 01908 default: 01909 comPrint("vs%d.data.number", tmpIndex); 01910 } 01911 } 01912 01913 /* ---------------------------------------------------------------------- 01914 * translate a string access 01915 */ 01916 void comTranslateString(Term term, int tmpIndex) 01917 { 01918 switch (term->type) { 01919 case TTString: 01920 comPrint("strings[%d] /* %s */", 01921 comRegisterString(term->data.string), term->data.string); 01922 break; 01923 case TTLabel: 01924 comPrint("lv%d->label", 01925 comIndexOfVarInfo(term->data.peek.varinfo)); 01926 break; 01927 case TTLevel: 01928 comPrint("lv%d->level->id", 01929 comIndexOfVarInfo(term->data.label)); 01930 break; 01931 default: 01932 comPrint("vs%d.data.string", tmpIndex); 01933 } 01934 } 01935 01936 /* ---------------------------------------------------------------------- 01937 * translate a term to c code 01938 */ 01939 void comTranslateTerm(Term term, 01940 Boolean insideFormula, Boolean needsSeparator, int tmpIndex) 01941 { 01942 ReturnType returnType = comReturnTypeOfTerm(term); 01943 01944 /* switch off specific terms */ 01945 if (term->type == TTBottomPeek || term->type == TTTopPeek) { 01946 String pathItem = (String) listElement(term->data.peek.path); 01947 if (strcmp("from", pathItem) != 0 && 01948 strcmp("to", pathItem) != 0 && 01949 /*strcmp("id", pathItem) != 0 &&*/ 01950 strcmp("word", pathItem) != 0) { 01951 needsSeparator = FALSE; 01952 } 01953 } else if (term->type == TTString || 01954 term->type == TTLabel || 01955 term->type == TTLevel || 01956 term->type == TTNumber) { 01957 needsSeparator = FALSE; 01958 } 01959 01960 if (needsSeparator && !(returnType & RTNoError)) { 01961 comPrint("("); 01962 } 01963 01964 switch (term->type) { 01965 /* ---------------------------------------------------------------------- */ 01966 case TTTopPeek: 01967 comTranslateTopPeek(term, tmpIndex); 01968 break; 01969 /* ---------------------------------------------------------------------- */ 01970 case TTBottomPeek: 01971 comTranslateBottomPeek(term, tmpIndex); 01972 break; 01973 /* ---------------------------------------------------------------------- */ 01974 case TTLabel: 01975 case TTLevel: 01976 case TTString: 01977 case TTNumber: 01978 break; 01979 /* ---------------------------------------------------------------------- */ 01980 case TTAdd: 01981 case TTSubtract: 01982 case TTMultiply: 01983 case TTDivide: 01984 comTranslateArithmetics(term, tmpIndex); 01985 break; 01986 /* ---------------------------------------------------------------------- */ 01987 case TTFunction: 01988 comTranslateFunction(term->data.function.functor, 01989 term->data.function.args, tmpIndex); 01990 break; 01991 } 01992 01993 if (needsSeparator) { 01994 if (!(returnType & RTNoError)) { 01995 if (insideFormula) { 01996 comPrintln(" != VTError) &&"); 01997 } else { 01998 comPrintln(" == VTError)? VTError : ", 01999 tmpIndex, tmpIndex); 02000 } 02001 } else { 02002 comPrintln(","); 02003 } 02004 } 02005 } 02006 02007 /* ---------------------------------------------------------------------- 02008 * translate the arithmetic term operations 02009 */ 02010 void comTranslateArithmetics(Term term, int tmpIndex) 02011 { /* CONT */ 02012 ReturnType returnType1 = comReturnTypeOfTerm(term->data.operation.op1) & ~RTNoError; 02013 ReturnType returnType2 = comReturnTypeOfTerm(term->data.operation.op2) & ~RTNoError; 02014 String operator = "horst"; 02015 02016 switch (term->type) { 02017 case TTAdd: 02018 operator = "+"; 02019 comPrintln("( /* add */"); 02020 break; 02021 case TTSubtract: 02022 operator = "-"; 02023 comPrintln("( /* substract */"); 02024 break; 02025 case TTMultiply: 02026 operator = "*"; 02027 comPrintln("( /* multiplty */"); 02028 break; 02029 case TTDivide: 02030 operator = "/"; 02031 comPrintln("( /* divide */"); 02032 break; 02033 default: 02034 break; 02035 } 02036 comIndent(); 02037 comTranslateTerm(term->data.operation.op1, FALSE, TRUE, tmpIndex); 02038 02039 switch (returnType1) { 02040 /* first term is a number */ 02041 case RTNumber: 02042 comTranslateTerm(term->data.operation.op2, FALSE, TRUE, tmpIndex+1); 02043 switch (returnType2) { 02044 case RTPeek: 02045 comPrintln(" != VTNumber ?"); 02046 comPrintln( 02047 "(cdgPrintf(CDG_ERROR, " 02048 "\"ERROR: type mismatch in term `%s'\\n\"), vs%d.type = VTError) :", 02049 operator, tmpIndex); 02050 comPrint("((vs%d.data.number = ", tmpIndex); 02051 comTranslateNumber(term->data.operation.op1, tmpIndex); 02052 comPrint(" %s ", operator); 02053 comTranslateLexicalAccess(term->data.operation.op2); 02054 comPrintln("->data.number), vs%d.type = VTNumber)", tmpIndex); 02055 break; 02056 case RTNumber: 02057 comPrint("((vs%d.data.number = ", tmpIndex); 02058 comTranslateNumber(term->data.operation.op1, tmpIndex); 02059 comPrint(" %s ", operator); 02060 comTranslateNumber(term->data.operation.op2, tmpIndex+1); 02061 comPrintln("), vs%d.type = VTNumber)", tmpIndex); 02062 break; 02063 default: 02064 comWriteError("2nd argument of type `%s' not a number", 02065 comReturnTypeToString(returnType2)); 02066 } 02067 break; 02068 /* first term is a lexical access */ 02069 case RTPeek: 02070 comPrint(" != VTNumber ?"); 02071 comPrintln( 02072 "(cdgPrintf(CDG_ERROR, " 02073 "\"ERROR: type mismatch of 1rst argument in term `%s'\\n\"), vs%d.type = VTError) :", 02074 operator, tmpIndex); 02075 comTranslateTerm(term->data.operation.op2, FALSE, TRUE, tmpIndex+1); 02076 switch (returnType2) { 02077 case RTPeek: 02078 comPrintln(" != VTNumber ?"); 02079 comPrintln( 02080 "(cdgPrintf(CDG_ERROR, " 02081 "\"ERROR: type mismatch of 2nd argument in term `%s'\\n\"), vs%d.type = VTError) :", 02082 operator, tmpIndex); 02083 comPrint("((vs%d.data.number = ", tmpIndex); 02084 comTranslateLexicalAccess(term->data.operation.op1); 02085 comPrint("->data.number %s ", operator); 02086 comTranslateLexicalAccess(term->data.operation.op2); 02087 comPrintln("->data.number), vs%d.type = VTNumber)", tmpIndex); 02088 break; 02089 case RTNumber: 02090 comPrint("(("); 02091 comTranslateLexicalAccess(term->data.operation.op1); 02092 comPrintln("->type != VTNumber)?"); 02093 comPrintln( 02094 "(cdgPrintf(CDG_ERROR, " 02095 "\"ERROR: type mismatch in term `%s'\\n\"), vs%d.type = VTError) :", 02096 operator, tmpIndex); 02097 comPrint("((vs%d.data.number = ", tmpIndex); 02098 comTranslateLexicalAccess(term->data.operation.op1); 02099 comPrint("->data.number %s ", operator); 02100 comTranslateNumber(term->data.operation.op2, tmpIndex+1); 02101 comPrintln("), vs%d.type = VTNumber)", tmpIndex); 02102 break; 02103 default: 02104 comWriteError("2nd argument of type `%s' not a number", 02105 comReturnTypeToString(returnType2)); 02106 } 02107 break; 02108 default: 02109 comWriteError("1rst argument of type `%s' not a number", 02110 comReturnTypeToString(returnType1)); 02111 } 02112 comOutdent(); 02113 comPrint(")"); 02114 } 02115 02116 /* ---------------------------------------------------------------------- 02117 * translate a bottom peek 02118 */ 02119 void comTranslateBottomPeek(Term term, int tmpIndex) 02120 { 02121 String pathItem = (String) listElement(term->data.peek.path); 02122 int varInfoIndex = comIndexOfVarInfo(term->data.peek.varinfo); 02123 List l; 02124 String att; 02125 02126 /* id */ 02127 if (strcmp("id", pathItem) == 0) { 02128 comPrintln("/* @id */"); 02129 return; 02130 } 02131 02132 /* from */ 02133 if (strcmp("from", pathItem) == 0) { 02134 comPrint("((vs%d.data.number = lv%d->modifier->arc->from), VTNumber)", 02135 tmpIndex, varInfoIndex); 02136 } 02137 02138 /* to */ 02139 else if (strcmp("to", pathItem) == 0) { 02140 comPrint("((vs%d.data.number = lv%d->modifier->arc->to), VTNumber)", 02141 tmpIndex, varInfoIndex, tmpIndex); 02142 } 02143 02144 /* word */ 02145 else if (strcmp("word", pathItem) == 0) { 02146 comPrint("((vs%d.data.string = lv%d->modifier->lexem->word), VTString)", 02147 tmpIndex, varInfoIndex); 02148 } 02149 02150 /* chunk_start */ 02151 else if (strcmp("chunk_start", pathItem) == 0) { 02152 comPrintln("(lv%d->modifier->grapheme->chunk ?", varInfoIndex); 02153 comPrintln("(vs%d.data.number = lv%d->modifier->grapheme->chunk->from->arc->from), vs%d.type = VTNumber :", 02154 tmpIndex, varInfoIndex, tmpIndex); 02155 comPrintln("VTError)"); 02156 } 02157 02158 /* chunk_end */ 02159 else if (strcmp("chunk_end", pathItem) == 0) { 02160 comPrintln("(lv%d->modifier->grapheme->chunk ?", varInfoIndex); 02161 comPrintln("(vs%d.data.number = lv%d->modifier->grapheme->chunk->to->arc->to), vs%d.type = VTNumber :", 02162 tmpIndex, varInfoIndex, tmpIndex); 02163 comPrintln("VTError)"); 02164 } 02165 02166 /* chunk_type */ 02167 else if (strcmp("chunk_type", pathItem) == 0) { 02168 comPrintln("(lv%d->modifier->grapheme->chunk ?", varInfoIndex); 02169 comPrintln("(vs%d.data.string = chunkerStringOfChunkType(lv%d->modifier->grapheme->chunk)), vs%d.type = VTString :", 02170 tmpIndex, varInfoIndex, tmpIndex); 02171 comPrintln("VTError)"); 02172 } 02173 02174 /* peek */ 02175 else { 02176 comPrint("/* peek modifier "); 02177 for (l = term->data.peek.path; l != NULL; l = listNext(l)) { 02178 att = (String)listElement(l); 02179 comPrint("%s", att); 02180 if (listNext(l)) 02181 comPrint("."); 02182 } 02183 comPrintln(" */"); 02184 comTranslateLexicalAccess(term); 02185 comPrint("->type"); 02186 } 02187 } 02188 02189 /* ---------------------------------------------------------------------- 02190 * translate a top peek 02191 */ 02192 void comTranslateTopPeek(Term term, int tmpIndex) 02193 { 02194 String pathItem = (String) listElement(term->data.peek.path); 02195 int varInfoIndex = comIndexOfVarInfo(term->data.peek.varinfo); 02196 List l; 02197 String att; 02198 02199 /* id */ 02200 if (strcmp("id", pathItem) == 0) { 02201 comPrintln("/* ^id */"); 02202 return; 02203 } 02204 02205 /* from */ 02206 if (strcmp("from", pathItem) == 0) { 02207 comPrintln("((lv%d->modifiee == NULL)?", varInfoIndex); 02208 comPrintln("(vs%d.type = VTError) : ", tmpIndex); 02209 comPrint("((vs%d.data.number = (lv%d->modifiee == NONSPEC)?", 02210 tmpIndex, varInfoIndex); 02211 comPrint("lg->max+2 : lv%d->modifiee->arc->from),", varInfoIndex); 02212 comPrintln("(vs%d.type = VTNumber)))", tmpIndex); 02213 } 02214 02215 /* to */ 02216 else if (strcmp("to", pathItem) == 0) { 02217 comPrintln("((lv%d->modifiee == NULL)?", varInfoIndex); 02218 comPrintln("(vs%d.type = VTError) : ", tmpIndex); 02219 comPrint("((vs%d.data.number = (lv%d->modifiee == NONSPEC)?", 02220 tmpIndex, varInfoIndex); 02221 comPrint("lg->max+2 : lv%d->modifiee->arc->to),", varInfoIndex); 02222 comPrintln("(vs%d.type = VTNumber)))", tmpIndex); 02223 } 02224 02225 /* word */ 02226 else if (strcmp("word", pathItem) == 0) { 02227 comPrintln("((lv%d->modifiee == NONSPEC || lv%d->modifiee == NULL)?", 02228 varInfoIndex, varInfoIndex); 02229 comIndent(); 02230 comPrintln("(vs%d.type = VTError) :", tmpIndex); 02231 comPrintln("((vs%d.data.string = lv%d->modifiee->lexem->word), (vs%d.type = VTString))", 02232 tmpIndex, varInfoIndex, tmpIndex); 02233 comOutdent(); 02234 comPrint(")"); 02235 } 02236 02237 /* chunk_start */ 02238 else if (strcmp("chunk_start", pathItem) == 0) { 02239 comPrintln("((lv%d->modifiee == NONSPEC || lv%d->modifiee == NULL)?", 02240 varInfoIndex, varInfoIndex); 02241 comIndent(); 02242 comPrintln("(vs%d.type = VTError) :", tmpIndex); 02243 comPrintln("(lv%d->modifiee->grapheme->chunk ?", varInfoIndex); 02244 comPrintln("(vs%d.data.number = lv%d->modifiee->grapheme->chunk->from->arc->from), vs%d.type = VTNumber :", 02245 tmpIndex, varInfoIndex, tmpIndex); 02246 comPrintln("VTError))"); 02247 } 02248 02249 /* chunk_end */ 02250 else if (strcmp("chunk_end", pathItem) == 0) { 02251 comPrintln("((lv%d->modifiee == NONSPEC || lv%d->modifiee == NULL)?", 02252 varInfoIndex, varInfoIndex); 02253 comIndent(); 02254 comPrintln("(vs%d.type = VTError) :", tmpIndex); 02255 comPrintln("(lv%d->modifiee->grapheme->chunk ?", varInfoIndex); 02256 comPrintln("(vs%d.data.number = lv%d->modifiee->grapheme->chunk->to->arc->to), vs%d.type = VTNumber :", 02257 tmpIndex, varInfoIndex, tmpIndex); 02258 comPrintln("VTError))"); 02259 } 02260 02261 /* chunk_type */ 02262 else if (strcmp("chunk_type", pathItem) == 0) { 02263 comPrintln("((lv%d->modifiee == NONSPEC || lv%d->modifiee == NULL)?", 02264 varInfoIndex, varInfoIndex); 02265 comIndent(); 02266 comPrintln("(vs%d.type = VTError) :", tmpIndex); 02267 comPrintln("(lv%d->modifiee->grapheme->chunk ?", varInfoIndex); 02268 comPrintln("(vs%d.data.string = chunkerStringOfChunkType(lv%d->modifiee->grapheme->chunk)), vs%d.type = VTString :", 02269 tmpIndex, varInfoIndex, tmpIndex); 02270 comPrintln("VTError))"); 02271 } 02272 02273 /* peek */ 02274 else { 02275 comPrint("/* peek modifiee "); 02276 for (l = term->data.peek.path; l != NULL; l = listNext(l)) { 02277 att = (String)listElement(l); 02278 comPrint("%s", att); 02279 if (listNext(l)) 02280 comPrint("."); 02281 } 02282 comPrintln(" */"); 02283 comPrintln("((lv%d->modifiee == NONSPEC || lv%d->modifiee == NULL)?", 02284 varInfoIndex, varInfoIndex); 02285 comPrint("(vs%d.type = VTError) : ", tmpIndex); 02286 comTranslateLexicalAccess(term); 02287 comPrint("->type)"); 02288 } 02289 } 02290 02291 /* ---------------------------------------------------------------------- 02292 * translate the print predicate 02293 */ 02294 void comTranslatePrint(List args, int tmpIndex) 02295 { 02296 Term term; 02297 List l; 02298 ReturnType returnType; 02299 02300 for (l = args; l != NULL; l = listNext(l)) { 02301 term = (Term)listElement(l); 02302 returnType = comReturnTypeOfTerm(term) & ~RTNoError; 02303 comTranslateTerm(term, FALSE, TRUE, tmpIndex); 02304 if (returnType == RTPeek) { 02305 comPrint("printValue(CDG_DEFAULT, "); 02306 comTranslateLexicalAccess(term); 02307 comPrintln(", 0),"); 02308 } else { 02309 comPrintln("printValue(CDG_DEFAULT, &vs%d, 0),", 02310 tmpIndex); 02311 } 02312 } 02313 comPrintln("TRUE"); 02314 } 02315 02316 /* ---------------------------------------------------------------------- 02317 * translate a predicate to c code 02318 */ 02319 void comTranslatePredicate(String functor, List args, int tmpIndex) 02320 { 02321 comPrintln("( /* %s */", functor); 02322 comIndent(); 02323 02324 /* start, stop */ 02325 if (strcmp("start", functor) == 0 || 02326 strcmp("stop", functor) == 0) { 02327 comTranslateStartStop(functor, args, tmpIndex); 02328 } 02329 02330 /* root, spec, nonspec */ 02331 else if (strcmp("root", functor) == 0 || 02332 strcmp("spec", functor) == 0 || 02333 strcmp("nonspec", functor) == 0) { 02334 comTranslateGuard(functor, args, tmpIndex); 02335 } 02336 02337 /* print */ 02338 else if (strcmp("print", functor) == 0) { 02339 comTranslatePrint(args, tmpIndex); 02340 } 02341 02342 /* exists */ 02343 else if (strcmp("exists", functor) == 0) { 02344 comTranslateExists(args); 02345 } 02346 02347 /* subsumes */ 02348 else if (strcmp("subsumes", functor) == 0 || 02349 strcmp("compatible", functor) == 0) { 02350 comTranslateSubsumes(functor, args, tmpIndex); 02351 } 02352 02353 /* chunk head */ 02354 else if (strcmp("chunk_head", functor) == 0) { 02355 comTranslateChunkHead(functor, args, tmpIndex); 02356 } 02357 02358 /* under */ 02359 else if (strcmp("under", functor) == 0) { 02360 comTranslateUnder(functor, args, tmpIndex); 02361 } 02362 02363 /* between */ 02364 else if (strcmp("between", functor) == 0) { 02365 comTranslateBetween(functor, args, tmpIndex); 02366 } 02367 02368 /* is */ 02369 else if (strcmp("is", functor) == 0) { 02370 comTranslateIs(functor, args, tmpIndex); 02371 } 02372 02373 /* connected */ 02374 else if (strcmp("connected", functor) == 0) { 02375 comTranslateConnected(functor, args, tmpIndex); 02376 } 02377 02378 /* has */ 02379 else if (strcmp("has", functor) == 0) { 02380 comTranslateHas(functor, args, tmpIndex); 02381 } 02382 02383 comOutdent(); 02384 comPrint(")"); 02385 } 02386 02387 /* ---------------------------------------------------------------------- 02388 * translate the subsumes and compatible predicates 02389 */ 02390 void comTranslateSubsumes(String functor, List args, int tmpIndex) 02391 { 02392 int i; 02393 Term term = (Term)listNthElement(args, 1); 02394 Term termA = (Term)listNthElement(args, 2); 02395 Term termB = (Term)listNthElement(args, 3); 02396 ReturnType returnType1 = comReturnTypeOfTerm(term) & ~RTNoError; 02397 ReturnType returnType2 = comReturnTypeOfTerm(termA) & ~RTNoError; 02398 ReturnType returnType3 = comReturnTypeOfTerm(termB) & ~RTNoError; 02399 02400 /* translate hierarchy term */ 02401 if (term->type != TTString) { 02402 comTranslateTerm(term, TRUE, TRUE, tmpIndex); 02403 } 02404 02405 /* check the hierarchy */ 02406 if (returnType1 == RTString) { 02407 02408 /* extra rule for static strings */ 02409 if (term->type == TTString) { 02410 i = comIndexOfHierarchy(term->data.string); 02411 if (i == -1) { 02412 comWriteError("hierarchy `%s' not found", term->data.string); 02413 } else { 02414 comPrintln("(hierarchy = hierarchies[%d].hierarchy),", i); 02415 } 02416 } 02417 02418 /* its a string but not provided staticaly */ 02419 else { 02420 comPrint("(hierarchy = _findHierarchy("); 02421 comTranslateString(term, tmpIndex); 02422 comPrintln(")),"); 02423 comPrintln("(hierarchy != NULL) &&"); 02424 } 02425 } 02426 /* hierarchy provided lexicaly */ 02427 else if (returnType1 == RTPeek) { 02428 comPrintln(" != VTString?"); 02429 comPrintln("(cdgPrintf(CDG_ERROR, \"ERROR: type mismatch of 1rst argument in `%s' of constraint `%s' in line %%d\\n\", __LINE__), FALSE) :", 02430 functor, comEscapeQuotes(com->currentConstraint->id)); 02431 comPrint("((hierarchy = _findHierarchy("); 02432 comTranslateLexicalAccess(term); 02433 comPrint("->data.string)), "); 02434 comPrintln("(hierarchy != NULL)) &&"); 02435 } 02436 /* hierarchy unknown at compile time */ 02437 else { 02438 comPrintln("((vs%d.type != VTString)?", tmpIndex); 02439 comPrintln("(cdgPrintf(CDG_ERROR, \"ERROR: type mismatch of 1rst argument in `%s' of constraint `%s' in line %%d\\n\", __LINE__), FALSE) :", 02440 functor, comEscapeQuotes(com->currentConstraint->id)); 02441 comPrint("((hierarchy = _findHierarchy("); 02442 comTranslateString(term, tmpIndex); 02443 comPrint(")), "); 02444 comPrintln("(hierarchy != NULL))) &&"); 02445 } 02446 02447 /* translate termA */ 02448 comPrint("("); 02449 comTranslateTerm(termA, TRUE, TRUE, tmpIndex); 02450 02451 /* check sort a */ 02452 if (returnType2 == RTPeek) { 02453 comPrintln(" != VTString ?"); 02454 comPrintln("(cdgPrintf(CDG_ERROR, \"ERROR: type mismatch of 2nd argument in `%s' of constraint `%s' in line %%d\\n\", __LINE__), FALSE) :", 02455 functor, comEscapeQuotes(com->currentConstraint->id)); 02456 } 02457 02458 /* translate termB */ 02459 comPrint("("); 02460 comTranslateTerm(termB, TRUE, TRUE, tmpIndex+1); 02461 02462 /* check sort b */ 02463 if (returnType3 == RTPeek) { 02464 comPrintln(" != VTString ?"); 02465 comPrintln("(cdgPrintf(CDG_ERROR, \"ERROR: type mismatch of 3nd argument of in `%s' of constraint `%s' in line %%d\\n\", __LINE__), FALSE):", 02466 functor, comEscapeQuotes(com->currentConstraint->id)); 02467 } 02468 02469 comPrint("("); 02470 if (returnType2 == RTPeek) { 02471 if (returnType3 == RTPeek) { 02472 comPrint("_%s(\"%s\", ", functor, comEscapeQuotes(com->currentConstraint->id)); 02473 comTranslateLexicalAccess(termA); 02474 comPrint("->data.string, "); 02475 comTranslateLexicalAccess(termB); 02476 comPrint("->data.string)"); 02477 } else { 02478 comPrint("_%s(\"%s\", ", functor, comEscapeQuotes(com->currentConstraint->id)); 02479 comTranslateLexicalAccess(termA); 02480 comPrint("->data.string, "); 02481 comTranslateString(termB, tmpIndex+1); 02482 comPrint(")"); 02483 } 02484 } else if (returnType3 == RTPeek) { 02485 comPrint("_%s(\"%s\", ", functor, comEscapeQuotes(com->currentConstraint->id)); 02486 comTranslateString(termA, tmpIndex); 02487 comPrint(", "); 02488 comTranslateLexicalAccess(termB); 02489 comPrint("->data.string)"); 02490 } else { 02491 comPrint("_%s(\"%s\", ", 02492 functor, comEscapeQuotes(com->currentConstraint->id), tmpIndex, tmpIndex+1); 02493 comTranslateString(termA, tmpIndex); 02494 comPrint(", "); 02495 comTranslateString(termB, tmpIndex+1); 02496 comPrint(")"); 02497 } 02498 comPrintln(")))"); 02499 } 02500 02501 /* ---------------------------------------------------------------------- 02502 * translate the exists predicate 02503 */ 02504 void comTranslateExists(List args) 02505 { 02506 String att; 02507 Term term = (Term)listElement(args); 02508 int varInfoIndex = comIndexOfVarInfo(term->data.peek.varinfo); 02509 String pathItem = (String) listElement(term->data.peek.path); 02510 List l; 02511 02512 /* verbosity */ 02513 comPrint("/* %s ", (term->type == TTTopPeek)?"modifiee":"modifier"); 02514 for (l = term->data.peek.path; l != NULL; l = listNext(l)) { 02515 att = (String)listElement(l); 02516 comPrint("%s", att); 02517 if (listNext(l)) 02518 comPrint("."); 02519 } 02520 comPrintln(" */"); 02521 02522 /* id */ 02523 if (strcmp("id", pathItem) == 0) { 02524 comPrintln("TRUE"); 02525 } 02526 02527 /* from, to */ 02528 if (strcmp("from", pathItem) == 0 || 02529 strcmp("to", pathItem) == 0) { 02530 if (term->type == TTTopPeek) { 02531 comPrintln("(lv%d->modifiee != NULL)", varInfoIndex); 02532 } else { 02533 comPrintln("TRUE"); 02534 } 02535 } 02536 /* word */ 02537 if (strcmp("word", pathItem) == 0) { 02538 if (term->type == TTTopPeek) { 02539 comPrintln("(lv%d->modifiee != NULL && lv%d->modifiee != NONSPEC)", 02540 varInfoIndex, varInfoIndex); 02541 } else { 02542 comPrintln("TRUE"); 02543 } 02544 } 02545 02546 /* peek */ 02547 else if (term->type == TTTopPeek) { 02548 comPrintln("((lv%d->modifiee != NONSPEC && lv%d->modifiee != NULL) &&", 02549 varInfoIndex, varInfoIndex); 02550 comPrintln("(lv%d->modifiee->lexem->values[%d]->type != VTError))", 02551 varInfoIndex, term->data.peek.pathindex); 02552 } else { 02553 comPrintln("(lv%d->modifier->lexem->values[%d]->type != VTError)", 02554 varInfoIndex, term->data.peek.pathindex); 02555 } 02556 } 02557 /* ---------------------------------------------------------------------- 02558 * translate the chunk_head predicate 02559 */ 02560 void comTranslateChunkHead(String functor, List args, int tmpIndex) 02561 { 02562 Term term = (Term)listElement(args); 02563 ReturnType returnType = comReturnTypeOfTerm(term) & ~RTNoError; 02564 02565 if (returnType & RTLexemNode){ 02566 if (returnType & RTLexemPosition) { 02567 comPrint("("); 02568 comTranslateLexemNodeAccess(term, tmpIndex); 02569 comPrint(" != NULL) && ("); 02570 comTranslateLexemNodeAccess(term, tmpIndex); 02571 comPrint(" != NONSPEC) &&"); 02572 } 02573 comPrint("(("); 02574 comTranslateLexemNodeAccess(term, tmpIndex); 02575 comPrintln("->grapheme->chunk) ?"); 02576 comPrint("("); 02577 comTranslateLexemNodeAccess(term, tmpIndex); 02578 comPrint("->grapheme == "); 02579 comTranslateLexemNodeAccess(term, tmpIndex); 02580 comPrint("->grapheme->chunk->head) : FALSE)"); 02581 } else { 02582 /* never reach */ 02583 comWriteError("illegal argument type `%s' in functor `%s'", 02584 comReturnTypeToString(returnType), functor); 02585 } 02586 02587 } 02588 02589 /* ---------------------------------------------------------------------- 02590 * translate the 'under' predicate 02591 */ 02592 void comTranslateUnder(String functor, List args, int tmpIndex) 02593 { 02594 Term term1, term2; 02595 ReturnType returnType1, returnType2; 02596 02597 term1 = (Term)listElement(args); 02598 returnType1 = comReturnTypeOfTerm(term1) & ~RTNoError; 02599 term2= (Term)listElement(listNext(args)); 02600 returnType2 = comReturnTypeOfTerm(term2) & ~RTNoError; 02601 02602 02603 if (returnType1 & RTLexemNode) { 02604 if (returnType2 & RTLexemNode) { 02605 comPrint("("); 02606 comPrint("(! "); 02607 comTranslateLexemNodeAccess(term1, tmpIndex); 02608 comPrint(" || "); 02609 comTranslateLexemNodeAccess(term1, tmpIndex); 02610 comPrintln(" == NONSPEC) ? FALSE : "); 02611 02612 comPrint("(! "); 02613 comTranslateLexemNodeAccess(term2, tmpIndex); 02614 comPrint(" || "); 02615 comTranslateLexemNodeAccess(term2, tmpIndex); 02616 comPrintln(" == NONSPEC) ? FALSE : "); 02617 comPrint("predUnderImpl("); 02618 comTranslateLexemNodeAccess(term1, tmpIndex); 02619 comPrint(", "); 02620 comTranslateLexemNodeAccess(term2, tmpIndex); 02621 comPrint(", lg, context)"); 02622 comPrint(")"); 02623 return; 02624 } 02625 } 02626 02627 comWriteError("illegal argument type in functor '%s'", functor); 02628 02629 } 02630 02631 /* ---------------------------------------------------------------------- 02632 * translate the 'between' predicate 02633 */ 02634 void comTranslateBetween(String functor, List args, int tmpIndex) 02635 { 02636 Term term; 02637 ReturnType returnType; 02638 02639 /* assign a */ 02640 term = (Term)listElement(args); 02641 returnType = comReturnTypeOfTerm(term); 02642 02643 comTranslateTerm(term, TRUE, TRUE, tmpIndex); 02644 if (returnType & RTLexemNode) { 02645 comPrint("(! "); 02646 comTranslateLexemNodeAccess(term, tmpIndex); 02647 if (returnType & RTLexemPosition) { 02648 comPrint(" || "); 02649 comTranslateLexemNodeAccess(term, tmpIndex); 02650 comPrint(" == NONSPEC"); 02651 } 02652 comPrintln(") ?"); 02653 comPrintln("FALSE :" ); 02654 comPrint("(a = "); 02655 comTranslateLexemNodeAccess(term, tmpIndex); 02656 comPrint("->arc->from)"); 02657 } 02658 if (returnType & RTNumber) { 02659 comPrint("(a = "); 02660 comTranslateNumber(term, tmpIndex); 02661 comPrintln("), (a < lg->min) ? (a = lg->min) :"); 02662 comPrintln("(a > lg->max) ? (a = lg->max) :"); 02663 comPrintln("TRUE"); 02664 } 02665 02666 comPrintln(", "); 02667 02668 /* assign b */ 02669 term = (Term)listElement(listNext(args)); 02670 returnType = comReturnTypeOfTerm(term); 02671 02672 comTranslateTerm(term, TRUE, TRUE, tmpIndex); 02673 if (returnType & RTLexemNode) { 02674 comPrint("(! "); 02675 comTranslateLexemNodeAccess(term, tmpIndex); 02676 if (returnType & RTLexemPosition) { 02677 comPrint(" || "); 02678 comTranslateLexemNodeAccess(term, tmpIndex); 02679 comPrint(" == NONSPEC"); 02680 } 02681 comPrintln(") ?"); 02682 comPrintln("FALSE :" ); 02683 comPrint("(b = "); 02684 comTranslateLexemNodeAccess(term, tmpIndex); 02685 comPrint("->arc->from)"); 02686 } 02687 if (returnType & RTNumber) { 02688 comPrint("(b = "); 02689 comTranslateNumber(term, tmpIndex); 02690 comPrintln("), (b < lg->min) ? (b = lg->min) :"); 02691 comPrintln("(b > lg->max) ? (b = lg->max) :"); 02692 comPrintln("TRUE"); 02693 } 02694 02695 comPrintln(", "); 02696 02697 /* call implementation */ 02698 term = (Term)listNthElement(args, 3); 02699 returnType = comReturnTypeOfTerm(term); 02700 02701 if (returnType & RTString) { 02702 comPrint("(a > b) ? predBetweenImpl(&b, &a, "); 02703 comTranslateString(term, tmpIndex); 02704 comPrintln(", lg, context) :"); 02705 comPrint("predBetweenImpl(&a, &b, "); 02706 comTranslateString(term, tmpIndex); 02707 comPrint(", lg, context)"); 02708 } 02709 02710 } 02711 02712 /* ---------------------------------------------------------------------- 02713 * translate the 'is' predicate 02714 */ 02715 void comTranslateIs(String functor, List args, int tmpIndex) 02716 { 02717 Term term1, term2, term3; 02718 ReturnType returnType; 02719 Constraint c = com->currentConstraint; 02720 int nrlevels = inputCurrentGrammar->noOfLevels; 02721 int levelno = -1; 02722 02723 /* check the third argument and set the levelno */ 02724 if (listSize(args) == 3 && (term3 = (Term)listNthElement(args, 3))) { 02725 Level level = findLevel(term3->data.string); 02726 if(!level) { 02727 comWriteWarning("WARNING: no level '%s' defined in '%s'", 02728 term3->data.string, c->id); 02729 return; 02730 } 02731 levelno = level->no; 02732 } else { 02733 VarInfo vi = listElement(c->vars); 02734 levelno = vi->level->no; 02735 } 02736 02737 /* first and second argument */ 02738 02739 term1 = (Term)listElement(args); 02740 returnType = comReturnTypeOfTerm(term1); 02741 02742 if (returnType & RTLexemNode) { 02743 comPrint("(! "); 02744 comTranslateLexemNodeAccess(term1, tmpIndex); 02745 if (returnType & RTLexemPosition) { 02746 comPrint(" || "); 02747 comTranslateLexemNodeAccess(term1, tmpIndex); 02748 comPrint(" == NONSPEC"); 02749 } 02750 comPrintln(") ?"); 02751 comPrintln("FALSE :" ); 02752 } 02753 02754 term2 = (Term)listElement(listNext(args)); 02755 02756 comPrint("(lv = ", tmpIndex); 02757 comPrint("vectorElement(context, %d * ", nrlevels); 02758 comTranslateLexemNodeAccess(term1, tmpIndex); 02759 comPrintln("->arc->from + %d))", levelno); 02760 comPrint(" && (lv->label == "); 02761 comTranslateString(term2, tmpIndex); 02762 comPrintln(") ? TRUE : FALSE"); 02763 } 02764 02765 /* ---------------------------------------------------------------------- 02766 * translate the 'connected' predicate 02767 */ 02768 void comTranslateConnected(String functor, List args, int tmpIndex) 02769 { 02770 Term term; 02771 ReturnType returnType; 02772 int nrlevels = inputCurrentGrammar->noOfLevels; 02773 VarInfo vi = listElement(com->currentConstraint->vars); 02774 int levelno = vi->level->no; 02775 02776 term = (Term)listElement(args); 02777 returnType = comReturnTypeOfTerm(term); 02778 if (returnType & RTLexemNode) { 02779 comPrint("(! "); 02780 comTranslateLexemNodeAccess(term, tmpIndex); 02781 if (returnType & RTLexemPosition) { 02782 comPrint(" || "); 02783 comTranslateLexemNodeAccess(term, tmpIndex); 02784 comPrint(" == NONSPEC"); 02785 } 02786 comPrintln(") ?"); 02787 comPrintln("FALSE :" ); 02788 comPrint("(a = "); 02789 comTranslateLexemNodeAccess(term, tmpIndex); 02790 comPrint("->arc->from)"); 02791 } 02792 comPrintln(","); 02793 02794 term = (Term)listElement(listNext(args)); 02795 returnType = comReturnTypeOfTerm(term); 02796 if (returnType & RTLexemNode) { 02797 comPrint("(! "); 02798 comTranslateLexemNodeAccess(term, tmpIndex); 02799 if (returnType & RTLexemPosition) { 02800 comPrint(" || "); 02801 comTranslateLexemNodeAccess(term, tmpIndex); 02802 comPrint(" == NONSPEC"); 02803 } 02804 comPrintln(") ?"); 02805 comPrintln("FALSE :" ); 02806 comPrint("(b = "); 02807 comTranslateLexemNodeAccess(term, tmpIndex); 02808 comPrint("->arc->from)"); 02809 } 02810 comPrintln(","); 02811 02812 comPrintln("_connected(a, b, %d, %d, lg, context)", nrlevels, levelno); 02813 } 02814 02815 /* ---------------------------------------------------------------------- 02816 * translate the 'has' predicate 02817 */ 02818 void comTranslateHas(String functor, List args, int tmpIndex) 02819 { 02820 Level level = inputGetMainlevel(inputCurrentGrammar); 02821 int mainno = level ? level->no : 0; 02822 Term term; 02823 ReturnType returnType; 02824 int nrArgs = listSize(args); 02825 Boolean useHierarchy = FALSE; 02826 02827 comPrintln("! context ? TRUE :"); 02828 02829 /* first argument */ 02830 term = (Term)listElement(args); 02831 returnType = comReturnTypeOfTerm(term); 02832 02833 comPrint("(! "); 02834 comTranslateLexemNodeAccess(term, tmpIndex); 02835 if (returnType & RTLexemPosition) { 02836 comPrint(" || "); 02837 comTranslateLexemNodeAccess(term, tmpIndex); 02838 comPrint(" == NONSPEC"); 02839 } 02840 comPrintln(") ?"); 02841 comPrintln("FALSE :" ); 02842 02843 /* use cache if possible */ 02844 if (5 > listSize(args)) { 02845 comPrintln("lock_counter > 0 ?"); 02846 comPrint("(a = has_cache[%d * lock_width + ", com->currentFormula->index); 02847 comTranslateLexemNodeAccess(term, tmpIndex); 02848 comPrintln("->arc->from]) :"); 02849 comPrintln("(a = -1),"); 02850 comPrintln("(lock_counter > 0 && 2 == a) ? TRUE : "); 02851 comPrintln("(lock_counter > 0 && 1 == a) ? FALSE : "); 02852 } 02853 02854 /* second argument -> assign Constraint constraint*/ 02855 term = (Term)listNthElement(args, 2); 02856 returnType = comReturnTypeOfTerm(term); 02857 02858 comPrint("((constraint = hashGet(inputCurrentGrammar->constraints, "); 02859 if (returnType & RTString) { 02860 comTranslateString(term, tmpIndex); 02861 } 02862 if (returnType & RTPeek) { 02863 comTranslateLexicalAccess(term); 02864 comPrint("->data.string"); 02865 } 02866 comPrintln(")),"); 02867 comPrintln("(constraint = (constraint && 1 != listSize(constraint->vars)) ? NULL : constraint),"); 02868 02869 /* third argument */ 02870 if (nrArgs >= 3) { 02871 useHierarchy = TRUE; 02872 term = (Term)listNthElement(args, 3); 02873 02874 comPrint("! (hierarchy = findHierarchy("); 02875 comTranslateString(term, tmpIndex); 02876 comPrintln(")) ? FALSE :"); 02877 } 02878 02879 /* build arguments array and call implementation */ 02880 term = (Term)listElement(args); 02881 comPrintln("(hasImplArgs[0] ="); 02882 comIndent(); 02883 /* lexemNode */ 02884 comTranslateLexemNodeAccess(term, tmpIndex); 02885 comPrintln("),"); 02886 comOutdent(); 02887 comPrintln("(hasImplArgs[1] ="); 02888 comIndent(); 02889 /* label */ 02890 term = (Term)listNthElement(args, 2); 02891 returnType = comReturnTypeOfTerm(term); 02892 if (returnType & RTString) { 02893 comTranslateString(term, tmpIndex); 02894 } 02895 if (returnType & RTPeek) { 02896 comTranslateLexicalAccess(term); 02897 comPrint("->data.string"); 02898 } 02899 comPrintln("),"); 02900 comOutdent(); 02901 comPrintln("(hasImplArgs[2] ="); 02902 comIndent(); 02903 /* constraint */ 02904 comPrintln("constraint),"); 02905 comOutdent(); 02906 comPrintln("(hasImplArgs[3] ="); 02907 comIndent(); 02908 /* hierarchy */ 02909 if (useHierarchy) { 02910 comPrintln("hierarchy),"); 02911 } else { 02912 comPrintln("NULL),"); 02913 } 02914 comOutdent(); 02915 comPrintln("(hasImplArgs[4] ="); 02916 comIndent(); 02917 /* labels */ 02918 if (nrArgs >= 4) { 02919 comTranslateString((Term)listNthElement(args, 4), tmpIndex); 02920 } else { 02921 comPrint("NULL"); 02922 } 02923 comPrintln("),"); 02924 comOutdent(); 02925 comPrintln("(hasImplArgs[5] ="); 02926 comIndent(); 02927 /* recursive */ 02928 if (nrArgs >= 4) { 02929 comPrint("((bool = TRUE), &bool)"); 02930 } else { 02931 comPrint("((bool = FALSE), &bool)"); 02932 } 02933 comPrintln("),"); 02934 comOutdent(); 02935 comPrintln("(hasImplArgs[6] = "); 02936 comIndent(); 02937 /* min */ 02938 comPrint("((a = ("); 02939 if (nrArgs >= 5) { 02940 term = (Term)listNthElement(args, 5); 02941 comTranslateTerm(term, FALSE, TRUE, tmpIndex); 02942 comTranslateNumber(term, tmpIndex); 02943 comPrintln(" > 0 ?"); 02944 comTranslateTerm(term, FALSE, TRUE, tmpIndex); 02945 comTranslateNumber(term, tmpIndex); 02946 comPrintln(" :"); 02947 } 02948 comPrintln("lg->min)), &a)),"); 02949 comOutdent(); 02950 comPrintln("(hasImplArgs[7] = "); 02951 comIndent(); 02952 /* max */ 02953 comPrint("((b = ("); 02954 // FIXME: a `max' argument of -1 should be interpreted as lg->max! 02955 if (nrArgs >= 6) { 02956 term = (Term)listNthElement(args, 6); 02957 comTranslateTerm(term, FALSE, TRUE, tmpIndex + 1); 02958 comTranslateNumber(term, tmpIndex + 1); 02959 comPrintln(" < lg->max ?"); 02960 comTranslateTerm(term, FALSE, TRUE, tmpIndex + 1); 02961 comTranslateNumber(term, tmpIndex + 1); 02962 comPrintln(" :"); 02963 } 02964 comPrintln("lg->max)), b = ((b == -1) ? lg->max : b), &b)),"); 02965 comOutdent(); 02966 comPrintln("(hasImplArgs[8] = "); 02967 comIndent(); 02968 /* context */ 02969 comPrintln("context),"); 02970 comOutdent(); 02971 comPrintln("(hasImplArgs[9] = "); 02972 comIndent(); 02973 /* nrlevels */ 02974 comPrintln("((c = %d), &c)),", inputCurrentGrammar->noOfLevels); 02975 comOutdent(); 02976 comPrintln("(hasImplArgs[10] = "); 02977 comIndent(); 02978 /* mainno */ 02979 comPrintln("((d = %d), &d)),", mainno); 02980 comOutdent(); 02981 02982 /* call preHasImpl */ 02983 comPrintln("predHasImpl(hasImplArgs))"); 02984 } 02985 02986 /* ---------------------------------------------------------------------- 02987 * translate the root, spec and nonspec guard-predicates 02988 */ 02989 void comTranslateGuard(String functor, List args, int tmpIndex) 02990 { 02991 Term term = (Term)listElement(args); 02992 ReturnType returnType = comReturnTypeOfTerm(term) & ~RTNoError; 02993 String operator = "horst"; 02994 02995 /* all modifier guards aren't needed */ 02996 if (!(returnType & RTLexemPosition)) { 02997 comPrintln("TRUE"); 02998 } 02999 03000 if (strcmp(functor, "root") == 0) { 03001 operator = "== NULL"; 03002 } else if (strcmp(functor, "nonspec") == 0) { 03003 operator = "== NONSPEC"; 03004 } else { 03005 operator = "!= NONSPEC"; 03006 } 03007 03008 comTranslateTerm(term, TRUE, TRUE, tmpIndex); 03009 switch (returnType & ~RTLexemPosition) { 03010 case RTLexemNode: 03011 comPrint("("); 03012 comTranslateLexemNodeAccess(term, tmpIndex); 03013 comPrintln(" %s)", operator); 03014 break; 03015 default: /* never reach */ 03016 comWriteError("illegal argument type `%s' in term `%s'", 03017 comReturnTypeToString(returnType), functor); 03018 } 03019 } 03020 03021 /* ---------------------------------------------------------------------- 03022 * translate the start and stop predicate 03023 */ 03024 void comTranslateStartStop(String functor, List args, int tmpIndex) 03025 { 03026 Term term = (Term)listElement(args); 03027 ReturnType returnType = comReturnTypeOfTerm(term) & ~RTNoError; 03028 String postfix = "horst"; 03029 03030 if (strcmp("start", functor) == 0) { 03031 postfix = "from == lg->min"; 03032 } else { 03033 postfix = "to == lg->max"; 03034 } 03035 03036 comTranslateTerm(term, TRUE, TRUE, tmpIndex); 03037 03038 switch(returnType & ~RTLexemPosition) { 03039 case RTLexemNode: 03040 if (returnType & RTLexemPosition) { 03041 comPrint("("); 03042 comTranslateLexemNodeAccess(term, tmpIndex); 03043 comPrintln(" != NULL) && "); 03044 comPrint("("); 03045 comTranslateLexemNodeAccess(term, tmpIndex); 03046 comPrintln(" != NONSPEC) &&"); 03047 } 03048 comPrint("("); 03049 comTranslateLexemNodeAccess(term, tmpIndex); 03050 comPrint("->arc->%s)", postfix); 03051 break; 03052 default: /* never reach */ 03053 comWriteError("illegal argument type `%s' in term `%s'", 03054 comReturnTypeToString(returnType), functor); 03055 } 03056 } 03057 03058 /* ---------------------------------------------------------------------- 03059 * translate the equal and not equal formulas 03060 */ 03061 void comTranslateEquation(Formula formula, int tmpIndex) 03062 { 03063 ReturnType returnType1 = comReturnTypeOfTerm(formula->data.relation.op1) & ~RTNoError; 03064 ReturnType returnType2 = comReturnTypeOfTerm(formula->data.relation.op2) & ~RTNoError; 03065 String operator = "horst"; 03066 03067 if (formula->type == FTNotEqual) { 03068 operator = "!="; 03069 comPrintln("( /* not equal */"); 03070 } else { 03071 operator = "=="; 03072 comPrintln("( /* equal */"); 03073 } 03074 03075 comIndent(); 03076 comTranslateTerm(formula->data.relation.op1, TRUE, TRUE, tmpIndex); 03077 03078 /* check known return types */ 03079 switch (returnType1 & ~RTLexemPosition) { 03080 /* first term returns a string --------------------------------------------- */ 03081 case RTString: 03082 comTranslateTerm(formula->data.relation.op2, TRUE, TRUE, tmpIndex+1); 03083 switch(returnType2) { 03084 case RTString: 03085 comPrint("("); 03086 comTranslateString(formula->data.relation.op1, tmpIndex); 03087 comPrint(" %s ", operator); 03088 comTranslateString(formula->data.relation.op2, tmpIndex+1); 03089 comPrintln(")"); 03090 break; 03091 case RTPeek: 03092 comPrintln(" == VTError ? FALSE :"); /* should be a grammar error */ 03093 comTranslateLexicalAccess(formula->data.relation.op2); 03094 comPrintln("->type == VTString ?"); 03095 comIndent(); 03096 comPrint("("); 03097 comTranslateString(formula->data.relation.op1, tmpIndex); 03098 comPrint(" %s ", operator); 03099 comTranslateLexicalAccess(formula->data.relation.op2); 03100 comPrintln("->data.string) : "); 03101 comPrint("(cdgPrintf(CDG_ERROR, " 03102 "\"ERROR: 2nd argument not a string in formula `%s' in constraint `%s', line %%d\\n\", __LINE__), ", 03103 operator, comEscapeQuotes(com->currentConstraint->id)); 03104 comPrintln("FALSE)"); 03105 comOutdent(); 03106 break; 03107 default: 03108 if (formula->type == FTEqual) { 03109 comPrintln("FALSE"); 03110 comWriteWarning("comparing type `%s' to `%s'", 03111 comReturnTypeToString(returnType1), 03112 comReturnTypeToString(returnType2)); 03113 } else { 03114 comPrintln("TRUE"); 03115 comWriteWarning("comparing type `%s' to `%s'", 03116 comReturnTypeToString(returnType1), 03117 comReturnTypeToString(returnType2)); 03118 } 03119 } 03120 break; 03121 /* first term returns a number --------------------------------------------- */ 03122 case RTNumber: 03123 comTranslateTerm(formula->data.relation.op2, TRUE, TRUE, tmpIndex+1); 03124 switch (returnType2) { 03125 case RTNumber: 03126 comPrint("("); 03127 comTranslateNumber(formula->data.relation.op1, tmpIndex); 03128 comPrint(" %s ", operator); 03129 comTranslateNumber(formula->data.relation.op2, tmpIndex+1); 03130 comPrintln(")"); 03131 break; 03132 case RTPeek: 03133 comPrintln(" == VTError ? FALSE :"); /* should be a grammar error */ 03134 comTranslateLexicalAccess(formula->data.relation.op2); 03135 comPrintln("->type == VTNumber ?"); 03136 comIndent(); 03137 comPrint("("); 03138 comTranslateNumber(formula->data.relation.op1, tmpIndex); 03139 comPrint(" %s ", operator); 03140 comTranslateLexicalAccess(formula->data.relation.op2); 03141 comPrintln("->data.number) : "); 03142 comPrint("(cdgPrintf(CDG_ERROR, " 03143 "\"ERROR: 2nd argument not a number in formula `%s' in constraint `%s', line %%d\\n\", __LINE__),", 03144 operator, comEscapeQuotes(com->currentConstraint->id)); 03145 comPrintln("FALSE)"); 03146 comOutdent(); 03147 break; 03148 default: 03149 if (formula->type == FTEqual) { 03150 comPrintln("FALSE"); 03151 comWriteWarning("comparing type `%s' to `%s'", 03152 comReturnTypeToString(returnType1), 03153 comReturnTypeToString(returnType2)); 03154 } else { 03155 comPrintln("TRUE"); 03156 comWriteWarning("comparing type `%s' to `%s'", 03157 comReturnTypeToString(returnType1), 03158 comReturnTypeToString(returnType2)); 03159 } 03160 } 03161 break; 03162 /* first term returns a lexemnode ------------------------------------------ */ 03163 case RTLexemNode: 03164 comTranslateTerm(formula->data.relation.op2, TRUE, TRUE, tmpIndex+1); 03165 switch (returnType2 & ~RTLexemPosition) { 03166 case RTLexemNode: 03167 /* TODO: this can be speeded up by dividing this disjunction, alas ... */ 03168 comPrint("("); 03169 if ((returnType1 & RTLexemPosition) || (returnType2 & RTLexemPosition)) { 03170 comTranslateLexemNodeAccess(formula->data.relation.op1, tmpIndex); 03171 comPrintln(" == NULL)?"); 03172 comPrint("("); 03173 comTranslateLexemNodeAccess(formula->data.relation.op2, tmpIndex); 03174 comPrintln(" %s NULL) :", operator); 03175 comPrint("(("); 03176 comTranslateLexemNodeAccess(formula->data.relation.op2, tmpIndex); 03177 comPrintln(" != NULL) &&"); 03178 comPrint("("); 03179 comTranslateLexemNodeAccess(formula->data.relation.op1, tmpIndex); 03180 comPrintln(" != NONSPEC) &&"); 03181 comPrint("("); 03182 comTranslateLexemNodeAccess(formula->data.relation.op2, tmpIndex); 03183 comPrintln(" != NONSPEC) &&"); 03184 } 03185 comPrint("("); 03186 comTranslateLexemNodeAccess(formula->data.relation.op1, tmpIndex); 03187 comPrint("->grapheme %s ", operator); 03188 comTranslateLexemNodeAccess(formula->data.relation.op2, tmpIndex); 03189 comPrintln("->grapheme))"); 03190 break; 03191 default: 03192 if (formula->type == FTEqual) { 03193 comPrintln("FALSE"); 03194 comWriteWarning("comparing type `%s' to `%s'", 03195 comReturnTypeToString(returnType1), 03196 comReturnTypeToString(returnType2)); 03197 } else { 03198 comPrintln("TRUE"); 03199 comWriteWarning("comparing type `%s' to `%s'", 03200 comReturnTypeToString(returnType1), 03201 comReturnTypeToString(returnType2)); 03202 } 03203 } 03204 break; 03205 /* first term is a lexical access ------------------------------------------ */ 03206 case RTPeek: 03207 switch (returnType2) { 03208 case RTNumber: 03209 comPrintln(" == VTError ? FALSE :"); /* should be a grammar error */ 03210 comTranslateLexicalAccess(formula->data.relation.op1); 03211 comPrintln("->type != VTNumber ?"); 03212 comPrintln("(cdgPrintf(CDG_ERROR, " 03213 "\"ERROR: 1rst argument not a number in formula `%s' in constraint `%s', line %%d\\n\", __LINE__), FALSE):", 03214 operator, comEscapeQuotes(com->currentConstraint->id)); 03215 comPrint("("); 03216 comTranslateTerm(formula->data.relation.op2, TRUE, TRUE, tmpIndex+1); 03217 comPrint("("); 03218 comTranslateLexicalAccess(formula->data.relation.op1); 03219 comPrint("->data.number %s ", operator); 03220 comTranslateNumber(formula->data.relation.op2, tmpIndex+1); 03221 comPrintln("))"); 03222 break; 03223 case RTString: 03224 comPrintln(" == VTError ? FALSE :"); /* should be a grammar error */ 03225 comTranslateLexicalAccess(formula->data.relation.op1); 03226 comPrintln("->type != VTString ?"); 03227 comPrintln("(cdgPrintf(CDG_ERROR, " 03228 "\"ERROR: 1rst argument not a string in formula `%s' in constraint `%s', line %%d\\n\", __LINE__), FALSE):", 03229 operator, comEscapeQuotes(com->currentConstraint->id)); 03230 comPrint("("); 03231 comTranslateTerm(formula->data.relation.op2, TRUE, TRUE, tmpIndex+1); 03232 comPrint("("); 03233 comTranslateLexicalAccess(formula->data.relation.op1); 03234 comPrint("->data.string %s ", operator); 03235 comTranslateString(formula->data.relation.op2, tmpIndex+1); 03236 comPrintln("))"); 03237 break; 03238 case RTPeek: /* first and second are lexical accesses */ 03239 comPrintln(" == VTError ? FALSE :"); /* should be a grammar error */ 03240 comTranslateTerm(formula->data.relation.op2, FALSE, TRUE, tmpIndex+1); 03241 comPrintln(" == VTError ? FALSE :"); /* should be a grammar error */ 03242 comTranslateLexicalAccess(formula->data.relation.op1); 03243 comPrint("->type != "); 03244 comTranslateLexicalAccess(formula->data.relation.op2); 03245 comPrintln("->type ?"); 03246 comPrintln("(cdgPrintf(CDG_ERROR, " 03247 "\"ERROR: type mismatch in formula `%s' in constraint `%s', line %%d\\n\", __LINE__), FALSE):", 03248 operator, comEscapeQuotes(com->currentConstraint->id)); 03249 comPrint("(("); 03250 comTranslateLexicalAccess(formula->data.relation.op1); 03251 comPrintln("->type == VTString)? "); 03252 comPrint("("); 03253 comTranslateLexicalAccess(formula->data.relation.op1); 03254 comPrint("->data.string %s ", operator); 03255 comTranslateLexicalAccess(formula->data.relation.op2); 03256 comPrintln("->data.string) : "); 03257 comPrint("("); 03258 comTranslateLexicalAccess(formula->data.relation.op1); 03259 comPrint("->data.number %s ", operator); 03260 comTranslateLexicalAccess(formula->data.relation.op2); 03261 comPrintln("->data.number))"); 03262 break; 03263 default: 03264 if (formula->type == FTEqual) { 03265 comPrintln("FALSE"); 03266 comWriteWarning("comparing type `%s' to `%s'", 03267 comReturnTypeToString(returnType1), 03268 comReturnTypeToString(returnType2)); 03269 } else { 03270 comPrintln("TRUE"); 03271 comWriteWarning("comparing type `%s' to `%s'", 03272 comReturnTypeToString(returnType1), 03273 comReturnTypeToString(returnType2)); 03274 } 03275 } 03276 break; 03277 default: 03278 comPrintln("FALSE"); 03279 comWriteError("unknown return type `%s'", 03280 comReturnTypeToString(returnType1)); /* never reach */ 03281 } 03282 comOutdent(); 03283 comPrint(")"); 03284 } 03285 03286 /* ---------------------------------------------------------------------- 03287 * translate the <, <=, >, >= formulas 03288 */ 03289 void comTranslateUnEquation(Formula formula, int tmpIndex) 03290 { 03291 ReturnType returnType1 = comReturnTypeOfTerm(formula->data.relation.op1) & ~RTNoError; 03292 ReturnType returnType2 = comReturnTypeOfTerm(formula->data.relation.op2) & ~RTNoError; 03293 String operator = "horst"; 03294 03295 switch (formula->type) { 03296 case FTGreater: 03297 comPrintln("( /* greater */ "); 03298 operator = ">"; 03299 break; 03300 case FTGreaterEqual: 03301 comPrintln("( /* greater equal */"); 03302 operator = ">="; 03303 break; 03304 case FTLess: 03305 comPrintln("( /* less */"); 03306 operator = "<"; 03307 break; 03308 case FTLessEqual: 03309 comPrintln("( /* less equal */"); 03310 operator = "<="; 03311 break; 03312 default: /* never reach */ 03313 break; 03314 } 03315 comIndent(); 03316 comTranslateTerm(formula->data.relation.op1, TRUE, TRUE, tmpIndex); 03317 03318 /* check known return types */ 03319 switch(returnType1) { 03320 case RTPeek: 03321 switch(returnType2) { 03322 case RTPeek: 03323 comPrint(" != VTNumber || ("); 03324 comTranslateTerm(formula->data.relation.op2, TRUE, TRUE, tmpIndex+1); 03325 comPrint(" != VTNumber ?"); 03326 #if 0 03327 comPrintln("(cdgPrintf(CDG_ERROR, " 03328 "\"type mismatch in formula `%s' in constraint `%s'\\n\"), FALSE) :", 03329 operator, comEscapeQuotes(com->currentConstraint->id)); 03330 #else 03331 comPrintln("FALSE :"); 03332 #endif 03333 comPrint("("); 03334 comTranslateLexicalAccess(formula->data.relation.op1); 03335 comPrint("->data.number %s ", operator); 03336 comTranslateLexicalAccess(formula->data.relation.op2); 03337 comPrintln("->data.number))"); 03338 break; 03339 case RTNumber: 03340 comPrintln(" != VTNumber ?", tmpIndex); 03341 #if 0 03342 comPrintln("(cdgPrintf(CDG_ERROR, " 03343 "\"type mismatch in formula `%s' in constraint `%s'\\n\"), FALSE) :", 03344 operator, comEscapeQuotes(com->currentConstraint->id)); 03345 #else 03346 comPrintln("FALSE :"); 03347 #endif 03348 comPrint("("); 03349 comTranslateTerm(formula->data.relation.op2, TRUE, TRUE, tmpIndex+1); 03350 comPrint("("); 03351 comTranslateLexicalAccess(formula->data.relation.op1); 03352 comPrint("->data.number %s ", operator); 03353 comTranslateNumber(formula->data.relation.op2, tmpIndex+1); 03354 comPrintln("))"); 03355 break; 03356 default: /* never reach */ 03357 comWriteError("2nd argument has an illegal return type `%s' in formula `%s'", 03358 comReturnTypeToString(returnType2), operator); 03359 } 03360 break; 03361 case RTNumber: 03362 switch(returnType2) { 03363 case RTPeek: 03364 comPrint("("); 03365 comTranslateTerm(formula->data.relation.op2, TRUE, TRUE, tmpIndex+1); 03366 comPrintln(" != VTNumber ?", tmpIndex); 03367 #if 0 03368 comPrintln("(cdgPrintf(CDG_ERROR, " 03369 "\"type mismatch in formula `%s' in constraint `%s'\\n\"), FALSE) :", 03370 operator, comEscapeQuotes(com->currentConstraint->id)); 03371 #else 03372 comPrintln("FALSE :"); 03373 #endif 03374 comPrint("("); 03375 comTranslateNumber(formula->data.relation.op1, tmpIndex); 03376 comPrint(" %s ", operator); 03377 comTranslateLexicalAccess(formula->data.relation.op2); 03378 comPrintln("->data.number))"); 03379 break; 03380 case RTNumber: 03381 comPrint("("); 03382 comTranslateTerm(formula->data.relation.op2, TRUE, TRUE, tmpIndex+1); 03383 comPrint("("); 03384 comTranslateNumber(formula->data.relation.op1, tmpIndex); 03385 comPrint(" %s ", operator); 03386 comTranslateNumber(formula->data.relation.op2, tmpIndex+1); 03387 comPrintln("))"); 03388 break; 03389 default: /* never reach */ 03390 comWriteError("2nd argument has an illegal return type `%s' in formula `%s'", 03391 comReturnTypeToString(returnType2), operator); 03392 } 03393 break; 03394 default: /* never reach */ 03395 comWriteError("1rst argument has an illegal return type `%s' in formula `%s'", 03396 comReturnTypeToString(returnType1), operator); 03397 } 03398 03399 comOutdent(); 03400 comPrint(")"); 03401 } 03402 03403 /* ---------------------------------------------------------------------- 03404 * translate the direction formulas 03405 */ 03406 void comTranslateDirection(Formula formula) 03407 { 03408 comPrintln("( /* direction `%s' */", 03409 comDirectionToString(formula->data.direction.d)); 03410 comIndent(); 03411 03412 /* anydir */ 03413 if (formula->data.direction.d == AnyDir) { 03414 comPrintln("TRUE"); 03415 } 03416 03417 /* nonnil */ 03418 else if (formula->data.direction.d == NonNil) { 03419 comPrintln("lv%d->modifiee != NULL", 03420 comIndexOfVarInfo(formula->data.direction.var)); 03421 } 03422 03423 /* nil */ 03424 else if (formula->data.direction.d == Nil) { 03425 comPrintln("lv%d->modifiee == NULL", 03426 comIndexOfVarInfo(formula->data.direction.var)); 03427 } 03428 03429 /* left */ 03430 else if (formula->data.direction.d == Left) { 03431 comPrintln("lv%d->modifiee != NULL && lv%d->modifiee != NONSPEC &&", 03432 comIndexOfVarInfo(formula->data.direction.var), 03433 comIndexOfVarInfo(formula->data.direction.var)); 03434 comPrintln("lv%d->modifiee->arc->from < lv%d->modifier->arc->from", 03435 comIndexOfVarInfo(formula->data.direction.var), 03436 comIndexOfVarInfo(formula->data.direction.var)); 03437 } 03438 03439 /* right */ 03440 else if (formula->data.direction.d == Right) { 03441 comPrintln("lv%d->modifiee != NULL &&", 03442 comIndexOfVarInfo(formula->data.direction.var)); 03443 comPrint("(lv%d->modifiee == NONSPEC || ", 03444 comIndexOfVarInfo(formula->data.direction.var)); 03445 comPrintln("lv%d->modifiee->arc->from >= lv%d->modifier->arc->from)", 03446 comIndexOfVarInfo(formula->data.direction.var), 03447 comIndexOfVarInfo(formula->data.direction.var)); 03448 } else { 03449 /* never reach */ 03450 comWriteError("illegal direction"); 03451 } 03452 comOutdent(); 03453 comPrint(")"); 03454 } 03455 03456 /* ---------------------------------------------------------------------- 03457 * translate a formula to c code 03458 */ 03459 void comTranslateFormula(Formula formula, int tmpIndex) 03460 { 03461 ReturnType returnType1; 03462 String operator = "horst"; 03463 int nextTmpIndex; 03464 03465 com->currentFormula = formula; 03466 returnType1 = comReturnTypeOfFormula(formula); 03467 if (returnType1 == RTError) 03468 return; 03469 03470 if (returnType1 & ~RTNoError & ~RTBoolean) { 03471 comPrint("FALSE"); 03472 comWriteWarning("illegal formula of type `%s'", 03473 comFormulaTypeToString(formula)); 03474 return; 03475 } 03476 03477 switch(formula->type) { 03478 /* ---------------------------------------------------------------------- */ 03479 case FTConstant: 03480 comPrint("%s", (formula->data.constant)?"TRUE":"FALSE"); 03481 break; 03482 /* ---------------------------------------------------------------------- */ 03483 case FTNegation: 03484 comPrintln("!( /* negation */"); 03485 comIndent(); 03486 comTranslateFormula(formula->data.formula, tmpIndex); 03487 comOutdent(); 03488 comPrintln(""); 03489 comPrint(")"); 03490 break; 03491 /* ---------------------------------------------------------------------- */ 03492 case FTEqual: 03493 case FTNotEqual: 03494 comTranslateEquation(formula, tmpIndex); 03495 break; 03496 /* ---------------------------------------------------------------------- */ 03497 case FTGreater: 03498 case FTGreaterEqual: 03499 case FTLess: 03500 case FTLessEqual: 03501 comTranslateUnEquation(formula, tmpIndex); 03502 break; 03503 /* ---------------------------------------------------------------------- */ 03504 case FTConjunction: 03505 case FTDisjunction: 03506 case FTImplication: 03507 case FTBiimplication: 03508 nextTmpIndex = tmpIndex; 03509 switch(formula->type) { 03510 case FTConjunction: 03511 comPrintln("( /* and */"); 03512 operator = "&&"; 03513 break; 03514 case FTDisjunction: 03515 comPrintln("( /* or */"); 03516 operator = "||"; 03517 break; 03518 case FTImplication: 03519 comPrintln("(!( /* impl */"); 03520 operator = "||"; 03521 break; 03522 case FTBiimplication: 03523 comPrintln("( /* biimpl */"); 03524 operator = "=="; 03525 nextTmpIndex = tmpIndex + comFormulaDepth(formula->data.junction.arg1); 03526 break; 03527 default: /* never reach */ 03528 break; 03529 } 03530 comIndent(); /* TODO: must we check VTError here? */ 03531 comTranslateFormula(formula->data.junction.arg1, tmpIndex); 03532 if (formula->type == FTImplication) { 03533 comPrint(")"); 03534 } 03535 comPrintln(" %s ", operator); 03536 comTranslateFormula(formula->data.junction.arg2, nextTmpIndex); 03537 comOutdent(); 03538 comPrintln(""); 03539 comPrint(")"); 03540 break; 03541 /* ---------------------------------------------------------------------- */ 03542 case FTPredicate: 03543 comTranslatePredicate(formula->data.predicate.functor, 03544 formula->data.predicate.args, tmpIndex); 03545 break; 03546 /* ---------------------------------------------------------------------- */ 03547 case FTConnexion: 03548 comTranslateConnexion(formula); 03549 break; 03550 /* ---------------------------------------------------------------------- */ 03551 case FTDirection: 03552 comTranslateDirection(formula); 03553 break; 03554 } 03555 } 03556 03557 /* ---------------------------------------------------------------------- 03558 * translate a connexion 03559 * in case of the unsymmetric connexions 'Under' & 'Over' a distinction between 03560 * the order (lv1, lv2) and (lv2, lv1) is made. in the other cases this doesn't 03561 * matter. 03562 */ 03563 void comTranslateConnexion(Formula formula) { 03564 int lv1Index = comIndexOfVarInfo(formula->data.connexion.var1); 03565 int lv2Index = comIndexOfVarInfo(formula->data.connexion.var2); 03566 03567 comPrintln("( /* connexion `%s' */", 03568 comConnextionToString(formula->data.connexion.c)); 03569 comIndent(); 03570 03571 /* AnyCon */ 03572 if (formula->data.connexion.c == AnyCon) { 03573 comPrintln("TRUE"); 03574 } 03575 03576 /* Top, Bottom */ 03577 else if (formula->data.connexion.c == Top || formula->data.connexion.c == Bottom) { 03578 comPrintln("_getConnextion(lv1, lv2) == %s || _getConnextion(lv1, lv2) == Identical", 03579 comConnextionToString(formula->data.connexion.c)); 03580 } 03581 03582 /* Over, Under */ 03583 else if (formula->data.connexion.c == Over || formula->data.connexion.c == Under) { 03584 comPrintln("_getConnextion(lv%d, lv%d) == %s || _getConnextion(lv%d, lv%d) == Inverse", 03585 lv1Index, lv2Index, comConnextionToString(formula->data.connexion.c), lv1Index, lv2Index); 03586 } 03587 03588 /* None, Inverse, Identical */ 03589 else { 03590 comPrintln("_getConnextion(lv1, lv2) == %s", 03591 comConnextionToString(formula->data.connexion.c)); 03592 } 03593 comOutdent(); 03594 comPrintln(")"); 03595 } 03596 03597 /* ---------------------------------------------------------------------- 03598 * translate each unary constraint into a separate c-function 03599 */ 03600 void comTranslateUnaryConstraints(void) 03601 { 03602 Constraint constraint; 03603 HashIterator hi = hashIteratorNew(inputCurrentGrammar->constraints); 03604 03605 while((constraint = hashIteratorNextValue(hi))) { 03606 if (constraint->sig->arity != 1) 03607 continue; 03608 comTranslateConstraint(constraint); 03609 } 03610 hashIteratorDelete(hi); 03611 assert(com->indent == 0); 03612 } 03613 03614 /* ---------------------------------------------------------------------- 03615 * translate a constraint into a c-function 03616 */ 03617 void comTranslateConstraint(Constraint constraint) 03618 { 03619 ReturnType returnType; 03620 com->currentConstraint = constraint; 03621 03622 /* write header */ 03623 comPrintln(""); 03624 comPrintln("/* ----------------------------------------------------------------------"); 03625 comPrintln(" * evaluate constraint %s", comEscapeQuotes(constraint->id)); 03626 comPrintln("*/"); 03627 if (constraint->sig->arity == 1) { 03628 comPrintln("Boolean _evalConstraint_%d(LexemGraph lg, Vector context, LevelValue lv1)", constraint->no); 03629 } else { 03630 comPrintln("Boolean _evalConstraint_%d(LexemGraph lg, Vector context, LevelValue lv1, LevelValue lv2)", constraint->no); 03631 } 03632 comPrintln("{"); 03633 comIndent(); 03634 03635 /* write some comments */ 03636 comPrintln(""); 03637 comPrintln("/*"); 03638 comPrintln(" * constraint: %s", comEscapeQuotes(constraint->id)); 03639 comPrintln(" * no : %d", constraint->no); 03640 comPrintln(" * filename : %s", constraint->filename); 03641 comPrintln(" * lineno : %d", constraint->lineNo); 03642 if (constraint->sig->arity == 1) { 03643 comPrintln(" * Signature : %s:%s", 03644 constraint->sig->l1->id, comDirectionToString(constraint->sig->d1)); 03645 } else { 03646 comPrintln(" * Signature : %s:%s %s %s:%s", 03647 constraint->sig->l1->id, comDirectionToString(constraint->sig->d1), 03648 comConnextionToString(constraint->sig->conn), 03649 constraint->sig->l2->id, comDirectionToString(constraint->sig->d2)); 03650 } 03651 03652 comPrintln(" */"); 03653 comPrintln(""); 03654 03655 /* the formula */ 03656 comPrintln("if(!"); 03657 comIndent(); 03658 comTranslateFormula(constraint->formula, 0); 03659 comOutdent(); 03660 comPrintln(""); 03661 comPrintln(") {"); 03662 comIndent(); 03663 03664 /* the penalty */ 03665 if (constraint->penaltyTerm != NULL) { 03666 comPrintln("constraints[%d].constraint->penalty = (", 03667 comIndexOfConstraint(constraint->id)); 03668 comIndent(); 03669 returnType = comReturnTypeOfTerm(constraint->penaltyTerm); 03670 if (!(returnType & RTNoError)) { 03671 comTranslateTerm(constraint->penaltyTerm, FALSE, FALSE, 0); 03672 comPrintln(" == VTError ? 0.0:", 0); 03673 } 03674 returnType &= ~RTNoError; 03675 03676 if (returnType == RTPeek) { 03677 comTranslateTerm(constraint->penaltyTerm, FALSE, FALSE, 0); 03678 comPrint(" != VTNumber ? 0.0 : "); 03679 comTranslateLexicalAccess(constraint->penaltyTerm); 03680 comPrintln("->data.number"); 03681 } else { 03682 comTranslateTerm(constraint->penaltyTerm, FALSE, TRUE, 0); 03683 comTranslateNumber(constraint->penaltyTerm, 0); 03684 comPrintln(""); 03685 } 03686 comOutdent(); 03687 comPrintln(");"); 03688 } 03689 03690 comPrintln("return FALSE;"); 03691 comOutdent(); 03692 comPrintln("}\n"); 03693 03694 com->currentConstraint = NULL; 03695 comPrintln(""); 03696 comPrintln("return TRUE;"); 03697 comOutdent(); 03698 comPrintln("}"); 03699 } 03700 03701 /* ---------------------------------------------------------------------- 03702 * translate each binary constraint into a separate c-function 03703 */ 03704 void comTranslateBinaryConstraints(void) 03705 { 03706 HashIterator hi = hashIteratorNew(inputCurrentGrammar->constraints); 03707 Constraint constraint; 03708 03709 while((constraint = hashIteratorNextValue(hi))) { 03710 if (constraint->sig->arity != 2) 03711 continue; 03712 comTranslateConstraint(constraint); 03713 } 03714 hashIteratorDelete(hi); 03715 assert(com->indent == 0); 03716 } 03717 03718 /* ---------------------------------------------------------------------- 03719 * translate the current cdg to C 03720 */ 03721 Boolean comTranslate(void) 03722 { 03723 Boolean success = TRUE; 03724 03725 cdgPrintf(CDG_INFO, "INFO: translating current grammar to `%s'\n", 03726 com->ccFileName); 03727 cdgFlush(); 03728 03729 /* write openers */ 03730 comWriteHeader(); 03731 03732 /* analyze the grammar */ 03733 comAnalyzeGrammar(); 03734 03735 /* write some declarations */ 03736 comWriteDeclarations(); 03737 03738 /* translate every constraint */ 03739 comTranslateUnaryConstraints(); 03740 comTranslateBinaryConstraints(); 03741 03742 /* write helper functions */ 03743 comWriteFunctions(); 03744 03745 return success; 03746 } 03747 03748 /* ---------------------------------------------------------------------- 03749 * compile a shared object from the recently translated code 03750 */ 03751 Boolean comMake(void) 03752 { 03753 String compileCmd = strAppend(makeInfo->cc, " ", 03754 makeInfo->cFlags, " ", 03755 makeInfo->includes, " -c ", 03756 com->ccFileName, NULL); // this is a registered string now 03757 String linkCmd = strAppend(makeInfo->ld, " ", 03758 makeInfo->ldFlags, " ", 03759 makeInfo->ldLibs, " ", 03760 com->objFileName, " -o ", 03761 com->soFileName, NULL); // this is a registered string now 03762 Boolean isOk = TRUE; 03763 03764 /* call the compiler */ 03765 cdgPrintf(CDG_INFO, "INFO: compiling `%s' to `%s'\n", 03766 com->ccFileName, com->objFileName); 03767 cdgPrintf(CDG_DEBUG, "DEBUG: %s\n", compileCmd); 03768 cdgFlush(); 03769 if (system(compileCmd) != 0) { 03770 cdgPrintf(CDG_ERROR, "ERROR: compiler error, message should have been provided\n"); 03771 isOk = FALSE; 03772 } else { 03773 03774 /* call the linker */ 03775 cdgPrintf(CDG_INFO, "INFO: linking `%s' to `%s'\n", 03776 com->objFileName, com->soFileName); 03777 cdgPrintf(CDG_DEBUG, "DEBUG: %s\n", linkCmd); 03778 cdgFlush(); 03779 if (system(linkCmd) != 0) { 03780 cdgPrintf(CDG_ERROR, "ERROR: linker error, message should have been provided\n"); 03781 isOk = FALSE; 03782 } 03783 } 03784 return isOk; 03785 } 03786 03787 /* ---------------------------------------------------------------------------- 03788 * load a dll grammar 03789 */ 03790 Input comLoad(String filename) 03791 { 03792 void *dllHandle; 03793 String sofilename; 03794 Input input = inputNewInput(); 03795 03796 if (filename == NULL) { 03797 sofilename = com->soFileName; 03798 } else { 03799 sofilename = filename; 03800 } 03801 03802 cdgPrintf(CDG_INFO, "INFO: loading `%s'\n", sofilename); 03803 03804 /* get the dll handle */ 03805 dllHandle = dlopen(sofilename, RTLD_NOW); 03806 if (!dllHandle) { 03807 cdgPrintf(CDG_ERROR, "ERROR: can't load `%s': %s\n", sofilename, dlerror()); 03808 return NULL; 03809 } 03810 03811 inputRegisterFilename(input, sofilename); 03812 input->dllHandle = dllHandle; 03813 03814 return input; 03815 } 03816 03817 /* ---------------------------------------------------------------------------- 03818 * check the return type of a predicate 03819 */ 03820 ReturnType comReturnTypeOfPredicate(String functor, List args) 03821 { 03822 Term term; 03823 ReturnType returnType1, returnType2, returnType3; 03824 03825 /* start, stop, root, spec, nonspec */ 03826 if (strcmp("start", functor) == 0 || 03827 strcmp("stop", functor) == 0 || 03828 strcmp("root", functor) == 0 || 03829 strcmp("nonspec", functor) == 0 || 03830 strcmp("spec", functor) == 0) { 03831 if (listSize(args) != 1 || args == NULL || listElement(args) == NULL) { 03832 comWriteWarning("`%s' needs one argument", functor); 03833 return RTError; 03834 } 03835 returnType1 = comReturnTypeOfTerm(listElement(args)) & ~RTLexemPosition; 03836 if (returnType1 == RTError) 03837 return RTError; 03838 if (returnType1 == (RTLexemNode | RTNoError)) { 03839 return RTBoolean | RTNoError; 03840 } else if (returnType1 == RTLexemNode) { 03841 return RTBoolean; 03842 } 03843 comWriteWarning("argument of type `%s' isn't a lexemnode in `%s'", 03844 comReturnTypeToString(returnType1), functor); 03845 return RTError; 03846 } 03847 03848 /* print */ 03849 if (strcmp("print", functor) == 0) { 03850 return RTBoolean | RTNoError; 03851 } 03852 03853 /* subsumes, compatible */ 03854 if (strcmp("subsumes", functor) == 0 || 03855 strcmp("compatible", functor) == 0) { 03856 if (listSize(args) != 3) { 03857 comWriteWarning("predicate `%s' needs three arguments", functor); 03858 return RTError; 03859 } 03860 03861 returnType1 = comReturnTypeOfTerm(listNthElement(args, 1)) & ~RTNoError; 03862 if (returnType1 == RTError) 03863 return RTError; 03864 if (!(returnType1 & (RTString | RTPeek))) { 03865 comWriteWarning("1rst argument of type `%s' isn't a string in `%s'", 03866 comReturnTypeToString(returnType1), functor); 03867 return RTError; 03868 } 03869 03870 returnType2 = comReturnTypeOfTerm(listNthElement(args, 2)) & ~RTNoError; 03871 if (returnType2 == RTError) 03872 return RTError; 03873 if (!(returnType2 & (RTString | RTPeek))) { 03874 comWriteWarning("2nd argument of type `%s' isn't a string in `%s'", 03875 comReturnTypeToString(returnType2), functor); 03876 return RTError; 03877 } 03878 03879 returnType3 = comReturnTypeOfTerm(listNthElement(args, 3)) & ~RTNoError; 03880 if (returnType3 == RTError) 03881 return RTError; 03882 if (!(returnType2 & (RTString | RTPeek))) { 03883 comWriteWarning("3nd argument of type `%s' isn't a string in `%s'", 03884 comReturnTypeToString(returnType3), functor); 03885 return RTError; 03886 } 03887 return RTBoolean; 03888 } 03889 03890 /* exists */ 03891 if (strcmp("exists", functor) == 0) { 03892 if (listSize(args) != 1 || args == NULL || listElement(args) == NULL) { 03893 comWriteWarning("predicate `exists' needs one argument"); 03894 return RTError; 03895 } 03896 term = (Term)listElement(args); 03897 if (term->type != TTTopPeek && term->type != TTBottomPeek) { 03898 comWriteWarning("predicate `exists' needs a lexical access"); 03899 return RTError; 03900 } 03901 return RTBoolean | RTNoError; 03902 } 03903 03904 /* chunk head */ 03905 if (strcmp("chunk_head", functor) == 0) { 03906 if (listSize(args) != 1) { 03907 comWriteWarning("'%s' needs one argument", functor); 03908 return RTError; 03909 } 03910 returnType1 = (comReturnTypeOfTerm(listElement(args)) & ~RTLexemPosition); 03911 if (returnType1 == RTError) { 03912 return RTError; 03913 } 03914 if (returnType1 == (RTLexemNode | RTNoError)) { 03915 return RTBoolean; 03916 } 03917 comWriteWarning("argument of type `%s' isn't a lexemnode in `%s'", 03918 comReturnTypeToString(returnType1), functor); 03919 return RTError; 03920 } 03921 03922 /* under */ 03923 if (strcmp("under", functor) == 0) { 03924 if (listSize(args) != 2) { 03925 comWriteWarning("'%s' needs two arguments", functor); 03926 return RTError; 03927 } 03928 term = (Term)listElement(args); 03929 returnType1 = (comReturnTypeOfTerm(term) & ~RTLexemPosition); 03930 if (returnType1 == RTError) { 03931 return RTError; 03932 } 03933 term = (Term)listElement(args); 03934 returnType2 = (comReturnTypeOfTerm(term) & ~RTLexemPosition); 03935 if (returnType2 == RTError) { 03936 return RTError; 03937 } 03938 if (returnType1 == (RTLexemNode | RTNoError)) { 03939 if (returnType2 == (RTLexemNode | RTNoError)) { 03940 return RTBoolean; 03941 } 03942 } 03943 comWriteWarning("argument of type `%s' isn't a lexemnode in `%s'", 03944 comReturnTypeToString(returnType1), functor); 03945 return RTError; 03946 } 03947 03948 /* between */ 03949 if (strcmp("between", functor) == 0) { 03950 if (listSize(args) != 3) { 03951 comWriteWarning("'%s' needs 3 arguments", functor); 03952 return RTError; 03953 } 03954 term = (Term)listElement(args); 03955 returnType1 = comReturnTypeOfTerm(term); 03956 term = (Term)listElement(listNext(args)); 03957 returnType2 = comReturnTypeOfTerm(term); 03958 term = (Term)listNthElement(args, 3); 03959 returnType3 = comReturnTypeOfTerm(term); 03960 03961 if ((returnType1 | returnType2 | returnType3) & RTError) { 03962 return RTError; 03963 } 03964 if (returnType1 & (RTLexemNode | RTNumber)) { 03965 if (returnType2 & (RTLexemNode | RTNumber)) { 03966 if (returnType3 & RTString) { 03967 return RTBoolean; 03968 } 03969 comWriteWarning("third argument of type `%s' isn't a string in `%s'", 03970 comReturnTypeToString(returnType3), functor); 03971 return RTError; 03972 } 03973 comWriteWarning("second argument of type `%s' isn't a lexemnode or number in `%s'", 03974 comReturnTypeToString(returnType2), functor); 03975 return RTError; 03976 } 03977 comWriteWarning("first argument of type `%s' isn't a lexemnode or number in `%s'", 03978 comReturnTypeToString(returnType1), functor); 03979 return RTError; 03980 } 03981 03982 /* is */ 03983 if (strcmp("is", functor) == 0) { 03984 if ((listSize(args) < 2) || (listSize(args) > 3)) { 03985 comWriteWarning("'%s' needs 2 or 3 arguments", functor); 03986 return RTError; 03987 } 03988 returnType1 = comReturnTypeOfTerm(listElement(args)) & ~RTNoError; 03989 if (returnType1 & RTError) { 03990 return RTError; 03991 } 03992 if (! (returnType1 & RTLexemNode)) { 03993 comWriteWarning("first argument of type `%s' isn't a lexemnode in `%s'", 03994 comReturnTypeToString(returnType1), functor); 03995 return RTError; 03996 } 03997 returnType2 = comReturnTypeOfTerm(listElement(listNext(args))) & ~RTNoError; 03998 if (returnType2 & RTError) { 03999 return RTError; 04000 } 04001 if (! (returnType2 & RTString)) { 04002 comWriteWarning("second argument of type `%s' isn't a string in `%s'", 04003 comReturnTypeToString(returnType1), functor); 04004 return RTError; 04005 } 04006 /* optional third argument */ 04007 if (listSize(args) == 3) { 04008 returnType3 = comReturnTypeOfTerm(listNthElement(args, 3)) & ~RTNoError; 04009 if (! (returnType3 & RTString)) { 04010 comWriteWarning("third argument of type `%s' isn't a string in `%s'", 04011 comReturnTypeToString(returnType1), functor); 04012 return RTError; 04013 } 04014 } 04015 return RTBoolean; 04016 } 04017 04018 /* connected */ 04019 if (strcmp("connected", functor) == 0) { 04020 if (listSize(args) != 2) { 04021 comWriteWarning("'%s' needs 2 arguments", functor); 04022 return RTError; 04023 } 04024 term = (Term)listElement(args); 04025 returnType1 = (comReturnTypeOfTerm(term) & ~RTLexemPosition); 04026 if (returnType1 == RTError) { 04027 return RTError; 04028 } 04029 if (! (returnType1 & RTLexemNode)) { 04030 comWriteWarning("first argument of type `%s' isn't a lexem node in `%s'", 04031 comReturnTypeToString(returnType1), functor); 04032 return RTError; 04033 } 04034 term = (Term)listElement(listNext(args)); 04035 returnType2 = (comReturnTypeOfTerm(term) & ~RTLexemPosition); 04036 if (returnType2 == RTError) { 04037 return RTError; 04038 } 04039 if (! (returnType2 & RTLexemNode)) { 04040 comWriteWarning("second argument of type `%s' isn't a lexem node in `%s'", 04041 comReturnTypeToString(returnType2), functor); 04042 return RTError; 04043 } 04044 return RTBoolean; 04045 } 04046 04047 /* has */ 04048 if (strcmp("has", functor) == 0) { 04049 if ((listSize(args) < 2) || (listSize(args) > 6)) { 04050 comWriteWarning("'%s' needs 2 to 6 arguments", functor); 04051 return RTError; 04052 } 04053 /* first argument */ 04054 term = (Term)listNthElement(args, 1); 04055 returnType1 = comReturnTypeOfTerm(term); 04056 if (returnType1 & RTError) { 04057 return RTError; 04058 } 04059 if (! (returnType1 & RTLexemNode)) { 04060 comWriteWarning("first argument of type `%s' isn't a lexemnode in `%s'", 04061 comReturnTypeToString(returnType1), functor); 04062 return RTError; 04063 } 04064 /* second argument */ 04065 term = (Term)listNthElement(args, 2); 04066 returnType1 = comReturnTypeOfTerm(term); 04067 if (returnType1 & RTError) { 04068 return RTError; 04069 } 04070 if (! (returnType1 & (RTString | RTPeek))) { 04071 comWriteWarning("second argument of type `%s' isn't a string in `%s'", 04072 comReturnTypeToString(returnType1), functor); 04073 return RTError; 04074 } 04075 /* third argument */ 04076 if (listSize(args) > 2) { 04077 term = (Term)listNthElement(args, 3); 04078 returnType1 = comReturnTypeOfTerm(term); 04079 if (returnType1 & RTError) { 04080 return RTError; 04081 } 04082 if (! (returnType1 & RTString)) { 04083 comWriteWarning("third argument of type `%s' isn't a string in `%s'", 04084 comReturnTypeToString(returnType1), functor); 04085 return RTError; 04086 } 04087 } 04088 /* fourth argument */ 04089 if (listSize(args) > 3) { 04090 term = (Term)listNthElement(args, 4); 04091 returnType1 = comReturnTypeOfTerm(term); 04092 if (returnType1 & RTError) { 04093 return RTError; 04094 } 04095 if (! (returnType1 & RTString)) { 04096 comWriteWarning("fourth argument of type `%s' isn't a string in `%s'", 04097 comReturnTypeToString(returnType1), functor); 04098 return RTError; 04099 } 04100 } 04101 /* fifth argument */ 04102 if (listSize(args) > 4) { 04103 term = (Term)listNthElement(args, 5); 04104 returnType1 = comReturnTypeOfTerm(term); 04105 if (returnType1 & RTError) { 04106 return RTError; 04107 } 04108 if (! (returnType1 & RTNumber)) { 04109 comWriteWarning("fifth argument of type `%s' isn't a number in `%s'", 04110 comReturnTypeToString(returnType1), functor); 04111 return RTError; 04112 } 04113 } 04114 /* sixth argument */ 04115 if (listSize(args) > 5) { 04116 term = (Term)listNthElement(args, 6); 04117 returnType1 = comReturnTypeOfTerm(term); 04118 if (returnType1 & RTError) { 04119 return RTError; 04120 } 04121 if (! (returnType1 & RTNumber)) { 04122 comWriteWarning("sixth argument of type `%s' isn't a number in `%s'", 04123 comReturnTypeToString(returnType1), functor); 04124 return RTError; 04125 } 04126 } 04127 return RTBoolean; 04128 } 04129 04130 comWriteError("unknown predicate `%s'", functor); 04131 return RTError; 04132 } 04133 04134 /* ---------------------------------------------------------------------------- 04135 * check the return type of a function 04136 */ 04137 ReturnType comReturnTypeOfFunction(String functor, List args) 04138 { 04139 List l; 04140 Term term; 04141 ReturnType returnType1, returnType2, returnType3; 04142 int i; 04143 04144 /* distance */ 04145 if (strcmp("distance", functor) == 0) { 04146 if (listSize(args) != 2 || 04147 listElement(args) == NULL || 04148 listElement(listNext(args)) == NULL) { 04149 comWriteWarning("function `distance' needs two lexemnodes as arguments"); 04150 return RTError; 04151 } 04152 returnType1 = comReturnTypeOfTerm(listNthElement(args, 1)) & ~RTLexemPosition; 04153 if (returnType1 == RTError) 04154 return RTError; 04155 if (returnType1 & ~RTNoError & ~RTLexemNode) { 04156 comWriteWarning( 04157 "1rst argument of type `%s' isn't a lexemnodes in `distance'", 04158 comReturnTypeToString(returnType1)); 04159 return RTError; 04160 } 04161 returnType2 = comReturnTypeOfTerm(listNthElement(args, 2)) & ~RTLexemPosition; 04162 if (returnType2 == RTError) 04163 return RTError; 04164 if (returnType2 & ~RTNoError & ~RTLexemNode) { 04165 comWriteWarning( 04166 "2nd argument of type `%s' isn't a lexemnodes in `distance'", 04167 comReturnTypeToString(returnType2)); 04168 return RTError; 04169 } 04170 04171 if (returnType1 & RTNoError & returnType2) { 04172 return RTNumber | RTNoError; 04173 } else { 04174 return RTNumber; 04175 } 04176 } 04177 04178 /* abs */ 04179 else if (strcmp("abs", functor) == 0) { 04180 if (listSize(args) != 1 || listElement(args) == NULL) { 04181 comWriteWarning("function `abs' needs one argument"); 04182 return RTError; 04183 } else { 04184 returnType1 = comReturnTypeOfTerm(listElement(args)); 04185 04186 if (returnType1 == RTError) 04187 return RTError; 04188 if (returnType1 & ~RTNoError & ~RTNumber) { 04189 comWriteWarning("argument type `%s' isn't numerical in `abs'", 04190 comReturnTypeToString(returnType1)); 04191 return RTError; 04192 } 04193 04194 if (returnType1 & RTNoError) { 04195 return RTNumber | RTNoError; 04196 } else { 04197 return RTNumber; 04198 } 04199 } 04200 } 04201 04202 /* min, max */ 04203 else if (strcmp("min", functor) == 0 || 04204 strcmp("max", functor) == 0) { 04205 if (listSize(args) <= 1) { 04206 comWriteWarning("function `%s' needs at least two arguments", 04207 functor); 04208 return RTError; 04209 } else { 04210 Boolean errorPossible = FALSE; 04211 04212 /* check the arguments */ 04213 for (l = args, i = 0; l != NULL; i++, l = listNext(l)) { 04214 term = (Term)listElement(l); 04215 returnType1 = comReturnTypeOfTerm(term); 04216 if (returnType1 == RTError) 04217 return RTError; 04218 if (returnType1 & ~RTNoError & ~RTNumber) { 04219 comWriteWarning("%d. argument type `%s' isn't numerical in `%s'", 04220 i, comReturnTypeToString(returnType1), functor); 04221 return RTError; 04222 } 04223 errorPossible &= !(returnType1 & RTNoError); 04224 } 04225 04226 if (errorPossible) { 04227 return RTNumber; 04228 } else { 04229 return RTNumber | RTNoError; 04230 } 04231 } 04232 } 04233 04234 /* match */ 04235 else if (strcmp("match", functor) == 0) { 04236 if (listSize(args) != 3) { 04237 comWriteWarning("function `match' needs three arguments"); 04238 return RTError; 04239 } 04240 returnType1 = comReturnTypeOfTerm(listNthElement(args, 1)) & ~RTNoError; 04241 if (returnType1 == RTError) 04242 return RTError; 04243 if (returnType1 & ~RTString) { 04244 comWriteWarning("1rst argument of type `%s' isn't a string in `match'", 04245 comReturnTypeToString(returnType1)); 04246 return RTError; 04247 } 04248 returnType2 = comReturnTypeOfTerm(listNthElement(args, 2)) & ~RTNoError; 04249 if (returnType2 == RTError) 04250 return RTError; 04251 if (returnType2 & ~RTList & ~RTString & ~RTPeek) { 04252 comWriteWarning("2nd argument of type `%s' isn't a string in `match'", 04253 comReturnTypeToString(returnType2)); 04254 return RTError; 04255 } 04256 returnType3 = comReturnTypeOfTerm(listNthElement(args, 3)) & ~RTNoError; 04257 if (returnType3 == RTError) 04258 return RTError; 04259 if (returnType3 & ~RTString & ~RTPeek) { 04260 comWriteWarning("3rd argument of type `%s' isn't a string in `match'", 04261 comReturnTypeToString(returnType3)); 04262 return RTError; 04263 } 04264 return RTNumber; 04265 } 04266 04267 /* phraseqotes */ 04268 else if (strcmp("phrasequotes", functor) == 0) { 04269 if (listSize(args) != 1) { 04270 comWriteWarning("function `match' needs one argument"); 04271 return RTError; 04272 } 04273 returnType1 = comReturnTypeOfTerm(listElement(args)) & ~RTNoError; 04274 if (returnType1 & RTLexemNode) { 04275 return RTNumber; 04276 } 04277 if (returnType1 & ~RTLexemNode & ~RTLexemPosition) { 04278 comWriteWarning("argument of function 'phrasequotes' not a lexeme node"); 04279 return RTError; 04280 } 04281 return RTError; // never reach 04282 } 04283 04284 /* lookup */ 04285 else if (strcmp("lookup", functor) == 0) { 04286 if (listSize(args) < 2) { 04287 comWriteWarning("function `lookup' needs 2 or more arguments"); 04288 return RTError; 04289 } else { 04290 Boolean errorPossible = FALSE; 04291 04292 /* check first argument */ 04293 returnType1 = comReturnTypeOfTerm((Term)listElement(args)); 04294 if (returnType1 & RTError) 04295 return RTError; 04296 if (returnType1 & ~RTNoError & ~RTString) { 04297 comWriteWarning("First argument type `%s' isn't a string in 'lookup'", 04298 comReturnTypeToString(returnType1)); 04299 return RTError; 04300 } 04301 04302 /* check the other arguments */ 04303 for (l = listNext(args), i = 2; l != NULL; i++, l = listNext(l)) { 04304 term = (Term)listElement(l); 04305 returnType1 = comReturnTypeOfTerm(term); 04306 if (returnType1 == RTError) 04307 return RTError; 04308 if (returnType1 & ~RTNoError & ~RTString & ~RTPeek) { 04309 comWriteWarning("%d. argument type `%s' isn't a string or peek in 'lookup'", 04310 i, comReturnTypeToString(returnType1)); 04311 return RTError; 04312 } 04313 errorPossible &= !(returnType1 & RTNoError); 04314 } 04315 04316 if (errorPossible) { 04317 return RTString; 04318 } else { 04319 return RTString | RTNoError; 04320 } 04321 } 04322 } 04323 04324 /* quotes */ 04325 else if (strcmp("quotes", functor) == 0) { 04326 if (listSize(args) != 1) { 04327 comWriteWarning("function `quotes' needs one argument"); 04328 return RTError; 04329 } 04330 term = (Term)listElement(args); 04331 returnType1 = comReturnTypeOfTerm(term); 04332 if (returnType1 & RTError) { 04333 return RTError; 04334 } 04335 if (returnType1 & ~RTLexemNode & ~RTLexemPosition & ~RTNoError) { 04336 comWriteWarning("First argument type `%s' isn't a LexemNode in 'quotes'", 04337 comReturnTypeToString(returnType1)); 04338 return RTError; 04339 } 04340 return RTNumber; 04341 } 04342 04343 04344 /* parent */ 04345 else if (strcmp("parent", functor) == 0) { 04346 if (listSize(args) != 1) { 04347 comWriteWarning("function `parent' needs one argument"); 04348 return RTError; 04349 } 04350 term = (Term)listElement(args); 04351 returnType1 = comReturnTypeOfTerm(term); 04352 if (returnType1 & RTError) { 04353 return RTError; 04354 } 04355 if (returnType1 & ~RTLexemNode & ~RTLexemPosition & ~RTNoError) { 04356 comWriteWarning("First argument type `%s' isn't a LexemNode in 'parent'", 04357 comReturnTypeToString(returnType1)); 04358 return RTError; 04359 } 04360 return RTLexemNode; 04361 } 04362 04363 /* pts */ 04364 else if (strcmp("parens", functor) == 0 || 04365 strcmp("pts", functor) == 0 || 04366 strcmp("height", functor) == 0) { 04367 if (listSize(args) != 1) { 04368 comWriteWarning("function `pts' needs one argument"); 04369 return RTError; 04370 } 04371 term = (Term)listElement(args); 04372 returnType1 = comReturnTypeOfTerm(term); 04373 if (returnType1 & RTError) { 04374 return RTError; 04375 } 04376 if (returnType1 & ~RTLexemNode & ~RTLexemPosition & ~RTNoError) { 04377 comWriteWarning("First argument type `%s' isn't a LexemNode in 'pts'", 04378 comReturnTypeToString(returnType1)); 04379 return RTError; 04380 } 04381 return RTNumber; 04382 } 04383 04384 /* default */ 04385 else { 04386 comWriteError("compile.c:%d: unknown function `%s'", __LINE__, functor); 04387 return RTError; 04388 } 04389 } 04390 04391 /* ---------------------------------------------------------------------------- 04392 * check the return type of a term 04393 */ 04394 ReturnType comReturnTypeOfTerm(Term term) 04395 { 04396 ReturnType returnType1, returnType2; 04397 04398 switch(term->type) { 04399 case TTString: 04400 case TTLabel: 04401 case TTLevel: 04402 return RTString | RTNoError; 04403 case TTNumber: 04404 return RTNumber | RTNoError; 04405 case TTAdd: 04406 case TTSubtract: 04407 case TTMultiply: 04408 case TTDivide: 04409 returnType1 = comReturnTypeOfTerm(term->data.operation.op1); 04410 if (returnType1 == RTError) 04411 return RTError; 04412 returnType2 = comReturnTypeOfTerm(term->data.operation.op2); 04413 if (returnType1 == RTError) 04414 return RTError; 04415 04416 if (returnType1 & ~RTNoError & (RTNumber | RTPeek)) { 04417 if (returnType2 & ~RTNoError & (RTNumber | RTPeek)) { 04418 if (returnType1 & returnType2 & RTNoError) { 04419 return RTNumber | RTNoError; 04420 } else { 04421 return RTNumber; 04422 } 04423 } 04424 } 04425 comWriteWarning("argument types `%s' and `%s' aren't numerical in `%s'", 04426 comReturnTypeToString(returnType1), 04427 comReturnTypeToString(returnType2), 04428 comTermTypeToString(term)); 04429 break; 04430 case TTFunction: 04431 return comReturnTypeOfFunction( 04432 term->data.function.functor, term->data.function.args); 04433 case TTTopPeek: 04434 if (term->data.peek.path == NULL) { 04435 return RTAVNode; 04436 } else { 04437 String pathItem = listElement(term->data.peek.path); 04438 if (strcmp("id", pathItem) == 0) { 04439 return RTLexemNode | RTNoError | RTLexemPosition; 04440 } else if (strcmp("from", pathItem) == 0) { 04441 return RTNumber; 04442 } else if (strcmp("to", pathItem) == 0) { 04443 return RTNumber; 04444 } else if (strcmp("word", pathItem) == 0) { 04445 return RTString; 04446 } else { 04447 return RTPeek | RTNoError; /* peek checks errors itself */ 04448 } 04449 } 04450 break; 04451 case TTBottomPeek: 04452 if (term->data.peek.path == NULL) { 04453 return RTAVNode; 04454 } else { 04455 String pathItem = listElement(term->data.peek.path); 04456 if (strcmp("from", pathItem) == 0) { 04457 return RTNumber | RTNoError; 04458 } else if (strcmp("to", pathItem) == 0) { 04459 return RTNumber | RTNoError; 04460 } else if (strcmp("word", pathItem) == 0) { 04461 return RTString | RTNoError; 04462 } else if (strcmp("id", pathItem) == 0) { 04463 return RTLexemNode | RTNoError; 04464 } else { 04465 return RTPeek | RTNoError; /* peek checks errors itself */ 04466 } 04467 } 04468 break; 04469 } 04470 04471 return RTError; 04472 } 04473 04474 /* ---------------------------------------------------------------------------- 04475 * check the return type of a formula 04476 */ 04477 ReturnType comReturnTypeOfFormula(Formula formula) 04478 { 04479 ReturnType returnType1, returnType2; 04480 04481 switch (formula->type) { 04482 case FTConnexion: 04483 case FTDirection: 04484 case FTConstant: 04485 return RTBoolean | RTNoError; 04486 case FTNegation: 04487 return comReturnTypeOfFormula(formula->data.formula); 04488 case FTConjunction: 04489 case FTDisjunction: 04490 case FTImplication: 04491 case FTBiimplication: 04492 returnType1 = comReturnTypeOfFormula(formula->data.junction.arg1); 04493 if (returnType1 == RTError) 04494 return RTError; 04495 returnType2 = comReturnTypeOfFormula(formula->data.junction.arg2); 04496 if (returnType2 == RTError) 04497 return RTError; 04498 04499 if (returnType1 & RTBoolean & ~RTNoError) { 04500 if (returnType2 & RTBoolean & ~RTNoError) { 04501 if (returnType1 & RTNoError & returnType2) { 04502 return RTBoolean | RTNoError; 04503 } else { 04504 return RTBoolean; 04505 } 04506 } 04507 } 04508 comWriteWarning("argument types `%s' and `%s' aren't boolean in `%s'", 04509 comReturnTypeToString(returnType1), 04510 comReturnTypeToString(returnType2), 04511 comFormulaTypeToString(formula)); 04512 break; 04513 case FTEqual: 04514 case FTNotEqual: 04515 returnType1 = comReturnTypeOfTerm(formula->data.relation.op1) & ~RTLexemPosition; 04516 if (returnType1 == RTError) 04517 return RTError; 04518 returnType2 = comReturnTypeOfTerm(formula->data.relation.op2) & ~RTLexemPosition; 04519 if (returnType2 == RTError) 04520 return RTError; 04521 04522 if (returnType1 & ~RTNoError & returnType2) { 04523 if (returnType1 & RTNoError & returnType2) { 04524 return RTBoolean | RTNoError; 04525 } else { 04526 return RTBoolean; 04527 } 04528 } 04529 if (returnType1 & ~RTNoError & RTPeek) { 04530 if (returnType2 & ~RTLexemNode) { 04531 return RTBoolean; 04532 } 04533 } else if (returnType1 & ~RTNoError & RTLexemNode) { 04534 if (returnType2 & ~RTNoError & ~RTPeek) { 04535 return RTBoolean; 04536 } 04537 } else if (returnType2 & ~RTNoError & RTPeek) { 04538 return RTBoolean; 04539 } 04540 04541 comWriteWarning("argument types `%s' and `%s' don't match in `%s'", 04542 comReturnTypeToString(returnType1), 04543 comReturnTypeToString(returnType2), 04544 comFormulaTypeToString(formula)); 04545 break; 04546 case FTGreater: 04547 case FTLess: 04548 case FTGreaterEqual: 04549 case FTLessEqual: 04550 returnType1 = comReturnTypeOfTerm(formula->data.relation.op1); 04551 if (returnType1 == RTError) 04552 return RTError; 04553 returnType2 = comReturnTypeOfTerm(formula->data.relation.op2); 04554 if (returnType2 == RTError) 04555 return RTError; 04556 04557 if (returnType1 & ~RTNoError & (RTNumber | RTPeek)) { 04558 if (returnType2 & ~RTNoError & (RTNumber | RTPeek)) { 04559 if (returnType1 & RTNoError & returnType2 & ~RTPeek) { 04560 return RTBoolean | RTNoError; 04561 } else { 04562 return RTBoolean; 04563 } 04564 } 04565 } 04566 comWriteWarning("argument types `%s' and `%s' aren't numerical in `%s'", 04567 comReturnTypeToString(returnType1), 04568 comReturnTypeToString(returnType2), 04569 comFormulaTypeToString(formula)); 04570 break; 04571 case FTPredicate: 04572 return comReturnTypeOfPredicate( 04573 formula->data.predicate.functor, formula->data.predicate.args); 04574 } 04575 04576 return RTError; 04577 } 04578 04579 /* ---------------------------------------------------------------------------- 04580 * analyze the currently loaded grammar 04581 */ 04582 void comAnalyzeGrammar(void) 04583 { 04584 HashIterator hi = hashIteratorNew(inputCurrentGrammar->constraints); 04585 Constraint constraint; 04586 int depth; 04587 int maxStrings; 04588 04589 04590 /* compute the number of variables needed to evaluate all constraints */ 04591 com->maxValues = 0; 04592 while((constraint = hashIteratorNextValue(hi))) { 04593 depth = comConstraintDepth(constraint); 04594 if (depth > com->maxValues) { 04595 com->maxValues = depth; 04596 } 04597 } 04598 hashIteratorDelete(hi); 04599 04600 /* compute the max. number of strings used in 'lookup' functions */ 04601 hi = hashIteratorNew(inputCurrentGrammar->constraints); 04602 com->maxLookupStrings = 0; 04603 while((constraint = hashIteratorNextValue(hi))) { 04604 maxStrings = comMaxLookupStrings(constraint); 04605 if (maxStrings > com->maxLookupStrings) { 04606 com->maxLookupStrings = maxStrings; 04607 } 04608 } 04609 hashIteratorDelete(hi); 04610 } 04611 04612 /* ---------------------------------------------------------------------------- 04613 * compute the number of strings needed for evaluationg 'lookup' functions in 04614 * a constraint 04615 */ 04616 int comMaxLookupStrings(Constraint constraint) { 04617 int max1 = comMaxLookupStringsInTerm(constraint->penaltyTerm); 04618 int max2 = comMaxLookupStringsInFormula(constraint->formula); 04619 04620 return max(max1, max2); 04621 } 04622 04623 /* ---------------------------------------------------------------------------- 04624 * compute the number of strings needed for evaluationg 'lookup' functions in 04625 * a formla 04626 */ 04627 int comMaxLookupStringsInFormula(Formula formula) { 04628 int tmp1 = 0, tmp2 = 0; 04629 04630 switch (formula->type) { 04631 case FTConstant: 04632 case FTConnexion: 04633 case FTDirection: 04634 break; 04635 case FTNegation: 04636 tmp1 = comMaxLookupStringsInFormula(formula->data.formula); 04637 break; 04638 case FTConjunction: 04639 case FTDisjunction: 04640 case FTImplication: 04641 case FTBiimplication: 04642 tmp1 = comMaxLookupStringsInFormula(formula->data.junction.arg1); 04643 tmp2 = comMaxLookupStringsInFormula(formula->data.junction.arg2); 04644 break; 04645 case FTEqual: 04646 case FTNotEqual: 04647 case FTGreater: 04648 case FTLess: 04649 case FTGreaterEqual: 04650 case FTLessEqual: 04651 tmp1 = comMaxLookupStringsInTerm(formula->data.relation.op1); 04652 tmp2 = comMaxLookupStringsInTerm(formula->data.relation.op1); 04653 break; 04654 case FTPredicate: 04655 break; 04656 } 04657 04658 return max(tmp1, tmp2); 04659 } 04660 04661 /* ---------------------------------------------------------------------------- 04662 * compute the number of strings needed for evaluationg 'lookup' functions in 04663 * a term 04664 */ 04665 int comMaxLookupStringsInTerm(Term term) 04666 { 04667 int tmp1 = 0; 04668 List l; 04669 04670 if (term == NULL) 04671 return 0; 04672 04673 switch (term->type) { 04674 case TTTopPeek: 04675 case TTBottomPeek: 04676 case TTLabel: 04677 case TTLevel: 04678 case TTString: 04679 case TTNumber: 04680 case TTAdd: 04681 case TTSubtract: 04682 case TTMultiply: 04683 case TTDivide: 04684 case TTFunction: 04685 if (strcmp(term->data.function.functor, "lookup") == 0) { 04686 for (l = listNext(term->data.function.args); l != NULL; l = listNext(l)) { 04687 tmp1++; 04688 } 04689 } 04690 } 04691 04692 return tmp1; 04693 } 04694 04695 /* ---------------------------------------------------------------------------- 04696 * compute the number of variables needed to evaluate a constraint 04697 */ 04698 int comConstraintDepth(Constraint constraint) 04699 { 04700 int depth1 = comTermDepth(constraint->penaltyTerm); 04701 int depth2 = comFormulaDepth(constraint->formula); 04702 04703 return max(depth1, depth2); 04704 } 04705 04706 /* ---------------------------------------------------------------------------- 04707 * compute the number of variables needed to evaluate a formula 04708 */ 04709 int comFormulaDepth(Formula formula) 04710 { 04711 int maxDepth = 0, depth; 04712 04713 switch (formula->type) { 04714 case FTConstant: 04715 case FTConnexion: 04716 case FTDirection: 04717 break; 04718 case FTNegation: 04719 maxDepth = comFormulaDepth(formula->data.formula); 04720 break; 04721 case FTConjunction: 04722 case FTDisjunction: 04723 case FTImplication: 04724 maxDepth = comFormulaDepth(formula->data.junction.arg1); 04725 depth = comFormulaDepth(formula->data.junction.arg2); 04726 maxDepth = max(maxDepth, depth); 04727 break; 04728 case FTBiimplication: 04729 maxDepth = 04730 comFormulaDepth(formula->data.junction.arg1) + 04731 comFormulaDepth(formula->data.junction.arg2); 04732 break; 04733 case FTEqual: 04734 case FTNotEqual: 04735 case FTGreater: 04736 case FTLess: 04737 case FTGreaterEqual: 04738 case FTLessEqual: 04739 maxDepth = comTermDepth(formula->data.relation.op1); 04740 depth = comTermDepth(formula->data.relation.op2)+1; 04741 maxDepth = max(maxDepth, depth); 04742 break; 04743 case FTPredicate: 04744 maxDepth = comPredicateDepth(formula->data.predicate.functor, 04745 formula->data.predicate.args); 04746 break; 04747 } 04748 04749 return maxDepth; 04750 } 04751 04752 /* ---------------------------------------------------------------------------- 04753 * compute the number of variables needed to evaluate a function 04754 */ 04755 int comFunctionDepth(String functor, List args) 04756 { 04757 int maxDepth = 0; 04758 int depth; 04759 Term term; 04760 List l; 04761 04762 /* distance */ 04763 if (strcmp("distance", functor) == 0) { 04764 term = (Term)listNthElement(args, 1); 04765 maxDepth = comTermDepth(term); 04766 term = (Term)listNthElement(args, 2); 04767 depth = comTermDepth(term)+1; 04768 maxDepth = max(maxDepth, depth); 04769 } 04770 04771 /* abs */ 04772 else if (strcmp("abs", functor) == 0) { 04773 term = (Term)listNthElement(args, 1); 04774 maxDepth = comTermDepth(term); 04775 } 04776 04777 /* min, max */ 04778 else if (strcmp("min", functor) == 0 || 04779 strcmp("max", functor) == 0) { 04780 04781 term = (Term)listElement(args); 04782 maxDepth = comTermDepth(term); 04783 for (l = listNext(args); l != NULL; l = listNext(l)) { 04784 term = (Term)listElement(l); 04785 depth = comTermDepth(term)+1; 04786 maxDepth = max(maxDepth, depth); 04787 } 04788 } 04789 04790 /* match */ 04791 else if (strcmp("match", functor) == 0) { 04792 term = (Term)listNthElement(args, 1); 04793 maxDepth = comTermDepth(term); 04794 04795 term = (Term)listNthElement(args, 2); 04796 depth = comTermDepth(term); 04797 maxDepth = max(maxDepth, depth); 04798 04799 term = (Term)listNthElement(args, 3); 04800 depth = comTermDepth(term)+1; 04801 maxDepth = max(maxDepth, depth); 04802 } 04803 04804 /* parent */ 04805 else if (strcmp("parent", functor) == 0) { 04806 term = (Term)listNthElement(args, 1); 04807 maxDepth = comTermDepth(term) + 1; 04808 } 04809 04810 return maxDepth; 04811 } 04812 04813 /* ---------------------------------------------------------------------------- 04814 * compute the number of variables needed to evaluate a predicate 04815 */ 04816 int comPredicateDepth(String functor, List args) 04817 { 04818 int maxDepth = 0; 04819 int depth; 04820 Term term; 04821 List l; 04822 04823 /* start, stop, root, spec, nonspec */ 04824 if (strcmp("start", functor) == 0 || 04825 strcmp("stop", functor) == 0 || 04826 strcmp("spec", functor) == 0 || 04827 strcmp("nonspec", functor) == 0 || 04828 strcmp("nonspec", functor) == 0 || 04829 strcmp("root", functor) == 0) { 04830 term = (Term)listElement(args); 04831 maxDepth = comTermDepth(term); 04832 } 04833 04834 /* print */ 04835 else if (strcmp("print", functor) == 0) { 04836 for (l = args; l != NULL; l = listNext(l)) { 04837 term = (Term)listElement(l); 04838 depth = comTermDepth(term); 04839 maxDepth = max(maxDepth, depth); 04840 } 04841 } 04842 04843 /* exists */ 04844 else if (strcmp("exists", functor) == 0) { 04845 /* no variables needed */ 04846 } 04847 04848 /* subsumes */ 04849 else if (strcmp("subsumes", functor) == 0 || 04850 strcmp("compatible", functor) == 0) { 04851 04852 term = (Term)listNthElement(args, 1); 04853 depth = comTermDepth(term); 04854 maxDepth = max(maxDepth, depth); 04855 04856 term = (Term)listNthElement(args, 2); 04857 depth = comTermDepth(term); 04858 maxDepth = max(maxDepth, depth); 04859 04860 term = (Term)listNthElement(args, 3); 04861 depth = comTermDepth(term)+1; 04862 maxDepth = max(maxDepth, depth); 04863 } 04864 04865 return maxDepth; 04866 } 04867 04868 /* ---------------------------------------------------------------------------- 04869 * compute the number of variables needed to evaluate a term 04870 */ 04871 int comTermDepth(Term term) 04872 { 04873 int maxDepth = 0; 04874 int depth; 04875 04876 if (term == NULL) 04877 return 0; 04878 04879 switch (term->type) { 04880 case TTTopPeek: 04881 case TTBottomPeek: 04882 { 04883 String pathItem = (String) listElement(term->data.peek.path); 04884 if (strcmp("id", pathItem) == 0) { 04885 maxDepth = 0; 04886 } else { 04887 maxDepth = 1; 04888 } 04889 } 04890 break; 04891 case TTLabel: 04892 case TTLevel: 04893 case TTString: 04894 case TTNumber: 04895 maxDepth = 0; 04896 break; 04897 case TTAdd: 04898 case TTSubtract: 04899 case TTMultiply: 04900 case TTDivide: 04901 maxDepth = comTermDepth(term->data.operation.op1); 04902 depth = comTermDepth(term->data.operation.op2)+1; 04903 maxDepth = max(maxDepth, depth); 04904 break; 04905 case TTFunction: 04906 maxDepth = comFunctionDepth(term->data.function.functor, 04907 term->data.function.args); 04908 break; 04909 } 04910 04911 return maxDepth; 04912 } 04913 04914 /* ---------------------------------------------------------------------------- 04915 * comCompile: entry function to this package. 04916 * - translate the currently loaded cdg into C 04917 * - make a shared object out of it 04918 * - load it 04919 * 04920 * returns the name of the so file, NULL on failure 04921 */ 04922 String comCompile(int no, char **args) 04923 { 04924 Boolean isOk = TRUE; 04925 int i; 04926 String outfileName = NULL, sofilename = NULL; 04927 04928 /* construct a compiler instance */ 04929 com = comNew(); 04930 04931 /* parse the commandline */ 04932 for (i = 0; i < no && args[i] != NULL; i++) { 04933 if (args[i][0] == '-' && strlen(args[i]) > 1) { 04934 switch (args[i][1]) { 04935 case 'o': /* outfile */ 04936 outfileName = args[++i]; 04937 break; 04938 case 'c': /* compile only flag */ 04939 com->translateOnly = TRUE; 04940 break; 04941 case 'h': /* help */ 04942 case '?': 04943 cdgPrintf(CDG_DEFAULT, 04944 "\n" 04945 "syntax: compile [-o <filename>] [-c] [-h]\n" 04946 " -o <filename> : define an outputfile\n" 04947 " -c : translate only, dont compile + dont load \n" 04948 " -h : this message\n\n" 04949 "settings:\n" 04950 " CC : %s\n" 04951 " LD : %s\n" 04952 " CFLAGS : %s\n" 04953 " LDFLAGS : %s\n" 04954 " LDLIBS : %s\n" 04955 "INCLUDES : %s\n\n", 04956 makeInfo->cc, 04957 makeInfo->ld, 04958 makeInfo->cFlags, 04959 makeInfo->ldFlags, 04960 makeInfo->ldLibs, 04961 makeInfo->includes); 04962 isOk = FALSE; 04963 break; 04964 } 04965 } 04966 if (!isOk) { 04967 break; 04968 } 04969 } 04970 04971 /* check parameters */ 04972 if (isOk && listSize(inputCurrentGrammar->files) == 0) { 04973 cdgPrintf(CDG_ERROR, "ERROR: no files loaded\n"); 04974 isOk = FALSE; 04975 } 04976 /* if no filename was specified then generate a default one */ 04977 if (isOk && outfileName == NULL) { 04978 outfileName = basename((String) listElement(inputCurrentGrammar->files)); 04979 } 04980 04981 /* construct the needed filenames */ 04982 if (isOk) { 04983 String ext = strrchr(outfileName, '.'); 04984 04985 if (ext != NULL) { 04986 ext[0] = 0; 04987 } 04988 com->ccFileName = strAppend(outfileName, ".c", NULL); 04989 com->objFileName = strAppend(outfileName, ".o", NULL); 04990 /* the linker requires an absolut path */ 04991 com->soFileName = strAppend(dirname((String) listElement(inputCurrentGrammar->files)), 04992 "/", basename((String) listElement(inputCurrentGrammar->files)), ".so", NULL); 04993 com->ccFile = fopen(com->ccFileName, "w"); 04994 if (com->ccFile == NULL) { 04995 cdgPrintf(CDG_ERROR, "ERROR: cannot open file `%s'\n", com->ccFileName); 04996 isOk = FALSE; 04997 } 04998 } 04999 05000 /* translate, compile and load */ 05001 isOk = isOk && comTranslate(); 05002 if (isOk && com->ccFile) 05003 fclose(com->ccFile); 05004 if (isOk && (!com->translateOnly && comMake())) { 05005 sofilename = strRegister(com->soFileName); 05006 } else { 05007 sofilename = NULL; 05008 } 05009 05010 /* finalize the compiler */ 05011 comFree(com); 05012 return sofilename; 05013 } 05014 05015 /* ---------------------------------------------------------------------------- 05016 * initialize the compiler module 05017 */ 05018 void comInitialize(void) 05019 { 05020 /* build a default makeInfo */ 05021 makeInfo = comMakeInfoNew(); 05022 05023 /* these are some default values that should work for most of us */ 05024 makeInfo->cc = strRegister("gcc"); 05025 makeInfo->ld = strRegister("gcc"); 05026 makeInfo->cFlags = strRegister(CFLAGS); 05027 makeInfo->ldFlags = strPrintf("-shared " LDFLAGS); 05028 makeInfo->ldLibs = strRegister(LDLIBS); 05029 makeInfo->includes = strPrintf(INCLUDES); 05030 05031 /* register make variables */ 05032 setRegister("CC", SET_STRING, &makeInfo->cc, NULL, NULL, NULL, NULL); 05033 setRegister("LD", SET_STRING, &makeInfo->ld, NULL, NULL, NULL, NULL); 05034 setRegister("CFLAGS", SET_STRING, &makeInfo->cFlags, NULL, NULL, NULL, NULL); 05035 setRegister("LDFLAGS", SET_STRING, &makeInfo->ldFlags, NULL, NULL, NULL, NULL); 05036 setRegister("LDLIBS", SET_STRING, &makeInfo->ldLibs, NULL, NULL, NULL, NULL); 05037 setRegister("INCLUDES", SET_STRING, &makeInfo->includes, NULL, NULL, NULL, NULL); 05038 } 05039 05040 /* ---------------------------------------------------------------------------- 05041 * initialize a dll grammar 05042 */ 05043 Boolean comInitGrammar(Input thisInput) 05044 { 05045 Boolean (*thisInitGrammar)(); 05046 05047 if (thisInput->dllHandle == NULL) 05048 return TRUE; 05049 05050 /* get the init function of the dll grammar */ 05051 thisInitGrammar = (Boolean (*)())dlsym(thisInput->dllHandle, INIT_GRAMMAR); 05052 if (!thisInitGrammar) { 05053 cdgPrintf(CDG_ERROR, "ERROR: can't find function `%s': %s\n", 05054 INIT_GRAMMAR, dlerror()); 05055 return FALSE; 05056 } 05057 05058 /* initialize the dll grammar */ 05059 return (*thisInitGrammar) (thisInput); 05060 } 05061 05062 /* ---------------------------------------------------------------------------- 05063 * finalize a dll grammar 05064 */ 05065 void comFinitGrammar(Input thisInput) 05066 { 05067 void (*thisFinitGrammar)(Input); 05068 05069 if (thisInput->dllHandle == NULL) 05070 return; 05071 05072 thisFinitGrammar = (void (*)(Input))dlsym(thisInput->dllHandle, FINIT_GRAMMAR); 05073 05074 if (!thisFinitGrammar) { 05075 cdgPrintf(CDG_ERROR, "ERROR: can't find function `%s': `%s'\n", 05076 FINIT_GRAMMAR, dlerror()); 05077 } else { 05078 (*thisFinitGrammar)(thisInput); 05079 } 05080 dlclose(thisInput->dllHandle); 05081 thisInput->dllHandle = NULL; 05082 } 05083 05084 /* ---------------------------------------------------------------------------- 05085 * finalize the compiler module 05086 */ 05087 void comFinalize(void) 05088 { 05089 comMakeInfoFree(makeInfo); 05090 } 05091 /* ---------------------------------------------------------------------------- 05092 * allocate a new approver 05093 */ 05094 Approver comNewApprover(void) 05095 { 05096 Approver ap = (Approver)memMalloc(sizeof(ApproverStruct)); 05097 05098 ap->noRounds = 1; 05099 ap->timer = timerNew(); 05100 ap->totalInterpretedUnaryTime = 0; 05101 ap->totalCompiledUnaryTime = 0; 05102 ap->totalInterpretedBinaryTime = 0; 05103 ap->totalCompiledBinaryTime = 0; 05104 05105 return ap; 05106 } 05107 05108 /* ---------------------------------------------------------------------------- 05109 * free an approver 05110 */ 05111 void comFreeApprover(Approver ap) 05112 { 05113 if (ap == NULL) 05114 return; 05115 05116 timerFree(ap->timer); 05117 memFree(ap); 05118 } 05119 05120 /* ---------------------------------------------------------------------------- 05121 * find a lv using the same modifier-lexem, label and modifiee-lexem 05122 */ 05123 LevelValue comFindComparableLv(ConstraintNet net, LevelValue lv) 05124 { 05125 LevelValue testLv; 05126 int i; 05127 05128 for (i = 0; i < vectorSize(net->values); i++) { 05129 testLv = (LevelValue)vectorElement(net->values, i); 05130 if (( 05131 (lv->modifiee == NULL && testLv->modifiee == NULL) || 05132 (lv->modifiee == NONSPEC && testLv->modifiee == NONSPEC) || 05133 ( 05134 lv->modifiee != NULL && testLv->modifiee != NULL && 05135 lv->modifiee != NONSPEC && testLv->modifiee != NONSPEC && 05136 lv->modifiee->arc->from == testLv->modifiee->arc->from && 05137 lv->modifiee->arc->to == testLv->modifiee->arc->to && 05138 lv->modifiee->lexem->description == testLv->modifiee->lexem->description 05139 ) 05140 ) && 05141 lv->modifier->arc->from == testLv->modifier->arc->from && 05142 lv->modifier->arc->to == testLv->modifier->arc->to && 05143 lv->modifier->lexem->description == testLv->modifier->lexem->description && 05144 strcmp(lv->label, testLv->label) == 0 && 05145 lv->level == testLv->level) { 05146 return testLv; 05147 } 05148 } 05149 05150 return NULL; 05151 } 05152 05153 /* ---------------------------------------------------------------------------- 05154 * compare two levelvalues 05155 * returns TRUE if equal, else FALSE 05156 */ 05157 Boolean comCompareLvs(LevelValue lv1, LevelValue lv2) 05158 { 05159 Boolean isEqual = TRUE; 05160 List l; 05161 Constraint c1; 05162 05163 if (lv2 == NULL) { 05164 cdgPrintf(CDG_ERROR, "ERROR: value %d not found\n", lv1->indexWRTNet); 05165 return FALSE; 05166 } 05167 05168 /* compare position in net */ 05169 if (lv1->indexWRTNet != lv2->indexWRTNet) { 05170 cdgPrintf(CDG_ERROR, "WARNING: value is at position %d, should be at %d\n", 05171 lv2->indexWRTNet, lv1->indexWRTNet); 05172 } 05173 05174 /* compare modifier */ 05175 if (lv1->modifier->lexem->description != lv2->modifier->lexem->description) { 05176 cdgPrintf(CDG_ERROR, "ERROR: value %d uses a different lexem `%s' in modifier position, should be `%s'\n", 05177 lv2->indexWRTNet, lv2->modifier->lexem->description, 05178 lv1->modifier->lexem->description); 05179 isEqual = FALSE; 05180 } 05181 05182 /* compare modifiee */ 05183 if (lv1->modifiee == NULL) { 05184 if (lv2->modifiee != NULL) { 05185 cdgPrintf(CDG_ERROR, "ERROR: value %d should be NIL\n", lv2->indexWRTNet); 05186 isEqual = FALSE; 05187 } 05188 } else if (lv1->modifiee == NONSPEC) { 05189 if (lv2->modifiee != NONSPEC) { 05190 cdgPrintf(CDG_ERROR, "ERROR: value %d should be NONSPEC\n", lv2->indexWRTNet); 05191 isEqual = FALSE; 05192 } 05193 } 05194 05195 if (lv1->modifiee != NULL && lv1->modifiee != NONSPEC && 05196 lv2->modifiee != NULL && lv2->modifiee != NONSPEC && 05197 lv1->modifiee->lexem->description != lv2->modifiee->lexem->description) { 05198 cdgPrintf(CDG_ERROR, "ERROR: value %d uses a different lexem `%s' in modifiee position, should be `%s'\n", 05199 lv2->indexWRTNet, lv2->modifiee->lexem->description, 05200 lv1->modifiee->lexem->description); 05201 isEqual = FALSE; 05202 } 05203 05204 /* compare levels */ 05205 if (lv1->level != lv2->level) { 05206 cdgPrintf(CDG_ERROR, "ERROR: value %d uses a different level `%s', should be `%s'\n", 05207 lv2->indexWRTNet, lv2->level->id, lv1->level->id); 05208 isEqual = FALSE; 05209 } 05210 05211 /* compare labels */ 05212 if (strcmp(lv1->label, lv2->label) != 0) { 05213 cdgPrintf(CDG_ERROR, "ERROR: value %d uses a different label `%s', should be `%s'\n", 05214 lv2->indexWRTNet, lv2->label, lv1->label); 05215 isEqual = FALSE; 05216 } 05217 05218 /* compare score */ 05219 if (fabs(lv1->score - lv2->score) > 1e-10) { 05220 cdgPrintf(CDG_ERROR, "ERROR: value %d has a different score %4.3e, should be %4.3e\n", 05221 lv2->indexWRTNet, lv2->score, lv1->score); 05222 isEqual = FALSE; 05223 05224 cdgPrintf(CDG_ERROR, " conflicts:\n", lv2->indexWRTNet); 05225 for (l = lv2->constraints; l != NULL; l = listNext(l)) { 05226 c1 = (Constraint)listElement(l); 05227 cdgPrintf(CDG_ERROR, " %s\n", c1->id); 05228 } 05229 cdgPrintf(CDG_ERROR, "\n"); 05230 if (lv1->constraints == NULL) { 05231 cdgPrintf(CDG_ERROR, " should be none.\n"); 05232 } else { 05233 cdgPrintf(CDG_ERROR, " should be:\n"); 05234 for (l = lv1->constraints; l != NULL; l = listNext(l)) { 05235 c1 = (Constraint)listElement(l); 05236 cdgPrintf(CDG_ERROR, " %s\n", c1->id); 05237 } 05238 } 05239 } 05240 05241 if (!isEqual) { 05242 cdgPrintf(CDG_ERROR, "\nOrig:"); 05243 lvPrint(CDG_ERROR, lv1, NULL, 0); 05244 cdgPrintf(CDG_ERROR, "\nTest:"); 05245 lvPrint(CDG_ERROR, lv2, NULL, 0); 05246 cdgPrintf(CDG_ERROR, "\n"); 05247 #if 1 05248 cdgPrintf(CDG_ERROR, "Modifier %d:\n", lv2->modifier->no); 05249 printLexiconItem(CDG_ERROR, lv2->modifier->lexem); 05250 cdgPrintf(CDG_ERROR, "\n"); 05251 if (lv2->modifiee != NULL && lv2->modifiee != NONSPEC) { 05252 cdgPrintf(CDG_ERROR, "Modifiee %d:\n", lv2->modifiee->no); 05253 printLexiconItem(CDG_ERROR, lv2->modifiee->lexem); 05254 cdgPrintf(CDG_ERROR, "\n"); 05255 } 05256 #endif 05257 } 05258 05259 return isEqual; 05260 } 05261 05262 /* ---------------------------------------------------------------------------- 05263 * compare each levelvalue in both networks 05264 * returns TRUE if all are equal, else FALSE 05265 */ 05266 Boolean comCompareAllLvs(Approver ap, ConstraintNet net1, ConstraintNet net2) 05267 { 05268 LevelValue lv1, lv2; 05269 int i; 05270 Boolean hasEqualValues = TRUE; 05271 05272 /* compare all values, must be in same order */ 05273 if (vectorSize(net1->values) > vectorSize(net2->values)) { 05274 for (i = 0; i < vectorSize(net1->values) && hasEqualValues && !cdgCtrlCTrapped; i++) { 05275 lv1 = (LevelValue)vectorElement(net1->values, i); 05276 lv2 = comFindComparableLv(net2, lv1); 05277 05278 if (lv2 == NULL) { 05279 cdgPrintf(CDG_ERROR, "ERROR: lv %d not found in net\n", lv1->indexWRTNet); 05280 lvPrint(CDG_ERROR, lv1, NULL, 0); 05281 cdgPrintf(CDG_ERROR, "\n"); 05282 hasEqualValues = FALSE; 05283 } else { 05284 hasEqualValues &= comCompareLvs(lv1, lv2); 05285 } 05286 } 05287 } else { 05288 for (i = 0; i < vectorSize(net2->values) && hasEqualValues && !cdgCtrlCTrapped; i++) { 05289 lv2 = (LevelValue)vectorElement(net2->values, i); 05290 lv1 = comFindComparableLv(net1, lv2); 05291 if (lv1 == NULL) { 05292 cdgPrintf(CDG_ERROR, "ERROR: lv %d not found in net\n", lv2->indexWRTNet); 05293 lvPrint(CDG_ERROR, lv2, NULL, 0); 05294 cdgPrintf(CDG_ERROR, "\n"); 05295 hasEqualValues = FALSE; 05296 } else { 05297 hasEqualValues &= comCompareLvs(lv1, lv2); 05298 } 05299 } 05300 } 05301 05302 return hasEqualValues; 05303 } 05304 05305 /* ---------------------------------------------------------------------------- 05306 * compare each pair of levelvalues in both networks 05307 */ 05308 Boolean comCompareAllLvPairs(Approver ap, ConstraintNet net) 05309 { 05310 Boolean hasEqualValuePairs = TRUE; 05311 int i,j,n; 05312 List l; 05313 ConstraintViolation cv; 05314 LevelValue lv1, lv2; 05315 BadnessStruct bad1, bad2; 05316 List conflicts1 = NULL, conflicts2 = NULL; 05317 Number score1 = 1.0, score2 = 1.0; 05318 05319 /* check all value pairs */ 05320 for (i = 0; i < vectorSize(net->values) && hasEqualValuePairs && !cdgCtrlCTrapped; i++) { 05321 lv1 = (LevelValue)vectorRemoveElementAt(net->values, i); 05322 for (j = i+1; j < vectorSize(net->values) && hasEqualValuePairs && !cdgCtrlCTrapped; j++) { 05323 lv2 = (LevelValue)vectorElement(net->values, j); 05324 05325 /* refresh cache */ 05326 scDelete(net->cache); 05327 if (scUseCache) { 05328 net->cache = scNew(vectorSize(net->values)); 05329 } else { 05330 net->cache = NULL; 05331 } 05332 05333 /* interpreted grammar */ 05334 evalEvaluationMethod = EMTInterpreted; 05335 for (n = ap->noRounds; n > 0; n--) { 05336 listForEachDelete(conflicts1, cvDelete); 05337 conflicts1 = NULL; 05338 bad1.no = 0; 05339 bad1.hard = 0; 05340 bad1.soft = 1.0; 05341 timerStart(ap->timer); 05342 score1 = evalBinary(lv1, lv2, net, NULL, FALSE, &bad1, &conflicts1); 05343 ap->totalInterpretedBinaryTime += timerElapsed(ap->timer); 05344 } 05345 05346 /* refresh cache */ 05347 scDelete(net->cache); 05348 if (scUseCache) { 05349 net->cache = scNew(vectorSize(net->values)); 05350 } else { 05351 net->cache = NULL; 05352 } 05353 05354 /* compiled grammar */ 05355 evalEvaluationMethod = EMTCompiled; 05356 for (n = ap->noRounds; n > 0; n--) { 05357 listForEachDelete(conflicts2, cvDelete); 05358 conflicts2 = NULL; 05359 bad2.no = 0; 05360 bad2.hard = 0; 05361 bad2.soft = 1.0; 05362 timerStart(ap->timer); 05363 score2 = evalBinary(lv1, lv2, net, NULL, FALSE, &bad2, &conflicts2); 05364 ap->totalCompiledBinaryTime += timerElapsed(ap->timer); 05365 } 05366 05367 /* compare score */ 05368 if (fabs(score1 - score2) > 1e-10) { 05369 hasEqualValuePairs = FALSE; 05370 cdgPrintf(CDG_ERROR, "ERROR: score %4.3e differs, should be %4.3e\n", 05371 score2, score1); 05372 } 05373 05374 /* compare badness */ 05375 if (bad1.no == bad2.no && 05376 bad1.hard == bad2.hard && 05377 fabs(bad1.soft - bad2.soft) < 1e-10) { 05378 if (fabs(score1 - score2) > 1e-10) { 05379 cdgPrintf(CDG_ERROR, "ERROR: same badness with different score %4.3e, should be %4.3e\n", 05380 score2, score1); 05381 hasEqualValuePairs = FALSE; 05382 } 05383 } else { 05384 hasEqualValuePairs = FALSE; 05385 cdgPrintf(CDG_ERROR, "ERROR: badness (%d,%d,%4.3e) differs, ", 05386 bad2.no, bad2.hard, bad2.soft); 05387 cdgPrintf(CDG_ERROR, "should be (%d,%d,%4.3e)\n", 05388 bad1.no, bad1.hard, bad1.soft); 05389 } 05390 05391 /* show comparrison */ 05392 if (!hasEqualValuePairs) { 05393 List conflicts = listSort(conflicts1, cvCompare); 05394 listDelete(conflicts1); 05395 conflicts1 = conflicts; 05396 conflicts = listSort(conflicts2, cvCompare); 05397 listDelete(conflicts2); 05398 conflicts2 = conflicts; 05399 05400 cdgPrintf(CDG_ERROR, "violations:\n"); 05401 for (l = conflicts2; l != NULL; l = listNext(l)) { 05402 cv = (ConstraintViolation)listElement(l); 05403 if (cv->constraint->sig->arity == 1) { 05404 cdgPrintf(CDG_ERROR, " %s:%4.3e:%d\n", 05405 cv->constraint->id, cv->penalty, 05406 cv->lv1->indexWRTNet); 05407 } else { 05408 cdgPrintf(CDG_ERROR, "%s:%4.3e:%d:%d\n", 05409 cv->constraint->id, cv->penalty, 05410 cv->lv1->indexWRTNet, cv->lv2->indexWRTNet); 05411 } 05412 } 05413 cdgPrintf(CDG_ERROR, "should be:\n"); 05414 for (l = conflicts1; l != NULL; l = listNext(l)) { 05415 cv = (ConstraintViolation)listElement(l); 05416 if (cv->constraint->sig->arity == 1) { 05417 cdgPrintf(CDG_ERROR, " %s:%4.3e:%d\n", 05418 cv->constraint->id, cv->penalty, 05419 cv->lv1->indexWRTNet); 05420 } else { 05421 cdgPrintf(CDG_ERROR, "%s:%4.3e:%d:%d\n", 05422 cv->constraint->id, cv->penalty, 05423 cv->lv1->indexWRTNet, cv->lv2->indexWRTNet); 05424 } 05425 } 05426 } 05427 05428 /* more info */ 05429 if (!hasEqualValuePairs) { 05430 cdgPrintf(CDG_ERROR, "\nlattice: %s\n", lv1->modifier->lexemgraph->lattice->id); 05431 cdgPrintf(CDG_ERROR, "%03d: ", lv1->indexWRTNet); 05432 lvPrint(CDG_ERROR, lv1, NULL, 0); 05433 cdgPrintf(CDG_ERROR, "\n%03d: ", lv2->indexWRTNet); 05434 lvPrint(CDG_ERROR, lv2, NULL, 0); 05435 cdgPrintf(CDG_ERROR, "\n"); 05436 05437 #if 1 05438 cdgPrintf(CDG_ERROR, "\nModifier1:\n"); 05439 printLexiconItem(CDG_ERROR, lv1->modifier->lexem); 05440 cdgPrintf(CDG_ERROR, "\n"); 05441 cdgPrintf(CDG_ERROR, "Modifiee1:\n"); 05442 if (lv1->modifiee == NULL) { 05443 cdgPrintf(CDG_ERROR, "NIL\n"); 05444 } else if (lv1->modifiee == NONSPEC) { 05445 cdgPrintf(CDG_ERROR, "NONSPEC\n"); 05446 } else { 05447 printLexiconItem(CDG_ERROR, lv1->modifiee->lexem); 05448 cdgPrintf(CDG_ERROR, "\n"); 05449 } 05450 cdgPrintf(CDG_ERROR, "\nModifier2:\n"); 05451 printLexiconItem(CDG_ERROR, lv2->modifier->lexem); 05452 cdgPrintf(CDG_ERROR, "\n"); 05453 cdgPrintf(CDG_ERROR, "Modifiee2:\n"); 05454 if (lv2->modifiee == NULL) { 05455 cdgPrintf(CDG_ERROR, "NIL\n"); 05456 } else if (lv2->modifiee == NONSPEC) { 05457 cdgPrintf(CDG_ERROR, "NONSPEC\n"); 05458 } else { 05459 printLexiconItem(CDG_ERROR, lv2->modifiee->lexem); 05460 cdgPrintf(CDG_ERROR, "\n"); 05461 } 05462 #endif 05463 } 05464 } 05465 } 05466 05467 return hasEqualValuePairs; 05468 } 05469 05470 /* ---------------------------------------------------------------------------- 05471 * compare the nets after applying context_sensitive constraints 05472 */ 05473 Boolean comCompareWithContext(Approver ap, ConstraintNet net, List contextList) 05474 { 05475 Boolean hasEqualValuePairs = TRUE; 05476 int i,j,n; 05477 List l; 05478 ConstraintViolation cv; 05479 LevelValue lv1, lv2; 05480 BadnessStruct bad1, bad2; 05481 List conflicts1 = NULL, conflicts2 = NULL; 05482 Number score1 = 1.0, score2 = 1.0; 05483 Vector context; 05484 05485 while (contextList) { 05486 context = listElement(contextList); 05487 /* check all value pairs */ 05488 for (i = 0; i < vectorSize(net->values) && hasEqualValuePairs && !cdgCtrlCTrapped; i++) { 05489 lv1 = (LevelValue)vectorRemoveElementAt(net->values, i); 05490 for (j = i+1; j < vectorSize(net->values) && hasEqualValuePairs && !cdgCtrlCTrapped; j++) { 05491 lv2 = (LevelValue)vectorElement(net->values, j); 05492 05493 /* refresh cache */ 05494 scDelete(net->cache); 05495 if (scUseCache) { 05496 net->cache = scNew(vectorSize(net->values)); 05497 } else { 05498 net->cache = NULL; 05499 } 05500 05501 /* interpreted grammar */ 05502 evalEvaluationMethod = EMTInterpreted; 05503 for (n = ap->noRounds; n > 0; n--) { 05504 listForEachDelete(conflicts1, cvDelete); 05505 conflicts1 = NULL; 05506 bad1.no = 0; 05507 bad1.hard = 0; 05508 bad1.soft = 1.0; 05509 timerStart(ap->timer); 05510 score1 = evalBinary(lv1, lv2, net, context, TRUE, &bad1, &conflicts1); 05511 ap->totalInterpretedBinaryTime += timerElapsed(ap->timer); 05512 } 05513 05514 /* refresh cache */ 05515 scDelete(net->cache); 05516 if (scUseCache) { 05517 net->cache = scNew(vectorSize(net->values)); 05518 } else { 05519 net->cache = NULL; 05520 } 05521 05522 /* compiled grammar */ 05523 evalEvaluationMethod = EMTCompiled; 05524 for (n = ap->noRounds; n > 0; n--) { 05525 listForEachDelete(conflicts2, cvDelete); 05526 conflicts2 = NULL; 05527 bad2.no = 0; 05528 bad2.hard = 0; 05529 bad2.soft = 1.0; 05530 timerStart(ap->timer); 05531 score2 = evalBinary(lv1, lv2, net, context, TRUE, &bad2, &conflicts2); 05532 ap->totalCompiledBinaryTime += timerElapsed(ap->timer); 05533 } 05534 05535 /* compare score */ 05536 if (fabs(score1 - score2) > 1e-10) { 05537 hasEqualValuePairs = FALSE; 05538 cdgPrintf(CDG_ERROR, "ERROR: score %4.3e differs, should be %4.3e\n", 05539 score2, score1); 05540 } 05541 05542 /* compare badness */ 05543 if (bad1.no == bad2.no && 05544 bad1.hard == bad2.hard && 05545 fabs(bad1.soft - bad2.soft) < 1e-10) { 05546 if (fabs(score1 - score2) > 1e-10) { 05547 cdgPrintf(CDG_ERROR, "ERROR: same badness with different score %4.3e, should be %4.3e\n", 05548 score2, score1); 05549 hasEqualValuePairs = FALSE; 05550 } 05551 } else { 05552 hasEqualValuePairs = FALSE; 05553 cdgPrintf(CDG_ERROR, "ERROR: badness (%d,%d,%4.3e) differs, ", 05554 bad2.no, bad2.hard, bad2.soft); 05555 cdgPrintf(CDG_ERROR, "should be (%d,%d,%4.3e)\n", 05556 bad1.no, bad1.hard, bad1.soft); 05557 } 05558 05559 /* show comparrison */ 05560 if (!hasEqualValuePairs) { 05561 List conflicts = listSort(conflicts1, cvCompare); 05562 listDelete(conflicts1); 05563 conflicts1 = conflicts; 05564 conflicts = listSort(conflicts2, cvCompare); 05565 listDelete(conflicts2); 05566 conflicts2 = conflicts; 05567 05568 cdgPrintf(CDG_ERROR, "violations:\n"); 05569 for (l = conflicts2; l != NULL; l = listNext(l)) { 05570 cv = (ConstraintViolation)listElement(l); 05571 if (cv->constraint->sig->arity == 1) { 05572 cdgPrintf(CDG_ERROR, " %s:%4.3e:%d\n", 05573 cv->constraint->id, cv->penalty, 05574 cv->lv1->indexWRTNet); 05575 } else { 05576 cdgPrintf(CDG_ERROR, "%s:%4.3e:%d:%d\n", 05577 cv->constraint->id, cv->penalty, 05578 cv->lv1->indexWRTNet, cv->lv2->indexWRTNet); 05579 } 05580 } 05581 cdgPrintf(CDG_ERROR, "should be:\n"); 05582 for (l = conflicts1; l != NULL; l = listNext(l)) { 05583 cv = (ConstraintViolation)listElement(l); 05584 if (cv->constraint->sig->arity == 1) { 05585 cdgPrintf(CDG_ERROR, " %s:%4.3e:%d\n", 05586 cv->constraint->id, cv->penalty, 05587 cv->lv1->indexWRTNet); 05588 } else { 05589 cdgPrintf(CDG_ERROR, "%s:%4.3e:%d:%d\n", 05590 cv->constraint->id, cv->penalty, 05591 cv->lv1->indexWRTNet, cv->lv2->indexWRTNet); 05592 } 05593 } 05594 } 05595 05596 /* more info */ 05597 if (!hasEqualValuePairs) { 05598 cdgPrintf(CDG_ERROR, "\nlattice: %s\n", lv1->modifier->lexemgraph->lattice->id); 05599 cdgPrintf(CDG_ERROR, "%03d: ", lv1->indexWRTNet); 05600 lvPrint(CDG_ERROR, lv1, NULL, 0); 05601 cdgPrintf(CDG_ERROR, "\n%03d: ", lv2->indexWRTNet); 05602 lvPrint(CDG_ERROR, lv2, NULL, 0); 05603 cdgPrintf(CDG_ERROR, "\n"); 05604 05605 #if 1 05606 cdgPrintf(CDG_ERROR, "\nModifier1:\n"); 05607 printLexiconItem(CDG_ERROR, lv1->modifier->lexem); 05608 cdgPrintf(CDG_ERROR, "\n"); 05609 cdgPrintf(CDG_ERROR, "Modifiee1:\n"); 05610 if (lv1->modifiee == NULL) { 05611 cdgPrintf(CDG_ERROR, "NIL\n"); 05612 } else if (lv1->modifiee == NONSPEC) { 05613 cdgPrintf(CDG_ERROR, "NONSPEC\n"); 05614 } else { 05615 printLexiconItem(CDG_ERROR, lv1->modifiee->lexem); 05616 cdgPrintf(CDG_ERROR, "\n"); 05617 } 05618 cdgPrintf(CDG_ERROR, "\nModifier2:\n"); 05619 printLexiconItem(CDG_ERROR, lv2->modifier->lexem); 05620 cdgPrintf(CDG_ERROR, "\n"); 05621 cdgPrintf(CDG_ERROR, "Modifiee2:\n"); 05622 if (lv2->modifiee == NULL) { 05623 cdgPrintf(CDG_ERROR, "NIL\n"); 05624 } else if (lv2->modifiee == NONSPEC) { 05625 cdgPrintf(CDG_ERROR, "NONSPEC\n"); 05626 } else { 05627 printLexiconItem(CDG_ERROR, lv2->modifiee->lexem); 05628 cdgPrintf(CDG_ERROR, "\n"); 05629 } 05630 #endif 05631 } 05632 } 05633 } 05634 contextList = listNext(contextList); 05635 } 05636 05637 return hasEqualValuePairs; 05638 } 05639 05640 /* ---------------------------------------------------------------------------- 05641 * compare two constraint networks 05642 */ 05643 Boolean comCompareNets(Approver ap, ConstraintNet net1, ConstraintNet net2) 05644 { 05645 Boolean hasEqualNets = TRUE; 05646 int noConflicts1, noConflicts2; 05647 int i, j, maxNumberOfContexts = 20; 05648 LevelValue lv, lValue; 05649 List net1ContextList = NULL; 05650 Vector context; 05651 ConstraintNode node; 05652 05653 /* compare number of values */ 05654 if (vectorSize(net1->values) != vectorSize(net2->values)) { 05655 cdgPrintf(CDG_ERROR, "ERROR: net has %d lvs, should be %d lvs\n", 05656 vectorSize(net2->values), vectorSize(net1->values)); 05657 hasEqualNets = FALSE; 05658 } 05659 05660 /* compare no conflicts */ 05661 noConflicts1 = 0; 05662 for (i = 0; i < vectorSize(net1->values); i++) { 05663 lv = (LevelValue)vectorElement(net1->values, i); 05664 noConflicts1 += listSize(lv->constraints); 05665 } 05666 noConflicts2 = 0; 05667 for (i = 0; i < vectorSize(net2->values); i++) { 05668 lv = (LevelValue)vectorElement(net2->values, i); 05669 noConflicts2 += listSize(lv->constraints); 05670 } 05671 if (noConflicts1 != noConflicts2) { 05672 cdgPrintf(CDG_ERROR, "ERROR: net has %d %s conflicts\n", 05673 abs(noConflicts1 - noConflicts2), 05674 (noConflicts1 < noConflicts2)?"more":"fewer"); 05675 } 05676 05677 /* build a list of contexts for net1 */ 05678 for (i = 0; i < maxNumberOfContexts; i++) { 05679 context = vectorNew(vectorSize(net1->nodes)); 05680 vectorSetAllElements(context, NULL); 05681 for (j = 0; j < vectorSize(net1->nodes); j++) { 05682 node = vectorElement(net1->nodes, j); 05683 lValue = vectorElement(node->values, i % vectorSize(node->values)); 05684 vectorSetElement(context, lValue, lvIndex(lValue)); 05685 } 05686 net1ContextList = listAppendElement(net1ContextList, context); 05687 } 05688 05689 hasEqualNets = comCompareAllLvs(ap, net1, net2) && 05690 comCompareAllLvPairs(ap, net1) && 05691 comCompareWithContext(ap, net1, net1ContextList) && 05692 hasEqualNets; 05693 05694 return hasEqualNets; 05695 } 05696 05697 /* ---------------------------------------------------------------------------- 05698 * approve a compiled grammar 05699 */ 05700 void comApprove(int no, char **args) 05701 { 05702 Approver ap; 05703 Lattice lattice; 05704 ConstraintNet net1, net2; 05705 int i = 0, noLattices; 05706 Boolean hasEqualNets = TRUE; 05707 Boolean isAtty = isatty(fileno(stdout)); 05708 unsigned long oldVerbosity = hkVerbosity; 05709 EvalMethodType oldEvaluationMethod = evalEvaluationMethod; 05710 List l; 05711 05712 cdgCtrlCAllowed = TRUE; 05713 cdgCtrlCTrapped = FALSE; 05714 // hkVerbosity &= ~(CDG_INFO | CDG_DEBUG | CDG_PROFILE); 05715 05716 if (inputCurrentGrammar == NULL) { 05717 cdgPrintf(CDG_ERROR, "ERROR: no grammar loaded\n"); 05718 return; 05719 } 05720 if (inputCurrentGrammar->dllHandle == NULL) { 05721 cdgPrintf(CDG_ERROR, "ERROR: no dll grammar loaded\n"); 05722 return; 05723 } 05724 05725 ap = comNewApprover(); 05726 noLattices = listSize(inputCurrentGrammar->lattices); 05727 05728 /* 05729 * build constraint nets for each available lattice 05730 */ 05731 cdgPrintf(CDG_DEFAULT, "\n"); 05732 for(l = inputCurrentGrammar->lattices; 05733 l != NULL && hasEqualNets && !cdgCtrlCTrapped; 05734 l = listNext(l)) { 05735 lattice = listElement(l); 05736 05737 05738 /* 05739 * build networks and eval binary 05740 */ 05741 05742 /* interpreted grammar */ 05743 evalEvaluationMethod = EMTInterpreted; 05744 timerStart(ap->timer); 05745 net1 = cnBuild(lattice, TRUE); 05746 hashSet(cdgNets, net1->id, net1); 05747 ap->totalInterpretedUnaryTime += timerElapsed(ap->timer); 05748 if (!net1) { 05749 cdgPrintf(CDG_WARNING, "WARNING: cannot build net for lattice `%s'\n", lattice->id); 05750 continue; 05751 } 05752 05753 /* compiled grammar */ 05754 evalEvaluationMethod = EMTCompiled; 05755 timerStart(ap->timer); 05756 net2 = cnBuild(lattice, TRUE); 05757 hashSet(cdgNets, net2->id, net2); 05758 ap->totalCompiledUnaryTime += timerElapsed(ap->timer); 05759 if (!net2) { 05760 cdgPrintf(CDG_WARNING, "WARNING: cannot build net for lattice `%s'\n", lattice->id); 05761 cnDelete(net1); 05762 continue; 05763 } 05764 05765 /* compare the two nets */ 05766 hasEqualNets = comCompareNets(ap, net1, net2); 05767 05768 cdgPrintf(CDG_DEFAULT, "%s(%03d/%03d) %s: %lums:%lums:%lums vs. %lums:%lums:%lums, speedup %4.2f:%4.2f:%4.2f%s", 05769 isAtty?"\r":"", 05770 i+1, noLattices, lattice->id, 05771 ap->totalInterpretedUnaryTime, 05772 ap->totalInterpretedBinaryTime, 05773 ap->totalInterpretedUnaryTime+ap->totalInterpretedBinaryTime, 05774 ap->totalCompiledUnaryTime, 05775 ap->totalCompiledBinaryTime, 05776 ap->totalCompiledUnaryTime+ap->totalCompiledBinaryTime, 05777 ap->totalInterpretedUnaryTime / (0.0 + ap->totalCompiledUnaryTime), 05778 ap->totalInterpretedBinaryTime / (0.0 + ap->totalCompiledBinaryTime), 05779 (ap->totalInterpretedUnaryTime + ap->totalInterpretedBinaryTime) / 05780 ( 0.0 + ap->totalCompiledUnaryTime + ap->totalCompiledBinaryTime), 05781 isAtty?"":"\n"); 05782 cdgFlush(); 05783 05784 /* clean up in each loop */ 05785 /* 05786 cnDelete(net1); 05787 cnDelete(net2); 05788 */ 05789 05790 } 05791 05792 cdgPrintf(CDG_DEFAULT, "\n"); 05793 comFreeApprover(ap); 05794 05795 cdgCtrlCTrapped = cdgCtrlCAllowed = FALSE; 05796 hkVerbosity = oldVerbosity; 05797 evalEvaluationMethod = oldEvaluationMethod; 05798 } 05799 #if 0 05800 /* ------------------------------------------------------------------------- 05801 * build a constraint net and evaluate a constraint on two levelvalues. 05802 * compare the results of this operation with a compiled vs. an evaluated 05803 * constraint 05804 * arguments are: 1. net, 2. lv1Index, 3. lv2Index, 4. constraintId 05805 */ 05806 void comAnalyzeConstraint(int no, char **args) { 05807 int constrain 05808 int lv1Index = 05809 05810 05811 05812 if (inputCurrentGrammar == NULL) { 05813 cdgPrintf(CDG_ERROR, "ERROR: no grammar loaded\n"); 05814 return; 05815 } 05816 if (inputCurrentGrammar->dllHandle == NULL) { 05817 cdgPrintf(CDG_ERROR, "ERROR: no dll grammar loaded\n"); 05818 return; 05819 } 05820 05821 05822 05823 05824 evalEvaluationMethod = EMTInterpreted; 05825 05826 05827 05828 05829 05830 evalEvaluationMethod = EMTCompiled; 05831 05832 05833 } 05834 #endif 05835 05836 05837 /* ------------------------------------------------------------------------- */ 05838 /* -- ENDOFFILE ------------------------------------------------------------ */ 05839 /** @} */

CDG 0.95 (20 Oct 2004)