Пример #1
0
void skipComments(Lexer &Lex, Token &Tok) {
  while (Tok.is(tok::comment))
    if (Lex.LexFromRawLexer(Tok))
      return;
}
Пример #2
0
void Template::Format::readFormat(Lexer & lex)
{
	enum {
		FO_PRODUCT = 1,
		FO_UPDATEFORMAT,
		FO_UPDATERESULT,
		FO_REQUIREMENT,
		FO_OPTION,
		FO_PREAMBLE,
		FO_TRANSFORMCOMMAND,
		FO_TRANSFORMOPTION,
		FO_REFERENCEDFILE,
		FO_END
	};

	LexerKeyword formattags[] = {
		{ "formatend", FO_END },
		{ "option", FO_OPTION },
		{ "preamble", FO_PREAMBLE },
		{ "product", FO_PRODUCT },
		{ "referencedfile", FO_REFERENCEDFILE },
		{ "requirement", FO_REQUIREMENT },
		{ "transformcommand", FO_TRANSFORMCOMMAND },
		{ "transformoption", FO_TRANSFORMOPTION },
		{ "updateformat", FO_UPDATEFORMAT },
		{ "updateresult", FO_UPDATERESULT }
	};

	PushPopHelper pph(lex, formattags);

	while (lex.isOK()) {
		switch (lex.lex()) {
		case FO_PRODUCT:
			lex.next(true);
			product = lex.getString();
			break;

		case FO_UPDATEFORMAT:
			lex.next(true);
			updateFormat = lex.getString();
			break;

		case FO_UPDATERESULT:
			lex.next(true);
			updateResult = lex.getString();
			break;

		case FO_REQUIREMENT:
			lex.next(true);
			requirements.push_back(lex.getString());
			break;

		case FO_PREAMBLE:
			lex.next(true);
			preambleNames.push_back(lex.getString());
			break;

		case FO_TRANSFORMCOMMAND: {
			lex.next(true);
			string const name = lex.getString();
			lex.next(true);
			setCommandFactory(*this, name, lex.getString());
			break;
		}

		case FO_TRANSFORMOPTION: {
			lex.next(true);
			string const name = lex.getString();
			lex.next(true);
			setOptionFactory(*this, name, lex.getString());
			break;
		}

		case FO_OPTION: {
			lex.next(true);
			string const name = lex.getString();
			lex.next(true);
			string const opt = lex.getString();
			options.push_back(Option(name, opt));
			break;
		}

		case FO_REFERENCEDFILE: {
			lex.next(true);
			string const format = lex.getString();
			lex.next(true);
			string const file = lex.getString();
			referencedFiles[format].push_back(file);
			break;
		}

		case FO_END:
			return;
		}
	}
}
Пример #3
0
void Layout::readLabelType(Lexer & lex)
{
	enum {
		LA_NO_LABEL = 1,
		LA_MANUAL,
		LA_ABOVE,
		LA_CENTERED,
		LA_STATIC,
		LA_SENSITIVE,
		LA_ENUMERATE,
		LA_ITEMIZE,
		LA_BIBLIO
	};


	LexerKeyword labelTypeTags[] = {
	  { "above",        LA_ABOVE },
		{ "bibliography", LA_BIBLIO },
		{ "centered",     LA_CENTERED },
		{ "enumerate",    LA_ENUMERATE },
		{ "itemize",      LA_ITEMIZE },
		{ "manual",       LA_MANUAL },
		{ "no_label",     LA_NO_LABEL },
		{ "sensitive",    LA_SENSITIVE },
		{ "static",       LA_STATIC }
	};

	PushPopHelper pph(lex, labelTypeTags);
	int le = lex.lex();
	switch (le) {
	case Lexer::LEX_UNDEF:
		lex.printError("Unknown labeltype tag `$$Token'");
		return;
	default: break;
	}
	switch (le) {
	case LA_NO_LABEL:
		labeltype = LABEL_NO_LABEL;
		break;
	case LA_MANUAL:
		labeltype = LABEL_MANUAL;
		break;
	case LA_ABOVE:
		labeltype = LABEL_ABOVE;
		break;
	case LA_CENTERED:
		labeltype = LABEL_CENTERED;
		break;
	case LA_STATIC:
		labeltype = LABEL_STATIC;
		break;
	case LA_SENSITIVE:
		labeltype = LABEL_SENSITIVE;
		break;
	case LA_ENUMERATE:
		labeltype = LABEL_ENUMERATE;
		break;
	case LA_ITEMIZE:
		labeltype = LABEL_ITEMIZE;
		break;
	case LA_BIBLIO:
		labeltype = LABEL_BIBLIO;
		break;
	}
}
Пример #4
0
double Calculator::prim(Lexer& lexer)
{
    Token tok = lexer.peek();
    switch(tok.Type)
    {
    case Token::FUNC:
        lexer.pop();
        return func(lexer);
    case Token::NUMBER:
        return lexer.pop().NumberValue;
    case Token::NAME:
    {
        string name = tok.StringValue;
        lexer.pop();
        if(lexer.peek().Type == Token::LP)
        {
            lexer.pop();
            return call(lexer, name);
        }
        else if (lexer.peek().Type == Token::ASSIGN)
        {
            lexer.pop();
            SymEntry* sym = symbols.Get(name);
            if(sym && sym->type != SymEntry::VAR) throw Error::SyntaxError("not a variable: "+name);
            double v = expr(lexer);
            symbols.Set(name, new SymVariable(v));
            return v;
        }
        else
        {
            SymEntry* sym = symbols.Get(name);
            if(!sym) throw Error::SyntaxError("undefined symbol: "+name);
            if(sym->type != SymEntry::VAR) throw Error::SyntaxError("not a variable: "+name);
            SymVariable* sVar = static_cast<SymVariable*>(sym);
            return sVar->value;
        }
    }
    case Token::MINUS:
        lexer.pop();
        return -prim(lexer);
    case Token::LP:
    {
        lexer.pop();
        double e = expr(lexer);
        Token tok = lexer.pop();
        if(tok.Type != Token::RP) throw Error::SyntaxError("')' expected");
        return e;
    }
    default:
        throw Error::SyntaxError("primary expected");
    }
}
Пример #5
0
// Expand __has_include and __has_include_next if possible. If there's no
// definitive answer return false.
bool InclusionRewriter::HandleHasInclude(
    FileID FileId, Lexer &RawLex, const DirectoryLookup *Lookup, Token &Tok,
    bool &FileExists) {
  // Lex the opening paren.
  RawLex.LexFromRawLexer(Tok);
  if (Tok.isNot(tok::l_paren))
    return false;

  RawLex.LexFromRawLexer(Tok);

  SmallString<128> FilenameBuffer;
  StringRef Filename;
  // Since the raw lexer doesn't give us angle_literals we have to parse them
  // ourselves.
  // FIXME: What to do if the file name is a macro?
  if (Tok.is(tok::less)) {
    RawLex.LexFromRawLexer(Tok);

    FilenameBuffer += '<';
    do {
      if (Tok.is(tok::eod)) // Sanity check.
        return false;

      if (Tok.is(tok::raw_identifier))
        PP.LookUpIdentifierInfo(Tok);

      // Get the string piece.
      SmallVector<char, 128> TmpBuffer;
      bool Invalid = false;
      StringRef TmpName = PP.getSpelling(Tok, TmpBuffer, &Invalid);
      if (Invalid)
        return false;

      FilenameBuffer += TmpName;

      RawLex.LexFromRawLexer(Tok);
    } while (Tok.isNot(tok::greater));

    FilenameBuffer += '>';
    Filename = FilenameBuffer;
  } else {
    if (Tok.isNot(tok::string_literal))
      return false;

    bool Invalid = false;
    Filename = PP.getSpelling(Tok, FilenameBuffer, &Invalid);
    if (Invalid)
      return false;
  }

  // Lex the closing paren.
  RawLex.LexFromRawLexer(Tok);
  if (Tok.isNot(tok::r_paren))
    return false;

  // Now ask HeaderInfo if it knows about the header.
  // FIXME: Subframeworks aren't handled here. Do we care?
  bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename);
  const DirectoryLookup *CurDir;
  const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
      Filename, SourceLocation(), isAngled, nullptr, CurDir,
      PP.getSourceManager().getFileEntryForID(FileId), nullptr, nullptr,
      nullptr, false);

  FileExists = File != nullptr;
  return true;
}
Пример #6
0
		bool	Parser::parseExpression (Lexer& lexer, Lookup& lookup, Int32u* slot, const Extractor** output)
		{
			BinaryOp				binaryOp;
			stack<BinaryOp>			binaryOps;
			stack<const Extractor*>	operands;
			const Extractor*		value;

			while (true)
			{
				switch (lexer.getType ())
				{
					case Lexer::PLUS:
						lexer.next ();

						if (!this->parseExpression (lexer, lookup, slot, &value))
							return false;

						break;

					case Lexer::MINUS:
						lexer.next ();

						if (!this->parseExpression (lexer, lookup, slot, &value))
							return false;

						value = new NumberUnaryExtractor (value, [] (Float64 number)
						{
							return Variant (-number);
						});

						this->extractors.push_back (value);

						break;

					case Lexer::NOT:
						lexer.next ();

						if (!this->parseExpression (lexer, lookup, slot, &value))
							return false;

						value = new BooleanUnaryExtractor (value, [] (bool value)
						{
							return Variant (!value);
						});

						this->extractors.push_back (value);

						break;

					case Lexer::PARENTHESIS_BEGIN:
						lexer.next ();

						if (!this->parseExpression (lexer, lookup, slot, &value) ||
						    !this->parseType (lexer, Lexer::PARENTHESIS_END, "closing parenthesis"))
							return false;

						break;

					default:
						if (!this->parseValue (lexer, lookup, slot, &value))
							return false;

						break;
				}

				operands.push (value);

				switch (lexer.getType ())
				{
					case Lexer::AMPERSAND:
						binaryOp = make_pair (1, [] (const Extractor* lhs, const Extractor* rhs) -> Extractor*
						{
							return new AndLogicalExtractor (lhs, rhs);
						});

						break;

					case Lexer::DIFFERENT:
						binaryOp = make_pair (2, [] (const Extractor* lhs, const Extractor* rhs) -> Extractor*
						{
							return new VariantBinaryExtractor (lhs, rhs, [] (const Variant& a, const Variant& b)
							{
								return Variant (a != b);
							});
						});

						break;

					case Lexer::DIVIDE:
						binaryOp = make_pair (4, [] (const Extractor* lhs, const Extractor* rhs) -> Extractor*
						{
							return new NumberBinaryExtractor (lhs, rhs, [] (Float64 a, Float64 b)
							{
								return b != 0 ? Variant (a / b) : Variant::empty;
							});
						});

						break;

					case Lexer::EQUAL:
						binaryOp = make_pair (2, [] (const Extractor* lhs, const Extractor* rhs) -> Extractor*
						{
							return new VariantBinaryExtractor (lhs, rhs, [] (const Variant& a, const Variant& b)
							{
								return Variant (a == b);
							});
						});

						break;

					case Lexer::GREATER_EQUAL:
						binaryOp = make_pair (2, [] (const Extractor* lhs, const Extractor* rhs) -> Extractor*
						{
							return new VariantBinaryExtractor (lhs, rhs, [] (const Variant& a, const Variant& b)
							{
								return Variant (a >= b);
							});
						});

						break;

					case Lexer::GREATER_THAN:
						binaryOp = make_pair (2, [] (const Extractor* lhs, const Extractor* rhs) -> Extractor*
						{
							return new VariantBinaryExtractor (lhs, rhs, [] (const Variant& a, const Variant& b)
							{
								return Variant (a > b);
							});
						});

						break;

					case Lexer::LOWER_EQUAL:
						binaryOp = make_pair (2, [] (const Extractor* lhs, const Extractor* rhs) -> Extractor*
						{
							return new VariantBinaryExtractor (lhs, rhs, [] (const Variant& a, const Variant& b)
							{
								return Variant (a <= b);
							});
						});

						break;

					case Lexer::LOWER_THAN:
						binaryOp = make_pair (2, [] (const Extractor* lhs, const Extractor* rhs) -> Extractor*
						{
							return new VariantBinaryExtractor (lhs, rhs, [] (const Variant& a, const Variant& b)
							{
								return Variant (a < b);
							});
						});

						break;

					case Lexer::MINUS:
						binaryOp = make_pair (3, [] (const Extractor* lhs, const Extractor* rhs) -> Extractor*
						{
							return new NumberBinaryExtractor (lhs, rhs, [] (Float64 a, Float64 b)
							{
								return Variant (a - b);
							});
						});

						break;

					case Lexer::MODULO:
						binaryOp = make_pair (4, [] (const Extractor* lhs, const Extractor* rhs) -> Extractor*
						{
							return new NumberBinaryExtractor (lhs, rhs, [] (Float64 a, Float64 b)
							{
								return b != 0 ? Variant (fmod (a, b)) : Variant::empty;
							});
						});

						break;

					case Lexer::MULTIPLY:
						binaryOp = make_pair (4, [] (const Extractor* lhs, const Extractor* rhs) -> Extractor*
						{
							return new NumberBinaryExtractor (lhs, rhs, [] (Float64 a, Float64 b)
							{
								return Variant (a * b);
							});
						});

						break;

					case Lexer::PIPE:
						binaryOp = make_pair (1, [] (const Extractor* lhs, const Extractor* rhs) -> Extractor*
						{
							return new OrLogicalExtractor (lhs, rhs);
						});

						break;

					case Lexer::PLUS:
						binaryOp = make_pair (3, [] (const Extractor* lhs, const Extractor* rhs) -> Extractor*
						{
							return new NumberBinaryExtractor (lhs, rhs, [] (Float64 a, Float64 b)
							{
								return Variant (a + b);
							});
						});

						break;

					default:
						for (; !binaryOps.empty (); binaryOps.pop ())
						{
							value = operands.top ();

							operands.pop ();

							value = binaryOps.top ().second (operands.top (), value);

							operands.pop ();
							operands.push (value);

							this->extractors.push_back (value);
						}

						if (operands.top ()->getFlags () == 0)
							return this->fail (lexer, "inconsistent expression");

						*output = operands.top ();

						return true;
				}

				lexer.next ();

				for (; !binaryOps.empty () && binaryOps.top ().first >= binaryOp.first; binaryOps.pop ())
				{
					value = operands.top ();

					operands.pop ();

					value = binaryOps.top ().second (operands.top (), value);

					operands.pop ();
					operands.push (value);

					this->extractors.push_back (value);
				}

				binaryOps.push (binaryOp);
			}
		}
Пример #7
0
int main(int argc, const char** argv) {
	auto params = getParams(argc, argv);

	auto exit_with_errors = [](int error_count) {
		cout << "Exiting with " << error_count << (error_count == 1 ? " error" : " errors") << endl;
	};

	Lexer lexer;
	vector<Token> tokens;
	int error_count = 0;

	if (paramIsSet(params, "evaluate")) {
		auto str = params["evaluate"][0];
		istringstream stream {str};
		tie(tokens, error_count) = lexer.tokenize(stream, "(command line)");
	} else if (paramIsSet(params, "files")) {
		auto filename = params["files"][0];
		ifstream file {filename};

		if (file.is_open()) {
			tie(tokens, error_count) = lexer.tokenize(file, filename);
		} else {
			++error_count;
			cerr << "ERROR: " << filename << " not found" << endl;
		}
	} else {
		tie(tokens, error_count) = lexer.tokenize(cin, "(stdin)");
	}

	bool ignore_errors = paramIsSet(params, "ignore-errors");

	if (!ignore_errors && error_count > 0) {
		exit_with_errors(error_count);
		return -1;
	}

	if (tokens.empty()) {
		return 0;
	}

	if (paramIsSet(params, "print-tokens")) {
		print_tokens(tokens);
	}

	TokenStream token_stream {begin(tokens), end(tokens), true};
	Parser parser;
	shared_ptr<ASTNode> tree;

	setupGlobalScope();
	tie(tree, error_count) = parser.parse(token_stream);

	if (!ignore_errors && error_count > 0) {
		exit_with_errors(error_count);
		return -1;
	}

	bool print_ast = paramIsSet(params, "print-ast");
	if (tree) {
		if (print_ast) {
			cout << "\nOutput: " << endl;
			tree->output(cout, 0);
			cout << endl;
		}

		if (print_ast || ignore_errors) {
			cout << "\nEvaluate: " << endl;
		}

		try {
			auto eval = tree->evaluate();
			if (eval) {
				eval->output(cout);
			}
		} catch (const exception& ex) {
			++error_count;
			cerr << ex.what() << endl;
		}

		cout << endl;
	} else if (print_ast) {
		cout << "No parse tree produced" << endl;
	}

	return 0;
}
Пример #8
0
void ConverterCache::Impl::readIndex()
{
	time_t const now = current_time();
	FileName const index(addName(cache_dir.absFileName(), "index"));
	ifstream is(index.toFilesystemEncoding().c_str());
	Lexer lex;
	lex.setStream(is);
	while (lex.isOK()) {
		if (!lex.next(true))
			break;
		string const orig_from = lex.getString();
		if (!lex.next())
			break;
		string const to_format = lex.getString();
		if (!lex.next())
			break;
		time_t const timestamp =
			convert<unsigned long>(lex.getString());
		if (!lex.next())
			break;
		unsigned long const checksum =
			convert<unsigned long>(lex.getString());
		FileName const orig_from_name(orig_from);
		CacheItem item(orig_from_name, to_format, timestamp, checksum);

		// Don't cache files that do not exist anymore
		if (!orig_from_name.exists()) {
			LYXERR(Debug::FILES, "Not caching file `"
				<< orig_from << "' (does not exist anymore).");
			item.cache_name.removeFile();
			continue;
		}

		// Don't add items that are not in the cache anymore
		// This can happen if two instances of LyX are running
		// at the same time and update the index file independantly.
		if (!item.cache_name.exists()) {
			LYXERR(Debug::FILES, "Not caching file `" << orig_from
				<< "' (cached copy does not exist anymore).");
			continue;
		}

		// Delete the cached file if it is too old
		if (difftime(now, item.cache_name.lastModified())
				> lyxrc.converter_cache_maxage) {
			LYXERR(Debug::FILES, "Not caching file `"
				<< orig_from << "' (too old).");
			item.cache_name.removeFile();
			continue;
		}

		FormatCache & format_cache = cache[orig_from_name];
		if (format_cache.from_format.empty())
			format_cache.from_format =
				formats.getFormatFromFile(orig_from_name);
		format_cache.cache[to_format] = item;
	}
	is.close();
}
Пример #9
0
int main() {
	system("mode con cols=100 lines=30");
	system("COLOR 0A");
    while(1){
        dat.init();
        lexer.init();
        buf.clear();
        deb.init();
        ending=0;
        cout << "请将要运行的程序放在与本程序相同的目录下" << endl;
        cout << "输入1运行程序,输入2调试程序,输入3退出程序" << endl;
        int type;
        while(cin >> type){
            if (type == 1) {
                cout << "输入要运行的程序文件名:" << endl;
                break;
            }
            else if (type == 2) {
                cout << "输入要调试的程序文件名:" << endl;
                break;
            }
            else if(type==3) exit(0);
            else {
                cout << "输入不合法!请重新输入:" << endl;
            }
        }
        string filename;
        //cin >> filename;
        ifstream file;
        string s;
        while(cin >> filename){
            file.open(filename);
            if(!file) cout << "输入文件名错误!重新输入:" << endl;
            else break;
        }
        while (!file.eof()) {
            getline(file, s);
            buf.push_back(s);
        }
        if(type==2){
            cout << "进入调试模式\n以下为调试器的命令,输入h即可再次查看" << endl;
            cout << "列出所有代码:l\n查看变量的值:p 变量名\n设置断点:b 行号\n取消断点:nb 行号\n查看当前所有的断点的行号:wb\n下一步:n\n运行程序:r\n" << endl;
            deb.wait();
        }
        /*buf.push_back("begin");
         buf.push_back("out 123;");
         buf.push_back("end");*/
        int x = 0, y = 0;
        bool flag=0;
        while (1) {
            if (x == buf.size()) break;
            if (buf[x].size() == 0) {
                x++;
                y = 0;
                continue;
            }
            if(buf[x][y]=='/' && y+1<buf[x].size() && buf[x][y]=='/'){
                x++;
                y=0;
            }
            if (y + 4<buf[x].size()) {
                if (buf[x].substr(y, 5) == "begin") {
                    lexer.curx = x + 1;
                    lexer.cury = 0;
                    if(deb.next) {
                        cout << lexer.curx << " -> " << buf[lexer.curx] << endl;
                        deb.wait();
                    }
                    if(deb.is_bp(lexer.curx)){
                        cout << lexer.curx << " -> " << buf[lexer.curx] << endl;
                        deb.wait();
                    }
                    flag=1;
                    lexer.domain();
                    break;
                }
            }
            y++;
            if (y == buf[x].size()) {
                x++;
                y = 0;
            }
        }
        if(!flag){
            cout << "没有检测到begin" <<endl;
            system("pause");
            exit(0);
        }
    }

	return 0;
}
Пример #10
0
Parser::Parser(Lexer &m_lexer): lexer_ptr(nullptr), lexer( m_lexer ), meta(m_lexer.size())
{
    parseToken( lexer, meta );
}
Пример #11
0
bool Font::fromString(string const & data, bool & toggle)
{
	istringstream is(data);
	Lexer lex;
	lex.setStream(is);

	int nset = 0;
	while (lex.isOK()) {
		string token;
		if (lex.next())
			token = lex.getString();

		if (token.empty() || !lex.next())
			break;

		if (token == "family") {
			int const next = lex.getInteger();
			bits_.setFamily(FontFamily(next));

		} else if (token == "series") {
			int const next = lex.getInteger();
			bits_.setSeries(FontSeries(next));

		} else if (token == "shape") {
			int const next = lex.getInteger();
			bits_.setShape(FontShape(next));

		} else if (token == "size") {
			int const next = lex.getInteger();
			bits_.setSize(FontSize(next));

		} else if (token == "emph" || token == "underbar" ||
			   token == "noun" || token == "number" ||
			   token == "uuline" || token == "uwave" ||
			   token == "strikeout") {

			int const next = lex.getInteger();
			FontState const misc = FontState(next);

			if (token == "emph")
				bits_.setEmph(misc);
			else if (token == "underbar")
				bits_.setUnderbar(misc);
			else if (token == "strikeout")
				bits_.setStrikeout(misc);
			else if (token == "uuline")
				bits_.setUuline(misc);
			else if (token == "uwave")
				bits_.setUwave(misc);
			else if (token == "noun")
				bits_.setNoun(misc);
			else if (token == "number")
				bits_.setNumber(misc);

		} else if (token == "color") {
			int const next = lex.getInteger();
			bits_.setColor(ColorCode(next));

		/**
		} else if (token == "background") {
			int const next = lex.getInteger();
			bits_.setBackground(ColorCode(next));
		*/

		} else if (token == "language") {
			string const next = lex.getString();
			setLanguage(languages.getLanguage(next));

		} else if (token == "toggleall") {
			toggle = lex.getBool();

		} else {
			// Unrecognised token
			break;
		}

		++nset;
	}
	return (nset > 0);
}
Пример #12
0
MinimalAction::MinimalAction(Lexer &l)
  : Idents(l.getIdentifierTable()) {
  TypeNameInfoTablePtr = new TypeNameInfoTable();
}
Пример #13
0
/*
================
ReadMesh
================
*/
static void ReadMesh( Lexer &lexer, aseMesh *inMesh ) {
	int idx;
	Vec3 temp;
	lexer.ExpectToken("{");
	const char *p;
	const Token *token;
	while ( (token = lexer.ReadToken()) != OG_NULL ) {
		p = token->GetString();
		if ( !p || !*p )
			continue;
		if ( String::Icmp( p, "}" ) == 0 ) 
			return;
		if ( String::Icmp( p, "*" ) != 0 ) 
			lexer.Error( Format("expected *, got '$*'") << p );

		if ( lexer.CheckToken( "MESH_NUMVERTEX" ) ) {
			inMesh->numVerts = lexer.ReadInt();
			inMesh->vertices = new aseVertex[inMesh->numVerts];
		}
		else if ( lexer.CheckToken( "MESH_NUMFACES" ) ) {
			inMesh->numTris = lexer.ReadInt();
			inMesh->triangles = new aseTriangle[inMesh->numTris];
		}
		else if ( lexer.CheckToken( "MESH_VERTEX_LIST" ) ) {
			lexer.ExpectToken("{");
			for( int i=0; i<inMesh->numVerts; i++ ) {
				lexer.ExpectToken("*");
				lexer.ExpectToken("MESH_VERTEX");
				idx = lexer.ReadInt();
				inMesh->vertices[idx].origin.x = lexer.ReadFloat() * ASE_MODEL_SCALE;
				inMesh->vertices[idx].origin.y = lexer.ReadFloat() * ASE_MODEL_SCALE;
				inMesh->vertices[idx].origin.z = lexer.ReadFloat() * ASE_MODEL_SCALE;
			}
			lexer.ExpectToken("}");
		}
		else if ( lexer.CheckToken( "MESH_NORMALS" ) ) {
			lexer.ExpectToken("{");
			for( ;; ) {
				if ( lexer.CheckToken("}") )
					break;
				lexer.ExpectToken("*");
				// don't need the face normal
				if ( lexer.CheckToken("MESH_FACENORMAL") ) {
					lexer.GotoNextLine();
					continue;
				}
				lexer.ExpectToken("MESH_VERTEXNORMAL");
				idx = lexer.ReadInt();
				inMesh->vertices[idx].normal.x = lexer.ReadFloat();
				inMesh->vertices[idx].normal.y = lexer.ReadFloat();
				inMesh->vertices[idx].normal.z = lexer.ReadFloat();
			}
		}
		else if ( lexer.CheckToken( "MESH_FACE_LIST" ) ) {
			lexer.ExpectToken("{");
			for( int i=0; i<inMesh->numTris; i++ ) {
				lexer.ExpectToken("*");
				lexer.ExpectToken("MESH_FACE");
				idx = lexer.ReadInt();
				lexer.CheckToken(":"); // might or might not be there
				lexer.ExpectToken("A");
				lexer.ExpectToken(":");
				inMesh->triangles[idx].v[0] = lexer.ReadInt();
				lexer.ExpectToken("B");
				lexer.ExpectToken(":");
				inMesh->triangles[idx].v[1] = lexer.ReadInt();
				lexer.ExpectToken("C");
				lexer.ExpectToken(":");
				inMesh->triangles[idx].v[2] = lexer.ReadInt();
				lexer.GotoNextLine();
			}
			lexer.ExpectToken("}");
		}
		else if ( lexer.CheckToken( "MESH_NUMTVERTEX" ) ) {
			inMesh->numTVerts = lexer.ReadInt();
			inMesh->texCoords = new Vec2[inMesh->numTVerts];
		}
		else if ( lexer.CheckToken( "MESH_TVERTLIST" ) ) {
			lexer.ExpectToken("{");
			for( int i=0; i<inMesh->numTVerts; i++ ) {
				lexer.ExpectToken("*");
				lexer.ExpectToken("MESH_TVERT");
				idx = lexer.ReadInt();
				inMesh->texCoords[idx].x = lexer.ReadFloat();
				inMesh->texCoords[idx].y = 1.0f-lexer.ReadFloat();
				lexer.ReadFloat();// don't need 3rd component
			}
			lexer.ExpectToken("}");
		}
		else if ( lexer.CheckToken( "MESH_NUMTVFACES" ) )
			lexer.ExpectToken( Format() << inMesh->numTris );
		else if ( lexer.CheckToken( "MESH_TFACELIST" ) ) {
			lexer.ExpectToken("{");
			for( int i=0; i<inMesh->numTris; i++ ) {
				lexer.ExpectToken("*");
				lexer.ExpectToken("MESH_TFACE");
				idx = lexer.ReadInt();

				inMesh->triangles[idx].t[0] = lexer.ReadInt();
				inMesh->triangles[idx].t[1] = lexer.ReadInt();
				inMesh->triangles[idx].t[2] = lexer.ReadInt();
			}
			lexer.ExpectToken("}");
		}
		else if ( lexer.CheckToken( "MATERIAL_REF" ) )
			inMesh->materialId = lexer.ReadInt();
		else if ( !SkipUnknown(lexer) )
			break;
	}
}
Пример #14
0
 inline expr_ptr get_root_node( Lexer & lex )
 {
     return convert_token_to_expression( lex.get_token() );
 }
