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