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:
Tyler Dauwalder
2002-08-06 08:37:14 +00:00
parent 01293d6ed7
commit 390dce8da6
2 changed files with 405 additions and 185 deletions
+27 -25
View File
@@ -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
View File
@@ -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()));
}