mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-08-20 04:13:07 +02:00
Code Cleanup
- Eliminated Lexer.
This commit is contained in:
parent
0c08b29e48
commit
9bf1ec2f7c
8 changed files with 5 additions and 989 deletions
|
@ -6,13 +6,10 @@ Deprecated Code
|
|||
This is code that is going to be phased out "soon", and therefore is not
|
||||
worth fixing or documenting.
|
||||
|
||||
- Arguments.{h,cpp}
|
||||
- Expression.{h,cpp}
|
||||
- Variant.{h,cpp}
|
||||
- Location.{h,cpp}
|
||||
- TDB.{h,cpp}
|
||||
- Att.{h,cpp}
|
||||
- Lexer.{h,cpp}
|
||||
|
||||
New Code Needs
|
||||
This is code that needs to be written, usually down at the C++ function level.
|
||||
|
|
|
@ -19,7 +19,6 @@ set (task_SRCS A3.cpp A3.h
|
|||
File.cpp File.h
|
||||
Hooks.cpp Hooks.h
|
||||
JSON.cpp JSON.h
|
||||
Lexer.cpp Lexer.h
|
||||
Location.cpp Location.h
|
||||
Nibbler.cpp Nibbler.h
|
||||
Path.cpp Path.h
|
||||
|
|
374
src/Lexer.cpp
374
src/Lexer.cpp
|
@ -1,374 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - a command line task list manager.
|
||||
//
|
||||
// Copyright 2011, Paul Beckingham, Federico Hernandez.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// This lexer works by breaking the input stream into tokens. The essence of
|
||||
// the algorithm lies in the distinction between adjacent tokens, such that
|
||||
// between the two extremes lies a good solution.
|
||||
//
|
||||
// At one extreme, the entire input is considered one token. Clearly this is
|
||||
// only correct for trivial input. At the other extreme, every character of the
|
||||
// input is a token. This is also wrong.
|
||||
//
|
||||
// If the input is as follows:
|
||||
//
|
||||
// It is almost 11:00am.
|
||||
//
|
||||
// The desired tokenization is:
|
||||
//
|
||||
// It
|
||||
// <space>
|
||||
// is
|
||||
// <space>
|
||||
// almost
|
||||
// <space>
|
||||
// 11
|
||||
// :
|
||||
// 00
|
||||
// am
|
||||
// .
|
||||
// \n
|
||||
//
|
||||
// This can be achieved by allowing transitions to denote token boundaries.
|
||||
// Given the following character classes:
|
||||
//
|
||||
// letter: a-z A-Z
|
||||
// digit: 0-9
|
||||
// whitespace: <space> <tab> <newline> <cr> <lf> <vertical-tab>
|
||||
// other: Everything else
|
||||
//
|
||||
// Then a token boundary is a transition between:
|
||||
// letter -> !letter
|
||||
// digit -> !digit
|
||||
// whitespace -> any
|
||||
// other -> any
|
||||
//
|
||||
// This has the effect of allowing groups of consecutive letters to be
|
||||
// considered one token, as well as groups of digits.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include <util.h>
|
||||
#include <Lexer.h>
|
||||
|
||||
static const int other = -1;
|
||||
static const int alpha = -2;
|
||||
static const int digit = -3;
|
||||
static const int white = -4;
|
||||
static const int quote = -5;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Lexer::Lexer (const std::string& input)
|
||||
: mInput (input)
|
||||
|
||||
, mAlpha ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
, mDigit ("0123456789")
|
||||
, mQuote ("'\"")
|
||||
, mWhite (" \t\n\r\f")
|
||||
|
||||
, mAlphaCoalesce (true)
|
||||
, mDigitCoalesce (true)
|
||||
, mQuotedCoalesce (false)
|
||||
, mWhiteCoalesce (false)
|
||||
, mSkipWhitespace (false)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::tokenize (std::vector <std::string>& all)
|
||||
{
|
||||
all.clear (); // Prevent repeated accumulation.
|
||||
|
||||
std::string token;
|
||||
bool inQuote = false;
|
||||
char quoteChar = '\0';
|
||||
for (unsigned int i = 0; i < mInput.length (); ++i)
|
||||
{
|
||||
bool specialFound = false;
|
||||
for (unsigned int s = 0; s < mSpecialTokens.size (); ++s)
|
||||
{
|
||||
std::string potential = mInput.substr (
|
||||
i, min (mSpecialTokens[s].length (), mInput.length () - i));
|
||||
|
||||
if (potential == mSpecialTokens[s])
|
||||
{
|
||||
// Capture currently assembled token, the special token, increment over
|
||||
// that token, and skip all remaining code in the loop.
|
||||
if (token.length ())
|
||||
{
|
||||
all.push_back (token);
|
||||
token = "";
|
||||
}
|
||||
|
||||
all.push_back (potential);
|
||||
i += potential.length () - 1;
|
||||
specialFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (specialFound)
|
||||
continue;
|
||||
|
||||
char c = mInput[i];
|
||||
char next = '\0';
|
||||
if (i < mInput.length () - 1)
|
||||
next = mInput[i + 1];
|
||||
|
||||
// Classify current and next characters.
|
||||
int thisChar = classify (c);
|
||||
int nextChar = classify (next);
|
||||
|
||||
// Properly set inQuote, quoteChar.
|
||||
if (!inQuote && thisChar == quote)
|
||||
{
|
||||
quoteChar = c;
|
||||
inQuote = true;
|
||||
}
|
||||
else if (inQuote && c == quoteChar)
|
||||
{
|
||||
inQuote = false;
|
||||
}
|
||||
|
||||
// Detect transitions.
|
||||
bool transition = false;
|
||||
if (thisChar != nextChar)
|
||||
transition = true;
|
||||
|
||||
token += c;
|
||||
|
||||
// Transitions mean new token. All 'other' characters are separate tokens.
|
||||
if (transition || nextChar == other)
|
||||
{
|
||||
if (!inQuote || !mQuotedCoalesce)
|
||||
{
|
||||
if (!mSkipWhitespace || thisChar != white)
|
||||
all.push_back (token);
|
||||
token = "";
|
||||
}
|
||||
}
|
||||
|
||||
// Non-transitions - runs.
|
||||
else
|
||||
{
|
||||
// Runs may be optionally coalesced.
|
||||
if (!(mAlphaCoalesce && nextChar == alpha) &&
|
||||
!(mDigitCoalesce && nextChar == digit) &&
|
||||
!(mWhiteCoalesce && nextChar == white))
|
||||
{
|
||||
if (!inQuote || !mQuotedCoalesce)
|
||||
{
|
||||
if (!mSkipWhitespace || thisChar != white)
|
||||
all.push_back (token);
|
||||
token = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::categorizeAsAlpha (char value)
|
||||
{
|
||||
if (mAlpha.find (value) == std::string::npos)
|
||||
mAlpha += value;
|
||||
|
||||
std::string::size_type pos;
|
||||
if ((pos = mDigit.find (value)) != std::string::npos) mDigit.erase (pos, 1);
|
||||
if ((pos = mQuote.find (value)) != std::string::npos) mQuote.erase (pos, 1);
|
||||
if ((pos = mWhite.find (value)) != std::string::npos) mWhite.erase (pos, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::ignoreAsAlpha (char value)
|
||||
{
|
||||
std::string::size_type pos;
|
||||
if ((pos = mAlpha.find (value)) != std::string::npos) mAlpha.erase (pos, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::setAlpha (const std::string& value)
|
||||
{
|
||||
mAlpha = value;
|
||||
|
||||
std::string::size_type pos;
|
||||
for (unsigned int i = 0; i < mAlpha.length (); ++i)
|
||||
{
|
||||
if ((pos = mDigit.find (mAlpha[i])) != std::string::npos) mDigit.erase (pos, 1);
|
||||
if ((pos = mQuote.find (mAlpha[i])) != std::string::npos) mQuote.erase (pos, 1);
|
||||
if ((pos = mWhite.find (mAlpha[i])) != std::string::npos) mWhite.erase (pos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::categorizeAsDigit (char value)
|
||||
{
|
||||
if (mDigit.find (value) == std::string::npos)
|
||||
mDigit += value;
|
||||
|
||||
std::string::size_type pos;
|
||||
if ((pos = mAlpha.find (value)) != std::string::npos) mAlpha.erase (pos, 1);
|
||||
if ((pos = mQuote.find (value)) != std::string::npos) mQuote.erase (pos, 1);
|
||||
if ((pos = mWhite.find (value)) != std::string::npos) mWhite.erase (pos, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::ignoreAsDigit (char value)
|
||||
{
|
||||
std::string::size_type pos;
|
||||
if ((pos = mDigit.find (value)) != std::string::npos) mDigit.erase (pos, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::setDigit (const std::string& value)
|
||||
{
|
||||
mDigit = value;
|
||||
|
||||
std::string::size_type pos;
|
||||
for (unsigned int i = 0; i < mDigit.length (); ++i)
|
||||
{
|
||||
if ((pos = mAlpha.find (mDigit[i])) != std::string::npos) mAlpha.erase (pos, 1);
|
||||
if ((pos = mQuote.find (mDigit[i])) != std::string::npos) mQuote.erase (pos, 1);
|
||||
if ((pos = mWhite.find (mDigit[i])) != std::string::npos) mWhite.erase (pos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::categorizeAsQuote (char value)
|
||||
{
|
||||
if (mQuote.find (value) == std::string::npos)
|
||||
mQuote += value;
|
||||
|
||||
std::string::size_type pos;
|
||||
if ((pos = mAlpha.find (value)) != std::string::npos) mAlpha.erase (pos, 1);
|
||||
if ((pos = mDigit.find (value)) != std::string::npos) mDigit.erase (pos, 1);
|
||||
if ((pos = mWhite.find (value)) != std::string::npos) mWhite.erase (pos, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::ignoreAsQuote (char value)
|
||||
{
|
||||
std::string::size_type pos;
|
||||
if ((pos = mQuote.find (value)) != std::string::npos) mQuote.erase (pos, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::setQuote (const std::string& value)
|
||||
{
|
||||
mQuote = value;
|
||||
|
||||
std::string::size_type pos;
|
||||
for (unsigned int i = 0; i < mQuote.length (); ++i)
|
||||
{
|
||||
if ((pos = mAlpha.find (mQuote[i])) != std::string::npos) mAlpha.erase (pos, 1);
|
||||
if ((pos = mDigit.find (mQuote[i])) != std::string::npos) mDigit.erase (pos, 1);
|
||||
if ((pos = mWhite.find (mQuote[i])) != std::string::npos) mWhite.erase (pos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::categorizeAsWhite (char value)
|
||||
{
|
||||
if (mWhite.find (value) == std::string::npos)
|
||||
mWhite += value;
|
||||
|
||||
std::string::size_type pos;
|
||||
if ((pos = mAlpha.find (value)) != std::string::npos) mAlpha.erase (pos, 1);
|
||||
if ((pos = mDigit.find (value)) != std::string::npos) mDigit.erase (pos, 1);
|
||||
if ((pos = mQuote.find (value)) != std::string::npos) mQuote.erase (pos, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::ignoreAsWhite (char value)
|
||||
{
|
||||
std::string::size_type pos;
|
||||
if ((pos = mWhite.find (value)) != std::string::npos) mWhite.erase (pos, 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::setWhite (const std::string& value)
|
||||
{
|
||||
mWhite = value;
|
||||
|
||||
std::string::size_type pos;
|
||||
for (unsigned int i = 0; i < mWhite.length (); ++i)
|
||||
{
|
||||
if ((pos = mAlpha.find (mWhite[i])) != std::string::npos) mAlpha.erase (pos, 1);
|
||||
if ((pos = mDigit.find (mWhite[i])) != std::string::npos) mDigit.erase (pos, 1);
|
||||
if ((pos = mQuote.find (mWhite[i])) != std::string::npos) mQuote.erase (pos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::coalesceAlpha (bool value)
|
||||
{
|
||||
mAlphaCoalesce = value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::coalesceDigits (bool value)
|
||||
{
|
||||
mDigitCoalesce = value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::coalesceQuoted (bool value)
|
||||
{
|
||||
mQuotedCoalesce = value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::coalesceWhite (bool value)
|
||||
{
|
||||
mWhiteCoalesce = value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::skipWhitespace (bool value)
|
||||
{
|
||||
mSkipWhitespace = value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Lexer::specialToken (const std::string& special)
|
||||
{
|
||||
mSpecialTokens.push_back (special);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Lexer::classify (char c)
|
||||
{
|
||||
if (mAlpha.find (c) != std::string::npos) return alpha;
|
||||
if (mDigit.find (c) != std::string::npos) return digit;
|
||||
if (mWhite.find (c) != std::string::npos) return white;
|
||||
if (mQuote.find (c) != std::string::npos) return quote;
|
||||
|
||||
return other;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
84
src/Lexer.h
84
src/Lexer.h
|
@ -1,84 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - a command line task list manager.
|
||||
//
|
||||
// Copyright 2011, Paul Beckingham, Federico Hernandez.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_LEXER
|
||||
#define INCLUDED_LEXER
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class Lexer
|
||||
{
|
||||
public:
|
||||
Lexer (const std::string&);
|
||||
void tokenize (std::vector <std::string>&);
|
||||
|
||||
void categorizeAsAlpha (char);
|
||||
void ignoreAsAlpha (char);
|
||||
void setAlpha (const std::string&);
|
||||
|
||||
void categorizeAsDigit (char);
|
||||
void ignoreAsDigit (char);
|
||||
void setDigit (const std::string&);
|
||||
|
||||
void categorizeAsQuote (char);
|
||||
void ignoreAsQuote (char);
|
||||
void setQuote (const std::string&);
|
||||
|
||||
void categorizeAsWhite (char);
|
||||
void ignoreAsWhite (char);
|
||||
void setWhite (const std::string&);
|
||||
|
||||
void coalesceAlpha (bool);
|
||||
void coalesceDigits (bool);
|
||||
void coalesceQuoted (bool);
|
||||
void coalesceWhite (bool);
|
||||
void skipWhitespace (bool);
|
||||
void specialToken (const std::string&);
|
||||
|
||||
private:
|
||||
int classify (char);
|
||||
|
||||
std::string mInput;
|
||||
|
||||
std::string mAlpha;
|
||||
std::string mDigit;
|
||||
std::string mQuote;
|
||||
std::string mWhite;
|
||||
|
||||
bool mAlphaCoalesce;
|
||||
bool mDigitCoalesce;
|
||||
bool mQuotedCoalesce;
|
||||
bool mWhiteCoalesce;
|
||||
bool mSkipWhitespace;
|
||||
|
||||
std::vector <std::string> mSpecialTokens;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -6,11 +6,10 @@ include_directories (${CMAKE_SOURCE_DIR}
|
|||
${CMAKE_SOURCE_DIR}/test
|
||||
${TASK_INCLUDE_DIRS})
|
||||
|
||||
set (test_SRCS arguments.t att.t autocomplete.t color.t config.t date.t
|
||||
directory.t dom.t duration.t file.t i18n.t json.t lexer.t list.t
|
||||
nibbler.t path.t record.t rx.t t.benchmark.t t.t taskmod.t tdb.t
|
||||
tdb2.t text.t uri.t util.t variant.t view.t
|
||||
json_test)
|
||||
set (test_SRCS att.t autocomplete.t color.t config.t date.t directory.t dom.t
|
||||
duration.t file.t i18n.t json.t list.t nibbler.t path.t record.t
|
||||
rx.t t.benchmark.t t.t taskmod.t tdb.t tdb2.t text.t uri.t util.t
|
||||
variant.t view.t json_test)
|
||||
|
||||
add_custom_target (test ./run_all DEPENDS ${test_SRCS}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/test)
|
||||
|
|
|
@ -1,190 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <Context.h>
|
||||
#include <Arguments.h>
|
||||
#include <text.h>
|
||||
#include <test.h>
|
||||
|
||||
Context context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
UnitTest t (95);
|
||||
|
||||
const char* fake[] =
|
||||
{
|
||||
// task list proj:foo 1,3,5-10 12 pattern1 rc.name1=value1 rc.name2:value2 \
|
||||
// 234 -- pattern2 n:v
|
||||
"task", // context.program
|
||||
"list", // command
|
||||
"proj:foo", // n:v
|
||||
"1,3,5-10", // sequence
|
||||
"12", // sequence
|
||||
"pattern1", // text
|
||||
"rc.name1=value1", // n:v
|
||||
"rc.name2:value2", // n:v
|
||||
"234", // text
|
||||
"--", // terminator
|
||||
"pattern2", // text
|
||||
"n:v", // text (due to terminator)
|
||||
};
|
||||
|
||||
// void capture (int, char**);
|
||||
Arguments a1;
|
||||
a1.capture (12, &fake[0]);
|
||||
t.is (a1.size (), (size_t)12, "12 arguments expected");
|
||||
|
||||
// std::string combine ();
|
||||
t.is (a1.combine (),
|
||||
"task list proj:foo 1,3,5-10 12 pattern1 rc.name1=value1 rc.name2:value2 "
|
||||
"234 -- pattern2 n:v",
|
||||
"combine good");
|
||||
|
||||
// bool is_attr (const std::string&);
|
||||
t.ok (Arguments::is_attr ("project:"), "name: -> attr");
|
||||
t.ok (Arguments::is_attr ("project:\"\""), "name:\"\" -> attr");
|
||||
t.ok (Arguments::is_attr ("project:one"), "name:one -> attr");
|
||||
t.ok (Arguments::is_attr ("project:\"one\""), "name:\"one\" -> attr");
|
||||
t.ok (Arguments::is_attr ("project:\"one two\""), "name:\"one two\" -> attr");
|
||||
|
||||
t.notok (Arguments::is_attr ("name"), "name -> not attr");
|
||||
t.notok (Arguments::is_attr ("(name=val and 1<2)"), "(name=val and 1<2) -> not attr");
|
||||
|
||||
// bool is_attmod (const std::string&);
|
||||
t.ok (Arguments::is_attmod ("project.is:"), "name.is: -> attmod");
|
||||
t.ok (Arguments::is_attmod ("project.is:\"\""), "name.is:\"\" -> attmod");
|
||||
t.ok (Arguments::is_attmod ("project.is:one"), "name.is:one -> attmod");
|
||||
t.ok (Arguments::is_attmod ("project.is:\"one\""), "name.is:\"one\" -> attmod");
|
||||
t.ok (Arguments::is_attmod ("project.is:\"one two\""), "name.is:\"one two\" -> attmod");
|
||||
|
||||
t.notok (Arguments::is_attmod ("name"), "name -> not attmod");
|
||||
t.notok (Arguments::is_attmod ("(name=value and 1<2"), "(name=value and 1<2 -> not attmod");
|
||||
|
||||
// bool is_subst (const std::string&);
|
||||
t.notok (Arguments::is_subst ("///"), "/// -> not subst");
|
||||
t.notok (Arguments::is_subst ("//to/"), "//to/ -> not subst");
|
||||
t.ok (Arguments::is_subst ("/from//"), "/from// -> subst");
|
||||
t.ok (Arguments::is_subst ("/from/to/"), "/from/to/ -> subst");
|
||||
t.ok (Arguments::is_subst ("/from from/to to/"), "/from from/to to/ -> subst");
|
||||
|
||||
t.notok (Arguments::is_subst ("///g"), "///g -> not subst");
|
||||
t.notok (Arguments::is_subst ("//to/g"), "//to/g -> not subst");
|
||||
t.ok (Arguments::is_subst ("/from//g"), "/from//g -> subst");
|
||||
t.ok (Arguments::is_subst ("/from/to/g"), "/from/to/g -> subst");
|
||||
t.ok (Arguments::is_subst ("/from from/to to/g"), "/from from/to to/g -> subst");
|
||||
|
||||
// bool is_pattern (const std::string&);
|
||||
t.notok (Arguments::is_pattern ("//"), "// -> not pattern");
|
||||
t.notok (Arguments::is_pattern ("///"), "/// -> not pattern");
|
||||
t.ok (Arguments::is_pattern ("/one/"), "/one/ -> pattern");
|
||||
t.ok (Arguments::is_pattern ("/one two/"), "/one two/ -> pattern");
|
||||
t.ok (Arguments::is_pattern ("/ /"), "/ / -> pattern");
|
||||
|
||||
// bool is_id (const std::string&);
|
||||
t.ok (Arguments::is_id ("1"), "1 -> id");
|
||||
t.ok (Arguments::is_id ("1,2"), "1,2 -> id");
|
||||
t.ok (Arguments::is_id ("1-2"), "1-2 -> id");
|
||||
t.ok (Arguments::is_id ("1,2,3"), "1,2,3 -> id");
|
||||
t.ok (Arguments::is_id ("1-2,3,4-5"), "1-2,3,4-5 -> id");
|
||||
t.notok (Arguments::is_id ("1-2-3"), "1-2-3 -> no id");
|
||||
|
||||
// bool is_uuid (const std::string&);
|
||||
t.ok (Arguments::is_uuid ("00000000-0000-0000-0000-000000000000"),
|
||||
"00000000-0000-0000-0000-000000000000 -> uuid");
|
||||
t.ok (Arguments::is_uuid ("eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee,ffffffff-ffff-ffff-ffff-ffffffffffff"),
|
||||
"eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee,ffffffff-ffff-ffff-ffff-ffffffffffff -> uuid");
|
||||
|
||||
// bool is_tag (const std::string&);
|
||||
t.ok (Arguments::is_tag ("+one"), "+one -> tag");
|
||||
t.ok (Arguments::is_tag ("-one"), "-one -> tag");
|
||||
t.notok (Arguments::is_tag ("+one "), "+one -> not tag");
|
||||
t.notok (Arguments::is_tag ("-one "), "-one -> not tag");
|
||||
t.notok (Arguments::is_tag ("+"), "+ -> not tag");
|
||||
t.notok (Arguments::is_tag ("-"), "- -> not tag");
|
||||
t.notok (Arguments::is_tag ("++"), "++ -> not tag");
|
||||
t.notok (Arguments::is_tag ("--"), "-- -> not tag");
|
||||
t.notok (Arguments::is_tag ("+one two"), "+one two -> not tag");
|
||||
|
||||
// bool is_operator (const std::string&);
|
||||
t.ok (Arguments::is_operator ("!"), "! -> operator");
|
||||
t.ok (Arguments::is_operator ("-"), "- -> operator");
|
||||
t.ok (Arguments::is_operator ("*"), "* -> operator");
|
||||
t.ok (Arguments::is_operator ("/"), "/ -> operator");
|
||||
t.ok (Arguments::is_operator ("+"), "+ -> operator");
|
||||
t.ok (Arguments::is_operator ("-"), "- -> operator");
|
||||
t.ok (Arguments::is_operator ("<"), "< -> operator");
|
||||
t.ok (Arguments::is_operator ("<="), "<= -> operator");
|
||||
t.ok (Arguments::is_operator (">="), ">= -> operator");
|
||||
t.ok (Arguments::is_operator (">"), "> -> operator");
|
||||
t.ok (Arguments::is_operator ("~"), "~ -> operator");
|
||||
t.ok (Arguments::is_operator ("!~"), "!~ -> operator");
|
||||
t.ok (Arguments::is_operator ("="), "= -> operator");
|
||||
t.ok (Arguments::is_operator ("!="), "!= -> operator");
|
||||
t.ok (Arguments::is_operator ("and"), "and -> operator");
|
||||
t.ok (Arguments::is_operator ("xor"), "xor -> operator");
|
||||
t.ok (Arguments::is_operator ("or"), "or -> operator");
|
||||
t.ok (Arguments::is_operator ("("), "( -> operator");
|
||||
t.ok (Arguments::is_operator (")"), ") -> operator");
|
||||
t.notok (Arguments::is_operator ("$"), "$ -> not operator");
|
||||
|
||||
// bool is_expression (const std::string&);
|
||||
t.notok (Arguments::is_expression ("foo"), "foo -> expression");
|
||||
t.ok (Arguments::is_expression ("1+1"), "1+1 -> expression");
|
||||
t.ok (Arguments::is_expression ("a~b"), "a~b -> expression");
|
||||
t.ok (Arguments::is_expression ("(1)"), "(1) -> expression");
|
||||
t.ok (Arguments::is_expression ("!a"), "!a -> expression");
|
||||
|
||||
// static bool valid_modifier (const std::string&);
|
||||
t.ok (Arguments::valid_modifier ("before"), "before -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("under"), "under -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("below"), "below -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("after"), "after -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("over"), "over -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("above"), "above -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("none"), "none -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("any"), "any -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("is"), "is -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("equals"), "equals -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("isnt"), "isnt -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("not"), "not -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("has"), "has -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("contains"), "contains -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("hasnt"), "hasnt -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("startswith"), "startswith -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("left"), "left -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("endswith"), "endswith -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("right"), "right -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("word"), "word -> modifier");
|
||||
t.ok (Arguments::valid_modifier ("noword"), "noword -> modifier");
|
||||
t.notok (Arguments::valid_modifier ("duck"), "duck -> not modified");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -47,7 +47,7 @@ int main (int argc, char** argv)
|
|||
try
|
||||
{
|
||||
// Prime the pump.
|
||||
context.args.capture ("task");
|
||||
context.a3.capture ("task");
|
||||
|
||||
// TODO dom.get rc.name
|
||||
DOM dom;
|
||||
|
|
331
test/lexer.t.cpp
331
test/lexer.t.cpp
|
@ -1,331 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2011, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or (at your option) any later
|
||||
// version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
// details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program; if not, write to the
|
||||
//
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <Lexer.h>
|
||||
#include <Context.h>
|
||||
#include <test.h>
|
||||
|
||||
Context context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
UnitTest t (80);
|
||||
|
||||
std::string input = "This is a test.";
|
||||
std::vector <std::string> tokens;
|
||||
{
|
||||
Lexer l (input);
|
||||
l.tokenize (tokens);
|
||||
}
|
||||
|
||||
t.is (tokens.size (), (size_t) 8, "'This is a test.' -> 'This| |is| |a| |test|.'");
|
||||
if (tokens.size () == 8)
|
||||
{
|
||||
t.is (tokens[0], "This", "'This is a test.' [0] -> 'This'");
|
||||
t.is (tokens[1], " ", "'This is a test.' [1] -> ' '");
|
||||
t.is (tokens[2], "is", "'This is a test.' [2] -> 'is'");
|
||||
t.is (tokens[3], " ", "'This is a test.' [3] -> ' '");
|
||||
t.is (tokens[4], "a", "'This is a test.' [4] -> 'a'");
|
||||
t.is (tokens[5], " ", "'This is a test.' [5] -> ' '");
|
||||
t.is (tokens[6], "test", "'This is a test.' [6] -> 'test'");
|
||||
t.is (tokens[7], ".", "'This is a test.' [7] -> '.'");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.skip ("'This is a test.' [0] -> 'This'");
|
||||
t.skip ("'This is a test.' [1] -> ' '");
|
||||
t.skip ("'This is a test.' [2] -> 'is'");
|
||||
t.skip ("'This is a test.' [3] -> ' '");
|
||||
t.skip ("'This is a test.' [4] -> 'a'");
|
||||
t.skip ("'This is a test.' [5] -> ' '");
|
||||
t.skip ("'This is a test.' [6] -> 'test'");
|
||||
t.skip ("'This is a test.' [7] -> '.'");
|
||||
}
|
||||
|
||||
input = "a12bcd345efgh6789";
|
||||
{
|
||||
Lexer l (input);
|
||||
l.tokenize (tokens);
|
||||
}
|
||||
|
||||
t.is (tokens.size (), (size_t) 6, "'a12bcd345efgh6789' -> 'a|12|bcd|345|efgh|6789'");
|
||||
if (tokens.size () == 6)
|
||||
{
|
||||
t.is (tokens[0], "a", "'a12bcd345efgh6789' [0] -> 'a'");
|
||||
t.is (tokens[1], "12", "'a12bcd345efgh6789' [1] -> '12'");
|
||||
t.is (tokens[2], "bcd", "'a12bcd345efgh6789' [2] -> 'bcd'");
|
||||
t.is (tokens[3], "345", "'a12bcd345efgh6789' [3] -> '345'");
|
||||
t.is (tokens[4], "efgh", "'a12bcd345efgh6789' [4] -> 'efgh'");
|
||||
t.is (tokens[5], "6789", "'a12bcd345efgh6789' [5] -> '6789'");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.skip ("'a12bcd345efgh6789' [0] -> 'a'");
|
||||
t.skip ("'a12bcd345efgh6789' [1] -> '12'");
|
||||
t.skip ("'a12bcd345efgh6789' [2] -> 'bcd'");
|
||||
t.skip ("'a12bcd345efgh6789' [3] -> '345'");
|
||||
t.skip ("'a12bcd345efgh6789' [4] -> 'efgh'");
|
||||
t.skip ("'a12bcd345efgh6789' [5] -> '6789'");
|
||||
}
|
||||
|
||||
// Let's throw some ugly Perl at it.
|
||||
input = "my $variable_name = 'single string';";
|
||||
{
|
||||
Lexer l (input);
|
||||
l.categorizeAsAlpha ('_');
|
||||
l.coalesceQuoted (true);
|
||||
l.tokenize (tokens);
|
||||
}
|
||||
|
||||
t.is (tokens.size (), (size_t) 9, "'my $variable_name = 'single string';' -> 'my| |$|variable_name| |=| |'|single string|'|;'");
|
||||
if (tokens.size () == 9)
|
||||
{
|
||||
t.is (tokens[0], "my", "'my $variable_name = 'single string';' [0] -> 'my'");
|
||||
t.is (tokens[1], " ", "'my $variable_name = 'single string';' [1] -> ' '");
|
||||
t.is (tokens[2], "$", "'my $variable_name = 'single string';' [2] -> '$'");
|
||||
t.is (tokens[3], "variable_name", "'my $variable_name = 'single string';' [3] -> 'variable_name'");
|
||||
t.is (tokens[4], " ", "'my $variable_name = 'single string';' [4] -> ' '");
|
||||
t.is (tokens[5], "=", "'my $variable_name = 'single string';' [5] -> '='");
|
||||
t.is (tokens[6], " ", "'my $variable_name = 'single string';' [6] -> ' '");
|
||||
t.is (tokens[7], "'single string'", "'my $variable_name = 'single string';' [8] -> ''single string''");
|
||||
t.is (tokens[8], ";", "'my $variable_name = 'single string';' [10] -> ';'");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.skip ("'my $variable_name = 'single string';' [0] -> 'my'");
|
||||
t.skip ("'my $variable_name = 'single string';' [1] -> ' '");
|
||||
t.skip ("'my $variable_name = 'single string';' [2] -> '$'");
|
||||
t.skip ("'my $variable_name = 'single string';' [3] -> 'variable_name'");
|
||||
t.skip ("'my $variable_name = 'single string';' [4] -> ' '");
|
||||
t.skip ("'my $variable_name = 'single string';' [5] -> '='");
|
||||
t.skip ("'my $variable_name = 'single string';' [6] -> ' '");
|
||||
t.skip ("'my $variable_name = 'single string';' [8] -> ''single string''");
|
||||
t.skip ("'my $variable_name = 'single string';' [10] -> ';'");
|
||||
}
|
||||
|
||||
// Now exercise all the configurable coalescence.
|
||||
input = "ab 12 'a'";
|
||||
{
|
||||
Lexer l (input);
|
||||
l.tokenize (tokens);
|
||||
}
|
||||
|
||||
t.is (tokens.size (), (size_t) 8, "'ab 12 'a'' -> 'ab| | |12| |'|a|''");
|
||||
if (tokens.size () == 8)
|
||||
{
|
||||
t.is (tokens[0], "ab", "'ab 12 'a'' [0] -> 'ab'");
|
||||
t.is (tokens[1], " ", "'ab 12 'a'' [1] -> ' '");
|
||||
t.is (tokens[2], " ", "'ab 12 'a'' [2] -> ' '");
|
||||
t.is (tokens[3], "12", "'ab 12 'a'' [3] -> '12'");
|
||||
t.is (tokens[4], " ", "'ab 12 'a'' [4] -> ' '");
|
||||
t.is (tokens[5], "'", "'ab 12 'a'' [5] -> '''");
|
||||
t.is (tokens[6], "a", "'ab 12 'a'' [6] -> 'a'");
|
||||
t.is (tokens[7], "'", "'ab 12 'a'' [7] -> '''");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.skip ("'ab 12 'a'' [0] -> 'ab'");
|
||||
t.skip ("'ab 12 'a'' [1] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [2] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [3] -> '12'");
|
||||
t.skip ("'ab 12 'a'' [4] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [5] -> '''");
|
||||
t.skip ("'ab 12 'a'' [6] -> 'a'");
|
||||
t.skip ("'ab 12 'a'' [7] -> '''");
|
||||
}
|
||||
|
||||
{
|
||||
Lexer l (input);
|
||||
l.coalesceAlpha (false);
|
||||
l.tokenize (tokens);
|
||||
}
|
||||
|
||||
t.is (tokens.size (), (size_t) 9, "'ab 12 'a'' -> 'a|b| | |12| |'|a|''");
|
||||
if (tokens.size () == 9)
|
||||
{
|
||||
t.is (tokens[0], "a", "'ab 12 'a'' [0] -> 'a'");
|
||||
t.is (tokens[1], "b", "'ab 12 'a'' [1] -> 'b'");
|
||||
t.is (tokens[2], " ", "'ab 12 'a'' [2] -> ' '");
|
||||
t.is (tokens[3], " ", "'ab 12 'a'' [3] -> ' '");
|
||||
t.is (tokens[4], "12", "'ab 12 'a'' [4] -> '12'");
|
||||
t.is (tokens[5], " ", "'ab 12 'a'' [5] -> ' '");
|
||||
t.is (tokens[6], "'", "'ab 12 'a'' [6] -> '''");
|
||||
t.is (tokens[7], "a", "'ab 12 'a'' [7] -> 'a'");
|
||||
t.is (tokens[8], "'", "'ab 12 'a'' [8] -> '''");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.skip ("'ab 12 'a'' [0] -> 'a'");
|
||||
t.skip ("'ab 12 'a'' [1] -> 'b'");
|
||||
t.skip ("'ab 12 'a'' [2] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [3] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [4] -> '12'");
|
||||
t.skip ("'ab 12 'a'' [5] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [6] -> '''");
|
||||
t.skip ("'ab 12 'a'' [7] -> 'a'");
|
||||
t.skip ("'ab 12 'a'' [8] -> '''");
|
||||
}
|
||||
|
||||
{
|
||||
Lexer l (input);
|
||||
l.coalesceDigits (false);
|
||||
l.tokenize (tokens);
|
||||
}
|
||||
|
||||
t.is (tokens.size (), (size_t) 9, "'ab 12 'a'' -> 'ab| | |1|2| |'|a|''");
|
||||
if (tokens.size () == 9)
|
||||
{
|
||||
t.is (tokens[0], "ab", "'ab 12 'a'' [0] -> 'ab'");
|
||||
t.is (tokens[1], " ", "'ab 12 'a'' [1] -> ' '");
|
||||
t.is (tokens[2], " ", "'ab 12 'a'' [2] -> ' '");
|
||||
t.is (tokens[3], "1", "'ab 12 'a'' [3] -> '1'");
|
||||
t.is (tokens[4], "2", "'ab 12 'a'' [4] -> '2'");
|
||||
t.is (tokens[5], " ", "'ab 12 'a'' [5] -> ' '");
|
||||
t.is (tokens[6], "'", "'ab 12 'a'' [6] -> '''");
|
||||
t.is (tokens[7], "a", "'ab 12 'a'' [7] -> 'a'");
|
||||
t.is (tokens[8], "'", "'ab 12 'a'' [8] -> '''");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.skip ("'ab 12 'a'' [0] -> 'ab'");
|
||||
t.skip ("'ab 12 'a'' [1] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [2] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [3] -> '1'");
|
||||
t.skip ("'ab 12 'a'' [4] -> '2'");
|
||||
t.skip ("'ab 12 'a'' [5] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [6] -> '''");
|
||||
t.skip ("'ab 12 'a'' [7] -> 'a'");
|
||||
t.skip ("'ab 12 'a'' [8] -> '''");
|
||||
}
|
||||
|
||||
{
|
||||
Lexer l (input);
|
||||
l.coalesceQuoted (true);
|
||||
l.tokenize (tokens);
|
||||
}
|
||||
|
||||
t.is (tokens.size (), (size_t) 6, "'ab 12 'a'' -> 'ab| | |12| |'a''");
|
||||
if (tokens.size () == 6)
|
||||
{
|
||||
t.is (tokens[0], "ab", "'ab 12 'a'' [0] -> 'ab'");
|
||||
t.is (tokens[1], " ", "'ab 12 'a'' [1] -> ' '");
|
||||
t.is (tokens[2], " ", "'ab 12 'a'' [2] -> ' '");
|
||||
t.is (tokens[3], "12", "'ab 12 'a'' [3] -> '12'");
|
||||
t.is (tokens[4], " ", "'ab 12 'a'' [4] -> ' '");
|
||||
t.is (tokens[5], "'a'", "'ab 12 'a'' [5] -> ''a''");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.skip ("'ab 12 'a'' [0] -> 'ab'");
|
||||
t.skip ("'ab 12 'a'' [1] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [2] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [3] -> '12'");
|
||||
t.skip ("'ab 12 'a'' [4] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [5] -> ''a''");
|
||||
}
|
||||
|
||||
{
|
||||
Lexer l (input);
|
||||
l.coalesceWhite (true);
|
||||
l.tokenize (tokens);
|
||||
}
|
||||
|
||||
t.is (tokens.size (), (size_t) 7, "'ab 12 'a'' -> 'ab| |12| |'|a|''");
|
||||
if (tokens.size () == 7)
|
||||
{
|
||||
t.is (tokens[0], "ab", "'ab 12 'a'' [0] -> 'ab'");
|
||||
t.is (tokens[1], " ", "'ab 12 'a'' [1] -> ' '");
|
||||
t.is (tokens[2], "12", "'ab 12 'a'' [2] -> '12'");
|
||||
t.is (tokens[3], " ", "'ab 12 'a'' [3] -> ' '");
|
||||
t.is (tokens[4], "'", "'ab 12 'a'' [4] -> '''");
|
||||
t.is (tokens[5], "a", "'ab 12 'a'' [5] -> 'a'");
|
||||
t.is (tokens[6], "'", "'ab 12 'a'' [6] -> '''");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.skip ("'ab 12 'a'' [0] -> 'ab'");
|
||||
t.skip ("'ab 12 'a'' [1] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [2] -> '12'");
|
||||
t.skip ("'ab 12 'a'' [3] -> ' '");
|
||||
t.skip ("'ab 12 'a'' [4] -> '''");
|
||||
t.skip ("'ab 12 'a'' [5] -> 'a'");
|
||||
t.skip ("'ab 12 'a'' [6] -> '''");
|
||||
}
|
||||
|
||||
{
|
||||
Lexer l (input);
|
||||
l.skipWhitespace (true);
|
||||
l.tokenize (tokens);
|
||||
}
|
||||
|
||||
t.is (tokens.size (), (size_t) 5, "'ab 12 'a'' -> 'ab|12|'|a|''");
|
||||
if (tokens.size () == 5)
|
||||
{
|
||||
t.is (tokens[0], "ab", "'ab 12 'a'' [0] -> 'ab'");
|
||||
t.is (tokens[1], "12", "'ab 12 'a'' [1] -> '12'");
|
||||
t.is (tokens[2], "'", "'ab 12 'a'' [2] -> '''");
|
||||
t.is (tokens[3], "a", "'ab 12 'a'' [3] -> 'a'");
|
||||
t.is (tokens[4], "'", "'ab 12 'a'' [4] -> '''");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.skip ("'ab 12 'a'' [0] -> 'ab'");
|
||||
t.skip ("'ab 12 'a'' [1] -> '12'");
|
||||
t.skip ("'ab 12 'a'' [2] -> '''");
|
||||
t.skip ("'ab 12 'a'' [3] -> 'a'");
|
||||
t.skip ("'ab 12 'a'' [4] -> '''");
|
||||
}
|
||||
|
||||
// Special tokens
|
||||
input = "a := 1";
|
||||
{
|
||||
Lexer l (input);
|
||||
l.skipWhitespace (true);
|
||||
l.specialToken (":=");
|
||||
l.tokenize (tokens);
|
||||
}
|
||||
|
||||
t.is (tokens.size (), (size_t) 3, "'a := 1' -> 'a|:=|1'");
|
||||
if (tokens.size () == 3)
|
||||
{
|
||||
t.is (tokens[0], "a", "'a := 1' [0] -> 'a'");
|
||||
t.is (tokens[1], ":=", "'a := 1' [1] -> ':='");
|
||||
t.is (tokens[2], "1", "'a := 1' [2] -> '1'");
|
||||
}
|
||||
else
|
||||
{
|
||||
t.skip ("'a := 1' [0] -> 'a'");
|
||||
t.skip ("'a := 1' [1] -> ':='");
|
||||
t.skip ("'a := 1' [2] -> '1'");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue