Parser is finished (or very nearly so)!!! :-)
+ Added support for extended notation floating point numbers, as well as signed (+ and -) floats. + Finished up parsing code + Moved Err class into it's own header/source pair, since I started using it all over the place in the sniffer code. + Did my darndest to make sure I wasn't leaking memory anywhere. + Matched up error messages as best as possible with R5's error message. Some couldn't be matched, some were improved. There *are* a few things left to do. I don't think priorities are verified to be valid (0.0 <= x <= 1.0). More tests also need to be written. Things have solidified enough now that documentation is a reasonable thing to start considering as well. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@608 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -10,23 +10,21 @@
|
|||||||
#define _sk_sniffer_parser_h_
|
#define _sk_sniffer_parser_h_
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
#include <sniffer/Err.h>
|
||||||
#include <sniffer/Range.h>
|
#include <sniffer/Range.h>
|
||||||
#include <sniffer/Rule.h>
|
#include <sniffer/Rule.h>
|
||||||
#include <List.h>
|
#include <List.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
class BString;
|
class BString;
|
||||||
|
|
||||||
namespace Sniffer {
|
namespace Sniffer {
|
||||||
|
|
||||||
class Rule;
|
class Rule;
|
||||||
class Expr;
|
class Expr;
|
||||||
class Range;
|
|
||||||
class RPattern;
|
class RPattern;
|
||||||
class Pattern;
|
class Pattern;
|
||||||
typedef std::vector<Expr*> ExprList;
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// The mighty parsing function ;-)
|
// The mighty parsing function ;-)
|
||||||
@@ -38,21 +36,6 @@ status_t parse(const char *rule, Rule *result, BString *parseError = NULL);
|
|||||||
// Classes used internally by the parser
|
// Classes used internally by the parser
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
class Err {
|
|
||||||
public:
|
|
||||||
Err(const char *msg, const ssize_t pos);
|
|
||||||
Err(const std::string &msg, const ssize_t pos);
|
|
||||||
Err(const Err &ref);
|
|
||||||
Err& operator=(const Err &ref);
|
|
||||||
const char* Msg() const;
|
|
||||||
ssize_t Pos() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void SetMsg(const char *msg);
|
|
||||||
char *fMsg;
|
|
||||||
ssize_t fPos;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CharStream {
|
class CharStream {
|
||||||
public:
|
public:
|
||||||
CharStream(const char *string = NULL);
|
CharStream(const char *string = NULL);
|
||||||
@@ -63,6 +46,7 @@ public:
|
|||||||
status_t InitCheck() const;
|
status_t InitCheck() const;
|
||||||
bool IsEmpty() const;
|
bool IsEmpty() const;
|
||||||
ssize_t Pos() const;
|
ssize_t Pos() const;
|
||||||
|
const char *String() const;
|
||||||
|
|
||||||
char Get();
|
char Get();
|
||||||
void Unget();
|
void Unget();
|
||||||
@@ -102,7 +86,7 @@ public:
|
|||||||
virtual int32 Int() const;
|
virtual int32 Int() const;
|
||||||
virtual double Float() const;
|
virtual double Float() const;
|
||||||
ssize_t Pos() const;
|
ssize_t Pos() const;
|
||||||
bool operator==(Token &ref);
|
bool operator==(Token &ref) const;
|
||||||
protected:
|
protected:
|
||||||
TokenType fType;
|
TokenType fType;
|
||||||
ssize_t fPos;
|
ssize_t fPos;
|
||||||
@@ -143,10 +127,16 @@ public:
|
|||||||
void Unset();
|
void Unset();
|
||||||
status_t InitCheck() const;
|
status_t InitCheck() const;
|
||||||
|
|
||||||
Token* Get();
|
const Token* Get();
|
||||||
void Unget(Token *token);
|
void Unget();
|
||||||
|
|
||||||
bool IsEmpty();
|
void Read(TokenType type);
|
||||||
|
bool CondRead(TokenType type);
|
||||||
|
|
||||||
|
ssize_t Pos() const;
|
||||||
|
ssize_t EndPos() const;
|
||||||
|
|
||||||
|
bool IsEmpty() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddToken(TokenType type, ssize_t pos);
|
void AddToken(TokenType type, ssize_t pos);
|
||||||
@@ -154,9 +144,12 @@ private:
|
|||||||
void AddInt(const char *str, ssize_t pos);
|
void AddInt(const char *str, ssize_t pos);
|
||||||
void AddFloat(const char *str, ssize_t pos);
|
void AddFloat(const char *str, ssize_t pos);
|
||||||
|
|
||||||
BList fTokenList;
|
std::vector<Token*> fTokenList;
|
||||||
|
int fPos;
|
||||||
|
int fStrLen;
|
||||||
status_t fCStatus;
|
status_t fCStatus;
|
||||||
|
|
||||||
|
|
||||||
TokenStream(const TokenStream &ref);
|
TokenStream(const TokenStream &ref);
|
||||||
TokenStream& operator=(const TokenStream &ref);
|
TokenStream& operator=(const TokenStream &ref);
|
||||||
};
|
};
|
||||||
@@ -164,22 +157,31 @@ private:
|
|||||||
class Parser {
|
class Parser {
|
||||||
public:
|
public:
|
||||||
Parser();
|
Parser();
|
||||||
|
~Parser();
|
||||||
status_t Parse(const char *rule, Rule *result, BString *parseError = NULL);
|
status_t Parse(const char *rule, Rule *result, BString *parseError = NULL);
|
||||||
private:
|
private:
|
||||||
std::string ErrorMessage(Err *err, const char *rule);
|
std::string ErrorMessage(Err *err, const char *rule);
|
||||||
|
|
||||||
|
// Things that get done a lot :-)
|
||||||
|
void ThrowEndOfStreamError();
|
||||||
|
inline void ThrowOutOfMemError(ssize_t pos);
|
||||||
|
void ThrowUnexpectedTokenError(TokenType expected, const Token *found);
|
||||||
|
void ThrowUnexpectedTokenError(TokenType expected1, TokenType expected2, const Token *found);
|
||||||
|
|
||||||
// Parsing functions
|
// Parsing functions
|
||||||
void ParseRule(Rule *result);
|
void ParseRule(Rule *result);
|
||||||
double ParsePriority();
|
double ParsePriority();
|
||||||
ExprList* ParseExprList();
|
std::vector<Expr*>* ParseExprList();
|
||||||
Expr* ParseExpr();
|
Expr* ParseExpr();
|
||||||
Range ParseRange();
|
Range ParseRange();
|
||||||
Expr* ParsePatternList();
|
Expr* ParsePatternList(Range range);
|
||||||
Expr* ParseRPatternList();
|
Expr* ParseRPatternList();
|
||||||
RPattern* ParseRPattern();
|
RPattern* ParseRPattern();
|
||||||
Pattern* ParsePattern();
|
Pattern* ParsePattern();
|
||||||
|
|
||||||
TokenStream stream;
|
TokenStream stream;
|
||||||
|
|
||||||
|
Err *fOutOfMemErr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Sniffer
|
} // namespace Sniffer
|
||||||
|
|||||||
+378
-160
@@ -9,10 +9,11 @@
|
|||||||
|
|
||||||
//#include <sniffer/Expr.h>
|
//#include <sniffer/Expr.h>
|
||||||
#include <sniffer/Parser.h>
|
#include <sniffer/Parser.h>
|
||||||
//#include <sniffer/Pattern.h>
|
#include <sniffer/Pattern.h>
|
||||||
//#include <sniffer/PatternList.h>
|
#include <sniffer/PatternList.h>
|
||||||
//#include <sniffer/Range.h>
|
#include <sniffer/Range.h>
|
||||||
//#include <sniffer/RPatternList.h>
|
#include <sniffer/RPattern.h>
|
||||||
|
#include <sniffer/RPatternList.h>
|
||||||
#include <sniffer/Rule.h>
|
#include <sniffer/Rule.h>
|
||||||
|
|
||||||
#include <new.h>
|
#include <new.h>
|
||||||
@@ -42,62 +43,6 @@ Sniffer::parse(const char *rule, Rule *result, BString *parseError) {
|
|||||||
return parser.Parse(rule, result, parseError);
|
return parser.Parse(rule, result, parseError);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// Err
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Err::Err(const char *msg, const ssize_t pos)
|
|
||||||
: fMsg(NULL)
|
|
||||||
, fPos(pos)
|
|
||||||
{
|
|
||||||
SetMsg(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
Err::Err(const std::string &msg, const ssize_t pos)
|
|
||||||
: fMsg(NULL)
|
|
||||||
, fPos(pos)
|
|
||||||
{
|
|
||||||
SetMsg(msg.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
Err::Err(const Err &ref)
|
|
||||||
: fMsg(NULL)
|
|
||||||
, fPos(-1)
|
|
||||||
{
|
|
||||||
*this = ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
Err&
|
|
||||||
Err::operator=(const Err &ref) {
|
|
||||||
SetMsg(ref.Msg());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char*
|
|
||||||
Err::Msg() const {
|
|
||||||
return fMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
Err::Pos() const {
|
|
||||||
return fPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Err::SetMsg(const char *msg) {
|
|
||||||
if (fMsg) {
|
|
||||||
delete fMsg;
|
|
||||||
fMsg = NULL;
|
|
||||||
}
|
|
||||||
if (msg == NULL)
|
|
||||||
fMsg = NULL;
|
|
||||||
else {
|
|
||||||
fMsg = new(nothrow) char[strlen(msg)+1];
|
|
||||||
if (fMsg)
|
|
||||||
strcpy(fMsg, msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// CharStream
|
// CharStream
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -154,6 +99,11 @@ CharStream::Pos() const {
|
|||||||
return fPos;
|
return fPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char*
|
||||||
|
CharStream::String() const {
|
||||||
|
return fString;
|
||||||
|
}
|
||||||
|
|
||||||
char
|
char
|
||||||
CharStream::Get() {
|
CharStream::Get() {
|
||||||
if (fCStatus != B_OK)
|
if (fCStatus != B_OK)
|
||||||
@@ -217,7 +167,7 @@ Token::Pos() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Token::operator==(Token &ref) {
|
Token::operator==(Token &ref) const {
|
||||||
// Compare types, then data if necessary
|
// Compare types, then data if necessary
|
||||||
if (Type() == ref.Type()) {
|
if (Type() == ref.Type()) {
|
||||||
switch (Type()) {
|
switch (Type()) {
|
||||||
@@ -325,6 +275,8 @@ FloatToken::Float() const {
|
|||||||
|
|
||||||
TokenStream::TokenStream(const char *string = NULL)
|
TokenStream::TokenStream(const char *string = NULL)
|
||||||
: fCStatus(B_NO_INIT)
|
: fCStatus(B_NO_INIT)
|
||||||
|
, fPos(-1)
|
||||||
|
, fStrLen(-1)
|
||||||
{
|
{
|
||||||
SetTo(string);
|
SetTo(string);
|
||||||
}
|
}
|
||||||
@@ -335,10 +287,12 @@ TokenStream::~TokenStream() {
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
TokenStream::SetTo(const char *string) {
|
TokenStream::SetTo(const char *string) {
|
||||||
|
int q = 0;
|
||||||
Unset();
|
Unset();
|
||||||
if (string) {
|
if (string) {
|
||||||
|
fStrLen = strlen(string);
|
||||||
CharStream stream(string);
|
CharStream stream(string);
|
||||||
if (stream.InitCheck() != B_OK)
|
if (stream.InitCheck() != B_OK)
|
||||||
throw new Err("Sniffer scanner error: Unable to intialize character stream", -1);
|
throw new Err("Sniffer scanner error: Unable to intialize character stream", -1);
|
||||||
|
|
||||||
typedef enum TokenStreamScannerState {
|
typedef enum TokenStreamScannerState {
|
||||||
@@ -353,8 +307,10 @@ TokenStream::SetTo(const char *string) {
|
|||||||
tsssIntOrFloat,
|
tsssIntOrFloat,
|
||||||
tsssFloat,
|
tsssFloat,
|
||||||
tsssLonelyDecimalPoint,
|
tsssLonelyDecimalPoint,
|
||||||
tsssLonelyMinusOrPlusSign,
|
tsssLonelyMinusOrPlus,
|
||||||
tsssPosNegInt,
|
tsssLonelyFloatExtension,
|
||||||
|
tsssLonelyFloatExtensionWithSign,
|
||||||
|
tsssExtendedFloat,
|
||||||
tsssUnquoted,
|
tsssUnquoted,
|
||||||
tsssEscape,
|
tsssEscape,
|
||||||
tsssEscapeX,
|
tsssEscapeX,
|
||||||
@@ -372,17 +328,19 @@ TokenStream::SetTo(const char *string) {
|
|||||||
char lastChar; // For two char lookahead
|
char lastChar; // For two char lookahead
|
||||||
char lastLastChar; // For three char lookahead
|
char lastLastChar; // For three char lookahead
|
||||||
bool keepLooping = true;
|
bool keepLooping = true;
|
||||||
|
ssize_t startPos;
|
||||||
while (keepLooping) {
|
while (keepLooping) {
|
||||||
ssize_t pos = stream.Pos();
|
ssize_t pos = stream.Pos();
|
||||||
char ch = stream.Get();
|
char ch = stream.Get();
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case tsssStart:
|
case tsssStart:
|
||||||
|
startPos = pos;
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 0x3: // End-Of-Text
|
case 0x3: // End-Of-Text
|
||||||
if (stream.IsEmpty())
|
if (stream.IsEmpty())
|
||||||
keepLooping = false;
|
keepLooping = false;
|
||||||
else
|
else
|
||||||
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
throw new Err(std::string("Sniffer scanner error: invalid character '") + ch + "'", pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\t':
|
case '\t':
|
||||||
@@ -404,7 +362,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
case '+':
|
case '+':
|
||||||
case '-':
|
case '-':
|
||||||
charStr = ch;
|
charStr = ch;
|
||||||
state = tsssLonelyMinusOrPlusSign;
|
state = tsssLonelyMinusOrPlus;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '.':
|
case '.':
|
||||||
@@ -446,7 +404,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
case '|': AddToken(Divider, pos); break;
|
case '|': AddToken(Divider, pos); break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
throw new Err(std::string("Sniffer scanner error: invalid character '") + ch + "'", pos);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -457,7 +415,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
state = tsssEscape; // Handle the escape sequence
|
state = tsssEscape; // Handle the escape sequence
|
||||||
break;
|
break;
|
||||||
case '\'':
|
case '\'':
|
||||||
AddString(charStr.c_str(), pos);
|
AddString(charStr.c_str(), startPos);
|
||||||
state = tsssStart;
|
state = tsssStart;
|
||||||
break;
|
break;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
@@ -479,7 +437,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
state = tsssEscape; // Handle the escape sequence
|
state = tsssEscape; // Handle the escape sequence
|
||||||
break;
|
break;
|
||||||
case '"':
|
case '"':
|
||||||
AddString(charStr.c_str(), pos);
|
AddString(charStr.c_str(), startPos);
|
||||||
state = tsssStart;
|
state = tsssStart;
|
||||||
break;
|
break;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
@@ -504,13 +462,9 @@ TokenStream::SetTo(const char *string) {
|
|||||||
} else if (ch == '.') {
|
} else if (ch == '.') {
|
||||||
charStr += ch;
|
charStr += ch;
|
||||||
state = tsssFloat;
|
state = tsssFloat;
|
||||||
} else if (ch == 0x3 && stream.IsEmpty()) {
|
|
||||||
// Terminate the number and then the loop
|
|
||||||
AddInt(charStr.c_str(), pos);
|
|
||||||
keepLooping = false;
|
|
||||||
} else {
|
} else {
|
||||||
// Terminate the number
|
// Terminate the number
|
||||||
AddInt(charStr.c_str(), pos);
|
AddInt(charStr.c_str(), startPos);
|
||||||
|
|
||||||
// Push the last char back on and try again
|
// Push the last char back on and try again
|
||||||
stream.Unget();
|
stream.Unget();
|
||||||
@@ -522,35 +476,27 @@ TokenStream::SetTo(const char *string) {
|
|||||||
if (isHexChar(ch)) {
|
if (isHexChar(ch)) {
|
||||||
lastChar = ch;
|
lastChar = ch;
|
||||||
state = tsssOneHex;
|
state = tsssOneHex;
|
||||||
} else if (ch == 0x3 && stream.IsEmpty())
|
} else
|
||||||
throw new Err(std::string("Sniffer scanner error: incomplete hex code"), pos);
|
throw new Err(std::string("Sniffer scanner error: incomplete hex code"), pos);
|
||||||
else
|
|
||||||
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tsssOneHex:
|
case tsssOneHex:
|
||||||
if (isHexChar(ch)) {
|
if (isHexChar(ch)) {
|
||||||
charStr += hexToChar(lastChar, ch);
|
charStr += hexToChar(lastChar, ch);
|
||||||
state = tsssTwoHex;
|
state = tsssTwoHex;
|
||||||
} else if (ch == 0x3 && stream.IsEmpty())
|
} else
|
||||||
throw new Err(std::string("Sniffer scanner error: incomplete hex code (the number of hex digits must be a multiple of two)"), pos);
|
throw new Err(std::string("Sniffer pattern error: bad hex literal"), pos); // Same as R5
|
||||||
else
|
|
||||||
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tsssTwoHex:
|
case tsssTwoHex:
|
||||||
if (isHexChar(ch)) {
|
if (isHexChar(ch)) {
|
||||||
lastChar = ch;
|
lastChar = ch;
|
||||||
state = tsssOneHex;
|
state = tsssOneHex;
|
||||||
} else if (isWhiteSpace(ch) || isPunctuation(ch)) {
|
} else {
|
||||||
AddString(charStr.c_str(), pos);
|
AddString(charStr.c_str(), startPos);
|
||||||
stream.Unget(); // So punctuation gets handled properly
|
stream.Unget(); // So punctuation gets handled properly
|
||||||
state = tsssStart;
|
state = tsssStart;
|
||||||
} else if (ch == 0x3 && stream.IsEmpty()) {
|
}
|
||||||
AddString(charStr.c_str(), pos);
|
|
||||||
keepLooping = false;
|
|
||||||
} else
|
|
||||||
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tsssIntOrFloat:
|
case tsssIntOrFloat:
|
||||||
@@ -559,9 +505,12 @@ TokenStream::SetTo(const char *string) {
|
|||||||
else if (ch == '.') {
|
else if (ch == '.') {
|
||||||
charStr += ch;
|
charStr += ch;
|
||||||
state = tsssFloat;
|
state = tsssFloat;
|
||||||
|
} else if (ch == 'e' || ch == 'E') {
|
||||||
|
charStr += ch;
|
||||||
|
state = tsssLonelyFloatExtension;
|
||||||
} else {
|
} else {
|
||||||
// Terminate the number
|
// Terminate the number
|
||||||
AddInt(charStr.c_str(), pos);
|
AddInt(charStr.c_str(), startPos);
|
||||||
|
|
||||||
// Push the last char back on and try again
|
// Push the last char back on and try again
|
||||||
stream.Unget();
|
stream.Unget();
|
||||||
@@ -572,9 +521,12 @@ TokenStream::SetTo(const char *string) {
|
|||||||
case tsssFloat:
|
case tsssFloat:
|
||||||
if (isDecimalChar(ch))
|
if (isDecimalChar(ch))
|
||||||
charStr += ch;
|
charStr += ch;
|
||||||
else {
|
else if (ch == 'e' || ch == 'E') {
|
||||||
|
charStr += ch;
|
||||||
|
state = tsssLonelyFloatExtension;
|
||||||
|
} else {
|
||||||
// Terminate the number
|
// Terminate the number
|
||||||
AddFloat(charStr.c_str(), pos);
|
AddFloat(charStr.c_str(), startPos);
|
||||||
|
|
||||||
// Push the last char back on and try again
|
// Push the last char back on and try again
|
||||||
stream.Unget();
|
stream.Unget();
|
||||||
@@ -586,30 +538,47 @@ TokenStream::SetTo(const char *string) {
|
|||||||
if (isDecimalChar(ch)) {
|
if (isDecimalChar(ch)) {
|
||||||
charStr += ch;
|
charStr += ch;
|
||||||
state = tsssFloat;
|
state = tsssFloat;
|
||||||
} else if (ch == 0x3 && stream.IsEmpty())
|
} else
|
||||||
throw new Err(std::string("Sniffer scanner error: incomplete floating point number"), pos);
|
throw new Err(std::string("Sniffer scanner error: incomplete floating point number"), pos);
|
||||||
else
|
|
||||||
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tsssLonelyMinusOrPlusSign:
|
case tsssLonelyMinusOrPlus:
|
||||||
if (isDecimalChar(ch)) {
|
if (isDecimalChar(ch)) {
|
||||||
charStr += ch;
|
charStr += ch;
|
||||||
state = tsssPosNegInt;
|
state = tsssIntOrFloat;
|
||||||
} else if (ch == 0x3 && stream.IsEmpty())
|
} else if (ch == '.') {
|
||||||
throw new Err(std::string("Sniffer scanner error: incomplete signed integer"), pos);
|
charStr += ch;
|
||||||
else
|
state = tsssLonelyDecimalPoint;
|
||||||
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
} else
|
||||||
|
throw new Err(std::string("Sniffer scanner error: incomplete signed number"), pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tsssPosNegInt:
|
case tsssLonelyFloatExtension:
|
||||||
if (isDecimalChar(ch))
|
if (ch == '+' || ch == '-') {
|
||||||
charStr += ch;
|
charStr += ch;
|
||||||
else if (ch == '.')
|
state = tsssLonelyFloatExtensionWithSign;
|
||||||
throw new Err(std::string("Sniffer scanner error: negative floating point numbers are useless and thus signs (both + and -) are disallowed on floating points"), pos);
|
} else if (isDecimalChar(ch)) {
|
||||||
else {
|
charStr += ch;
|
||||||
|
state = tsssExtendedFloat;
|
||||||
|
} else
|
||||||
|
throw new Err(std::string("Sniffer pattern error: incomplete extended-notation floating point number"), pos);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tsssLonelyFloatExtensionWithSign:
|
||||||
|
if (isDecimalChar(ch)) {
|
||||||
|
charStr += ch;
|
||||||
|
state = tsssExtendedFloat;
|
||||||
|
} else
|
||||||
|
throw new Err(std::string("Sniffer pattern error: incomplete extended-notation floating point number"), pos);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tsssExtendedFloat:
|
||||||
|
if (isDecimalChar(ch)) {
|
||||||
|
charStr += ch;
|
||||||
|
state = tsssExtendedFloat;
|
||||||
|
} else {
|
||||||
// Terminate the number
|
// Terminate the number
|
||||||
AddInt(charStr.c_str(), pos);
|
AddFloat(charStr.c_str(), startPos);
|
||||||
|
|
||||||
// Push the last char back on and try again
|
// Push the last char back on and try again
|
||||||
stream.Unget();
|
stream.Unget();
|
||||||
@@ -622,13 +591,13 @@ TokenStream::SetTo(const char *string) {
|
|||||||
escapedState = state; // Save our state
|
escapedState = state; // Save our state
|
||||||
state = tsssEscape; // Handle the escape sequence
|
state = tsssEscape; // Handle the escape sequence
|
||||||
} else if (isWhiteSpace(ch) || isPunctuation(ch)) {
|
} else if (isWhiteSpace(ch) || isPunctuation(ch)) {
|
||||||
AddString(charStr.c_str(), pos);
|
AddString(charStr.c_str(), startPos);
|
||||||
stream.Unget(); // In case it's punctuation, let tsssStart handle it
|
stream.Unget(); // In case it's punctuation, let tsssStart handle it
|
||||||
state = tsssStart;
|
state = tsssStart;
|
||||||
} else if (ch == '\'' || ch == '"') {
|
} else if (ch == '\'' || ch == '"') {
|
||||||
throw new Err(std::string("Sniffer scanner error: illegal unquoted character '") + ch + "'", pos);
|
throw new Err(std::string("Sniffer scanner error: illegal unquoted character '") + ch + "'", pos);
|
||||||
} else if (ch == 0x3 && stream.IsEmpty()) {
|
} else if (ch == 0x3 && stream.IsEmpty()) {
|
||||||
AddString(charStr.c_str(), pos);
|
AddString(charStr.c_str(), startPos);
|
||||||
keepLooping = false;
|
keepLooping = false;
|
||||||
} else {
|
} else {
|
||||||
charStr += ch;
|
charStr += ch;
|
||||||
@@ -642,7 +611,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
} else {
|
} else {
|
||||||
// Check for a true end-of-text marker
|
// Check for a true end-of-text marker
|
||||||
if (ch == 0x3 && stream.IsEmpty())
|
if (ch == 0x3 && stream.IsEmpty())
|
||||||
throw new Err(std::string("Sniffer scanner error: unterminated escape sequence"), pos);
|
throw new Err(std::string("Sniffer scanner error: incomplete escape sequence"), pos);
|
||||||
else {
|
else {
|
||||||
charStr += escapeChar(ch);
|
charStr += escapeChar(ch);
|
||||||
state = escapedState; // Return to the state we were in before the escape
|
state = escapedState; // Return to the state we were in before the escape
|
||||||
@@ -693,18 +662,18 @@ TokenStream::SetTo(const char *string) {
|
|||||||
if (isHexChar(ch)) {
|
if (isHexChar(ch)) {
|
||||||
charStr += hexToChar(lastChar, ch);
|
charStr += hexToChar(lastChar, ch);
|
||||||
state = escapedState;
|
state = escapedState;
|
||||||
} else if (ch == 0x3 && stream.IsEmpty())
|
} else
|
||||||
throw new Err(std::string("Sniffer scanner error: incomplete escaped hex code (the number of hex digits must be a multiple of two)"), pos);
|
throw new Err(std::string("Sniffer scanner error: incomplete escaped hex code"), pos);
|
||||||
else
|
|
||||||
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (state == tsssStart)
|
if (state == tsssStart) {
|
||||||
fCStatus = B_OK;
|
fCStatus = B_OK;
|
||||||
else
|
fPos = 0;
|
||||||
|
} else {
|
||||||
throw new Err("Sniffer pattern error: unterminated rule", stream.Pos());
|
throw new Err("Sniffer pattern error: unterminated rule", stream.Pos());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fCStatus;
|
return fCStatus;
|
||||||
@@ -712,9 +681,12 @@ TokenStream::SetTo(const char *string) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
TokenStream::Unset() {
|
TokenStream::Unset() {
|
||||||
while (!fTokenList.IsEmpty())
|
std::vector<Token*>::iterator i;
|
||||||
delete (Token*)fTokenList.RemoveItem((int32)0);
|
for (i = fTokenList.begin(); i != fTokenList.end(); i++)
|
||||||
|
delete *i;
|
||||||
|
fTokenList.clear();
|
||||||
fCStatus = B_NO_INIT;
|
fCStatus = B_NO_INIT;
|
||||||
|
fStrLen = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
@@ -722,31 +694,74 @@ TokenStream::InitCheck() const {
|
|||||||
return fCStatus;
|
return fCStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token*
|
const Token*
|
||||||
TokenStream::Get() {
|
TokenStream::Get() {
|
||||||
return (Token*)fTokenList.RemoveItem((int32)0);
|
if (fCStatus != B_OK)
|
||||||
|
throw new Err("Sniffer parser error: TokenStream::Get() called on uninitialized TokenStream object", -1);
|
||||||
|
if (fPos < fTokenList.size())
|
||||||
|
return fTokenList[fPos++];
|
||||||
|
else {
|
||||||
|
throw new Err("Sniffer pattern error: unterminated rule", EndPos());
|
||||||
|
// fPos++; // Increment fPos to keep Unget()s consistent
|
||||||
|
// return NULL; // Return NULL to signal end of list
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TokenStream::Unget(Token *token) {
|
TokenStream::Unget() {
|
||||||
fTokenList.AddItem(token, 0);
|
if (fCStatus != B_OK)
|
||||||
|
throw new Err("Sniffer parser error: TokenStream::Unget() called on uninitialized TokenStream object", -1);
|
||||||
|
if (fPos > 0)
|
||||||
|
fPos--;
|
||||||
|
else
|
||||||
|
throw new Err("Sniffer parser error: TokenStream::Unget() called at beginning of token stream", -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TokenStream::Read(TokenType type) {
|
||||||
|
const Token *t = Get();
|
||||||
|
if (t->Type() != type) {
|
||||||
|
throw new Err((std::string("Sniffer pattern error: expected ") + tokenTypeToString(type)
|
||||||
|
+ ", found " + tokenTypeToString(t->Type())).c_str(), t->Pos());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TokenStream::IsEmpty() {
|
TokenStream::CondRead(TokenType type) {
|
||||||
return fCStatus != B_OK || fTokenList.IsEmpty();
|
const Token *t = Get();
|
||||||
|
if (t->Type() == type) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
Unget();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
TokenStream::Pos() const {
|
||||||
|
return fPos < fTokenList.size() ? fTokenList[fPos]->Pos() : fStrLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
TokenStream::EndPos() const {
|
||||||
|
return fStrLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TokenStream::IsEmpty() const {
|
||||||
|
return fCStatus != B_OK || fPos >= fTokenList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TokenStream::AddToken(TokenType type, ssize_t pos) {
|
TokenStream::AddToken(TokenType type, ssize_t pos) {
|
||||||
Token *token = new Token(type, pos);
|
Token *token = new Token(type, pos);
|
||||||
fTokenList.AddItem(token);
|
fTokenList.push_back(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TokenStream::AddString(const char *str, ssize_t pos) {
|
TokenStream::AddString(const char *str, ssize_t pos) {
|
||||||
Token *token = new StringToken(str, pos);
|
Token *token = new StringToken(str, pos);
|
||||||
fTokenList.AddItem(token);
|
fTokenList.push_back(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -754,7 +769,7 @@ TokenStream::AddInt(const char *str, ssize_t pos) {
|
|||||||
// Convert the string to an int
|
// Convert the string to an int
|
||||||
int32 value = atol(str);
|
int32 value = atol(str);
|
||||||
Token *token = new IntToken(value, pos);
|
Token *token = new IntToken(value, pos);
|
||||||
fTokenList.AddItem(token);
|
fTokenList.push_back(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -762,7 +777,7 @@ TokenStream::AddFloat(const char *str, ssize_t pos) {
|
|||||||
// Convert the string to a float
|
// Convert the string to a float
|
||||||
double value = atof(str);
|
double value = atof(str);
|
||||||
Token *token = new FloatToken(value, pos);
|
Token *token = new FloatToken(value, pos);
|
||||||
fTokenList.AddItem(token);
|
fTokenList.push_back(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -914,7 +929,13 @@ Sniffer::tokenTypeToString(TokenType type) {
|
|||||||
// Parser
|
// Parser
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
Parser::Parser() {
|
Parser::Parser()
|
||||||
|
: fOutOfMemErr(new(nothrow) Err("Sniffer parser error: out of memory", -1))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Parser::~Parser() {
|
||||||
|
delete fOutOfMemErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
@@ -959,35 +980,76 @@ Parser::ParseRule(Rule *result) {
|
|||||||
// Priority
|
// Priority
|
||||||
double priority = ParsePriority();
|
double priority = ParsePriority();
|
||||||
// Expression List
|
// Expression List
|
||||||
// ExprList* list = ParseExprList();
|
std::vector<Expr*>* list = ParseExprList();
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
Parser::ParsePriority() {
|
Parser::ParsePriority() {
|
||||||
Token *t = stream.Get();
|
|
||||||
Err *err = NULL;
|
|
||||||
double result;
|
double result;
|
||||||
|
const Token *t = stream.Get();
|
||||||
// cout << tokenTypeToString(t->Type()) << endl;
|
|
||||||
if (t->Type() == FloatingPoint || t->Type() == Integer)
|
if (t->Type() == FloatingPoint || t->Type() == Integer)
|
||||||
result = t->Float();
|
result = t->Float();
|
||||||
else
|
else
|
||||||
err = new Err("Sniffer pattern error: match level expected", t->Pos());
|
throw new Err("Sniffer pattern error: match level expected", t->Pos()); // Same as R5
|
||||||
|
|
||||||
delete t;
|
|
||||||
if (err)
|
|
||||||
throw err;
|
|
||||||
else
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprList*
|
std::vector<Expr*>*
|
||||||
Parser::ParseExprList() {
|
Parser::ParseExprList() {
|
||||||
// Expr+
|
std::vector<Expr*> *list = new(nothrow) std::vector<Expr*>;
|
||||||
|
if (!list)
|
||||||
|
ThrowOutOfMemError(stream.Pos());
|
||||||
|
try {
|
||||||
|
// Expr+
|
||||||
|
int count = 0;
|
||||||
|
while (true) {
|
||||||
|
Expr* expr = ParseExpr();
|
||||||
|
if (!expr)
|
||||||
|
break;
|
||||||
|
else {
|
||||||
|
list->push_back(expr);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count == 0)
|
||||||
|
throw new Err("Sniffer pattern error: missing expression", -1);
|
||||||
|
} catch (...) {
|
||||||
|
delete list;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr*
|
Expr*
|
||||||
Parser::ParseExpr() {
|
Parser::ParseExpr() {
|
||||||
|
// If we've run out of tokens right now, it's okay, but
|
||||||
|
// we need to let ParseExprList() know what's up
|
||||||
|
if (stream.IsEmpty())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Peek ahead, then let the appropriate Parse*List()
|
||||||
|
// functions handle things
|
||||||
|
const Token *t1 = stream.Get();
|
||||||
|
|
||||||
|
// PatternList | RangeList
|
||||||
|
if (t1->Type() == LeftParen) {
|
||||||
|
const Token *t2 = stream.Get();
|
||||||
|
stream.Unget();
|
||||||
|
stream.Unget();
|
||||||
|
// RangeList
|
||||||
|
if (t2->Type() == LeftBracket) {
|
||||||
|
return ParseRPatternList();
|
||||||
|
// PatternList
|
||||||
|
} else {
|
||||||
|
return ParsePatternList(Range(0,0));
|
||||||
|
}
|
||||||
|
// Range, PatternList
|
||||||
|
} else if (t1->Type() == LeftBracket) {
|
||||||
|
stream.Unget();
|
||||||
|
return ParsePatternList(ParseRange());
|
||||||
|
} else {
|
||||||
|
throw new Err("Sniffer pattern error: missing pattern", t1->Pos()); // Same as R5
|
||||||
|
}
|
||||||
|
|
||||||
// PatternList
|
// PatternList
|
||||||
// RangeList
|
// RangeList
|
||||||
// Range + PatternList
|
// Range + PatternList
|
||||||
@@ -995,41 +1057,197 @@ Parser::ParseExpr() {
|
|||||||
|
|
||||||
Range
|
Range
|
||||||
Parser::ParseRange() {
|
Parser::ParseRange() {
|
||||||
|
int32 start, end;
|
||||||
// LeftBracket
|
// LeftBracket
|
||||||
|
stream.Read(LeftBracket);
|
||||||
// Integer
|
// Integer
|
||||||
// [Colon
|
{
|
||||||
// Integer]
|
const Token *t = stream.Get();
|
||||||
// RightBracket
|
if (t->Type() == Integer) {
|
||||||
|
start = t->Int();
|
||||||
|
end = start; // In case we aren't given an explicit end
|
||||||
|
} else
|
||||||
|
throw new Err("Sniffer pattern error: pattern offset expected", t->Pos());
|
||||||
|
}
|
||||||
|
// [Colon, Integer] RightBracket
|
||||||
|
{
|
||||||
|
const Token *t = stream.Get();
|
||||||
|
// Colon, Integer, RightBracket
|
||||||
|
if (t->Type() == Colon) {
|
||||||
|
// Integer
|
||||||
|
{
|
||||||
|
const Token *t = stream.Get();
|
||||||
|
if (t->Type() == Integer) {
|
||||||
|
end = t->Int();
|
||||||
|
} else
|
||||||
|
ThrowUnexpectedTokenError(Integer, t);
|
||||||
|
}
|
||||||
|
// RightBracket
|
||||||
|
stream.Read(RightBracket);
|
||||||
|
// !(Colon, Integer) RightBracket
|
||||||
|
} else if (t->Type() == RightBracket) {
|
||||||
|
// Nothing to do here...
|
||||||
|
|
||||||
|
// Something else...
|
||||||
|
} else
|
||||||
|
ThrowUnexpectedTokenError(Colon, Integer, t);
|
||||||
|
}
|
||||||
|
Range range(start, end);
|
||||||
|
if (range.InitCheck() == B_OK)
|
||||||
|
return range;
|
||||||
|
else
|
||||||
|
throw range.GetErr();
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr*
|
Expr*
|
||||||
Parser::ParsePatternList() {
|
Parser::ParsePatternList(Range range) {
|
||||||
// LeftParen
|
PatternList *list = new(nothrow) PatternList(range);
|
||||||
// Pattern
|
if (!list)
|
||||||
// [Divider
|
ThrowOutOfMemError(stream.Pos());
|
||||||
// Pattern]*
|
try {
|
||||||
// RightParen
|
// LeftParen
|
||||||
|
stream.Read(LeftParen);
|
||||||
|
// Pattern, (Divider, Pattern)*
|
||||||
|
bool keepLooping = true;
|
||||||
|
while (true) {
|
||||||
|
// Pattern
|
||||||
|
list->Add(ParsePattern());
|
||||||
|
// [Divider]
|
||||||
|
if (!stream.CondRead(Divider))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// RightParen
|
||||||
|
const Token *t = stream.Get();
|
||||||
|
if (t->Type() != RightParen)
|
||||||
|
throw new Err("Sniffer pattern error: expecting '|', ')', or possibly '&'", t->Pos());
|
||||||
|
} catch (...) {
|
||||||
|
delete list;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr*
|
Expr*
|
||||||
Parser::ParseRPatternList() {
|
Parser::ParseRPatternList() {
|
||||||
// LeftParen
|
RPatternList *list = new(nothrow) RPatternList();
|
||||||
// RPattern
|
if (!list)
|
||||||
// [Divider
|
ThrowOutOfMemError(stream.Pos());
|
||||||
// RPattern]*
|
try {
|
||||||
// RightParen
|
// LeftParen
|
||||||
|
stream.Read(LeftParen);
|
||||||
|
// RPattern, (Divider, RPattern)*
|
||||||
|
bool keepLooping = true;
|
||||||
|
while (true) {
|
||||||
|
// RPattern
|
||||||
|
list->Add(ParseRPattern());
|
||||||
|
// [Divider]
|
||||||
|
if (!stream.CondRead(Divider))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// RightParen
|
||||||
|
const Token *t = stream.Get();
|
||||||
|
if (t->Type() != RightParen)
|
||||||
|
throw new Err("Sniffer pattern error: expecting '|', ')', or possibly '&'", t->Pos());
|
||||||
|
} catch (...) {
|
||||||
|
delete list;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
RPattern*
|
RPattern*
|
||||||
Parser::ParseRPattern() {
|
Parser::ParseRPattern() {
|
||||||
// Range
|
// Range
|
||||||
|
Range range = ParseRange();
|
||||||
// Pattern
|
// Pattern
|
||||||
|
Pattern *pattern = ParsePattern();
|
||||||
|
|
||||||
|
RPattern *result = new(nothrow) RPattern(range, pattern);
|
||||||
|
if (result) {
|
||||||
|
if (result->InitCheck() == B_OK)
|
||||||
|
return result;
|
||||||
|
else {
|
||||||
|
Err *err = result->GetErr();
|
||||||
|
delete result;
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ThrowOutOfMemError(stream.Pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern*
|
Pattern*
|
||||||
Parser::ParsePattern() {
|
Parser::ParsePattern() {
|
||||||
|
std::string str;
|
||||||
// String
|
// String
|
||||||
// [Ampersand
|
{
|
||||||
// String]
|
const Token *t = stream.Get();
|
||||||
|
if (t->Type() == CharacterString)
|
||||||
|
str = t->String();
|
||||||
|
else
|
||||||
|
throw new Err("Sniffer pattern error: missing pattern", t->Pos());
|
||||||
|
}
|
||||||
|
// [Ampersand, String]
|
||||||
|
if (stream.CondRead(Ampersand)) {
|
||||||
|
// String (i.e. Mask)
|
||||||
|
const Token *t = stream.Get();
|
||||||
|
if (t->Type() == CharacterString) {
|
||||||
|
Pattern *result = new(nothrow) Pattern(str.c_str(), t->String());
|
||||||
|
if (!result)
|
||||||
|
ThrowOutOfMemError(t->Pos());
|
||||||
|
if (result->InitCheck() == B_OK) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
Err *err = result->GetErr();
|
||||||
|
delete result;
|
||||||
|
if (err) {
|
||||||
|
err->SetPos(t->Pos());
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ThrowUnexpectedTokenError(CharacterString, t);
|
||||||
|
} else {
|
||||||
|
// No mask specified.
|
||||||
|
Pattern *result = new(nothrow) Pattern(str.c_str());
|
||||||
|
if (result) {
|
||||||
|
if (result->InitCheck() == B_OK)
|
||||||
|
return result;
|
||||||
|
else {
|
||||||
|
Err *err = result->GetErr();
|
||||||
|
delete result;
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ThrowOutOfMemError(stream.Pos());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Parser::ThrowEndOfStreamError() {
|
||||||
|
throw new Err("Sniffer pattern error: unterminated rule", stream.EndPos());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
Parser::ThrowOutOfMemError(ssize_t pos) {
|
||||||
|
if (fOutOfMemErr)
|
||||||
|
fOutOfMemErr->SetPos(pos);
|
||||||
|
Err *err = fOutOfMemErr;
|
||||||
|
fOutOfMemErr = NULL;
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Parser::ThrowUnexpectedTokenError(TokenType expected, const Token *found) {
|
||||||
|
throw new Err((std::string("Sniffer pattern error: expected ") + tokenTypeToString(expected)
|
||||||
|
+ ", found " + (found ? tokenTypeToString(found->Type()) : "NULL token")).c_str()
|
||||||
|
, (found ? found->Pos() : stream.EndPos()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Parser::ThrowUnexpectedTokenError(TokenType expected1, TokenType expected2, const Token *found) {
|
||||||
|
throw new Err((std::string("Sniffer pattern error: expected ") + tokenTypeToString(expected1)
|
||||||
|
+ " or " + tokenTypeToString(expected2) + ", found "
|
||||||
|
+ (found ? tokenTypeToString(found->Type()) : "NULL token")).c_str()
|
||||||
|
, (found ? found->Pos() : stream.EndPos()));
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user