34 namespace PgfInternals {
    37 #define PGFINTERNALS_DECLARE_TYPEINFO(type, typeclass) \    39   DYNGENPAR_DECLARE_TYPEINFO(PgfInternals::type, typeclass); \    40   namespace PgfInternals {    45 class HaskellDataStream {
    47     enum Status {Ok, ReadPastEnd, ReadCorruptData, IOError};
    48     HaskellDataStream(QIODevice *d) : iodevice(d), m_status(Ok), m_version(0),
    50     bool atEnd()
 const {
return iodevice->atEnd();}
    51     QIODevice *device()
 const {
return iodevice;}
    52     void setStatus (Status status) {m_status = status;}
    53     Status status()
 const {
return m_status;}
    56     unsigned short version() {
return m_version;}
    57     unsigned short minorVersion() {
return m_minorVersion;}
    63     HaskellDataStream &
operator>>(QByteArray &bytes);
    68     unsigned char nextUChar() {
return (
unsigned char) nextChar();}
    73     unsigned short m_version;
    74     unsigned short m_minorVersion;
    76 PGFINTERNALS_DECLARE_TYPEINFO(HaskellDataStream, Q_MOVABLE_TYPE);
    77 PGFINTERNALS_DECLARE_TYPEINFO(HaskellDataStream::Status,
    80 char HaskellDataStream::nextChar()
    82   if (m_status != Ok) 
return 0;
    83   if (iodevice->atEnd()) {
    84     m_status = ReadPastEnd;
    88   if (!iodevice->getChar(&c)) {
    96 void HaskellDataStream::readVersion()
    98   unsigned char c1 = nextUChar();
    99   unsigned char c2 = nextUChar();
   100   m_version = (c1 << 8) + c2;
   101   if (m_version != 1 && m_version != 2 && m_status == Ok)
   102     m_status = ReadCorruptData;
   105   m_minorVersion = (c1 << 8) + c2;
   106   if (((m_version == 1 && m_minorVersion)
   107        || (m_version == 2 && m_minorVersion > 1))
   108       && m_status == Ok) m_status = ReadCorruptData;
   113   unsigned char c = nextUChar();
   115     m_status = ReadCorruptData;
   132   unsigned char c = nextUChar();
   133   unsigned u = c & 0x7Fu;
   138     u |= (c & 0x7Fu) << (shift += 7u);
   149   unsigned char c1 = nextUChar();
   150   unsigned char c2 = nextUChar();
   151   bool negative = (c1 & 0x80);
   152   int exponent = (((c1 & 0x7f) << 4) + (c2 >> 4));
   153   unsigned char c3 = nextUChar();
   154   unsigned char c4 = nextUChar();
   155   unsigned char c5 = nextUChar();
   156   unsigned char c6 = nextUChar();
   157   unsigned char c7 = nextUChar();
   158   unsigned char c8 = nextUChar();
   163   exponent -= (1023 + 52);
   164   unsigned long long mantissa = (1ull << 52)
   165                                 + ((
unsigned long long) (c2 & 0xf) << 48)
   166                                 + ((
unsigned long long) c3 << 40)
   167                                 + ((
unsigned long long) c4 << 32)
   168                                 + ((
unsigned long long) c5 << 24)
   169                                 + ((
unsigned long long) c6 << 16)
   170                                 + ((
unsigned long long) c7 << 8)
   171                                 + (
unsigned long long) c8;
   173   d = std::ldexp((
double) mantissa, exponent);
   174   if (negative) d = -d;
   181   bytes = QByteArray();
   187     m_status = ReadCorruptData;
   191   for (
int i=0; i<len; i++) {
   192     bytes.append(nextChar());
   204     m_status = ReadCorruptData;
   212   for (
int i=0; i<len; i++) {
   215     if (c >= 0) 
continue;
   217       m_status = ReadCorruptData;
   227           m_status = ReadCorruptData;
   233     for (
int j=0; j<n; j++) {
   235       if ((c & 0xc0) != 0x80) {
   236         m_status = ReadCorruptData;
   244   s = QString::fromUtf8(bytes);
   250 HaskellDataStream &
operator>>(HaskellDataStream &stream, QVariant &v)
   278       stream.setStatus(HaskellDataStream::ReadCorruptData);
   286 template <
typename T1, 
typename T2> HaskellDataStream
   287   &
operator>>(HaskellDataStream &stream, QPair<T1, T2> &p)
   289   return (stream >> p.first >> p.second);
   292 template <
typename T> HaskellDataStream &
operator>>(HaskellDataStream &stream,
   299     stream.setStatus(HaskellDataStream::ReadCorruptData);
   304   for (
int i=0; i<n; i++) {
   313 template <
typename T1, 
typename T2> HaskellDataStream
   314   &
operator>>(HaskellDataStream &stream, QHash<T1, T2> &h)
   320     stream.setStatus(HaskellDataStream::ReadCorruptData);
   325   for (
int i=0; i<n; i++) {
   330     h.insert(key, value);
   339 PGFINTERNALS_DECLARE_TYPEINFO(Type, Q_PRIMITIVE_TYPE);
   341 HaskellDataStream &
operator>>(HaskellDataStream &stream, Type &dummy);
   346 PGFINTERNALS_DECLARE_TYPEINFO(Hypo, Q_PRIMITIVE_TYPE);
   348 HaskellDataStream &
operator>>(HaskellDataStream &stream, Hypo &dummy);
   353 PGFINTERNALS_DECLARE_TYPEINFO(Expr, Q_PRIMITIVE_TYPE);
   355 HaskellDataStream &
operator>>(HaskellDataStream &, Expr &)
   357   qFatal(
"dependent types not supported");
   360 HaskellDataStream &
operator>>(HaskellDataStream &stream, Type &)
   365   return (stream >> hypos >> cat >> exps);
   368 HaskellDataStream &
operator>>(HaskellDataStream &stream, Hypo &)
   373   return (stream >> bindtype >> cat >> type);
   379 PGFINTERNALS_DECLARE_TYPEINFO(Equation, Q_PRIMITIVE_TYPE);
   381 HaskellDataStream &
operator>>(HaskellDataStream &, Equation &)
   383   qFatal(
"dependent types not supported");
   389 PGFINTERNALS_DECLARE_TYPEINFO(AbsFun, Q_PRIMITIVE_TYPE);
   391 HaskellDataStream &
operator>>(HaskellDataStream &stream, AbsFun &)
   396   stream >> type >> arity >> haveEquations;
   402   return (stream >> probability);
   409 PGFINTERNALS_DECLARE_TYPEINFO(AbsCat, Q_MOVABLE_TYPE);
   411 HaskellDataStream &
operator>>(HaskellDataStream &stream, AbsCat &absCat)
   413   if (stream.version() >= 2) {
   415     return (stream >> absCat.context >> absCat.functions >> probability);
   416   } 
else return (stream >> absCat.context >> absCat.functions);
   420   enum SymType {
Cat, Lit, Var, KS, KP, BIND, SOFT_BIND, NE, SOFT_SPACE, CAPIT,
   421                 ALL_CAPIT, Invalid = -1};
   427 PGFINTERNALS_DECLARE_TYPEINFO(Symbol, Q_MOVABLE_TYPE);
   428 PGFINTERNALS_DECLARE_TYPEINFO(Symbol::SymType, Q_PRIMITIVE_TYPE);
   430 HaskellDataStream &
operator>>(HaskellDataStream &stream, Symbol &symbol)
   436     case (
int) Symbol::Lit:
   437     case (
int) Symbol::Var:
   438       stream >> symbol.n >> symbol.l;
   440     case (
int) Symbol::KS:
   441       if (stream.version() >= 2) {
   444         symbol.tokens = QStringList(token);
   445       } 
else stream >> symbol.tokens;
   447     case (
int) Symbol::KP:
   448       if (stream.version() >= 2) {
   450         typedef QPair<QList<Symbol>, QStringList> SymAlternative;
   452         stream >> symbols >> symAlternatives;
   453         symbol.tokens.clear();
   454         foreach (
const Symbol &sym, symbols) {
   455           if (sym.symtype == Symbol::KS) {
   456             symbol.tokens << sym.tokens;
   458             qFatal(
"non-token symbols in pre prefixes not supported");
   461         symbol.alternatives.clear();
   462         foreach (
const SymAlternative &symAlternative, symAlternatives) {
   463           QPair<QStringList, QStringList> alternative;
   464           foreach (
const Symbol & sym, symAlternative.first) {
   465             switch (sym.symtype) {
   466               case (
int) Symbol::KS:
   467                 alternative.first << sym.tokens;
   469               case (
int) Symbol::BIND:
   472               case (
int) Symbol::SOFT_BIND:
   473               case (
int) Symbol::SOFT_SPACE:
   474               case (
int) Symbol::CAPIT:
   475               case (
int) Symbol::ALL_CAPIT:
   479                 qFatal(
"non-token, non-bind symbols in pre not supported");
   482           alternative.second = symAlternative.second;
   483           symbol.alternatives << alternative;
   485       } 
else stream >> symbol.tokens >> symbol.alternatives;
   487     case (
int) Symbol::BIND:
   488     case (
int) Symbol::SOFT_BIND:
   489     case (
int) Symbol::NE:
   490       if (stream.version() >= 2) 
break; 
else goto corrupt;
   491     case (
int) Symbol::SOFT_SPACE:
   492     case (
int) Symbol::CAPIT:
   493     case (
int) Symbol::ALL_CAPIT:
   494       if (stream.version() > 2
   495           || (stream.version() == 2 && stream.minorVersion() >= 1)) 
break;
   499       stream.setStatus(HaskellDataStream::ReadCorruptData);
   503   symbol.symtype = (Symbol::SymType) symtype;
   512 PGFINTERNALS_DECLARE_TYPEINFO(CncFun, Q_MOVABLE_TYPE);
   514 HaskellDataStream &
operator>>(HaskellDataStream &stream, CncFun &cncfun)
   516   return (stream >> cncfun.fun >> cncfun.lins);
   523 PGFINTERNALS_DECLARE_TYPEINFO(PArg, Q_PRIMITIVE_TYPE);
   525 HaskellDataStream &
operator>>(HaskellDataStream &stream, PArg &parg)
   530     qFatal(
"dependent types not supported");
   532   return (stream >> parg.fid);
   540 PGFINTERNALS_DECLARE_TYPEINFO(Production, Q_MOVABLE_TYPE);
   542 HaskellDataStream &
operator>>(HaskellDataStream &stream, Production &production)
   544   stream >> production.isCoercion >> production.id;
   546   if (!production.isCoercion)
   547     stream >> production.args;
   556 PGFINTERNALS_DECLARE_TYPEINFO(CncCat, Q_MOVABLE_TYPE);
   558 HaskellDataStream &
operator>>(HaskellDataStream &stream, CncCat &cnccat)
   560   return (stream >> cnccat.s >> cnccat.e >> cnccat.labels);
   564   QHash<QByteArray, QVariant> cflags;
   565   QHash<QByteArray, QString> printnames;
   568   QHash<int, QList<int> > lindefs;
   569   QHash<int, QList<Production> > productions;
   570   QHash<QByteArray, CncCat> cnccats;
   573 PGFINTERNALS_DECLARE_TYPEINFO(Concr, Q_MOVABLE_TYPE);
   575 HaskellDataStream &
operator>>(HaskellDataStream &stream, Concr &concrete)
   577   if (stream.version() >= 2) {
   578     QHash<int, QList<int> > linrefs; 
   579     return (stream >> concrete.cflags >> concrete.printnames
   580                    >> concrete.sequences >> concrete.cncfuns >> concrete.lindefs
   581                    >> linrefs >> concrete.productions >> concrete.cnccats
   582                    >> concrete.totalCats);
   584     return (stream >> concrete.cflags >> concrete.printnames
   585                    >> concrete.sequences >> concrete.cncfuns >> concrete.lindefs
   586                    >> concrete.productions >> concrete.cnccats
   587                    >> concrete.totalCats);
   602 Pgf::Pgf(
const QString &fileName, 
const QString &concreteName)
   604   using namespace PgfInternals;
   607   static const int CAT_OFFSET = 6;
   610   QFile file(fileName);
   611   file.open(QIODevice::ReadOnly);
   612   HaskellDataStream stream(&file);
   614 #define CHECK_STATUS() if (stream.status() != HaskellDataStream::Ok) \   615                          qFatal("invalid PGF file or wrong version of GF")   617   stream.readVersion();
   620   QHash<QByteArray, QVariant> gflags;
   628   QHash<QByteArray, QVariant> aflags;
   632   QHash<QByteArray, AbsFun> funs;
   636   QHash<QByteArray, AbsCat> cats;
   640   QHash<QByteArray, Concr> concretes;
   644   if (!stream.atEnd()) qFatal(
"invalid PGF file or wrong version of GF");
   648   if (concretes.isEmpty())
   649     qFatal(
"invalid PGF file or wrong version of GF");
   652   if (concreteName.isEmpty()) {
   653     if (concretes.size() > 1)
   654       qFatal(
"must specify the name of the concrete grammar");
   655     QHashIterator<QByteArray, Concr> it(concretes);
   656     concrete = it.next().value();
   658     QByteArray concreteName8Bit = concreteName.toLocal8Bit();
   659     if (!concretes.contains(concreteName8Bit))
   660       qFatal(
"concrete grammar '%s' not found in PGF file",
   661              concreteName8Bit.data());
   662     concrete = concretes.value(concreteName8Bit);
   666   if (!aflags.contains(
"startcat")) qFatal(
"no start category specified");
   667   QByteArray startcatName = aflags.value(
"startcat").toString().toLocal8Bit();
   668   CncCat startcat = concrete.cnccats.value(startcatName);
   669   if (startcat.s != startcat.e)
   670     qFatal(
"start category '%s' has parameters", startcatName.data());
   671   pmcfg.startCat = startcat.s + CAT_OFFSET;
   674   catNames << 
"EPSILON" << 
"LEX_ERROR";
   675   while (catNames.size() < concrete.totalCats + CAT_OFFSET)
   676     catNames.append(QString());
   678     QHashIterator<QByteArray, CncCat> it(concrete.cnccats);
   679     while (it.hasNext()) {
   680       CncCat cnccat = it.next().value();
   681       QString cat = QString::fromLocal8Bit(it.key());
   682       for (
int i=cnccat.s; i<=cnccat.e; i++)
   683         catNames[i + CAT_OFFSET] = cat;
   684       componentNames.insert(cat, cnccat.labels);
   689   for (
int i=2; i<CAT_OFFSET; i++) pmcfg.tokens.insert(i);
   693   typedef QPair<QString, int> PrefixMatch;
   694   typedef QPair<int, QList<PrefixMatch> > PrefixInfo;
   697   foreach (
const QList<Symbol> &gfsequence, concrete.sequences) {
   699     bool isSuffix = 
false;
   700     foreach (
const Symbol &symbol, gfsequence) {
   701       switch (symbol.symtype) {
   706             qWarning(
"ignoring unsupported use of Prelude.Bind (only suffix "   707                      "tokens supported)");
   710           sequence.append(
Term(symbol.n, symbol.l));
   714             QStringList tokens = symbol.tokens;
   715             foreach (
const QString &token, tokens) {
   718                   qWarning(
"ignoring duplicate Prelude.Bind");
   723                 typedef QPair<QString, int> Suffix;
   725                 foreach (
const Suffix &suffix, suffixes) {
   726                   if (suffix.first == token) {
   732                   id = catNames.size();
   733                   catNames.append(QString(
PreludeBind) + 
' ' + token);
   734                   suffixes.append(qMakePair(token, 
id));
   735                   pmcfg.tokens.insert(
id);
   743                 QStringList splitTokens;
   744                 if (token.endsWith(
'.') && token != 
".") {
   745                   QString choppedToken = token;
   746                   choppedToken.chop(1);
   747                   splitTokens.append(choppedToken);
   748                   splitTokens.append(
".");
   749                 } 
else splitTokens.append(token);
   750                 foreach (
const QString &splitToken, splitTokens) {
   751                   if (tokenHash.contains(splitToken))
   752                     sequence.append(tokenHash.value(splitToken));
   754                     int id = catNames.size();
   755                     catNames.append(splitToken);
   756                     tokenHash.insert(splitToken, 
id);
   757                     pmcfg.tokens.insert(
id);
   768               qWarning(
"ignoring unsupported use of Prelude.Bind (only suffix "   769                        "tokens supported)");
   775             uniqueAlternatives.append(symbol.tokens);
   777             typedef QPair<QStringList, QStringList> PreAlternative;
   779             foreach (
const PreAlternative &alternative, symbol.alternatives) {
   780               int index = uniqueAlternatives.indexOf(alternative.first);
   782                 QString &constraintName = catNames[constraintIds[index-1]];
   783                 constraintName.append(
'|');
   784                 constraintName.append(alternative.second.join(
"*|"));
   785                 constraintName.append(
'*');
   786               } 
else if (index < 0) {
   787                 index = uniqueAlternatives.size();
   788                 uniqueAlternatives.append(alternative.first);
   789                 constraintIds.append(catNames.size());
   790                 catNames.append(alternative.second.join(
"*|")+
'*');
   792               foreach (
const QString &prefix, alternative.second)
   793                 info.append(qMakePair(prefix, index));
   795             QStringList uniqueAlternativeNames;
   796             foreach (
const QStringList &uniqueAlternative, uniqueAlternatives)
   797               uniqueAlternativeNames.append(uniqueAlternative.join(
" "));
   798             QString name = 
"pre {" + uniqueAlternativeNames.join(
"; ") + 
'}';
   799             int id = catNames.size();
   800             catNames.append(name);
   803             foreach (
const QStringList &uniqueAlternative, uniqueAlternatives) {
   805               foreach (
const QString &token, uniqueAlternative) {
   807                   qWarning(
"ignoring unsupported use of Prelude.Bind in pre");
   810                 if (tokenHash.contains(token))
   811                   rule.append(tokenHash.value(token));
   813                   int tokenId = catNames.size();
   814                   catNames.append(token);
   815                   tokenHash.insert(token, tokenId);
   816                   pmcfg.tokens.insert(tokenId);
   817                   rule.append(tokenId);
   822               cfRules.append(rule);
   824             pmcfg.cfRules[id] = cfRules;
   826             prefixInfo.append(qMakePair(
id, info));
   831             qWarning(
"ignoring duplicate Prelude.Bind");
   834         case Symbol::SOFT_BIND: 
   835         case Symbol::SOFT_SPACE: 
   837         case Symbol::ALL_CAPIT: 
   844             nonExistCat = catNames.size();
   845             catNames.append(
"nonExist");
   847           sequence.append(nonExistCat);
   851           qFatal(
"invalid symbol");
   855       qWarning(
"ignoring unsupported use of Prelude.Bind (only suffix tokens "   857     sequences.append(sequence);
   861   foreach (
const PrefixInfo &info, prefixInfo) {
   863     Rule &defaultRule = cfRules.first();
   864     int s = cfRules.size();
   865     QHashIterator<QString, int> it(tokenHash);
   866     while (it.hasNext()) {
   868       const QString &token = it.key();
   869       if (token.startsWith(
'$') || token.startsWith(
'`')) {
   871         const int &tokenId = it.value();
   872         for (
int i=1; i<s; i++)
   873           pmcfg.cfRules[cfRules[i].nextTokenConstraints.expect.first()]
   874             .append(
Rule() << tokenId);
   877         foreach (
const PrefixMatch &prefix, info.second) {
   878           if (token.startsWith(prefix.first)) {
   879             ruleno = prefix.second;
   884           const int &tokenId = it.value();
   885           pmcfg.cfRules[cfRules[ruleno].nextTokenConstraints.expect.first()]
   886             .append(
Rule() << tokenId);
   894   QHash<QString, int> coercionFunctions;
   896     QHashIterator<int, QList<int> > it (concrete.lindefs);
   897     while (it.hasNext()) {
   899       if (lindefs.size() != 1) qFatal(
"expected exactly 1 lindef per category");
   900       QString cat = catNames.at(it.key() + CAT_OFFSET);
   901       coercionFunctions.insert(cat, lindefs.first());
   909   int numFunctions = concrete.cncfuns.size();
   910   for (; i<numFunctions; i++) {
   911     const CncFun &cncfun = concrete.cncfuns.at(i);
   912     QString name = QString::fromLocal8Bit(cncfun.fun);
   913     if (!name.startsWith(
"lindef ")) {
   917     int dim = cncfun.lins.size();
   919     for (
int j=0; j<dim; j++)
   921     pmcfg.functions.append(
function);
   922     functionNames.append(name.replace(
"lindef ", 
"coerce "));
   927   for (; i<numFunctions; i++) {
   928     const CncFun &cncfun = concrete.cncfuns.at(i);
   930     foreach (
int lin, cncfun.lins) 
function.append(sequences.at(lin));
   931     pmcfg.functions.append(
function);
   932     functionNames.append(QString::fromLocal8Bit(cncfun.fun));
   938     QHash<int, int> coercions;
   939     QHashIterator<int, QList<Production> > it (concrete.productions);
   940     while (it.hasNext()) {
   942       int lhs = it.key() + CAT_OFFSET;
   943       foreach (
const Production &production, productions)
   944         if (production.isCoercion) {
   945           int rhs = production.id + CAT_OFFSET;
   946           if (!coercions.contains(lhs) || rhs < coercions.value(lhs))
   947             coercions.insert(lhs, rhs);
   950     it = concrete.productions;
   951     while (it.hasNext()) {
   953       int lhs = it.key() + CAT_OFFSET;
   955       foreach (
const Production &production, productions) {
   956         if (production.isCoercion) {
   957           int cat = production.id + CAT_OFFSET;
   958           QString catName = catNames.at(cat);
   960           while (catName.isEmpty()
   961                  || catName.endsWith(
"(coerced)")) {
   962             if (!coercions.contains(cat))
   963               qFatal(
"failed to look up real category for C%d", production.id);
   964             cat = coercions.value(cat);
   965             catName = catNames.at(cat);
   967           QString catNameCoerced = catName + 
"(coerced)";
   968           catNames[lhs] = catNameCoerced;
   969           if (!componentNames.contains(catNameCoerced))
   970             componentNames.insert(catNameCoerced,
   971                                   componentNames.value(catName));
   972           Rule rule(coercionFunctions.value(catName));
   976           Rule rule(production.id);
   977           foreach (PArg parg, production.args)
   978             rule.append(parg.fid + CAT_OFFSET);
   990       return new PgfLexerStateData(*
this);
   997 DYNGENPAR_DECLARE_TYPEINFO(PgfLexerStateData, Q_MOVABLE_TYPE);
  1003     PgfTokenSource(
Pgf *p)
  1004       : 
TokenSource(), pgf_p(p), stream(
new QFile()), inFormula(
false),
  1006       {
static_cast<QFile *
>(stream)->open(stdin, QIODevice::ReadOnly);}
  1007     virtual ~PgfTokenSource() {
delete stream;}
  1009     virtual bool matchParseTree(
const Node &treeToMatch) {
  1010       return (treeToMatch.
cat == tree.cat) && (treeToMatch.
data == tree.data);
  1012     virtual bool rewindTo(
int pos,
  1017       if (stream->isSequential() || (pos && lexerState.isNull()))
  1019       else if (!pos && currPos) { 
  1024         if (pos != currPos) {
  1025           const PgfLexerStateData *data
  1026             = 
static_cast<const PgfLexerStateData *
>(lexerState.data());
  1027           if (!stream->seek(data->streamPos)) {
  1031           inFormula = data->inFormula;
  1032           pastFormula = data->pastFormula;
  1033           suffixes = data->suffixes;
  1035         return simpleRewind(pos);
  1041       if (stream->isSequential()) 
return LexerState();
  1042       PgfLexerStateData *data = 
new PgfLexerStateData;
  1043       data->streamPos = stream->pos();
  1044       data->inFormula = inFormula;
  1045       data->pastFormula = pastFormula;
  1046       data->suffixes = suffixes;
  1049     void setInputStdin() {
  1051       stream = 
new QFile();
  1052       static_cast<QFile *
>(stream)->open(stdin, QIODevice::ReadOnly);
  1055     void setInputFile(
const QString &fileName) {
  1057       stream = 
new QFile(fileName);
  1058       stream->open(QIODevice::ReadOnly);
  1061     void setInputBytes(
const QByteArray &bytes) {
  1063       stream = 
new QBuffer();
  1064       static_cast<QBuffer *
>(stream)->setData(bytes);
  1065       stream->open(QIODevice::ReadOnly);
  1068     void setInputString(
const QString &
string) {
  1069       setInputBytes(
string.toLocal8Bit());
  1071     void setInputBuffer(QByteArray *buffer) {
  1073       stream = 
new QBuffer(buffer);
  1074       stream->open(QIODevice::ReadOnly);
  1078     virtual Cat readToken();
  1083       inFormula = pastFormula = 
false;
  1092 DYNGENPAR_DECLARE_TYPEINFO(PgfTokenSource, Q_MOVABLE_TYPE);
  1094 static bool isTextChar(
char c)
  1096   return (c >= 
'a' && c <= 
'z')
  1097          || (c >= 
'A' && c <= 
'Z')
  1099          || c == 
'_' || c == 
'\'' || c == 
'\\';
  1102 Cat PgfTokenSource::readToken()
  1107   if (!suffixes.isEmpty())
  1108     return suffixes.takeFirst();
  1113   QByteArray tokenBytes;
  1117       if (stream->atEnd()) 
break; 
  1122         stream->ungetChar(c);
  1125       tokenBytes.append(c);
  1127         if (stream->atEnd()) 
break; 
  1131         tokenBytes.append(c);
  1135     tree.data = QString::fromLocal8Bit(tokenBytes.data()).trimmed();
  1142   bool continueLoop = 
true;
  1143   bool isNumber = 
false;
  1144   while (continueLoop) {
  1148         if (std::isspace(c)) {
  1150         } 
else if (isTextChar(c)
  1151                    || (pastFormula && c == 
'$')) {
  1152           pastFormula = 
false;
  1153           tokenBytes.append(c);
  1155           if (stream->atEnd()) continueLoop = 
false; 
  1156         } 
else if (c == 
'$') {
  1158           tokenBytes.append(c);
  1159           continueLoop = 
false;
  1160         } 
else if (c == 
'-') {
  1161           tokenBytes.append(c);
  1163           if (stream->atEnd()) continueLoop = 
false; 
  1164         } 
else if (c >= 
'0' && c <= 
'9') {
  1165           tokenBytes.append(c);
  1168           if (stream->atEnd()) continueLoop = 
false; 
  1170           tokenBytes.append(c);
  1171           continueLoop = 
false;
  1175         if (isTextChar(c) || c == 
'-' || (c >= 
'0' && c <= 
'9')) {
  1176           tokenBytes.append(c);
  1177           if (stream->atEnd()) continueLoop = 
false; 
  1179           stream->ungetChar(c);
  1180           continueLoop = 
false;
  1185           tokenBytes.append(c);
  1186           if (stream->atEnd()) continueLoop = 
false; 
  1187         } 
else if (isTextChar(c)) {
  1188           tokenBytes.append(c);
  1190           if (stream->atEnd()) continueLoop = 
false; 
  1191         } 
else if (c >= 
'0' && c <= 
'9') {
  1192           tokenBytes.append(c);
  1195           if (stream->atEnd()) continueLoop = 
false; 
  1197           stream->ungetChar(c);
  1198           continueLoop = 
false;
  1202         if ((c >= 
'0' && c <= 
'9') || c == 
'e' || c == 
'-') {
  1203           tokenBytes.append(c);
  1204           if (stream->atEnd()) continueLoop = 
false; 
  1205         } 
else if (c == 
'.') { 
  1206           if (stream->atEnd()) { 
  1207             stream->ungetChar(c);
  1208             continueLoop = 
false;
  1212             if (c2 >= 
'0' && c2 <= 
'9') 
  1213               tokenBytes.append(c);
  1215               stream->ungetChar(c);
  1216               continueLoop = 
false;
  1220           stream->ungetChar(c);
  1221           continueLoop = 
false;
  1227   QString tokenString = QString::fromLocal8Bit(tokenBytes.data());
  1229     if (tokenString.contains(
'.') || tokenString.contains(
'e')) { 
  1231       double d = tokenString.toDouble(&ok);
  1238       int i = tokenString.toInt(&ok);
  1254     if (pgf_p->tokenHash.contains(tokenString))
  1255       token = pgf_p->tokenHash.value(tokenString);
  1258       QString tokenStringLower = tokenString;
  1259       tokenStringLower[0] = tokenStringLower[0].toLower();
  1260       if (pgf_p->tokenHash.contains(tokenStringLower))
  1261         token = pgf_p->tokenHash.value(tokenStringLower);
  1263         QString tokenStringChopped = tokenString;
  1265           typedef QPair<QString, int> Suffix;
  1266           bool suffixMatched = 
false;
  1267           foreach (
const Suffix &suffix, pgf_p->suffixes) {
  1268             if (tokenStringChopped.endsWith(suffix.first)) {
  1269               suffixMatched = 
true;
  1270               suffixes.prepend(suffix.second);
  1271               int suffixLen = suffix.first.size();
  1272               tokenStringChopped.chop(suffixLen);
  1273               tokenStringLower.chop(suffixLen);
  1277           if (!suffixMatched) 
break;
  1278           if (tokenStringChopped.isEmpty()) 
  1280             token = suffixes.takeFirst();
  1281           if (pgf_p->tokenHash.contains(tokenStringChopped))
  1282             token = pgf_p->tokenHash.value(tokenStringChopped);
  1283           else if (pgf_p->tokenHash.contains(tokenStringLower))
  1284             token = pgf_p->tokenHash.value(tokenStringLower);
  1291           tree.data = tokenString;
  1305       : 
Parser(new PgfTokenSource(&
pgf)), 
pgf(fileName, concreteName)
  1348                                                .at(component.second));
  1350         return QString(
"%1[%2]").arg(name).arg(component.second);
  1351     } 
else return QString::number(cat); 
  1357   for (
int i=0; i<tree.
children.size(); ) {
  1359     QVariant label = child.
label();
  1361       tree.
children.append(child.first().children);
  1366   for (
int i=0; i<s; i++) {
  1368     int l = child.size();
  1369     for (
int j=0; j<l; j++)
 
void setInputString(const QString &string)
 
QDataStream & operator>>(QDataStream &stream, DynGenPar::Action *&data)
 
QHash< Cat, QPair< Cat, int > > componentCats
maps categories which represent components of a multi-component category to the category and componen...
 
void setInputBytes(const QByteArray &bytes)
 
representation of the information in .pgf files in a format we can process 
 
QList< Cat > expect
list of context-free categories the next token MUST match 
 
QString Cat
Category type: string or integer depending on DYNGENPAR_INTEGER_CATEGORIES. 
 
QStringList catNames
names of categories, in general not unique 
 
term in the expression of a component of a PMCFG function 
 
component of a PMCFG function, a sequence of terms 
 
QHash< QString, QStringList > componentNames
names of category components 
 
QString catName(int cat) const
 
void setInputFile(const QString &fileName)
 
QList< Cat > taboo
list of context-free categories the next token MUST NOT match 
 
virtual bool rewindTo(int pos, const LexerState &=LexerState())
rewind to an older position (requires buffering) 
 
TokenSource * inputSource
input source 
 
int firstFunction
the function ID of the first non-coercion function 
 
API for stateful lexers to save their state for rewinding. 
 
void setInputBuffer(QByteArray *buffer)
 
void filterCoercionsFromSyntaxTree(Node &tree) const
 
QHash< Cat, QPair< Cat, QList< Cat > > > pseudoCats
pseudo-categories, used to represent PMCFGs internally 
 
Pgf()
dummy default constructor for bindings 
 
NextTokenConstraints nextTokenConstraints
 
QList< Alternative > children
 
STATIC const char *const PreludeBind