Пример #15
0
bool InsetLayout::read(Lexer & lex, TextClass const & tclass)
{
	enum {
		IL_BGCOLOR,
		IL_CONTENTASLABEL,
		IL_COPYSTYLE,
		IL_COUNTER,
		IL_CUSTOMPARS,
		IL_DECORATION,
		IL_FONT,
		IL_FORCELTR,
		IL_FORCEPLAIN,
		IL_FREESPACING,
		IL_HTMLTAG,
		IL_HTMLATTR,
		IL_HTMLFORCECSS,
		IL_HTMLINNERTAG,
		IL_HTMLINNERATTR,
		IL_HTMLISBLOCK,
		IL_HTMLLABEL,
		IL_HTMLSTYLE,
		IL_HTMLPREAMBLE,
		IL_INTOC,
		IL_LABELFONT,
		IL_LABELSTRING,
		IL_LATEXNAME,
		IL_LATEXPARAM,
		IL_LATEXTYPE,
		IL_LYXTYPE,
		IL_KEEPEMPTY,
		IL_MULTIPAR,
		IL_NEEDPROTECT,
		IL_PASSTHRU,
		IL_PARBREAKISNEWLINE,
		IL_PREAMBLE,
		IL_REQUIRES,
		IL_SPELLCHECK,
		IL_REFPREFIX,
		IL_END
	};


	LexerKeyword elementTags[] = {
		{ "bgcolor", IL_BGCOLOR },
		{ "contentaslabel", IL_CONTENTASLABEL },
		{ "copystyle", IL_COPYSTYLE }, 
		{ "counter", IL_COUNTER},
		{ "custompars", IL_CUSTOMPARS },
		{ "decoration", IL_DECORATION },
		{ "end", IL_END },
		{ "font", IL_FONT },
		{ "forceltr", IL_FORCELTR },
		{ "forceplain", IL_FORCEPLAIN },
		{ "freespacing", IL_FREESPACING },
		{ "htmlattr", IL_HTMLATTR },
		{ "htmlforcecss", IL_HTMLFORCECSS },
		{ "htmlinnerattr", IL_HTMLINNERATTR},
		{ "htmlinnertag", IL_HTMLINNERTAG},
		{ "htmlisblock", IL_HTMLISBLOCK},
		{ "htmllabel", IL_HTMLLABEL },
		{ "htmlpreamble", IL_HTMLPREAMBLE },
		{ "htmlstyle", IL_HTMLSTYLE },
		{ "htmltag", IL_HTMLTAG },
		{ "intoc", IL_INTOC },
		{ "keepempty", IL_KEEPEMPTY },
		{ "labelfont", IL_LABELFONT },
		{ "labelstring", IL_LABELSTRING },
		{ "latexname", IL_LATEXNAME },
		{ "latexparam", IL_LATEXPARAM },
		{ "latextype", IL_LATEXTYPE },
		{ "lyxtype", IL_LYXTYPE },
		{ "multipar", IL_MULTIPAR },
		{ "needprotect", IL_NEEDPROTECT },
		{ "parbreakisnewline", IL_PARBREAKISNEWLINE },
		{ "passthru", IL_PASSTHRU },
		{ "preamble", IL_PREAMBLE },
		{ "refprefix", IL_REFPREFIX },
		{ "requires", IL_REQUIRES },
		{ "spellcheck", IL_SPELLCHECK }
	};

	lex.pushTable(elementTags);

	FontInfo font = inherit_font;
	labelfont_ = inherit_font;
	bgcolor_ = Color_none;
	bool getout = false;
	// whether we've read the CustomPars or ForcePlain tag
	// for issuing a warning in case MultiPars comes later
	bool readCustomOrPlain = false;

	string tmp;	
	while (!getout && lex.isOK()) {
		int le = lex.lex();
		switch (le) {
		case Lexer::LEX_UNDEF:
			lex.printError("Unknown InsetLayout tag");
			continue;
		default:
			break;
		}
		switch (le) {
		// FIXME
		// Perhaps a more elegant way to deal with the next two would be the
		// way this sort of thing is handled in Layout::read(), namely, by
		// using the Lexer.
		case IL_LYXTYPE: {
			string lt;
			lex >> lt;
			lyxtype_ = translateLyXType(lt);
			if (lyxtype_  == NOLYXTYPE)
				LYXERR0("Unknown LyXType `" << lt << "'.");
			if (lyxtype_ == CHARSTYLE)
				multipar_ = false;
			break;
		}
		case IL_LATEXTYPE:  {
			string lt;
			lex >> lt;
			latextype_ = translateLaTeXType(lt);
			if (latextype_  == ILT_ERROR)
				LYXERR0("Unknown LaTeXType `" << lt << "'.");
			break;
		}
		case IL_LABELSTRING:
			lex >> labelstring_;
			break;
		case IL_DECORATION:
			lex >> tmp;
			decoration_ = translateDecoration(tmp);
			break;
		case IL_LATEXNAME:
			lex >> latexname_;
			break;
		case IL_LATEXPARAM:
			lex >> tmp;
			latexparam_ = support::subst(tmp, "&quot;", "\"");
			break;
		case IL_LABELFONT:
			labelfont_ = lyxRead(lex, inherit_font);
			break;
		case IL_FORCELTR:
			lex >> forceltr_;
			break;
		case IL_INTOC:
			lex >> intoc_;
			break;
		case IL_MULTIPAR:
			lex >> multipar_;
			// the defaults for these depend upon multipar_
			if (readCustomOrPlain)
				LYXERR0("Warning: Read MultiPar after CustomPars or ForcePlain. "
				        "Previous value may be overwritten!");
			readCustomOrPlain = false;
			custompars_ = multipar_;
			forceplain_ = !multipar_;
			break;
		case IL_COUNTER:
			lex >> counter_;
			break;
		case IL_CUSTOMPARS:
			lex >> custompars_;
			readCustomOrPlain = true;
			break;
		case IL_FORCEPLAIN:
			lex >> forceplain_;
			readCustomOrPlain = true;
			break;
		case IL_PASSTHRU:
			lex >> passthru_;
			break;
		case IL_PARBREAKISNEWLINE:
			lex >> parbreakisnewline_;
			break;
		case IL_KEEPEMPTY:
			lex >> keepempty_;
			break;
		case IL_FREESPACING:
			lex >> freespacing_;
			break;
		case IL_NEEDPROTECT:
			lex >> needprotect_;
			break;
		case IL_CONTENTASLABEL:
			lex >> contentaslabel_;
			break;
		case IL_COPYSTYLE: {     // initialize with a known style
			docstring style;
			lex >> style;
			style = support::subst(style, '_', ' ');

			// We don't want to apply the algorithm in DocumentClass::insetLayout()
			// here. So we do it the long way.
			TextClass::InsetLayouts::const_iterator it = 
					tclass.insetLayouts().find(style);
			if (it != tclass.insetLayouts().end()) {
				docstring const tmpname = name_;
				this->operator=(it->second);
				name_ = tmpname;
			} else {
				LYXERR0("Cannot copy unknown InsetLayout `"
					<< style << "'\n"
					<< "All InsetLayouts so far:");
				TextClass::InsetLayouts::const_iterator lit = 
						tclass.insetLayouts().begin();
				TextClass::InsetLayouts::const_iterator len = 
						tclass.insetLayouts().end();
				for (; lit != len; ++lit)
					lyxerr << lit->second.name() << "\n";
			}
			break;
		}

		case IL_FONT: {
			font_ = lyxRead(lex, inherit_font);
			// If you want to define labelfont, you need to do so after
			// font is defined.
			labelfont_ = font_;
			break;
		}
		case IL_BGCOLOR:
			lex >> tmp;
			bgcolor_ = lcolor.getFromLyXName(tmp);
			break;
		case IL_PREAMBLE:
			preamble_ = from_utf8(lex.getLongString("EndPreamble"));
			break;
		case IL_REFPREFIX:
			lex >> refprefix_;
			break;
		case IL_HTMLTAG:
			lex >> htmltag_;
			break;
		case IL_HTMLATTR:
			lex >> htmlattr_;
			break;
		case IL_HTMLFORCECSS:
			lex >> htmlforcecss_;
			break;
		case IL_HTMLINNERTAG:
			lex >> htmlinnertag_;
			break;
		case IL_HTMLINNERATTR:
			lex >> htmlinnerattr_;
			break;
		case IL_HTMLLABEL:
			lex >> htmllabel_;
			break;
		case IL_HTMLISBLOCK:
			lex >> htmlisblock_;
			break;
		case IL_HTMLSTYLE:
			htmlstyle_ = from_utf8(lex.getLongString("EndHTMLStyle"));
			break;
		case IL_HTMLPREAMBLE:
			htmlpreamble_ = from_utf8(lex.getLongString("EndPreamble"));
			break;
		case IL_REQUIRES: {
			lex.eatLine();
			vector<string> const req 
				= support::getVectorFromString(lex.getString());
			requires_.insert(req.begin(), req.end());
			break;
		}
		case IL_SPELLCHECK:
			lex >> spellcheck_;
			break;
		case IL_END:
			getout = true;
			break;
		}
	}

	// Here add element to list if getout == true
	if (!getout)
		return false;
	
	// The label font is generally used as-is without
	// any realization against a given context.
	labelfont_.realize(sane_font);

	lex.popTable();
	return true;
}
Пример #16
0
long double Calculation::Resolve(const string& str) const
    throw(invalid_argument)
{
    if (!CheckParenthesis(str))
        throw invalid_argument("The number of left parenthesis is not equal with"
                               " the number of right parenthesis");

    /*
     * TODO
     *  To test special cases.
     *      5 + * 2
     *      5 + 2 *
     *      * 5 + 2
     *
     *      5 (2 + 3)
     *      (2 + 3) 5
     *
     *      5 2 * 3
     *      5 sin(90)
     *
     *      sin(90) cos(90)
     *      sin 90 cos(45)
     *
     *  To test if there are the functions that are called.
     */



    Lexer l;
    list<Token*> tokens = l.Split(str);
    long double r;

    if (l.PrintErrors())
    {
        throw invalid_argument("Invalid input");
    }

    if (tokens.size() == 0)
    {
        throw invalid_argument("No tokens");
    }

    AddZero(tokens);

    try
    {
        r = Resolve(tokens);

        for (auto it = tokens.begin(); it != tokens.end(); ++it)
            delete (*it);

        return r;
    }
    catch (invalid_argument& e)
    {
        for (auto it = tokens.begin(); it != tokens.end(); ++it)
            delete (*it);

        throw e;
    }
}
Пример #17
0
		bool	Parser::parseValue (Lexer& lexer, Lookup& lookup, Int32u* slot, const Extractor** output)
		{
			const Extractor*	argument;
			Extractors			arguments;
			const Constant*		constant;
			const Function*		function;
			string				name;
			Float64				number;

			switch (lexer.getType ())
			{
				case Lexer::IDENTIFIER:
					name = lexer.getCurrent ();

					lexer.next ();

					if (lexer.getType () == Lexer::PARENTHESIS_BEGIN)
					{
						function = 0;

						for (Int32u i = 0; Function::functions[i].name; ++i)
						{
							if (Function::functions[i].name == name)
							{
								function = &Function::functions[i];

								break;
							}
						}

						if (!function)
							return this->fail (lexer, string ("unknown function name '") + lexer.getCurrent () + "'");

						lexer.next ();

						while (lexer.getType () != Lexer::PARENTHESIS_END)
						{
							if (arguments.size () > 0 && !this->parseType (lexer, Lexer::COMMA, "argument separator"))
								return false;

							if (!this->parseExpression (lexer, lookup, slot, &argument))
								return false;

							arguments.push_back (argument);
						}

						lexer.next ();

						if (arguments.size () < function->min || (function->max > 0 && arguments.size () > function->max))
							return this->fail (lexer, "wrong number of arguments");

						*output = function->builder (arguments, slot);
					}
					else
					{
						constant = 0;

						for (Int32u i = 0; Constant::constants[i].name; ++i)
						{
							if (Constant::constants[i].name == name)
							{
								constant = &Constant::constants[i];

								break;
							}
						}

						if (constant)
							*output = new ConstantExtractor (constant->value);
						else
							*output = new FieldExtractor (lookup.store (name));
					}

					break;

				case Lexer::NUMBER:
					if (!Convert::toFloat (&number, lexer.getCurrent ().data (), lexer.getCurrent ().length ()))
						return this->fail (lexer, "invalid number");

					*output = new ConstantExtractor (Variant (number));

					lexer.next ();

					break;

				case Lexer::STRING:
					*output = new ConstantExtractor (Variant (lexer.getCurrent ()));

					lexer.next ();

					break;

				default:
					this->fail (lexer, "unexpected character");

					return false;
			}

			this->extractors.push_back (*output);

			return true;
		}
Пример #18
0
Parser::Parser(Lexer lexer, Tokenizer tokenizer, const char *output_file, const char *processing) : lexer_tokens(lexer.get_tokens()),
    lexer_parser_pos(0), look(this->scan()), document_tokens(tokenizer.get_tokens()) {
        view v = view("Document");
        col c = col("text");
        span s = span(tokenizer.get_text(), 0, tokenizer.get_text().length());
        c.spans.push_back(s);
        v.cols.push_back(c);
        this->views.push_back(v);
        this->output_file = fopen(output_file, "w+");
        fprintf(this->output_file, "Processing %s\n", processing);
}
Пример #19
0
        void Interface::instrument_emit_post(PragmaCustomConstruct ctr)
        {
            ObjectList<std::string> arguments;
            if (!ctr.is_parameterized()
                    || (arguments = ctr.get_parameter_arguments(ExpressionTokenizerTrim())).size() != 2)
            {
                invalid_instrument_emit(ctr);
                ctr.get_ast().remove_in_list();
                return;
            }

            Lexer l = Lexer::get_current_lexer();
            ObjectList<Lexer::pair_token> tokens_key = l.lex_string(arguments[0]);
            ObjectList<Lexer::pair_token> tokens_descr = l.lex_string(arguments[1]);

            if (tokens_key.size() != 1
                    || tokens_descr.size() != 1)
            {
                invalid_instrument_emit(ctr);
                return;
            }

            if ((IS_C_LANGUAGE && (tokens_key[0].first != TokensC::IDENTIFIER))
                    || (IS_CXX_LANGUAGE && (tokens_key[0].first != TokensCXX::IDENTIFIER)))
            {
                std::cerr << ctr.get_ast().get_locus() << ": warning: first argument must be an identifier" << std::endl;
                invalid_instrument_emit(ctr);
                return;
            }

            if ((IS_C_LANGUAGE && (tokens_descr[0].first != TokensC::STRING_LITERAL))
                    || (IS_CXX_LANGUAGE && (tokens_descr[0].first != TokensCXX::STRING_LITERAL)))
            {
                std::cerr << ctr.get_ast().get_locus() << ": warning: second argument must be a string-literal" << std::endl;
                invalid_instrument_emit(ctr);
                return;
            }

            if (_map_events.find(arguments[0]) == _map_events.end())
            {
                std::cerr << ctr.get_ast().get_locus() << ": warning: event key '" << arguments[0] << "' has not been previously declared" << std::endl;
                invalid_instrument_emit(ctr);
                ctr.get_ast().remove_in_list();
                return;
            }

            Source src;
            src
                << "{"
                << "static int nanos_funct_id_init = 0;"
                << "static nanos_event_key_t nanos_instr_name_key = 0;"
                << "static nanos_event_value_t nanos_instr_name_value = 0;"
                << "if (nanos_funct_id_init == 0)"
                << "{"
                <<    "nanos_err_t err = nanos_instrument_get_key(\"" << arguments[0] << "\", &nanos_instr_name_key);"
                <<    "if (err != NANOS_OK) nanos_handle_error(err);"
                <<    "err = nanos_instrument_register_value (&nanos_instr_name_value, "
                <<             "\"" << arguments[0] << "\", " 
                <<             arguments[1] << ", "
                <<             "\"" << ctr.get_ast().get_locus() << "\"," 
                <<             "/* abort_if_registered */ 0);"
                <<    "if (err != NANOS_OK) nanos_handle_error(err);"
                <<    "nanos_funct_id_init = 1;"
                << "}"
                << "nanos_event_t _events[1];"
                << "_events[0].type = NANOS_POINT;"
                << "_events[0].info.point.nkvs = 1;"
                << "_events[0].info.point.keys = &nanos_instr_name_key;"
                << "_events[0].info.point.values = &nanos_instr_name_value;"
                << "nanos_instrument_events(1, _events);"
                << "}"
                ;

            AST_t tree = src.parse_statement(ctr.get_ast(), ctr.get_scope_link());
            ctr.get_ast().replace(tree);
        }
Пример #20
0
	ASTNode::ASTNode(Lexer& l) {
		_lineNumber = l.getLineNumber();
		_charNumber = l.getCharNumber();
	}
Пример #21
0
static void compile_structure( Lexer& lexer, types::VariantStructDescription& result, const types::NormalizeFunctionMap* typemap, const types::keymap<types::FormDescriptionR>& formmap, std::vector<std::string>& unresolvedSymbols)
{
	bool seenCloseStruct = false;
	Lexem lx;
	for (lx = lexer.next2(false); lx.id() != Lexem::CloseStruct; lx=lexer.next2(false))
	{
		if (lx.id() != Lexem::Identifier && lx.id() != Lexem::String)
		{
			throw std::runtime_error( std::string("unexpected ") + lexer.curtoken() + ", structure element name as identifier or string expected");
		}
		std::string elementname( lx.value());		//< name of the element
		bool isOptional = false;			//< element is optional (also in strict validation)
		bool isMandatory = false;			//< element is mandatory (also in relaxed validation)
		bool isIndirection = false;			//< element is an indirection (means it is expanded only when it exists)
		bool isArray = false;				//< element is an array
		bool isAttribute = false;			//< element is an attribute (for languages that know attributes like XML)
		bool isInherited = (elementname == "_");	//< element is inherited (means it has no name and it acts as content of the enclosing element)

		for (lx=lexer.next2(true);; lx=lexer.next2(true))
		{
			if (lx.id() == Lexem::Separator)
			{
				for (lx=lexer.next2(true); lx.id() == Lexem::Separator; lx=lexer.next2(true)){}
				if (lx.id() != Lexem::OpenStruct)
				{
					throw std::runtime_error("unexpected end of line in the middle of an atomic element definition");
				}
			}
			if (lx.id() == Lexem::OpenStruct)
			{
				types::VariantStructDescription substruct;
				compile_structure( lexer, substruct, typemap, formmap, unresolvedSymbols);
				int elementidx = result.addStructure( elementname, substruct);
				if (isArray) result.at( elementidx)->makeArray();
				if (isOptional) result.at( elementidx)->setOptional();
				if (isMandatory) result.at( elementidx)->setMandatory();
				if (isIndirection) throw std::runtime_error("cannot declare embedded substructure as indirection ('^')");
				if (isAttribute) throw std::runtime_error("cannot declare structure as attribute ('@')");
				if (isInherited) throw std::runtime_error("cannot declare embedded substructure with name \"_\" used to declare inheritance");
				lx = lexer.next2(true);
				if (lx.id() == Lexem::CloseStruct)
				{
					seenCloseStruct = true;
				}
				else if (lx.id() != Lexem::Separator)
				{
					throw std::runtime_error("expected close structure '}' or end of line or comma ',' as separator after close struct");
				}
				break;
			}
			else if (lx.id() == Lexem::Identifier)
			{
				std::string elementtype( lx.value());
				std::string defaultvalue;
				bool hasDefault = false;

				lx = lexer.next2(true);
				for (; lx.id() != Lexem::Separator && lx.id() != Lexem::CloseStruct; lx = lexer.next2(true))
				{
					if (lx.id() == Lexem::ArrayTag)
					{
						if (hasDefault) throw std::runtime_error("unexpected array marker after default value assignment");
						if (isArray) throw std::runtime_error("cannot handle duplicate array tag '[]'");
						isArray = true;
					}
					else if (lx.id() == Lexem::Assign)
					{
						if (isArray) throw std::runtime_error("cannot handle default value assignment for array");
						if (hasDefault) throw std::runtime_error("cannot handle duplicate default value assignment");
						lx = lexer.next2(true);
						if (lx.id() != Lexem::String && lx.id() != Lexem::Identifier)
						{
							throw std::runtime_error( "string or identifier expected for default value declaration after '='");
						}
						defaultvalue = lx.value();
						hasDefault = true;
					}
					else
					{
						throw std::runtime_error( std::string("unexpected token ") + lexer.curtoken() + ", default value assignment or array marker or following structure element declaration expected");
					}
				}
				if (lx.id() == Lexem::CloseStruct)
				{
					seenCloseStruct = true;
				}

				// Resolve type:
				types::keymap<types::FormDescriptionR>::const_iterator fmi;
				fmi = formmap.find( elementtype);
				if (fmi != formmap.end())
				{
					// ... type referenced is a sub structure
					if (isAttribute) throw std::runtime_error("cannot declare structure as attribute ('@')");

					// Sub structure referenced by 'elementtype':
					const types::FormDescription* substruct = fmi->second.get();
					if (isIndirection)
					{
						// ... resolved indirection
						int elementidx = result.addIndirection( elementname, substruct);
						if (isArray) result.at( elementidx)->makeArray();
					}
					else if (isInherited)
					{
						// ... resolved inheritance
						result.inherit( *substruct);
					}
					else
					{
						// ... resolved sub structure
						int elementidx = result.addStructure( elementname, *substruct);
						if (isArray) result.at( elementidx)->makeArray();
						if (isOptional) result.at( elementidx)->setOptional();
						if (isMandatory) result.at( elementidx)->setMandatory();
					}
				}
				else if (boost::algorithm::iequals( elementtype, "string"))
				{
					// ... type referenced is the reserved type string (no normalizer defined)
					if (isIndirection) throw std::runtime_error("cannot declare atomic string type as indirection ('^')");
					int elementidx; //< index of atomic element created
					if (isAttribute)
					{
						elementidx = result.addAttribute( elementname, hasDefault?types::Variant(defaultvalue):types::Variant(types::Variant::String));
						//... atomic attribute value
					}
					else if (isInherited)
					{
						elementidx = result.addAtom( "", hasDefault?types::Variant(defaultvalue):types::Variant(types::Variant::String));
						//... atomic unnamed (inherited) content value
					}
					else
					{
						elementidx = result.addAtom( elementname, hasDefault?types::Variant(defaultvalue):types::Variant(types::Variant::String));
						//... atomic named content value (non attribute)
					}
					if (isArray) result.at( elementidx)->makeArray();
					if (isOptional) result.at( elementidx)->setOptional();
					if (isMandatory) result.at( elementidx)->setMandatory();
				}
				else
				{
					// ... type referenced must be an atomic type defined in a .wnmp file or a custom data type
					const types::NormalizeFunction* atomictype;
					if (isIndirection)
					{
						// ... unresolved indirection
						int elementidx = result.addUnresolved( elementname, elementtype);
						if (isArray) result.at( elementidx)->makeArray();
						unresolvedSymbols.push_back( elementtype);
					}
					else if (0!=(atomictype=typemap->get( elementtype)))
					{
						// ... type referenced is an atomic type defined in a .wnmp file or a custom data type
						int elementidx; //< index of atomic element created
						if (isIndirection) throw std::runtime_error("cannot declare atomic type as indirection ('^')");
						if (isAttribute)
						{
							elementidx = result.addAttribute( elementname, atomictype->execute(hasDefault?types::Variant(defaultvalue):types::Variant()), atomictype);
							//... atomic attribute value
						}
						else if (isInherited)
						{
							elementidx = result.addAtom( "", atomictype->execute(hasDefault?types::Variant(defaultvalue):types::Variant()), atomictype);
							//... atomic unnamed (inherited) content value
						}
						else
						{
							elementidx = result.addAtom( elementname, atomictype->execute(hasDefault?types::Variant(defaultvalue):types::Variant()), atomictype);
							//... atomic named content value (non attribute)
						}
						if (isArray) result.at( elementidx)->makeArray();
						if (isOptional) result.at( elementidx)->setOptional();
						if (isMandatory) result.at( elementidx)->setMandatory();
					}
					else if (isInherited)
					{
						// ... unresolved inheritance = error
						throw std::runtime_error( std::string("undefined atomic data type or inherited structure '") + elementtype + "'");
					}
					else
					{
						throw std::runtime_error( std::string("cannot find type '") + elementtype + "'");
					}
				}
				break;
			}
			else if (lx.id() == Lexem::ArrayTag)
			{
				if (isInherited) throw std::runtime_error("contradicting array/inheritance tag '[]' and '_'");
				if (isArray) throw std::runtime_error("cannot handle duplicate array tag '[]'");
				isArray = true;
			}
			else if (lx.id() == Lexem::AttributeTag)
			{
				if (isInherited) throw std::runtime_error("contradicting attribute/inheritance tag '@' and '_'");
				if (isAttribute) throw std::runtime_error("cannot handle duplicate attribute tag '@'");
				isAttribute = true;
			}
			else if (lx.id() == Lexem::MandatoryTag)
			{
				if (isInherited) throw std::runtime_error("contradicting mandatory/inheritance tag '!' and '_'");
				if (isOptional) throw std::runtime_error("contradicting optional/mandatory tag '?' and '!'");
				if (isMandatory) throw std::runtime_error("cannot handle duplicate mandatory tag '!'");
				isMandatory = true;
			}
			else if (lx.id() == Lexem::OptionalTag)
			{
				if (isInherited) throw std::runtime_error("contradicting optional/inheritance tag '?' and '_'");
				if (isMandatory) throw std::runtime_error("contradicting optional/mandatory tag '?' and '!'");
				if (isOptional) throw std::runtime_error("cannot handle duplicate optional tag '?'");
				isOptional = true;
			}
			else if (lx.id() == Lexem::Indirection)
			{
				if (isInherited) throw std::runtime_error("contradicting indirection/inheritance tag '^' and '_'");
				if (isOptional) throw std::runtime_error("contradicting indirection/optional tag '^' and '?'");
				if (isMandatory) throw std::runtime_error("contradicting indirection/mandatory tag '^' and '!'");
				if (isIndirection) throw std::runtime_error("cannot handle duplicate indirection tag '^'");
				isIndirection = true;
			}
			else
			{
				throw std::runtime_error( std::string("unexpected token ") + lexer.curtoken() + ", attribute or type name or substructure expected");
			}
		}
		if (seenCloseStruct)
		{
			break;
		}
	}
}
Пример #22
0
		/*
		 * DROP TABLE <name>
		 */
		void DropTable::Parse(Lexer& lex)
		{
			Token t = lex.NextToken(TokenType::Identifier, false);
			SetName(t.strData);
		}
Пример #23
0
int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    try {
        if(qApp->arguments().length() != 3) {
            throw std::runtime_error("Incorrect arguments (thriftDir generatedDir)");
        }
        QString thriftDir = qApp->arguments().at(1);
        QString generatedDir = qApp->arguments().at(2);

//        QString thriftDir = "D:/sources/lib/QEverCloud/src/QEverCloud/thrift/src";
//        QString generatedDir = "D:/tmp/2";

        Lexer* lexer = new Lexer(&app);
        QDir dir(thriftDir);
        for(QString thriftFile : dir.entryList(QStringList() << "*.thrift", QDir::Files, QDir::Name)) {
            lexer->feedFile(dir.absoluteFilePath(thriftFile));
        }

        /*QFile outFile("D:/tmp/2/lexer.txt");
        outFile.open(QIODevice::WriteOnly);
        QTextStream out(&outFile);
        out.setCodec("UTF-8");
        for(const Lexer::TerminalSymbol& term : lexer->terminals()) {
            out << "[" << term.line << "] " << static_cast<int>(term.type) << " " << term.data << endl;
        }*/

        Parser* parser = new Parser(&app);
        for(const Lexer::TerminalSymbol& term : lexer->terminals()) {
            parser->setFile(term.file);
            //qDebug() << term.file << term.line << term.data;
            parser->feed(term.type, term.data);
            if(parser->isError()) {
                throw std::runtime_error(QString("%4 in file %1 at line %2: %3\ndetected token type: %5").arg(term.file).arg(term.line).arg(term.data)
                                         .arg(parser->errorMessage()).arg(static_cast<int>(term.type)).toStdString());
            }
        }
        parser->complete();
        if(parser->isError()) {
            throw std::runtime_error(QString("Parser error at completion: %1").arg(parser->errorMessage()).toStdString());
        }

//        qDebug() << "=========== NAMESPACES ==============";
//        for(const Parser::Namespace& n : parser->namespaces()) {
//            qDebug() << n.name << n.scope << n.file;
//        }

//        qDebug() << "=========== INCLUDES ==============";
//        for(const Parser::Include& i : parser->includes()) {
//            qDebug() << i.name << i.file;
//        }

//        qDebug() << "=========== TYPEDEFS ==============";
//        for(const Parser::TypeDefinition& td : parser->typedefs()) {
//            QString s;
//            if(td.type.dynamicCast<Parser::BaseType>()) {
//                s = td.type.dynamicCast<Parser::BaseType>()->basetype;
//            }
//            qDebug() << td.name << s << td.file;
//        }

//        qDebug() << "=========== CONSTANTS ==============";
//        for(const Parser::Constant& c : parser->constants()) {
//            QString s;
//            if(c.type.dynamicCast<Parser::BaseType>()) {
//                s = c.type.dynamicCast<Parser::BaseType>()->basetype;
//            }
//            if(c.type.dynamicCast<Parser::IdentifierType>()) {
//                s = c.type.dynamicCast<Parser::IdentifierType>()->identifier;
//            }
//            if(c.type.dynamicCast<Parser::MapType>()) {
//                s = "MAP";
//            }
//            if(c.type.dynamicCast<Parser::SetType>()) {
//                s = "SET";
//            }
//            if(c.type.dynamicCast<Parser::ListType>()) {
//                s = "LIST";
//            }
//            QString v;
//            if(c.value && c.value.dynamicCast<Parser::LiteralValue>()) {
//                v = c.value.dynamicCast<Parser::LiteralValue>()->value;
//            }
//            qDebug() << c.name << s << v << c.file;
//        }

//        qDebug() << "=========== STRUCTURES ==============";
//        for(const Parser::Structure& s : parser->structures()) {
//            QString fields;
//            for(const Parser::Field& f: s.fields) {
//                fields += f.name + (f.required == Parser::Field::RequiredFlag::Optional ? "*" : "") + " ";
//            }
//            qDebug() << s.name << fields << s.file;
//        }

//        qDebug() << "=========== UNIONS ==============";
//        for(const Parser::Structure& s : parser->unions()) {
//            QString fields;
//            for(const Parser::Field& f: s.fields) {
//                fields += f.name + (f.required == Parser::Field::RequiredFlag::Optional ? "*" : "") + " ";
//            }
//            qDebug() << s.name << fields << s.file;
//        }

//        qDebug() << "=========== EXCEPTIONS ==============";
//        for(const Parser::Structure& s : parser->exceptions()) {
//            QString fields;
//            for(const Parser::Field& f: s.fields) {
//                fields += f.name + (f.required == Parser::Field::RequiredFlag::Optional ? "*" : "") + " ";
//            }
//            qDebug() << s.name << fields << s.file;
//        }

//        qDebug() << "=========== SERVICES ==============";
//        for(const Parser::Service& s : parser->services()) {
//            qDebug() << "******** " << s.name << "       " << s.file;
//            for(const Parser::Function& f: s.functions) {
//                qDebug() << f.name << f.isOneway;
//            }
//        }

//        qDebug() << "=========== ENUMS ==============";
//        for(const Parser::Enumeration& e : parser->enumerations()) {
//            QString values;
//            for(auto v: e.values) {
//                values += v.first + "=" + v.second + " ";
//            }
//            qDebug() << e.name << values << e.file;
//        }

//        qDebug() << "=========== FILES ==============";
//        for(QString file : parser->files()) {
//            qDebug() << file;
//        }

        generateSources(parser, generatedDir);


    } catch(const std::exception& e) {
        qDebug() << "\nFAILURE!!!";
        qDebug() << e.what();
        return 1;
    } catch(...) {
        qDebug() << "\nFAILURE!!! Unknown exception\n";
        return 2;
    }

    return 0;
}
Пример #24
0
bool Counter::read(Lexer & lex)
{
	enum {
		CT_WITHIN = 1,
		CT_LABELSTRING,
		CT_LABELSTRING_APPENDIX,
		CT_PRETTYFORMAT,
		CT_END
	};

	LexerKeyword counterTags[] = {
		{ "end", CT_END },
		{ "labelstring", CT_LABELSTRING },
		{ "labelstringappendix", CT_LABELSTRING_APPENDIX },
		{ "prettyformat", CT_PRETTYFORMAT },
		{ "within", CT_WITHIN }
	};

	lex.pushTable(counterTags);

	bool getout = false;
	while (!getout && lex.isOK()) {
		int le = lex.lex();
		switch (le) {
			case Lexer::LEX_UNDEF:
				lex.printError("Unknown counter tag `$$Token'");
				continue;
			default: 
				break;
		}
		switch (le) {
			case CT_WITHIN:
				lex.next();
				master_ = lex.getDocString();
				if (master_ == "none")
					master_.erase();
				break;
			case CT_PRETTYFORMAT:
				lex.next();
				prettyformat_ = lex.getDocString();
				break;
			case CT_LABELSTRING:
				lex.next();
				labelstring_ = lex.getDocString();
				labelstringappendix_ = labelstring_;
				break;
			case CT_LABELSTRING_APPENDIX:
				lex.next();
				labelstringappendix_ = lex.getDocString();
				break;
			case CT_END:
				getout = true;
				break;
		}
	}

	// Here if have a full counter if getout == true
	if (!getout)
		LYXERR0("No End tag found for counter!");
	lex.popTable();
	return getout;
}
Пример #25
0
void Template::readTemplate(Lexer & lex)
{
	enum {
		TO_GUINAME = 1,
		TO_HELPTEXT,
		TO_INPUTFORMAT,
		TO_FILTER,
		TO_AUTOMATIC,
		TO_PREVIEW,
		TO_TRANSFORM,
		TO_FORMAT,
		TO_END
	};

	LexerKeyword templateoptiontags[] = {
		{ "automaticproduction", TO_AUTOMATIC },
		{ "filefilter", TO_FILTER },
		{ "format", TO_FORMAT },
		{ "guiname", TO_GUINAME },
		{ "helptext", TO_HELPTEXT },
		{ "inputformat", TO_INPUTFORMAT },
		{ "preview", TO_PREVIEW },
		{ "templateend", TO_END },
		{ "transform", TO_TRANSFORM }
	};

	PushPopHelper pph(lex, templateoptiontags);
	lex.setContext("Template::readTemplate");

	string token;
	while (lex.isOK()) {
		switch (lex.lex()) {
		case TO_GUINAME:
			lex.next(true);
			guiName = lex.getString();
			break;

		case TO_HELPTEXT:
			helpText = lex.getLongString("HelpTextEnd");
			break;

		case TO_INPUTFORMAT:
			lex.next(true);
			inputFormat = lex.getString();
			break;

		case TO_FILTER:
			lex.next(true);
			fileRegExp = lex.getString();
			break;

		case TO_AUTOMATIC:
			lex.next();
			automaticProduction = lex.getBool();
			break;

		case TO_PREVIEW:
			lex >> token;
			if (token == "InstantPreview")
				preview_mode = PREVIEW_INSTANT;
			else if (token == "Graphics")
				preview_mode = PREVIEW_GRAPHICS;
			else
				preview_mode = PREVIEW_OFF;
			break;

		case TO_TRANSFORM: {
			lex >> token;
			TransformID id = transformIDTranslator().find(token);
			if (int(id) == -1)
				LYXERR0("Transform " << token << " is not recognized");
			else
				transformIds.push_back(id);
			break;
		}

		case TO_FORMAT:
			lex.next(true);
			formats[lex.getString()].readFormat(lex);
			break;

		case TO_END:
			return;

		default:
			lex.printError("external::Template::readTemplate: "
				       "Wrong tag: $$Token");
			LASSERT(false, /**/);
			break;
		}
	}
}
Пример #26
0
int main (int, char**)
{
  UnitTest t (1208);

  std::vector <std::pair <std::string, Lexer::Type>> tokens;
  std::string token;
  Lexer::Type type;

  // Feed in some attributes and types, so that the Lexer knows what a DOM
  // reference is.
  Lexer::attributes["due"]         = "date";
  Lexer::attributes["tags"]        = "string";
  Lexer::attributes["description"] = "string";

  // White space detection.
  t.notok (Lexer::isWhitespace (0x0041), "U+0041 (A) ! isWhitespace");
  t.ok (Lexer::isWhitespace (0x0020), "U+0020 isWhitespace");
  t.ok (Lexer::isWhitespace (0x0009), "U+0009 isWhitespace");
  t.ok (Lexer::isWhitespace (0x000A), "U+000A isWhitespace");
  t.ok (Lexer::isWhitespace (0x000B), "U+000B isWhitespace");
  t.ok (Lexer::isWhitespace (0x000C), "U+000C isWhitespace");
  t.ok (Lexer::isWhitespace (0x000D), "U+000D isWhitespace");
  t.ok (Lexer::isWhitespace (0x0085), "U+0085 isWhitespace");
  t.ok (Lexer::isWhitespace (0x00A0), "U+00A0 isWhitespace");
  t.ok (Lexer::isWhitespace (0x1680), "U+1680 isWhitespace"); // 10
  t.ok (Lexer::isWhitespace (0x180E), "U+180E isWhitespace");
  t.ok (Lexer::isWhitespace (0x2000), "U+2000 isWhitespace");
  t.ok (Lexer::isWhitespace (0x2001), "U+2001 isWhitespace");
  t.ok (Lexer::isWhitespace (0x2002), "U+2002 isWhitespace");
  t.ok (Lexer::isWhitespace (0x2003), "U+2003 isWhitespace");
  t.ok (Lexer::isWhitespace (0x2004), "U+2004 isWhitespace");
  t.ok (Lexer::isWhitespace (0x2005), "U+2005 isWhitespace");
  t.ok (Lexer::isWhitespace (0x2006), "U+2006 isWhitespace");
  t.ok (Lexer::isWhitespace (0x2007), "U+2007 isWhitespace");
  t.ok (Lexer::isWhitespace (0x2008), "U+2008 isWhitespace"); // 20
  t.ok (Lexer::isWhitespace (0x2009), "U+2009 isWhitespace");
  t.ok (Lexer::isWhitespace (0x200A), "U+200A isWhitespace");
  t.ok (Lexer::isWhitespace (0x2028), "U+2028 isWhitespace");
  t.ok (Lexer::isWhitespace (0x2029), "U+2029 isWhitespace");
  t.ok (Lexer::isWhitespace (0x202F), "U+202F isWhitespace");
  t.ok (Lexer::isWhitespace (0x205F), "U+205F isWhitespace");
  t.ok (Lexer::isWhitespace (0x3000), "U+3000 isWhitespace");

  // static bool Lexer::isBoundary (int, int);
  t.ok    (Lexer::isBoundary (' ', 'a'), "' ' --> 'a' = isBoundary");
  t.ok    (Lexer::isBoundary ('a', ' '), "'a' --> ' ' = isBoundary");
  t.ok    (Lexer::isBoundary (' ', '+'), "' ' --> '+' = isBoundary");
  t.ok    (Lexer::isBoundary (' ', ','), "' ' --> ',' = isBoundary");
  t.notok (Lexer::isBoundary ('3', '4'), "'3' --> '4' = isBoundary");
  t.ok    (Lexer::isBoundary ('(', '('), "'(' --> '(' = isBoundary");
  t.notok (Lexer::isBoundary ('r', 'd'), "'r' --> 'd' = isBoundary");

  // static bool Lexer::wasQuoted (const std::string&);
  t.notok (Lexer::wasQuoted (""),        "'' --> !wasQuoted");
  t.notok (Lexer::wasQuoted ("foo"),     "'foo' --> !wasQuoted");
  t.ok    (Lexer::wasQuoted ("a b"),     "'a b' --> wasQuoted");
  t.ok    (Lexer::wasQuoted ("(a)"),     "'(a)' --> wasQuoted");

  // static bool Lexer::dequote (std::string&, const std::string& quotes = "'\"");
  token = "foo";
  Lexer::dequote (token);
  t.is (token, "foo", "dequote foo --> foo");

  token = "'foo'";
  Lexer::dequote (token);
  t.is (token, "foo", "dequote 'foo' --> foo");

  token = "'o\\'clock'";
  Lexer::dequote (token);
  t.is (token, "o\\'clock", "dequote 'o\\'clock' --> o\\'clock");

  token = "abba";
  Lexer::dequote (token, "a");
  t.is (token, "bb", "dequote 'abba' (a) --> bb");

  // Should result in no tokens.
  Lexer l0 ("");
  t.notok (l0.token (token, type), "'' --> no tokens");

  // Should result in no tokens.
  Lexer l1 ("       \t ");
  t.notok (l1.token (token, type), "'       \\t ' --> no tokens");

  // \u20ac = Euro symbol.
  Lexer l2 (" one 'two \\'three\\''+456-(1.3*2 - 0x12) 1.2e-3.4    foo.bar and '\\u20ac'");

  tokens.clear ();
  while (l2.token (token, type))
  {
    std::cout << "# «" << token << "» " << Lexer::typeName (type) << "\n";
    tokens.push_back (std::pair <std::string, Lexer::Type> (token, type));
  }

  t.is (tokens[0].first,                     "one",           "tokens[0] = 'one'"); // 30
  t.is (Lexer::typeName (tokens[0].second),  "identifier",    "tokens[0] = identifier");
  t.is (tokens[1].first,                     "'two 'three''", "tokens[1] = 'two 'three''");
  t.is (Lexer::typeName (tokens[1].second),  "string",        "tokens[1] = string");
  t.is (tokens[2].first,                     "+",             "tokens[2] = '+'");
  t.is (Lexer::typeName (tokens[2].second),  "op",            "tokens[2] = op");
  t.is (tokens[3].first,                     "456",           "tokens[3] = '456'");
  t.is (Lexer::typeName (tokens[3].second),  "number",        "tokens[3] = number");
  t.is (tokens[4].first,                     "-",             "tokens[4] = '-'");
  t.is (Lexer::typeName (tokens[4].second),  "op",            "tokens[4] = op");
  t.is (tokens[5].first,                     "(",             "tokens[5] = '('"); // 40
  t.is (Lexer::typeName (tokens[5].second),  "op",            "tokens[5] = op");
  t.is (tokens[6].first,                     "1.3",           "tokens[6] = '1.3'");
  t.is (Lexer::typeName (tokens[6].second),  "number",        "tokens[6] = number");
  t.is (tokens[7].first,                     "*",             "tokens[7] = '*'");
  t.is (Lexer::typeName (tokens[7].second),  "op",            "tokens[7] = op");
  t.is (tokens[8].first,                     "2",             "tokens[8] = '2'");
  t.is (Lexer::typeName (tokens[8].second),  "number",        "tokens[8] = number");
  t.is (tokens[9].first,                     "-",             "tokens[9] = '-'");
  t.is (Lexer::typeName (tokens[9].second),  "op",            "tokens[9] = op");
  t.is (tokens[10].first,                    "0x12",          "tokens[10] = '0x12'"); // 50
  t.is (Lexer::typeName (tokens[10].second), "hex",           "tokens[10] = hex");
  t.is (tokens[11].first,                    ")",             "tokens[11] = ')'");
  t.is (Lexer::typeName (tokens[11].second), "op",            "tokens[11] = op");
  t.is (tokens[12].first,                    "1.2e-3.4",      "tokens[12] = '1.2e-3.4'");
  t.is (Lexer::typeName (tokens[12].second), "number",        "tokens[12] = number");
  t.is (tokens[13].first,                    "foo.bar",       "tokens[13] = 'foo.bar'");
  t.is (Lexer::typeName (tokens[13].second), "identifier",    "tokens[13] = identifier");
  t.is (tokens[14].first,                    "and",           "tokens[14] = 'and'"); // 60
  t.is (Lexer::typeName (tokens[14].second), "op",            "tokens[14] = op");
  t.is (tokens[15].first,                    "'€'",           "tokens[15] = \\u20ac --> ''€''");
  t.is (Lexer::typeName (tokens[15].second), "string",        "tokens[15] = string");

  // Test for numbers that are no longer ISO-8601 dates.
  Lexer l3 ("1 12 123 1234 12345 123456 1234567");
  tokens.clear ();
  while (l3.token (token, type))
  {
    std::cout << "# «" << token << "» " << Lexer::typeName (type) << "\n";
    tokens.push_back (std::pair <std::string, Lexer::Type> (token, type));
  }

  t.is ((int)tokens.size (),     7,                         "7 tokens");
  t.is (tokens[0].first,         "1",                       "tokens[0] == '1'");
  t.is ((int) tokens[0].second,  (int) Lexer::Type::number, "tokens[0] == Type::number");
  t.is (tokens[1].first,         "12",                      "tokens[1] == '12'");
  t.is ((int) tokens[1].second,  (int) Lexer::Type::number, "tokens[1] == Type::date");
  t.is (tokens[2].first,         "123",                     "tokens[2] == '123'");
  t.is ((int) tokens[2].second,  (int) Lexer::Type::number, "tokens[2] == Type::number"); // 70
  t.is (tokens[3].first,         "1234",                    "tokens[3] == '1234'");
  t.is ((int) tokens[3].second,  (int) Lexer::Type::number, "tokens[3] == Type::date");
  t.is (tokens[4].first,         "12345",                   "tokens[4] == '12345'");
  t.is ((int) tokens[4].second,  (int) Lexer::Type::number, "tokens[4] == Type::number");
  t.is (tokens[5].first,         "123456",                  "tokens[5] == '123456'");
  t.is ((int) tokens[5].second,  (int) Lexer::Type::number, "tokens[5] == Type::date");
  t.is (tokens[6].first,         "1234567",                 "tokens[6] == '1234567'");
  t.is ((int) tokens[6].second,  (int) Lexer::Type::number, "tokens[6] == Type::number");

  // void split (std::vector<std::string>&, const std::string&);
  std::string unsplit = " ( A or B ) ";
  std::vector <std::string> items;
  items = Lexer::split (unsplit);
  t.is (items.size (), (size_t) 5, "split ' ( A or B ) '");
  t.is (items[0], "(",             "split ' ( A or B ) ' -> [0] '('");
  t.is (items[1], "A",             "split ' ( A or B ) ' -> [1] 'A'");
  t.is (items[2], "or",            "split ' ( A or B ) ' -> [2] 'or'");
  t.is (items[3], "B",             "split ' ( A or B ) ' -> [3] 'B'");
  t.is (items[4], ")",             "split ' ( A or B ) ' -> [4] ')'");

  // Test simple mode with contrived tokens that ordinarily split.
  unsplit = "  +-* a+b 12.3e4 'c d'";
  items = Lexer::split (unsplit);
  t.is (items.size (), (size_t) 8, "split '  +-* a+b 12.3e4 'c d''");
  t.is (items[0], "+",             "split '  +-* a+b 12.3e4 'c d'' -> [0] '+'");
  t.is (items[1], "-",             "split '  +-* a+b 12.3e4 'c d'' -> [1] '-'");
  t.is (items[2], "*",             "split '  +-* a+b 12.3e4 'c d'' -> [2] '*'");
  t.is (items[3], "a",             "split '  +-* a+b 12.3e4 'c d'' -> [3] 'a'");
  t.is (items[4], "+",             "split '  +-* a+b 12.3e4 'c d'' -> [4] '+'");
  t.is (items[5], "b",             "split '  +-* a+b 12.3e4 'c d'' -> [5] 'b'");
  t.is (items[6], "12.3e4",        "split '  +-* a+b 12.3e4 'c d'' -> [6] '12.3e4'");
  t.is (items[7], "'c d'",         "split '  +-* a+b 12.3e4 'c d'' -> [7] ''c d''");

  // static bool decomposePair (const std::string&, std::string&, std::string&, std::string&, std::string&);
  // 2 * 4 * 2 * 5 = 80 tests.
  std::string outName, outMod, outValue, outSep;
  for (auto& name : {"name"})
  {
    for (auto& mod : {"", "mod"})
    {
      for (auto& sep : {":", "=", "::", ":="})
      {
        for (auto& value : {"", "value", "a:b", "a::b", "a=b", "a:=b"})
        {
          std::string input = std::string ("name") + (strlen (mod) ? "." : "") + mod + sep + value;
          t.ok (Lexer::decomposePair (input, outName, outMod, outSep, outValue), "decomposePair '" + input + "' --> true");
          t.is (name,  outName,  "  '" + input + "' --> name '"  + name  + "'");
          t.is (mod,   outMod,   "  '" + input + "' --> mod '"   + mod   + "'");
          t.is (value, outValue, "  '" + input + "' --> value '" + value + "'");
          t.is (sep,   outSep,   "  '" + input + "' --> sep '"   + sep   + "'");
        }
      }
    }
  }

  // static bool readWord (const std::string&, const std::string&, std::string::size_type&, std::string&);
  std::string::size_type cursor = 0;
  std::string word;
  t.ok (Lexer::readWord ("'one two'", "'\"", cursor, word), "readWord ''one two'' --> true");
  t.is (word, "'one two'",                                  "  word '" + word + "'");
  t.is ((int)cursor, 9,                                     "  cursor");

  // Unterminated quoted string is invalid.
  cursor = 0;
  t.notok (Lexer::readWord ("'one", "'\"", cursor, word),   "readWord ''one' --> false");

  // static bool readWord (const std::string&, std::string::size_type&, std::string&);
  cursor = 0;
  t.ok (Lexer::readWord ("input", cursor, word),            "readWord 'input' --> true");
  t.is (word, "input",                                      "  word '" + word + "'");
  t.is ((int)cursor, 5,                                     "  cursor");

  cursor = 0;
  t.ok (Lexer::readWord ("one\\ two", cursor, word),        "readWord 'one\\ two' --> true");
  t.is (word, "one two",                                    "  word '" + word + "'");
  t.is ((int)cursor, 8,                                     "  cursor");

  cursor = 0;
  t.ok (Lexer::readWord ("\\u20A43", cursor, word),         "readWord '\\u20A43' --> true");
  t.is (word, "₤3",                                         "  word '" + word + "'");
  t.is ((int)cursor, 7,                                     "  cursor");

  cursor = 0;
  t.ok (Lexer::readWord ("U+20AC4", cursor, word),          "readWord '\\u20AC4' --> true");
  t.is (word, "€4",                                         "  word '" + word + "'");
  t.is ((int)cursor, 7,                                     "  cursor");

  std::string text = "one 'two' three\\ four";
  cursor = 0;
  t.ok (Lexer::readWord (text, cursor, word),               "readWord \"one 'two' three\\ four\" --> true");
  t.is (word, "one",                                        "  word '" + word + "'");
  cursor++;
  t.ok (Lexer::readWord (text, cursor, word),               "readWord \"one 'two' three\\ four\" --> true");
  t.is (word, "'two'",                                      "  word '" + word + "'");
  cursor++;
  t.ok (Lexer::readWord (text, cursor, word),               "readWord \"one 'two' three\\ four\" --> true");
  t.is (word, "three four",                                 "  word '" + word + "'");

  text = "one     ";
  cursor = 0;
  t.ok (Lexer::readWord (text, cursor, word),               "readWord \"one     \" --> true");
  t.is (word, "one",                                        "  word '" + word + "'");

  // bool isLiteral (const std::string&, bool, bool);
  Lexer l4 ("one.two");
  t.notok (l4.isLiteral("zero", false, false),              "isLiteral 'one.two' --> false");
  t.ok    (l4.isLiteral("one",  false, false),              "isLiteral 'one.two' --> 'one'");
  t.ok    (l4.isLiteral(".",    false, false),              "isLiteral 'one.two' --> '.'");
  t.ok    (l4.isLiteral("two",  false, true),               "isLiteral 'one.two' --> 'two'");

  Lexer l5 ("wonder");
  t.notok (l5.isLiteral ("wonderful", false, false),        "isLiteral 'wonderful' != 'wonder' without abbreviation");
  t.ok    (l5.isLiteral ("wonderful", true,  false),        "isLiteral 'wonderful' == 'wonder' with abbreviation");

  // bool isOneOf (const std::string&, bool, bool);
  Lexer l6 ("Grumpy.");
  std::vector <std::string> dwarves = {"Sneezy", "Doc", "Bashful", "Grumpy", "Happy", "Sleepy", "Dopey"};
  t.notok (l6.isOneOf (dwarves, false, true),               "isOneof ('Grumpy', true) --> false");
  t.ok    (l6.isOneOf (dwarves, false, false),              "isOneOf ('Grumpy', false) --> true");

  // static std::string::size_type commonLength (const std::string&, const std::string&);
  t.is ((int)Lexer::commonLength ("", ""),           0, "commonLength '' : '' --> 0");
  t.is ((int)Lexer::commonLength ("a", "a"),         1, "commonLength 'a' : 'a' --> 1");
  t.is ((int)Lexer::commonLength ("abcde", "abcde"), 5, "commonLength 'abcde' : 'abcde' --> 5");
  t.is ((int)Lexer::commonLength ("abc", ""),        0, "commonLength 'abc' : '' --> 0");
  t.is ((int)Lexer::commonLength ("abc", "def"),     0, "commonLength 'abc' : 'def' --> 0");
  t.is ((int)Lexer::commonLength ("foobar", "foo"),  3, "commonLength 'foobar' : 'foo' --> 3");
  t.is ((int)Lexer::commonLength ("foo", "foobar"),  3, "commonLength 'foo' : 'foobar' --> 3");

  // static std::string::size_type commonLength (const std::string&, std::string::size_type, const std::string&, std::string::size_type);
  t.is ((int)Lexer::commonLength ("wonder", 0, "prowonderbread", 3), 6, "'wonder'+0 : 'prowonderbread'+3 --> 6");

  // Test all Lexer types.
  #define NO {"",Lexer::Type::word}
  struct
  {
    const char* input;
    struct
    {
      const char* token;
      Lexer::Type type;
    } results[5];
  } lexerTests[] =
  {
    // Pattern
    { "/foo/",                                        { { "/foo/",                                        Lexer::Type::pattern      }, NO, NO, NO, NO }, },
    { "/a\\/b/",                                      { { "/a\\/b/",                                      Lexer::Type::pattern      }, NO, NO, NO, NO }, },
    { "/'/",                                          { { "/'/",                                          Lexer::Type::pattern      }, NO, NO, NO, NO }, },

    // Substitution
    { "/from/to/g",                                   { { "/from/to/g",                                   Lexer::Type::substitution }, NO, NO, NO, NO }, },
    { "/from/to/",                                    { { "/from/to/",                                    Lexer::Type::substitution }, NO, NO, NO, NO }, },

    // Tag
    { "+tag",                                         { { "+tag",                                         Lexer::Type::tag          }, NO, NO, NO, NO }, },
    { "-tag",                                         { { "-tag",                                         Lexer::Type::tag          }, NO, NO, NO, NO }, },
    { "+@tag",                                        { { "+@tag",                                        Lexer::Type::tag          }, NO, NO, NO, NO }, },

    // Path
    { "/long/path/to/file.txt",                       { { "/long/path/to/file.txt",                       Lexer::Type::path         }, NO, NO, NO, NO }, },

    // Word
    { "1.foo.bar",                                    { { "1.foo.bar",                                    Lexer::Type::word         }, NO, NO, NO, NO }, },

    // Identifier
    { "foo",                                          { { "foo",                                          Lexer::Type::identifier   }, NO, NO, NO, NO }, },
    { "Çirçös",                                       { { "Çirçös",                                       Lexer::Type::identifier   }, NO, NO, NO, NO }, },
    { "☺",                                            { { "☺",                                            Lexer::Type::identifier   }, NO, NO, NO, NO }, },
    { "name",                                         { { "name",                                         Lexer::Type::identifier   }, NO, NO, NO, NO }, },
    { "f1",                                           { { "f1",                                           Lexer::Type::identifier   }, NO, NO, NO, NO }, },
    { "foo.bar",                                      { { "foo.bar",                                      Lexer::Type::identifier   }, NO, NO, NO, NO }, },
    { "a1a1a1a1_a1a1_a1a1_a1a1_a1a1a1a1a1a1",         { { "a1a1a1a1_a1a1_a1a1_a1a1_a1a1a1a1a1a1",         Lexer::Type::identifier   }, NO, NO, NO, NO }, },

    // Word that starts wih 'or', which is an operator, but should be ignored.
    { "ordinary",                                     { { "ordinary",                                     Lexer::Type::identifier   }, NO, NO, NO, NO }, },

    // DOM
    { "due",                                          { { "due",                                          Lexer::Type::dom          }, NO, NO, NO, NO }, },
    { "123.tags",                                     { { "123.tags",                                     Lexer::Type::dom          }, NO, NO, NO, NO }, },
    { "123.tags.PENDING",                             { { "123.tags.PENDING",                             Lexer::Type::dom          }, NO, NO, NO, NO }, },
    { "123.description",                              { { "123.description",                              Lexer::Type::dom          }, NO, NO, NO, NO }, },
    { "123.annotations.1.description",                { { "123.annotations.1.description",                Lexer::Type::dom          }, NO, NO, NO, NO }, },
    { "123.annotations.1.entry",                      { { "123.annotations.1.entry",                      Lexer::Type::dom          }, NO, NO, NO, NO }, },
    { "123.annotations.1.entry.year",                 { { "123.annotations.1.entry.year",                 Lexer::Type::dom          }, NO, NO, NO, NO }, },
    { "a360fc44-315c-4366-b70c-ea7e7520b749.due",     { { "a360fc44-315c-4366-b70c-ea7e7520b749.due",     Lexer::Type::dom          }, NO, NO, NO, NO }, },
    { "12345678-1234-1234-1234-123456789012.due",     { { "12345678-1234-1234-1234-123456789012.due",     Lexer::Type::dom          }, NO, NO, NO, NO }, },
    { "system.os",                                    { { "system.os",                                    Lexer::Type::dom          }, NO, NO, NO, NO }, },
    { "rc.foo",                                       { { "rc.foo",                                       Lexer::Type::dom          }, NO, NO, NO, NO }, },

    // URL
    { "http://tasktools.org",                         { { "http://tasktools.org",                         Lexer::Type::url          }, NO, NO, NO, NO }, },
    { "https://bug.tasktools.org",                    { { "https://bug.tasktools.org",                    Lexer::Type::url          }, NO, NO, NO, NO }, },

    // String
    { "'one two'",                                    { { "'one two'",                                    Lexer::Type::string       }, NO, NO, NO, NO }, },
    { "\"three\"",                                    { { "\"three\"",                                    Lexer::Type::string       }, NO, NO, NO, NO }, },
    { "'\\''",                                        { { "'''",                                          Lexer::Type::string       }, NO, NO, NO, NO }, },
    { "\"\\\"\"",                                     { { "\"\"\"",                                       Lexer::Type::string       }, NO, NO, NO, NO }, },
    { "\"\tfoo\t\"",                                  { { "\"\tfoo\t\"",                                  Lexer::Type::string       }, NO, NO, NO, NO }, },
    { "\"\\u20A43\"",                                 { { "\"₤3\"",                                       Lexer::Type::string       }, NO, NO, NO, NO }, },
    { "\"U+20AC4\"",                                  { { "\"€4\"",                                       Lexer::Type::string       }, NO, NO, NO, NO }, },

    // Number
    { "1",                                            { { "1",                                            Lexer::Type::number       }, NO, NO, NO, NO }, },
    { "3.14",                                         { { "3.14",                                         Lexer::Type::number       }, NO, NO, NO, NO }, },
    { "6.02217e23",                                   { { "6.02217e23",                                   Lexer::Type::number       }, NO, NO, NO, NO }, },
    { "1.2e-3.4",                                     { { "1.2e-3.4",                                     Lexer::Type::number       }, NO, NO, NO, NO }, },
    { "0x2f",                                         { { "0x2f",                                         Lexer::Type::hex          }, NO, NO, NO, NO }, },

    // Set (1,2,4-7,9)
    { "1,2",                                          { { "1,2",                                          Lexer::Type::set          }, NO, NO, NO, NO }, },
    { "1-2",                                          { { "1-2",                                          Lexer::Type::set          }, NO, NO, NO, NO }, },
    { "1-2,4",                                        { { "1-2,4",                                        Lexer::Type::set          }, NO, NO, NO, NO }, },
    { "1-2,4,6-8",                                    { { "1-2,4,6-8",                                    Lexer::Type::set          }, NO, NO, NO, NO }, },
    { "1-2,4,6-8,10-12",                              { { "1-2,4,6-8,10-12",                              Lexer::Type::set          }, NO, NO, NO, NO }, },

    // Pair
    { "name:value",                                   { { "name:value",                                   Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "name=value",                                   { { "name=value",                                   Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "name:=value",                                  { { "name:=value",                                  Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "name.mod:value",                               { { "name.mod:value",                               Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "name.mod=value",                               { { "name.mod=value",                               Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "name:",                                        { { "name:",                                        Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "name=",                                        { { "name=",                                        Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "name.mod:",                                    { { "name.mod:",                                    Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "name.mod=",                                    { { "name.mod=",                                    Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "pro:'P 1'",                                    { { "pro:'P 1'",                                    Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "rc:x",                                         { { "rc:x",                                         Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "rc.name:value",                                { { "rc.name:value",                                Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "rc.name=value",                                { { "rc.name=value",                                Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "rc.name:=value",                               { { "rc.name:=value",                               Lexer::Type::pair         }, NO, NO, NO, NO }, },
    { "due:='eow - 2d'",                              { { "due:='eow - 2d'",                              Lexer::Type::pair         }, NO, NO, NO, NO }, },

    // Operator - complete set
    { "^",                                            { { "^",                                            Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "!",                                            { { "!",                                            Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "_neg_",                                        { { "_neg_",                                        Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "_pos_",                                        { { "_pos_",                                        Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "_hastag_",                                     { { "_hastag_",                                     Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "_notag_",                                      { { "_notag_",                                      Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "*",                                            { { "*",                                            Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "/",                                            { { "/",                                            Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "%",                                            { { "%",                                            Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "+",                                            { { "+",                                            Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "-",                                            { { "-",                                            Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "<=",                                           { { "<=",                                           Lexer::Type::op           }, NO, NO, NO, NO }, },
    { ">=",                                           { { ">=",                                           Lexer::Type::op           }, NO, NO, NO, NO }, },
    { ">",                                            { { ">",                                            Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "<",                                            { { "<",                                            Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "=",                                            { { "=",                                            Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "==",                                           { { "==",                                           Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "!=",                                           { { "!=",                                           Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "!==",                                          { { "!==",                                          Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "~",                                            { { "~",                                            Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "!~",                                           { { "!~",                                           Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "and",                                          { { "and",                                          Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "or",                                           { { "or",                                           Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "xor",                                          { { "xor",                                          Lexer::Type::op           }, NO, NO, NO, NO }, },
    { "(",                                            { { "(",                                            Lexer::Type::op           }, NO, NO, NO, NO }, },
    { ")",                                            { { ")",                                            Lexer::Type::op           }, NO, NO, NO, NO }, },

    // UUID
    { "ffffffff-ffff-ffff-ffff-ffffffffffff",         { { "ffffffff-ffff-ffff-ffff-ffffffffffff",         Lexer::Type::uuid         }, NO, NO, NO, NO }, },
    { "00000000-0000-0000-0000-0000000",              { { "00000000-0000-0000-0000-0000000",              Lexer::Type::uuid         }, NO, NO, NO, NO }, },
    { "00000000-0000-0000-0000",                      { { "00000000-0000-0000-0000",                      Lexer::Type::uuid         }, NO, NO, NO, NO }, },
    { "00000000-0000-0000",                           { { "00000000-0000-0000",                           Lexer::Type::uuid         }, NO, NO, NO, NO }, },
    { "00000000-0000",                                { { "00000000-0000",                                Lexer::Type::uuid         }, NO, NO, NO, NO }, },
    { "00000000",                                     { { "00000000",                                     Lexer::Type::uuid         }, NO, NO, NO, NO }, },
    { "a360fc44-315c-4366-b70c-ea7e7520b749",         { { "a360fc44-315c-4366-b70c-ea7e7520b749",         Lexer::Type::uuid         }, NO, NO, NO, NO }, },
    { "a360fc44-315c-4366-b70c-ea7e752",              { { "a360fc44-315c-4366-b70c-ea7e752",              Lexer::Type::uuid         }, NO, NO, NO, NO }, },
    { "a360fc44-315c-4366-b70c",                      { { "a360fc44-315c-4366-b70c",                      Lexer::Type::uuid         }, NO, NO, NO, NO }, },
    { "a360fc44-315c-4366",                           { { "a360fc44-315c-4366",                           Lexer::Type::uuid         }, NO, NO, NO, NO }, },
    { "a360fc44-315c",                                { { "a360fc44-315c",                                Lexer::Type::uuid         }, NO, NO, NO, NO }, },
    { "a360fc44",                                     { { "a360fc44",                                     Lexer::Type::uuid         }, NO, NO, NO, NO }, },

    // Date
    { "2015-W01",                                     { { "2015-W01",                                     Lexer::Type::date         }, NO, NO, NO, NO }, },
    { "2015-02-17",                                   { { "2015-02-17",                                   Lexer::Type::date         }, NO, NO, NO, NO }, },
    { "2013-11-29T22:58:00Z",                         { { "2013-11-29T22:58:00Z",                         Lexer::Type::date         }, NO, NO, NO, NO }, },
    { "20131129T225800Z",                             { { "20131129T225800Z",                             Lexer::Type::date         }, NO, NO, NO, NO }, },
    { "9th",                                          { { "9th",                                          Lexer::Type::date         }, NO, NO, NO, NO }, },
    { "10th",                                         { { "10th",                                         Lexer::Type::date         }, NO, NO, NO, NO }, },
    { "today",                                        { { "today",                                        Lexer::Type::date         }, NO, NO, NO, NO }, },

    // Duration
    { "year",                                         { { "year",                                         Lexer::Type::duration     }, NO, NO, NO, NO }, },
    { "4weeks",                                       { { "4weeks",                                       Lexer::Type::duration     }, NO, NO, NO, NO }, },
    { "PT23H",                                        { { "PT23H",                                        Lexer::Type::duration     }, NO, NO, NO, NO }, },
    { "1second",                                      { { "1second",                                      Lexer::Type::duration     }, NO, NO, NO, NO }, },
    { "1s",                                           { { "1s",                                           Lexer::Type::duration     }, NO, NO, NO, NO }, },
    { "1minute",                                      { { "1minute",                                      Lexer::Type::duration     }, NO, NO, NO, NO }, },
    { "2hour",                                        { { "2hour",                                        Lexer::Type::duration     }, NO, NO, NO, NO }, },
    { "3 days",                                       { { "3 days",                                       Lexer::Type::duration     }, NO, NO, NO, NO }, },
    { "4w",                                           { { "4w",                                           Lexer::Type::duration     }, NO, NO, NO, NO }, },
    { "5mo",                                          { { "5mo",                                          Lexer::Type::duration     }, NO, NO, NO, NO }, },
    { "6 years",                                      { { "6 years",                                      Lexer::Type::duration     }, NO, NO, NO, NO }, },
    { "P1Y",                                          { { "P1Y",                                          Lexer::Type::duration     }, NO, NO, NO, NO }, },
    { "PT1H",                                         { { "PT1H",                                         Lexer::Type::duration     }, NO, NO, NO, NO }, },
    { "P1Y1M1DT1H1M1S",                               { { "P1Y1M1DT1H1M1S",                               Lexer::Type::duration     }, NO, NO, NO, NO }, },

    // Misc
    { "--",                                           { { "--",                                           Lexer::Type::separator    }, NO, NO, NO, NO }, },

    // Expression
    //   due:eom-2w
    //   due < eom + 1w + 1d
    //   ( /pattern/ or 8ad2e3db-914d-4832-b0e6-72fa04f6e331,3b6218f9-726a-44fc-aa63-889ff52be442 )
    { "(1+2)",                                        { { "(",                                            Lexer::Type::op           },
                                                        { "1",                                            Lexer::Type::number       },
                                                        { "+",                                            Lexer::Type::op           },
                                                        { "2",                                            Lexer::Type::number       },
                                                        { ")",                                            Lexer::Type::op           },                }, },
    { "description~pattern",                          { { "description",                                  Lexer::Type::dom          },
                                                        { "~",                                            Lexer::Type::op           },
                                                        { "pattern",                                      Lexer::Type::identifier   },         NO, NO }, },
    { "(+tag)",                                       { { "(",                                            Lexer::Type::op           },
                                                        { "+tag",                                         Lexer::Type::tag          },
                                                        { ")",                                            Lexer::Type::op           },         NO, NO }, },
    { "(name:value)",                                 { { "(",                                            Lexer::Type::op           },
                                                        { "name:value",                                   Lexer::Type::pair         },
                                                        { ")",                                            Lexer::Type::op           },         NO, NO }, },
  };
  #define NUM_TESTS (sizeof (lexerTests) / sizeof (lexerTests[0]))

  for (unsigned int i = 0; i < NUM_TESTS; i++)
  {
    // The isolated test puts the input string directly into the Lexer.
    Lexer isolated (lexerTests[i].input);

    for (int j = 0; j < 5; j++)
    {
      if (lexerTests[i].results[j].token[0])
      {
        // Isolated: "<token>"
        t.ok (isolated.token (token, type),                  "Isolated Lexer::token(...) --> true");
        t.is (token, lexerTests[i].results[j].token,         "  token --> " + token);
        t.is ((int)type, (int)lexerTests[i].results[j].type, "  type --> Lexer::Type::" + Lexer::typeToString (type));
      }
    }

    // The embedded test surrounds the input string with a space.
    Lexer embedded (std::string (" ") + lexerTests[i].input + " ");

    for (int j = 0; j < 5; j++)
    {
      if (lexerTests[i].results[j].token[0])
      {
        // Embedded: "<token>"
        t.ok (embedded.token (token, type),                  "Embedded Lexer::token(...) --> true");
        t.is (token, lexerTests[i].results[j].token,         "  token --> " + token);
        t.is ((int)type, (int)lexerTests[i].results[j].type, "  type --> Lexer::Type::" + Lexer::typeToString (type));
      }
    }
  }

  return 0;
}
Пример #27
0
PTHEntry PTHWriter::LexTokens(Lexer& L) {
  // Pad 0's so that we emit tokens to a 4-byte alignment.
  // This speed up reading them back in.
  using namespace llvm::support;
  endian::Writer<little> LE(Out);
  uint32_t TokenOff = Out.tell();
  for (uint64_t N = llvm::OffsetToAlignment(TokenOff, 4); N; --N, ++TokenOff)
    LE.write<uint8_t>(0);

  // Keep track of matching '#if' ... '#endif'.
  typedef std::vector<std::pair<Offset, unsigned> > PPCondTable;
  PPCondTable PPCond;
  std::vector<unsigned> PPStartCond;
  bool ParsingPreprocessorDirective = false;
  Token Tok;

  do {
    L.LexFromRawLexer(Tok);
  NextToken:

    if ((Tok.isAtStartOfLine() || Tok.is(tok::eof)) &&
        ParsingPreprocessorDirective) {
      // Insert an eod token into the token cache.  It has the same
      // position as the next token that is not on the same line as the
      // preprocessor directive.  Observe that we continue processing
      // 'Tok' when we exit this branch.
      Token Tmp = Tok;
      Tmp.setKind(tok::eod);
      Tmp.clearFlag(Token::StartOfLine);
      Tmp.setIdentifierInfo(nullptr);
      EmitToken(Tmp);
      ParsingPreprocessorDirective = false;
    }

    if (Tok.is(tok::raw_identifier)) {
      PP.LookUpIdentifierInfo(Tok);
      EmitToken(Tok);
      continue;
    }

    if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
      // Special processing for #include.  Store the '#' token and lex
      // the next token.
      assert(!ParsingPreprocessorDirective);
      Offset HashOff = (Offset) Out.tell();

      // Get the next token.
      Token NextTok;
      L.LexFromRawLexer(NextTok);

      // If we see the start of line, then we had a null directive "#".  In
      // this case, discard both tokens.
      if (NextTok.isAtStartOfLine())
        goto NextToken;

      // The token is the start of a directive.  Emit it.
      EmitToken(Tok);
      Tok = NextTok;

      // Did we see 'include'/'import'/'include_next'?
      if (Tok.isNot(tok::raw_identifier)) {
        EmitToken(Tok);
        continue;
      }

      IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok);
      tok::PPKeywordKind K = II->getPPKeywordID();

      ParsingPreprocessorDirective = true;

      switch (K) {
      case tok::pp_not_keyword:
        // Invalid directives "#foo" can occur in #if 0 blocks etc, just pass
        // them through.
      default:
        break;

      case tok::pp_include:
      case tok::pp_import:
      case tok::pp_include_next: {
        // Save the 'include' token.
        EmitToken(Tok);
        // Lex the next token as an include string.
        L.setParsingPreprocessorDirective(true);
        L.LexIncludeFilename(Tok);
        L.setParsingPreprocessorDirective(false);
        assert(!Tok.isAtStartOfLine());
        if (Tok.is(tok::raw_identifier))
          PP.LookUpIdentifierInfo(Tok);

        break;
      }
      case tok::pp_if:
      case tok::pp_ifdef:
      case tok::pp_ifndef: {
        // Add an entry for '#if' and friends.  We initially set the target
        // index to 0.  This will get backpatched when we hit #endif.
        PPStartCond.push_back(PPCond.size());
        PPCond.push_back(std::make_pair(HashOff, 0U));
        break;
      }
      case tok::pp_endif: {
        // Add an entry for '#endif'.  We set the target table index to itself.
        // This will later be set to zero when emitting to the PTH file.  We
        // use 0 for uninitialized indices because that is easier to debug.
        unsigned index = PPCond.size();
        // Backpatch the opening '#if' entry.
        assert(!PPStartCond.empty());
        assert(PPCond.size() > PPStartCond.back());
        assert(PPCond[PPStartCond.back()].second == 0);
        PPCond[PPStartCond.back()].second = index;
        PPStartCond.pop_back();
        // Add the new entry to PPCond.
        PPCond.push_back(std::make_pair(HashOff, index));
        EmitToken(Tok);

        // Some files have gibberish on the same line as '#endif'.
        // Discard these tokens.
        do
          L.LexFromRawLexer(Tok);
        while (Tok.isNot(tok::eof) && !Tok.isAtStartOfLine());
        // We have the next token in hand.
        // Don't immediately lex the next one.
        goto NextToken;
      }
      case tok::pp_elif:
      case tok::pp_else: {
        // Add an entry for #elif or #else.
        // This serves as both a closing and opening of a conditional block.
        // This means that its entry will get backpatched later.
        unsigned index = PPCond.size();
        // Backpatch the previous '#if' entry.
        assert(!PPStartCond.empty());
        assert(PPCond.size() > PPStartCond.back());
        assert(PPCond[PPStartCond.back()].second == 0);
        PPCond[PPStartCond.back()].second = index;
        PPStartCond.pop_back();
        // Now add '#elif' as a new block opening.
        PPCond.push_back(std::make_pair(HashOff, 0U));
        PPStartCond.push_back(index);
        break;
      }
      }
    }

    EmitToken(Tok);
  }
  while (Tok.isNot(tok::eof));

  assert(PPStartCond.empty() && "Error: imblanced preprocessor conditionals.");

  // Next write out PPCond.
  Offset PPCondOff = (Offset) Out.tell();

  // Write out the size of PPCond so that clients can identifer empty tables.
  Emit32(PPCond.size());

  for (unsigned i = 0, e = PPCond.size(); i!=e; ++i) {
    Emit32(PPCond[i].first - TokenOff);
    uint32_t x = PPCond[i].second;
    assert(x != 0 && "PPCond entry not backpatched.");
    // Emit zero for #endifs.  This allows us to do checking when
    // we read the PTH file back in.
    Emit32(x == i ? 0 : x);
  }

  return PTHEntry(TokenOff, PPCondOff);
}
Пример #28
0
Parser::stmt_t Parser::p_stmt_toks(Lexer &lex,const Context &ctx,std::vector<Lexer::Token> *toks){
  Lexer::Token tok,tok1,tok2;
  lex >> tok;

  stmt_t res_stmt = stmt_t::nop();
  std::vector<Lexer::Token> mytoks;

  switch(tok.type){
  case Lexer::NOP:
    ppush(&mytoks,tok);
    res_stmt = stmt_t::nop(tok.pos,mytoks);
    break;
  case Lexer::READ:
    {
      ppush(&mytoks,tok);
      force_toks(lex,Lexer::COLON,&mytoks);
      lex >> tok1;
      if(tok1.type == Lexer::REG){
        ppush(&mytoks,tok1);
        force_toks(lex,Lexer::ASSIGNMENT,&mytoks);
        memloc_or_pointer_t ml = p_memloc_toks(lex,ctx,&mytoks);
        res_stmt = resolve_pointer(ml,[&tok1,&tok](const memloc_t &ml){
            return stmt_t::read_assign(tok1.value,ml,tok.pos);
          },ctx,mytoks);
      }else{
        lex.putback(tok1);
        Parser::memloc_or_pointer_t ml = p_memloc_toks(lex,ctx,&mytoks);
        force_toks(lex,Lexer::EQ,&mytoks);
        expr_t e = p_expr_toks(lex,&mytoks);
        res_stmt = resolve_pointer(ml,[&e,&tok](const memloc_t &ml){
            return stmt_t::read_assert(ml,e,tok.pos);
          },ctx,mytoks);
      }
      break;
    }
  case Lexer::SYNCRD:
    {
      ppush(&mytoks,tok);
      force_toks(lex,Lexer::COLON,&mytoks);
      lex >> tok1;
      if(tok1.type == Lexer::REG){
        ppush(&mytoks,tok1);
        force_toks(lex,Lexer::ASSIGNMENT,&mytoks);
        memloc_or_pointer_t ml = p_memloc_toks(lex,ctx,&mytoks);
        res_stmt = resolve_pointer(ml,[&tok1,&tok](const memloc_t &ml){
            return stmt_t::syncrd_assign(tok1.value,ml,tok.pos);
          },ctx,mytoks);
      }else{
        lex.putback(tok1);
        Parser::memloc_or_pointer_t ml = p_memloc_toks(lex,ctx,&mytoks);
        force_toks(lex,Lexer::EQ,&mytoks);
        expr_t e = p_expr_toks(lex,&mytoks);
        res_stmt = resolve_pointer(ml,[&e,&tok](const memloc_t &ml){
            return stmt_t::syncrd_assert(ml,e,tok.pos);
          },ctx,mytoks);
      }
      break;
    }
  case Lexer::WRITE:
    {
      ppush(&mytoks,tok);
      force_toks(lex,Lexer::COLON,&mytoks);
      Parser::memloc_or_pointer_t ml = p_memloc_toks(lex,ctx,&mytoks);
      force_toks(lex,Lexer::ASSIGNMENT,&mytoks);
      expr_t e = p_expr_toks(lex,&mytoks);
      res_stmt = resolve_pointer(ml,[&e,&tok](const memloc_t &ml){
          return stmt_t::write(ml,e,tok.pos);
        },ctx,mytoks);
      break;
    }
  case Lexer::SYNCWR:
    {
      ppush(&mytoks,tok);
      force_toks(lex,Lexer::COLON,&mytoks);
      Parser::memloc_or_pointer_t ml = p_memloc_toks(lex,ctx,&mytoks);
      force_toks(lex,Lexer::ASSIGNMENT,&mytoks);
      expr_t e = p_expr_toks(lex,&mytoks);
      res_stmt = resolve_pointer(ml,[&e,&tok](const memloc_t &ml){
          return stmt_t::syncwr(ml,e,tok.pos);
        },ctx,mytoks);
      break;
    }
  case Lexer::FENCE:
    {
      ppush(&mytoks,tok);
      res_stmt = stmt_t::full_fence(tok.pos,mytoks);
      break;
    }
  case Lexer::SSFENCE:
    {
      ppush(&mytoks,tok);
      res_stmt = stmt_t::ss_fence(tok.pos,mytoks);
      break;
    }
  case Lexer::LLFENCE:
    {
      ppush(&mytoks,tok);
      res_stmt = stmt_t::ll_fence(tok.pos,mytoks);
      break;
    }
  case Lexer::CAS:
    {
      ppush(&mytoks,tok);
      force_toks(lex,Lexer::LPAREN,&mytoks);
      Parser::memloc_or_pointer_t ml = p_memloc_toks(lex,ctx,&mytoks);
      force_toks(lex,Lexer::COMMA,&mytoks);
      expr_t v0(p_expr_toks(lex,&mytoks));
      force_toks(lex,Lexer::COMMA,&mytoks);
      expr_t v1(p_expr_toks(lex,&mytoks));
      force_toks(lex,Lexer::RPAREN,&mytoks);
      res_stmt = resolve_pointer(ml,[&v0,&v1,&tok](const memloc_t &ml){
          return stmt_t::cas(ml,v0,v1,tok.pos);
        },ctx,mytoks);
      break;
    }
  case Lexer::REG:
    {
      ppush(&mytoks,tok);
      force_toks(lex,Lexer::ASSIGNMENT,&mytoks);
      expr_t e = p_expr_toks(lex,&mytoks);
      res_stmt = stmt_t::assignment(tok.value,e,tok.pos,mytoks);
      break;
    }
  case Lexer::IF:
    {
      ppush(&mytoks,tok);
      bexpr_t b(p_bexpr_toks(lex,&mytoks));

      force_toks(lex,Lexer::THEN,&mytoks);
      stmt_t::labeled_stmt_t s0 = p_lstmt(lex,ctx,&mytoks);
      lex >> tok1;
      if(tok1.type == Lexer::ELSE){
        ppush(&mytoks,tok1);
        stmt_t::labeled_stmt_t s1 = p_lstmt(lex,ctx,&mytoks);
        res_stmt = stmt_t::if_stmt(b,s0,s1,tok.pos,mytoks);
      }else{
        lex.putback(tok1);
        res_stmt = stmt_t::if_stmt(b,s0,tok.pos,mytoks);
      }
      break;
    }
  case Lexer::WHILE:
    {
      ppush(&mytoks,tok);
      bexpr_t b(p_bexpr_toks(lex,&mytoks));
      force_toks(lex,Lexer::DO,&mytoks);
      stmt_t::labeled_stmt_t s = p_lstmt(lex,ctx,&mytoks);
      res_stmt = stmt_t::while_stmt(b,s,tok.pos,mytoks);
      break;
    }
  case Lexer::GOTO:
    {
      ppush(&mytoks,tok);
      Lang::label_t lbl = p_label(lex,&mytoks);
      res_stmt = stmt_t::goto_stmt(lbl,tok.pos,mytoks);
      break;
    }
  case Lexer::EITHER:
    {
      ppush(&mytoks,tok);
      Lexer::TokenPos pos0 = tok.pos;
      std::vector<stmt_t> seq;
      Lexer::Token lctok;
      Lexer::Token tok;
      lex >> lctok;
      lex.putback(lctok);
      force_toks(lex,Lexer::LCURL,&mytoks);

      seq.push_back(p_stmt_list(lex,ctx,&mytoks));
      lex >> tok;
      while(tok.type == Lexer::EITHER_OR){
        ppush(&mytoks,tok);
        seq.push_back(p_stmt_list(lex,ctx,&mytoks));
        lex >> tok;
      }
      lex.putback(tok);
      force_toks(lex,Lexer::RCURL,&mytoks,"Expected '}' at "," to match '{' at "+
                 lctok.pos.to_long_string()+".");

      res_stmt = stmt_t::either(seq,pos0);
      break;
    }
  case Lexer::LOCKED:
    {
      ppush(&mytoks,tok);
      Lexer::TokenPos pos0 = tok.pos;
      std::vector<stmt_t> seq;
      Lexer::Token lctok;
      Lexer::Token tok;
      lex >> lctok;
      if(lctok.type == Lexer::WRITE){
        ppush(&mytoks,lctok);
        force_toks(lex,Lexer::COLON,&mytoks);
        Parser::memloc_or_pointer_t ml = p_memloc_toks(lex,ctx,&mytoks);
        force_toks(lex,Lexer::ASSIGNMENT,&mytoks);
        expr_t e = p_expr_toks(lex,&mytoks);
        res_stmt = resolve_pointer(ml,[&e,&pos0](const memloc_t &ml){
            return stmt_t::locked_write(ml,e,pos0);
          },ctx,mytoks);
      }else{
        lex.putback(lctok);
        force_toks(lex,Lexer::LCURL,&mytoks);

        stmt_t s = p_stmt_list(lex,ctx,&mytoks);
        std::string cmt;
        if(!stmt_t::check_locked_invariant(s,&cmt)){
          throw new SyntaxError("Error in locked block at "+lctok.pos.to_long_string()+": "+cmt,lctok.pos);
        }
        seq.push_back(s);
        lex >> tok;
        while(tok.type == Lexer::EITHER_OR){
          ppush(&mytoks,tok);
          s = p_stmt_list(lex,ctx,&mytoks);
          if(!stmt_t::check_locked_invariant(s,&cmt)){
            throw new SyntaxError("Error in locked block at "+tok.pos.to_long_string()+": "+cmt,tok.pos);
          }
          seq.push_back(s);
          lex >> tok;
        }
        lex.putback(tok);
        force_toks(lex,Lexer::RCURL,&mytoks,"Expected '}' at "," to match '{' at "+
                   lctok.pos.to_long_string()+".");

        res_stmt = stmt_t::locked_block(seq,pos0);
      }
      break;
    }
 case Lexer::SLOCKED:
    {
      Lexer::TokenPos pos0 = tok.pos;
      force(lex,Lexer::WRITE);
      force(lex,Lexer::COLON);
      Parser::memloc_or_pointer_t ml = p_memloc(lex,ctx);
      force(lex,Lexer::ASSIGNMENT);
      expr_t e = p_expr(lex);
      return resolve_pointer(ml,[&e,&pos0](const memloc_t &ml){
          return stmt_t::slocked_write(ml,e,pos0);
        },ctx,mytoks);
    }
  case Lexer::LCURL:
    {
      ppush(&mytoks,tok);
      stmt_t sl = p_stmt_list(lex,ctx,&mytoks);
      force_toks(lex,Lexer::RCURL,&mytoks,"Expected '}' at "," to match '{' at "+
                 tok.pos.to_long_string()+".");
      res_stmt = sl;
      break;
    }
  case Lexer::ASSUME:
    {
      ppush(&mytoks,tok);
      force_toks(lex,Lexer::COLON,&mytoks);
      bexpr_t cnd = p_bexpr_toks(lex,&mytoks);
      res_stmt = stmt_t::assume(cnd,tok.pos,mytoks);
      break;
    }
  default:
    throw new SyntaxError("Expected statement at "+tok.pos.to_long_string()+".",tok.pos);
  }
  if(toks) toks->insert(toks->end(),mytoks.begin(),mytoks.end());
  return res_stmt;
}
Пример #29
0
void Layout::readArgument(Lexer & lex)
{
	latexarg arg;
	// writeArgument() makes use of these default values
	arg.mandatory = false;
	arg.autoinsert = false;
	bool error = false;
	bool finished = false;
	arg.font = inherit_font;
	arg.labelfont = inherit_font;
	string id;
	lex >> id;
	bool const itemarg = prefixIs(id, "item:");
	bool const postcmd = prefixIs(id, "post:");

	while (!finished && lex.isOK() && !error) {
		lex.next();
		string const tok = ascii_lowercase(lex.getString());

		if (tok.empty()) {
			continue;
		} else if (tok == "endargument") {
			finished = true;
		} else if (tok == "labelstring") {
			lex.next();
			arg.labelstring = lex.getDocString();
		} else if (tok == "menustring") {
			lex.next();
			arg.menustring = lex.getDocString();
		} else if (tok == "mandatory") {
			lex.next();
			arg.mandatory = lex.getBool();
		} else if (tok == "autoinsert") {
			lex.next();
			arg.autoinsert = lex.getBool();
		} else if (tok == "leftdelim") {
			lex.next();
			arg.ldelim = lex.getDocString();
			arg.ldelim = support::subst(arg.ldelim, from_ascii("<br/>"),
						    from_ascii("\n"));
		} else if (tok == "rightdelim") {
			lex.next();
			arg.rdelim = lex.getDocString();
			arg.rdelim = support::subst(arg.rdelim, from_ascii("<br/>"),
						    from_ascii("\n"));
		} else if (tok == "defaultarg") {
			lex.next();
			arg.defaultarg = lex.getDocString();
		} else if (tok == "presetarg") {
			lex.next();
			arg.presetarg = lex.getDocString();
		} else if (tok == "tooltip") {
			lex.next();
			arg.tooltip = lex.getDocString();
		} else if (tok == "requires") {
			lex.next();
			arg.requires = lex.getString();
		} else if (tok == "decoration") {
			lex.next();
			arg.decoration = lex.getString();
		} else if (tok == "font") {
			arg.font = lyxRead(lex, arg.font);
		} else if (tok == "labelfont") {
			arg.labelfont = lyxRead(lex, arg.labelfont);
		} else {
			lex.printError("Unknown tag");
			error = true;
		}
	}
	if (arg.labelstring.empty())
		LYXERR0("Incomplete Argument definition!");
	else if (itemarg)
		itemargs_[id] = arg;
	else if (postcmd)
		postcommandargs_[id] = arg;
	else
		latexargs_[id] = arg;
}
Пример #30
0
ExpPtr parseiPut (Lexer& lex)
{
	throw lex.current().span.die("^put unimplemented");
}