175 lines
6.0 KiB
C++
Executable File
175 lines
6.0 KiB
C++
Executable File
// ======================================================================== //
|
|
// Copyright 2009-2014 Intel Corporation //
|
|
// //
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
|
// you may not use this file except in compliance with the License. //
|
|
// You may obtain a copy of the License at //
|
|
// //
|
|
// http://www.apache.org/licenses/LICENSE-2.0 //
|
|
// //
|
|
// Unless required by applicable law or agreed to in writing, software //
|
|
// distributed under the License is distributed on an "AS IS" BASIS, //
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
|
// See the License for the specific language governing permissions and //
|
|
// limitations under the License. //
|
|
// ======================================================================== //
|
|
|
|
#include "tokenstream.h"
|
|
|
|
namespace embree
|
|
{
|
|
/* shorthands for common sets of characters */
|
|
const std::string TokenStream::alpha = "abcdefghijklmnopqrstuvwxyz";
|
|
const std::string TokenStream::ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
const std::string TokenStream::numbers = "0123456789";
|
|
const std::string TokenStream::separators = "\n\t\r ";
|
|
|
|
/* creates map for fast categorization of characters */
|
|
static void createCharMap(bool map[256], const std::string& chrs) {
|
|
for (size_t i=0; i<256; i++) map[i] = false;
|
|
for (size_t i=0; i<chrs.size(); i++) map[uint8(chrs[i])] = true;
|
|
}
|
|
|
|
/* build full tokenizer that takes list of valid characters and keywords */
|
|
TokenStream::TokenStream(const Ref<Stream<int> >& cin, //< stream to read from
|
|
const std::string& alpha, //< valid characters for identifiers
|
|
const std::string& seps, //< characters that act as separators
|
|
const std::vector<std::string>& symbols) //< symbols
|
|
: cin(cin), symbols(symbols)
|
|
{
|
|
createCharMap(isAlphaMap,alpha);
|
|
createCharMap(isSepMap,seps);
|
|
}
|
|
|
|
bool TokenStream::decDigits(std::string& str_o)
|
|
{
|
|
bool ok = false;
|
|
std::string str;
|
|
if (cin->peek() == '+' || cin->peek() == '-') str += (char)cin->get();
|
|
while (isDigit(cin->peek())) { ok = true; str += (char)cin->get(); }
|
|
if (ok) str_o += str;
|
|
else cin->unget(str.size());
|
|
return ok;
|
|
}
|
|
|
|
bool TokenStream::decDigits1(std::string& str_o)
|
|
{
|
|
bool ok = false;
|
|
std::string str;
|
|
while (isDigit(cin->peek())) { ok = true; str += (char)cin->get(); }
|
|
if (ok) str_o += str; else cin->unget(str.size());
|
|
return ok;
|
|
}
|
|
|
|
bool TokenStream::trySymbol(const std::string& symbol)
|
|
{
|
|
size_t pos = 0;
|
|
while (pos < symbol.size()) {
|
|
if (symbol[pos] != cin->peek()) { cin->unget(pos); return false; }
|
|
cin->drop(); pos++;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TokenStream::trySymbols(Token& token, const ParseLocation& loc)
|
|
{
|
|
for (size_t i=0; i<symbols.size(); i++) {
|
|
if (!trySymbol(symbols[i])) continue;
|
|
token = Token(symbols[i],Token::TY_SYMBOL,loc);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool TokenStream::tryFloat(Token& token, const ParseLocation& loc)
|
|
{
|
|
bool ok = false;
|
|
std::string str;
|
|
if (decDigits(str))
|
|
{
|
|
if (cin->peek() == '.') {
|
|
str += (char)cin->get();
|
|
decDigits(str);
|
|
if (cin->peek() == 'e' || cin->peek() == 'E') {
|
|
str += (char)cin->get();
|
|
if (decDigits(str)) ok = true; // 1.[2]E2
|
|
}
|
|
else ok = true; // 1.[2]
|
|
}
|
|
else if (cin->peek() == 'e' || cin->peek() == 'E') {
|
|
str += (char)cin->get();
|
|
if (decDigits(str)) ok = true; // 1E2
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (cin->peek() == '.') {
|
|
str += (char)cin->get();
|
|
if (decDigits(str)) {
|
|
if (cin->peek() == 'e' || cin->peek() == 'E') {
|
|
str += (char)cin->get();
|
|
if (decDigits(str)) ok = true; // .3E2
|
|
}
|
|
else ok = true; // .3
|
|
}
|
|
}
|
|
}
|
|
if (ok) {
|
|
token = Token((float)atof(str.c_str()),loc);
|
|
}
|
|
else cin->unget(str.size());
|
|
return ok;
|
|
}
|
|
|
|
bool TokenStream::tryInt(Token& token, const ParseLocation& loc) {
|
|
std::string str;
|
|
if (decDigits(str)) {
|
|
token = Token(atoi(str.c_str()),loc);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool TokenStream::tryString(Token& token, const ParseLocation& loc)
|
|
{
|
|
std::string str;
|
|
if (cin->peek() != '\"') return false;
|
|
cin->drop();
|
|
while (cin->peek() != '\"') str += (char)cin->get();
|
|
cin->drop();
|
|
token = Token(str,Token::TY_STRING,loc);
|
|
return true;
|
|
}
|
|
|
|
bool TokenStream::tryIdentifier(Token& token, const ParseLocation& loc)
|
|
{
|
|
std::string str;
|
|
if (!isAlpha(cin->peek())) return false;
|
|
str += (char)cin->get();
|
|
while (isAlphaNum(cin->peek())) str += (char)cin->get();
|
|
token = Token(str,Token::TY_IDENTIFIER,loc);
|
|
return true;
|
|
}
|
|
|
|
void TokenStream::skipSeparators()
|
|
{
|
|
/* skip separators */
|
|
while (cin->peek() != EOF && isSeparator(cin->peek()))
|
|
cin->drop();
|
|
}
|
|
|
|
Token TokenStream::next()
|
|
{
|
|
Token token;
|
|
skipSeparators();
|
|
ParseLocation loc = cin->loc();
|
|
if (trySymbols (token,loc)) return token; /**< try to parse a symbol */
|
|
if (tryFloat (token,loc)) return token; /**< try to parse float */
|
|
if (tryInt (token,loc)) return token; /**< try to parse integer */
|
|
if (tryString (token,loc)) return token; /**< try to parse string */
|
|
if (tryIdentifier(token,loc)) return token; /**< try to parse identifier */
|
|
if (cin->peek() == EOF ) return Token(loc); /**< return EOF token */
|
|
return Token((char)cin->get(),loc); /**< return invalid character token */
|
|
}
|
|
}
|