mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-04 22:11:26 +12:00
Added a peek token command (for the parser to use).
This commit is contained in:
parent
07d4cac48f
commit
ed6c294749
6 changed files with 109 additions and 113 deletions
15
document.cpp
15
document.cpp
|
@ -5,6 +5,9 @@
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "token.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
Document::Document(): m_pRoot(0)
|
Document::Document(): m_pRoot(0)
|
||||||
|
@ -34,10 +37,16 @@ namespace YAML
|
||||||
std::ifstream fin(fileName.c_str());
|
std::ifstream fin(fileName.c_str());
|
||||||
Scanner scanner(fin);
|
Scanner scanner(fin);
|
||||||
|
|
||||||
scanner.Scan();
|
// scan and output, for now
|
||||||
|
while(1) {
|
||||||
|
Token *pToken = scanner.GetNextToken();
|
||||||
|
if(!pToken)
|
||||||
|
break;
|
||||||
|
|
||||||
|
std::cout << typeid(*pToken).name() << ": " << *pToken << std::endl;
|
||||||
|
delete pToken;
|
||||||
|
}
|
||||||
getchar();
|
getchar();
|
||||||
// if(!scanner)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// m_pRoot = parser.ReadNextNode();
|
// m_pRoot = parser.ReadNextNode();
|
||||||
}
|
}
|
||||||
|
|
35
exceptions.h
35
exceptions.h
|
@ -5,33 +5,34 @@
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
class Exception: public std::exception {};
|
class Exception: public std::exception {};
|
||||||
|
class ScannerException: public Exception {};
|
||||||
|
|
||||||
class UnknownToken: public Exception {};
|
class UnknownToken: public ScannerException {};
|
||||||
class IllegalBlockEntry: public Exception {};
|
class IllegalBlockEntry: public ScannerException {};
|
||||||
class IllegalMapKey: public Exception {};
|
class IllegalMapKey: public ScannerException {};
|
||||||
class IllegalMapValue: public Exception {};
|
class IllegalMapValue: public ScannerException {};
|
||||||
class IllegalScalar: public Exception {};
|
class IllegalScalar: public ScannerException {};
|
||||||
class IllegalTabInIndentation: public Exception {};
|
class IllegalTabInIndentation: public ScannerException {};
|
||||||
class IllegalFlowEnd: public Exception {};
|
class IllegalFlowEnd: public ScannerException {};
|
||||||
class IllegalDocIndicator: public Exception {};
|
class IllegalDocIndicator: public ScannerException {};
|
||||||
class IllegalEOF: public Exception {};
|
class IllegalEOF: public ScannerException {};
|
||||||
class RequiredSimpleKeyNotFound: public Exception {};
|
class RequiredSimpleKeyNotFound: public ScannerException {};
|
||||||
class ZeroIndentationInBlockScalar: public Exception {};
|
class ZeroIndentationInBlockScalar: public ScannerException {};
|
||||||
class UnexpectedCharacterInBlockScalar: public Exception {};
|
class UnexpectedCharacterInBlockScalar: public ScannerException {};
|
||||||
class AnchorNotFound: public Exception {};
|
class AnchorNotFound: public ScannerException {};
|
||||||
class IllegalCharacterInAnchor: public Exception {};
|
class IllegalCharacterInAnchor: public ScannerException {};
|
||||||
|
|
||||||
class UnknownEscapeSequence: public Exception {
|
class UnknownEscapeSequence: public ScannerException {
|
||||||
public:
|
public:
|
||||||
UnknownEscapeSequence(char ch_): ch(ch_) {}
|
UnknownEscapeSequence(char ch_): ch(ch_) {}
|
||||||
char ch;
|
char ch;
|
||||||
};
|
};
|
||||||
class NonHexNumber: public Exception {
|
class NonHexNumber: public ScannerException {
|
||||||
public:
|
public:
|
||||||
NonHexNumber(char ch_): ch(ch_) {}
|
NonHexNumber(char ch_): ch(ch_) {}
|
||||||
char ch;
|
char ch;
|
||||||
};
|
};
|
||||||
class InvalidUnicode: public Exception {
|
class InvalidUnicode: public ScannerException {
|
||||||
public:
|
public:
|
||||||
InvalidUnicode(unsigned value_): value(value_) {}
|
InvalidUnicode(unsigned value_): value(value_) {}
|
||||||
unsigned value;
|
unsigned value;
|
||||||
|
|
161
scanner.cpp
161
scanner.cpp
|
@ -2,7 +2,6 @@
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "exp.h"
|
#include "exp.h"
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
|
@ -23,39 +22,51 @@ namespace YAML
|
||||||
delete *it;
|
delete *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
// GetNextToken
|
||||||
// Misc. helpers
|
// . Removes and returns the next token on the queue.
|
||||||
|
Token *Scanner::GetNextToken()
|
||||||
// IsWhitespaceToBeEaten
|
|
||||||
// . We can eat whitespace if:
|
|
||||||
// 1. It's a space
|
|
||||||
// 2. It's a tab, and we're either:
|
|
||||||
// a. In the flow context
|
|
||||||
// b. In the block context but not where a simple key could be allowed
|
|
||||||
// (i.e., not at the beginning of a line, or following '-', '?', or ':')
|
|
||||||
bool Scanner::IsWhitespaceToBeEaten(char ch)
|
|
||||||
{
|
{
|
||||||
if(ch == ' ')
|
Token *pToken = PeekNextToken();
|
||||||
return true;
|
if(!m_tokens.empty())
|
||||||
|
m_tokens.pop();
|
||||||
if(ch == '\t' && (m_flowLevel >= 0 || !m_simpleKeyAllowed))
|
return pToken;
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScanAndEnqueue
|
// PeekNextToken
|
||||||
// . Scans the token, then pushes it in the queue.
|
// . Returns (but does not remove) the next token on the queue, and scans if only we need to.
|
||||||
// . Note: we also use a set of "limbo tokens", i.e., tokens
|
Token *Scanner::PeekNextToken()
|
||||||
// that haven't yet been pushed. This way, if ScanToken()
|
|
||||||
// throws an exception, we'll be keeping track of 'pToken'
|
|
||||||
// somewhere, and it will be automatically cleaned up when
|
|
||||||
// the Scanner destructs.
|
|
||||||
template <typename T> void Scanner::ScanAndEnqueue(T *pToken)
|
|
||||||
{
|
{
|
||||||
m_limboTokens.insert(pToken);
|
while(1) {
|
||||||
m_tokens.push(ScanToken(pToken));
|
Token *pToken = 0;
|
||||||
m_limboTokens.erase(pToken);
|
|
||||||
|
// is there a token in the queue?
|
||||||
|
if(!m_tokens.empty())
|
||||||
|
pToken = m_tokens.front();
|
||||||
|
|
||||||
|
// (here's where we clean up the impossible tokens)
|
||||||
|
if(pToken && pToken->status == TS_INVALID) {
|
||||||
|
m_tokens.pop();
|
||||||
|
delete pToken;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// on unverified tokens, we just have to wait
|
||||||
|
if(pToken && pToken->status == TS_UNVERIFIED)
|
||||||
|
pToken = 0;
|
||||||
|
|
||||||
|
// then that's what we want
|
||||||
|
if(pToken)
|
||||||
|
return pToken;
|
||||||
|
|
||||||
|
// no token? maybe we've actually finished
|
||||||
|
if(m_endedStream)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// no? then scan...
|
||||||
|
ScanNextToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScanNextToken
|
// ScanNextToken
|
||||||
|
@ -166,7 +177,8 @@ namespace YAML
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// otherwise, let's eat the line break and keep going
|
// otherwise, let's eat the line break and keep going
|
||||||
INPUT.EatLineBreak();
|
int n = Exp::Break.Match(INPUT);
|
||||||
|
INPUT.Eat(n);
|
||||||
|
|
||||||
// oh yeah, and let's get rid of that simple key
|
// oh yeah, and let's get rid of that simple key
|
||||||
VerifySimpleKey();
|
VerifySimpleKey();
|
||||||
|
@ -177,6 +189,41 @@ namespace YAML
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
// Misc. helpers
|
||||||
|
|
||||||
|
// IsWhitespaceToBeEaten
|
||||||
|
// . We can eat whitespace if:
|
||||||
|
// 1. It's a space
|
||||||
|
// 2. It's a tab, and we're either:
|
||||||
|
// a. In the flow context
|
||||||
|
// b. In the block context but not where a simple key could be allowed
|
||||||
|
// (i.e., not at the beginning of a line, or following '-', '?', or ':')
|
||||||
|
bool Scanner::IsWhitespaceToBeEaten(char ch)
|
||||||
|
{
|
||||||
|
if(ch == ' ')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(ch == '\t' && (m_flowLevel >= 0 || !m_simpleKeyAllowed))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ScanAndEnqueue
|
||||||
|
// . Scans the token, then pushes it in the queue.
|
||||||
|
// . Note: we also use a set of "limbo tokens", i.e., tokens
|
||||||
|
// that haven't yet been pushed. This way, if ScanToken()
|
||||||
|
// throws an exception, we'll be keeping track of 'pToken'
|
||||||
|
// somewhere, and it will be automatically cleaned up when
|
||||||
|
// the Scanner destructs.
|
||||||
|
template <typename T> void Scanner::ScanAndEnqueue(T *pToken)
|
||||||
|
{
|
||||||
|
m_limboTokens.insert(pToken);
|
||||||
|
m_tokens.push(ScanToken(pToken));
|
||||||
|
m_limboTokens.erase(pToken);
|
||||||
|
}
|
||||||
|
|
||||||
// PushIndentTo
|
// PushIndentTo
|
||||||
// . Pushes an indentation onto the stack, and enqueues the
|
// . Pushes an indentation onto the stack, and enqueues the
|
||||||
// proper token (sequence start or mapping start).
|
// proper token (sequence start or mapping start).
|
||||||
|
@ -216,56 +263,4 @@ namespace YAML
|
||||||
m_tokens.push(new BlockEndToken);
|
m_tokens.push(new BlockEndToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNextToken
|
|
||||||
// . Returns the next token on the queue, and scans if only we need to.
|
|
||||||
Token *Scanner::GetNextToken()
|
|
||||||
{
|
|
||||||
while(1) {
|
|
||||||
Token *pToken = 0;
|
|
||||||
|
|
||||||
// is there a token in the queue?
|
|
||||||
if(!m_tokens.empty())
|
|
||||||
pToken = m_tokens.front();
|
|
||||||
|
|
||||||
// (here's where we clean up the impossible tokens)
|
|
||||||
if(pToken && pToken->status == TS_INVALID) {
|
|
||||||
m_tokens.pop();
|
|
||||||
delete pToken;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// on unverified tokens, we just have to wait
|
|
||||||
if(pToken && pToken->status == TS_UNVERIFIED)
|
|
||||||
pToken = 0;
|
|
||||||
|
|
||||||
// then that's what we want
|
|
||||||
if(pToken) {
|
|
||||||
m_tokens.pop();
|
|
||||||
return pToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no token? maybe we've actually finished
|
|
||||||
if(m_endedStream)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// no? then scan...
|
|
||||||
ScanNextToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// temporary function for testing
|
|
||||||
void Scanner::Scan()
|
|
||||||
{
|
|
||||||
while(1) {
|
|
||||||
Token *pToken = GetNextToken();
|
|
||||||
if(!pToken)
|
|
||||||
break;
|
|
||||||
|
|
||||||
std::cout << typeid(*pToken).name() << ": " << *pToken << std::endl;
|
|
||||||
delete pToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace YAML
|
||||||
~Scanner();
|
~Scanner();
|
||||||
|
|
||||||
Token *GetNextToken();
|
Token *GetNextToken();
|
||||||
void Scan();
|
Token *PeekNextToken();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// scanning
|
// scanning
|
||||||
|
|
|
@ -32,12 +32,4 @@ namespace YAML
|
||||||
for(int i=0;i<n;i++)
|
for(int i=0;i<n;i++)
|
||||||
GetChar();
|
GetChar();
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLineBreak
|
|
||||||
// . Eats with no checking
|
|
||||||
void Stream::EatLineBreak()
|
|
||||||
{
|
|
||||||
Eat(1);
|
|
||||||
column = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
1
stream.h
1
stream.h
|
@ -18,7 +18,6 @@ namespace YAML
|
||||||
char GetChar();
|
char GetChar();
|
||||||
std::string GetChar(int n);
|
std::string GetChar(int n);
|
||||||
void Eat(int n = 1);
|
void Eat(int n = 1);
|
||||||
void EatLineBreak();
|
|
||||||
|
|
||||||
std::istream& input;
|
std::istream& input;
|
||||||
int line, column;
|
int line, column;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue