+ Got rid of global TokenStream object
+ Started on Parser class + Moved parsing functions into Parser class + Added Pos() member to Err class to allow for snazzy BMimeType::CheckSnifferRule() error strings. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@531 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -10,14 +10,23 @@
|
|||||||
#define _sk_sniffer_parser_h_
|
#define _sk_sniffer_parser_h_
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
#include <sniffer/Range.h>
|
||||||
|
#include <sniffer/Rule.h>
|
||||||
#include <List.h>
|
#include <List.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
class BString;
|
class BString;
|
||||||
|
|
||||||
namespace Sniffer {
|
namespace Sniffer {
|
||||||
|
|
||||||
class Rule;
|
class Rule;
|
||||||
|
class Expr;
|
||||||
|
class Range;
|
||||||
|
class RPattern;
|
||||||
|
class Pattern;
|
||||||
|
typedef std::vector<Expr*> ExprList;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// The mighty parsing function ;-)
|
// The mighty parsing function ;-)
|
||||||
@@ -31,15 +40,17 @@ status_t parse(const char *rule, Rule *result, BString *parseError = NULL);
|
|||||||
|
|
||||||
class Err {
|
class Err {
|
||||||
public:
|
public:
|
||||||
Err(const char *msg);
|
Err(const char *msg, const ssize_t pos);
|
||||||
Err(const std::string &msg);
|
Err(const std::string &msg, const ssize_t pos);
|
||||||
Err(const Err &ref);
|
Err(const Err &ref);
|
||||||
Err& operator=(const Err &ref);
|
Err& operator=(const Err &ref);
|
||||||
const char* Msg() const;
|
const char* Msg() const;
|
||||||
|
ssize_t Pos() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetMsg(const char *msg);
|
void SetMsg(const char *msg);
|
||||||
char *fMsg;
|
char *fMsg;
|
||||||
|
ssize_t fPos;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CharStream {
|
class CharStream {
|
||||||
@@ -51,14 +62,14 @@ public:
|
|||||||
void Unset();
|
void Unset();
|
||||||
status_t InitCheck() const;
|
status_t InitCheck() const;
|
||||||
bool IsEmpty() const;
|
bool IsEmpty() const;
|
||||||
size_t Pos() const;
|
ssize_t Pos() const;
|
||||||
|
|
||||||
char Get();
|
char Get();
|
||||||
void Unget();
|
void Unget();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char *fString;
|
char *fString;
|
||||||
size_t fPos;
|
ssize_t fPos;
|
||||||
ssize_t fLen;
|
ssize_t fLen;
|
||||||
status_t fCStatus;
|
status_t fCStatus;
|
||||||
|
|
||||||
@@ -84,21 +95,22 @@ const char* tokenTypeToString(TokenType type);
|
|||||||
|
|
||||||
class Token {
|
class Token {
|
||||||
public:
|
public:
|
||||||
Token(TokenType type = EmptyToken, const size_t posInStream = -1);
|
Token(TokenType type = EmptyToken, const ssize_t pos = -1);
|
||||||
virtual ~Token();
|
virtual ~Token();
|
||||||
TokenType Type() const;
|
TokenType Type() const;
|
||||||
virtual const char* String() const;
|
virtual const char* String() const;
|
||||||
virtual int32 Int() const;
|
virtual int32 Int() const;
|
||||||
virtual double Float() const;
|
virtual double Float() const;
|
||||||
|
ssize_t Pos() const;
|
||||||
bool operator==(Token &ref);
|
bool operator==(Token &ref);
|
||||||
protected:
|
protected:
|
||||||
TokenType fType;
|
TokenType fType;
|
||||||
size_t fPosInStream;
|
ssize_t fPos;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StringToken : public Token {
|
class StringToken : public Token {
|
||||||
public:
|
public:
|
||||||
StringToken(const char *string, const size_t posInStream);
|
StringToken(const char *string, const ssize_t pos);
|
||||||
virtual ~StringToken();
|
virtual ~StringToken();
|
||||||
virtual const char* String() const;
|
virtual const char* String() const;
|
||||||
protected:
|
protected:
|
||||||
@@ -107,7 +119,7 @@ protected:
|
|||||||
|
|
||||||
class IntToken : public Token {
|
class IntToken : public Token {
|
||||||
public:
|
public:
|
||||||
IntToken(const int32 value, const size_t posInStream);
|
IntToken(const int32 value, const ssize_t pos);
|
||||||
virtual int32 Int() const;
|
virtual int32 Int() const;
|
||||||
virtual double Float() const;
|
virtual double Float() const;
|
||||||
protected:
|
protected:
|
||||||
@@ -116,7 +128,7 @@ protected:
|
|||||||
|
|
||||||
class FloatToken : public Token {
|
class FloatToken : public Token {
|
||||||
public:
|
public:
|
||||||
FloatToken(const double value, const size_t posInStream);
|
FloatToken(const double value, const ssize_t pos);
|
||||||
virtual double Float() const;
|
virtual double Float() const;
|
||||||
protected:
|
protected:
|
||||||
double fValue;
|
double fValue;
|
||||||
@@ -137,10 +149,10 @@ public:
|
|||||||
bool IsEmpty();
|
bool IsEmpty();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddToken(TokenType type, size_t posInStream);
|
void AddToken(TokenType type, ssize_t pos);
|
||||||
void AddString(const char *str, size_t posInStream);
|
void AddString(const char *str, ssize_t pos);
|
||||||
void AddInt(const char *str, size_t posInStream);
|
void AddInt(const char *str, ssize_t pos);
|
||||||
void AddFloat(const char *str, size_t posInStream);
|
void AddFloat(const char *str, ssize_t pos);
|
||||||
|
|
||||||
BList fTokenList;
|
BList fTokenList;
|
||||||
status_t fCStatus;
|
status_t fCStatus;
|
||||||
@@ -149,7 +161,28 @@ private:
|
|||||||
TokenStream& operator=(const TokenStream &ref);
|
TokenStream& operator=(const TokenStream &ref);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Sniffer
|
class Parser {
|
||||||
|
public:
|
||||||
|
Parser();
|
||||||
|
status_t Parse(const char *rule, Rule *result, BString *parseError = NULL);
|
||||||
|
private:
|
||||||
|
std::string ErrorMessage(Err *err, const char *rule);
|
||||||
|
|
||||||
|
// Parsing functions
|
||||||
|
void ParseRule(Rule *result);
|
||||||
|
double ParsePriority();
|
||||||
|
ExprList* ParseExprList();
|
||||||
|
Expr* ParseExpr();
|
||||||
|
Range ParseRange();
|
||||||
|
Expr* ParsePatternList();
|
||||||
|
Expr* ParseRPatternList();
|
||||||
|
RPattern* ParseRPattern();
|
||||||
|
Pattern* ParsePattern();
|
||||||
|
|
||||||
|
TokenStream stream;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Sniffer
|
||||||
|
|
||||||
|
|
||||||
#endif // _sk_sniffer_parser_h_
|
#endif // _sk_sniffer_parser_h_
|
||||||
|
|||||||
@@ -23,20 +23,6 @@
|
|||||||
|
|
||||||
using namespace Sniffer;
|
using namespace Sniffer;
|
||||||
|
|
||||||
// Our global token stream object
|
|
||||||
TokenStream stream;
|
|
||||||
|
|
||||||
// Private parsing functions
|
|
||||||
double parsePriority();
|
|
||||||
/*
|
|
||||||
BList* parseExprList();
|
|
||||||
Expr* parseExpr();
|
|
||||||
Range parseRange();
|
|
||||||
Expr* parsePatternList();
|
|
||||||
Expr* parseRPatternList();
|
|
||||||
Pattern* parsePattern();
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Miscellaneous helper functions
|
// Miscellaneous helper functions
|
||||||
char escapeChar(char ch);
|
char escapeChar(char ch);
|
||||||
char hexToChar(char hi, char low);
|
char hexToChar(char hi, char low);
|
||||||
@@ -51,42 +37,33 @@ bool isDecimalChar(char ch);
|
|||||||
bool isPunctuation(char ch);
|
bool isPunctuation(char ch);
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Sniffer::parse(const char *rule, Rule *result, BString *parseError = NULL) {
|
Sniffer::parse(const char *rule, Rule *result, BString *parseError) {
|
||||||
try {
|
Parser parser;
|
||||||
if (!rule)
|
return parser.Parse(rule, result, parseError);
|
||||||
throw new Err("Sniffer pattern error: NULL pattern");
|
|
||||||
if (!result)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
if (stream.SetTo(rule) != B_OK)
|
|
||||||
throw new Err("Sniffer parser error: Unable to intialize token stream");
|
|
||||||
|
|
||||||
double priority;
|
|
||||||
BList* exprList;
|
|
||||||
|
|
||||||
priority = parsePriority();
|
|
||||||
|
|
||||||
} catch (Err *err) {
|
|
||||||
if (parseError && err)
|
|
||||||
parseError->SetTo((err->Msg() ? err->Msg() : "Sniffer parser rule: Unexpected error with no supplied error message"));
|
|
||||||
return B_BAD_MIME_SNIFFER_RULE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Sniffer::Err
|
// Err
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
Err::Err(const char *msg)
|
Err::Err(const char *msg, const ssize_t pos)
|
||||||
: fMsg(NULL)
|
: fMsg(NULL)
|
||||||
|
, fPos(pos)
|
||||||
{
|
{
|
||||||
SetMsg(msg);
|
SetMsg(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
Err::Err(const std::string &msg) {
|
Err::Err(const std::string &msg, const ssize_t pos)
|
||||||
|
: fMsg(NULL)
|
||||||
|
, fPos(pos)
|
||||||
|
{
|
||||||
SetMsg(msg.c_str());
|
SetMsg(msg.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
Err::Err(const Err &ref) {
|
Err::Err(const Err &ref)
|
||||||
|
: fMsg(NULL)
|
||||||
|
, fPos(-1)
|
||||||
|
{
|
||||||
*this = ref;
|
*this = ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +78,11 @@ Err::Msg() const {
|
|||||||
return fMsg;
|
return fMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
Err::Pos() const {
|
||||||
|
return fPos;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Err::SetMsg(const char *msg) {
|
Err::SetMsg(const char *msg) {
|
||||||
if (fMsg) {
|
if (fMsg) {
|
||||||
@@ -116,7 +98,6 @@ Err::SetMsg(const char *msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// CharStream
|
// CharStream
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -168,7 +149,7 @@ CharStream::IsEmpty() const {
|
|||||||
return fPos >= fLen;
|
return fPos >= fLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
ssize_t
|
||||||
CharStream::Pos() const {
|
CharStream::Pos() const {
|
||||||
return fPos;
|
return fPos;
|
||||||
}
|
}
|
||||||
@@ -176,7 +157,7 @@ CharStream::Pos() const {
|
|||||||
char
|
char
|
||||||
CharStream::Get() {
|
CharStream::Get() {
|
||||||
if (fCStatus != B_OK)
|
if (fCStatus != B_OK)
|
||||||
throw new Err("Sniffer parser error: CharStream::Get() called on uninitialized CharStream object");
|
throw new Err("Sniffer parser error: CharStream::Get() called on uninitialized CharStream object", -1);
|
||||||
if (fPos < fLen)
|
if (fPos < fLen)
|
||||||
return fString[fPos++];
|
return fString[fPos++];
|
||||||
else {
|
else {
|
||||||
@@ -188,20 +169,20 @@ CharStream::Get() {
|
|||||||
void
|
void
|
||||||
CharStream::Unget() {
|
CharStream::Unget() {
|
||||||
if (fCStatus != B_OK)
|
if (fCStatus != B_OK)
|
||||||
throw new Err("Sniffer parser error: CharStream::Unget() called on uninitialized CharStream object");
|
throw new Err("Sniffer parser error: CharStream::Unget() called on uninitialized CharStream object", -1);
|
||||||
if (fPos > 0)
|
if (fPos > 0)
|
||||||
fPos--;
|
fPos--;
|
||||||
else
|
else
|
||||||
throw new Err("Sniffer parser error: CharStream::Unget() called at beginning of character stream");
|
throw new Err("Sniffer parser error: CharStream::Unget() called at beginning of character stream", -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Token
|
// Token
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
Token::Token(TokenType type, const size_t posInStream)
|
Token::Token(TokenType type, const ssize_t pos)
|
||||||
: fType(type)
|
: fType(type)
|
||||||
, fPosInStream(posInStream)
|
, fPos(pos)
|
||||||
{
|
{
|
||||||
// if (type != EmptyToken)
|
// if (type != EmptyToken)
|
||||||
// cout << "New Token, fType == " << tokenTypeToString(fType) << endl;
|
// cout << "New Token, fType == " << tokenTypeToString(fType) << endl;
|
||||||
@@ -217,17 +198,22 @@ Token::Type() const {
|
|||||||
|
|
||||||
const char*
|
const char*
|
||||||
Token::String() const {
|
Token::String() const {
|
||||||
throw new Err("Sniffer scanner error: Token::String() called on non-string token");
|
throw new Err("Sniffer scanner error: Token::String() called on non-string token", fPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32
|
int32
|
||||||
Token::Int() const {
|
Token::Int() const {
|
||||||
throw new Err("Sniffer scanner error: Token::Int() called on non-integer token");
|
throw new Err("Sniffer scanner error: Token::Int() called on non-integer token", fPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
Token::Float() const {
|
Token::Float() const {
|
||||||
throw new Err("Sniffer scanner error: Token::Float() called on non-float token");
|
throw new Err("Sniffer scanner error: Token::Float() called on non-float token", fPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
Token::Pos() const {
|
||||||
|
return fPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -278,8 +264,8 @@ Token::operator==(Token &ref) {
|
|||||||
// StringToken
|
// StringToken
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
StringToken::StringToken(const char *string, const size_t posInStream)
|
StringToken::StringToken(const char *string, const ssize_t pos)
|
||||||
: Token(CharacterString, posInStream)
|
: Token(CharacterString, pos)
|
||||||
, fString(NULL)
|
, fString(NULL)
|
||||||
{
|
{
|
||||||
if (string) {
|
if (string) {
|
||||||
@@ -302,8 +288,8 @@ StringToken::String() const {
|
|||||||
// IntToken
|
// IntToken
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
IntToken::IntToken(const int32 value, const size_t posInStream)
|
IntToken::IntToken(const int32 value, const ssize_t pos)
|
||||||
: Token(Integer, posInStream)
|
: Token(Integer, pos)
|
||||||
, fValue(value)
|
, fValue(value)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -322,8 +308,8 @@ IntToken::Float() const {
|
|||||||
// FloatToken
|
// FloatToken
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
FloatToken::FloatToken(const double value, const size_t posInStream)
|
FloatToken::FloatToken(const double value, const ssize_t pos)
|
||||||
: Token(FloatingPoint, posInStream)
|
: Token(FloatingPoint, pos)
|
||||||
, fValue(value)
|
, fValue(value)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -353,7 +339,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
if (string) {
|
if (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");
|
throw new Err("Sniffer scanner error: Unable to intialize character stream", -1);
|
||||||
|
|
||||||
typedef enum TokenStreamScannerState {
|
typedef enum TokenStreamScannerState {
|
||||||
tsssStart,
|
tsssStart,
|
||||||
@@ -387,7 +373,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
char lastLastChar; // For three char lookahead
|
char lastLastChar; // For three char lookahead
|
||||||
bool keepLooping = true;
|
bool keepLooping = true;
|
||||||
while (keepLooping) {
|
while (keepLooping) {
|
||||||
size_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:
|
||||||
@@ -396,7 +382,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
if (stream.IsEmpty())
|
if (stream.IsEmpty())
|
||||||
keepLooping = false;
|
keepLooping = false;
|
||||||
else
|
else
|
||||||
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'");
|
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\t':
|
case '\t':
|
||||||
@@ -460,7 +446,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 + "'");
|
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -476,7 +462,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
break;
|
break;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
if (stream.IsEmpty())
|
if (stream.IsEmpty())
|
||||||
throw new Err(std::string("Sniffer scanner error: unterminated single-quoted string"));
|
throw new Err(std::string("Sniffer scanner error: unterminated single-quoted string"), pos);
|
||||||
else
|
else
|
||||||
charStr += ch;
|
charStr += ch;
|
||||||
break;
|
break;
|
||||||
@@ -498,7 +484,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
break;
|
break;
|
||||||
case 0x3:
|
case 0x3:
|
||||||
if (stream.IsEmpty())
|
if (stream.IsEmpty())
|
||||||
throw new Err(std::string("Sniffer scanner error: unterminated single-quoted string"));
|
throw new Err(std::string("Sniffer scanner error: unterminated single-quoted string"), pos);
|
||||||
else
|
else
|
||||||
charStr += ch;
|
charStr += ch;
|
||||||
break;
|
break;
|
||||||
@@ -537,9 +523,9 @@ TokenStream::SetTo(const char *string) {
|
|||||||
lastChar = ch;
|
lastChar = ch;
|
||||||
state = tsssOneHex;
|
state = tsssOneHex;
|
||||||
} else if (ch == 0x3 && stream.IsEmpty())
|
} else if (ch == 0x3 && stream.IsEmpty())
|
||||||
throw new Err(std::string("Sniffer scanner error: incomplete hex code"));
|
throw new Err(std::string("Sniffer scanner error: incomplete hex code"), pos);
|
||||||
else
|
else
|
||||||
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'");
|
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tsssOneHex:
|
case tsssOneHex:
|
||||||
@@ -547,9 +533,9 @@ TokenStream::SetTo(const char *string) {
|
|||||||
charStr += hexToChar(lastChar, ch);
|
charStr += hexToChar(lastChar, ch);
|
||||||
state = tsssTwoHex;
|
state = tsssTwoHex;
|
||||||
} else if (ch == 0x3 && stream.IsEmpty())
|
} else if (ch == 0x3 && stream.IsEmpty())
|
||||||
throw Err(std::string("Sniffer scanner error: incomplete hex code (the number of hex digits must be a multiple of two)"));
|
throw new Err(std::string("Sniffer scanner error: incomplete hex code (the number of hex digits must be a multiple of two)"), pos);
|
||||||
else
|
else
|
||||||
throw Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'");
|
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tsssTwoHex:
|
case tsssTwoHex:
|
||||||
@@ -564,7 +550,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
AddString(charStr.c_str(), pos);
|
AddString(charStr.c_str(), pos);
|
||||||
keepLooping = false;
|
keepLooping = false;
|
||||||
} else
|
} else
|
||||||
throw Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'");
|
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tsssIntOrFloat:
|
case tsssIntOrFloat:
|
||||||
@@ -601,9 +587,9 @@ TokenStream::SetTo(const char *string) {
|
|||||||
charStr += ch;
|
charStr += ch;
|
||||||
state = tsssFloat;
|
state = tsssFloat;
|
||||||
} else if (ch == 0x3 && stream.IsEmpty())
|
} else if (ch == 0x3 && stream.IsEmpty())
|
||||||
throw new Err(std::string("Sniffer scanner error: incomplete floating point number"));
|
throw new Err(std::string("Sniffer scanner error: incomplete floating point number"), pos);
|
||||||
else
|
else
|
||||||
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'");
|
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tsssLonelyMinusOrPlusSign:
|
case tsssLonelyMinusOrPlusSign:
|
||||||
@@ -611,16 +597,16 @@ TokenStream::SetTo(const char *string) {
|
|||||||
charStr += ch;
|
charStr += ch;
|
||||||
state = tsssPosNegInt;
|
state = tsssPosNegInt;
|
||||||
} else if (ch == 0x3 && stream.IsEmpty())
|
} else if (ch == 0x3 && stream.IsEmpty())
|
||||||
throw new Err(std::string("Sniffer scanner error: incomplete signed integer"));
|
throw new Err(std::string("Sniffer scanner error: incomplete signed integer"), pos);
|
||||||
else
|
else
|
||||||
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'");
|
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tsssPosNegInt:
|
case tsssPosNegInt:
|
||||||
if (isDecimalChar(ch))
|
if (isDecimalChar(ch))
|
||||||
charStr += ch;
|
charStr += ch;
|
||||||
else if (ch == '.')
|
else if (ch == '.')
|
||||||
throw new Err(std::string("Sniffer scanner error: negative floating point numbers are useless and thus signs (both + and -) are disallowed on floating points"));
|
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 {
|
else {
|
||||||
// Terminate the number
|
// Terminate the number
|
||||||
AddInt(charStr.c_str(), pos);
|
AddInt(charStr.c_str(), pos);
|
||||||
@@ -640,7 +626,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
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 + "'");
|
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(), pos);
|
||||||
keepLooping = false;
|
keepLooping = false;
|
||||||
@@ -656,7 +642,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"));
|
throw new Err(std::string("Sniffer scanner error: unterminated 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
|
||||||
@@ -669,7 +655,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
lastChar = ch;
|
lastChar = ch;
|
||||||
state = tsssEscapeOneHex;
|
state = tsssEscapeOneHex;
|
||||||
} else
|
} else
|
||||||
throw new Err(std::string("Sniffer scanner error: incomplete hex code"));
|
throw new Err(std::string("Sniffer scanner error: incomplete hex code"), pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case tsssEscapeOneOctal:
|
case tsssEscapeOneOctal:
|
||||||
@@ -708,9 +694,9 @@ TokenStream::SetTo(const char *string) {
|
|||||||
charStr += hexToChar(lastChar, ch);
|
charStr += hexToChar(lastChar, ch);
|
||||||
state = escapedState;
|
state = escapedState;
|
||||||
} else if (ch == 0x3 && stream.IsEmpty())
|
} else if (ch == 0x3 && stream.IsEmpty())
|
||||||
throw new Err(std::string("Sniffer scanner error: incomplete escaped hex code (the number of hex digits must be a multiple of two)"));
|
throw new Err(std::string("Sniffer scanner error: incomplete escaped hex code (the number of hex digits must be a multiple of two)"), pos);
|
||||||
else
|
else
|
||||||
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'");
|
throw new Err(std::string("Sniffer scanner error: unexpected character '") + ch + "'", pos);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -718,7 +704,7 @@ TokenStream::SetTo(const char *string) {
|
|||||||
if (state == tsssStart)
|
if (state == tsssStart)
|
||||||
fCStatus = B_OK;
|
fCStatus = B_OK;
|
||||||
else
|
else
|
||||||
throw new Err("Sniffer pattern error: unterminated rule");
|
throw new Err("Sniffer pattern error: unterminated rule", stream.Pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
return fCStatus;
|
return fCStatus;
|
||||||
@@ -752,30 +738,30 @@ TokenStream::IsEmpty() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TokenStream::AddToken(TokenType type, size_t posInStream) {
|
TokenStream::AddToken(TokenType type, ssize_t pos) {
|
||||||
Token *token = new Token(type, posInStream);
|
Token *token = new Token(type, pos);
|
||||||
fTokenList.AddItem(token);
|
fTokenList.AddItem(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TokenStream::AddString(const char *str, size_t posInStream) {
|
TokenStream::AddString(const char *str, ssize_t pos) {
|
||||||
Token *token = new StringToken(str, posInStream);
|
Token *token = new StringToken(str, pos);
|
||||||
fTokenList.AddItem(token);
|
fTokenList.AddItem(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TokenStream::AddInt(const char *str, size_t posInStream) {
|
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, posInStream);
|
Token *token = new IntToken(value, pos);
|
||||||
fTokenList.AddItem(token);
|
fTokenList.AddItem(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TokenStream::AddFloat(const char *str, size_t posInStream) {
|
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, posInStream);
|
Token *token = new FloatToken(value, pos);
|
||||||
fTokenList.AddItem(token);
|
fTokenList.AddItem(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,7 +812,7 @@ hexToChar(char hex) {
|
|||||||
else if ('A' <= hex && hex <= 'F')
|
else if ('A' <= hex && hex <= 'F')
|
||||||
return hex-'a'+10;
|
return hex-'a'+10;
|
||||||
else
|
else
|
||||||
throw new Err(std::string("Sniffer parser error: invalid hex digit '") + hex + "' passed to hexToChar()");
|
throw new Err(std::string("Sniffer parser error: invalid hex digit '") + hex + "' passed to hexToChar()", -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
char
|
char
|
||||||
@@ -844,7 +830,7 @@ octalToChar(char hi, char mid, char low) {
|
|||||||
if (isOctalChar(hi) && isOctalChar(mid) && isOctalChar(low)) {
|
if (isOctalChar(hi) && isOctalChar(mid) && isOctalChar(low)) {
|
||||||
return ((hi-'0') << 6) | ((mid-'0') << 3) | (low-'0');
|
return ((hi-'0') << 6) | ((mid-'0') << 3) | (low-'0');
|
||||||
} else
|
} else
|
||||||
throw new Err(std::string("Sniffer parser error: invalid octal digit passed to hexToChar()"));
|
throw new Err(std::string("Sniffer parser error: invalid octal digit passed to hexToChar()"), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -925,10 +911,125 @@ Sniffer::tokenTypeToString(TokenType type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Parsing functions
|
// Parser
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
double
|
Parser::Parser() {
|
||||||
parsePriority() {
|
|
||||||
// stream.Read(LeftBracket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Parser::Parse(const char *rule, Rule *result, BString *parseError) {
|
||||||
|
try {
|
||||||
|
if (!rule)
|
||||||
|
throw new Err("Sniffer pattern error: NULL pattern", -1);
|
||||||
|
if (!result)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
if (stream.SetTo(rule) != B_OK)
|
||||||
|
throw new Err("Sniffer parser error: Unable to intialize token stream", -1);
|
||||||
|
|
||||||
|
ParseRule(result);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
} catch (Err *err) {
|
||||||
|
// cout << "Caught error" << endl;
|
||||||
|
if (parseError)
|
||||||
|
parseError->SetTo(ErrorMessage(err, rule).c_str());
|
||||||
|
delete err;
|
||||||
|
return B_BAD_MIME_SNIFFER_RULE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
Parser::ErrorMessage(Err *err, const char *rule) {
|
||||||
|
const char* msg = (err && err->Msg())
|
||||||
|
? err->Msg()
|
||||||
|
: "Sniffer parser error: Unexpected error with no supplied error message";
|
||||||
|
size_t pos = err && (err->Pos() >= 0) ? err->Pos() : 0;
|
||||||
|
std::string str = std::string(rule) + "\n";
|
||||||
|
for (int i = 0; i < pos; i++)
|
||||||
|
str += " ";
|
||||||
|
str += "^ ";
|
||||||
|
str += msg;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Parser::ParseRule(Rule *result) {
|
||||||
|
// Priority
|
||||||
|
double priority = ParsePriority();
|
||||||
|
// Expression List
|
||||||
|
// ExprList* list = ParseExprList();
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
Parser::ParsePriority() {
|
||||||
|
Token *t = stream.Get();
|
||||||
|
Err *err = NULL;
|
||||||
|
double result;
|
||||||
|
|
||||||
|
// cout << tokenTypeToString(t->Type()) << endl;
|
||||||
|
if (t->Type() == FloatingPoint || t->Type() == Integer)
|
||||||
|
result = t->Float();
|
||||||
|
else
|
||||||
|
err = new Err("Sniffer pattern error: match level expected", t->Pos());
|
||||||
|
|
||||||
|
delete t;
|
||||||
|
if (err)
|
||||||
|
throw err;
|
||||||
|
else
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExprList*
|
||||||
|
Parser::ParseExprList() {
|
||||||
|
// Expr+
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr*
|
||||||
|
Parser::ParseExpr() {
|
||||||
|
// PatternList
|
||||||
|
// RangeList
|
||||||
|
// Range + PatternList
|
||||||
|
}
|
||||||
|
|
||||||
|
Range
|
||||||
|
Parser::ParseRange() {
|
||||||
|
// LeftBracket
|
||||||
|
// Integer
|
||||||
|
// [Colon
|
||||||
|
// Integer]
|
||||||
|
// RightBracket
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr*
|
||||||
|
Parser::ParsePatternList() {
|
||||||
|
// LeftParen
|
||||||
|
// Pattern
|
||||||
|
// [Divider
|
||||||
|
// Pattern]*
|
||||||
|
// RightParen
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr*
|
||||||
|
Parser::ParseRPatternList() {
|
||||||
|
// LeftParen
|
||||||
|
// RPattern
|
||||||
|
// [Divider
|
||||||
|
// RPattern]*
|
||||||
|
// RightParen
|
||||||
|
}
|
||||||
|
|
||||||
|
RPattern*
|
||||||
|
Parser::ParseRPattern() {
|
||||||
|
// Range
|
||||||
|
// Pattern
|
||||||
|
}
|
||||||
|
|
||||||
|
Pattern*
|
||||||
|
Parser::ParsePattern() {
|
||||||
|
// String
|
||||||
|
// [Ampersand
|
||||||
|
// String]
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user