Commit b43f8271 authored by jbeder's avatar jbeder
Browse files

Set the eol style to native for all files.

parent 859ac5e5
#pragma once #pragma once
#include <vector> #include <vector>
#include <string> #include <string>
#include <ios> #include <ios>
namespace YAML namespace YAML
{ {
struct Stream; struct Stream;
enum REGEX_OP { REGEX_EMPTY, REGEX_MATCH, REGEX_RANGE, REGEX_OR, REGEX_AND, REGEX_NOT, REGEX_SEQ }; enum REGEX_OP { REGEX_EMPTY, REGEX_MATCH, REGEX_RANGE, REGEX_OR, REGEX_AND, REGEX_NOT, REGEX_SEQ };
// simplified regular expressions // simplified regular expressions
// . Only straightforward matches (no repeated characters) // . Only straightforward matches (no repeated characters)
// . Only matches from start of string // . Only matches from start of string
class RegEx class RegEx
{ {
private: private:
struct Operator { struct Operator {
virtual ~Operator() {} virtual ~Operator() {}
virtual int Match(const std::string& str, const RegEx& regex) const = 0; virtual int Match(const std::string& str, const RegEx& regex) const = 0;
virtual int Match(std::istream& in, const RegEx& regex) const = 0; virtual int Match(std::istream& in, const RegEx& regex) const = 0;
}; };
struct MatchOperator: public Operator { struct MatchOperator: public Operator {
virtual int Match(const std::string& str, const RegEx& regex) const; virtual int Match(const std::string& str, const RegEx& regex) const;
virtual int Match(std::istream& in, const RegEx& regex) const; virtual int Match(std::istream& in, const RegEx& regex) const;
}; };
struct RangeOperator: public Operator { struct RangeOperator: public Operator {
virtual int Match(const std::string& str, const RegEx& regex) const; virtual int Match(const std::string& str, const RegEx& regex) const;
virtual int Match(std::istream& in, const RegEx& regex) const; virtual int Match(std::istream& in, const RegEx& regex) const;
}; };
struct OrOperator: public Operator { struct OrOperator: public Operator {
virtual int Match(const std::string& str, const RegEx& regex) const; virtual int Match(const std::string& str, const RegEx& regex) const;
virtual int Match(std::istream& in, const RegEx& regex) const; virtual int Match(std::istream& in, const RegEx& regex) const;
}; };
struct AndOperator: public Operator { struct AndOperator: public Operator {
virtual int Match(const std::string& str, const RegEx& regex) const; virtual int Match(const std::string& str, const RegEx& regex) const;
virtual int Match(std::istream& in, const RegEx& regex) const; virtual int Match(std::istream& in, const RegEx& regex) const;
}; };
struct NotOperator: public Operator { struct NotOperator: public Operator {
virtual int Match(const std::string& str, const RegEx& regex) const; virtual int Match(const std::string& str, const RegEx& regex) const;
virtual int Match(std::istream& in, const RegEx& regex) const; virtual int Match(std::istream& in, const RegEx& regex) const;
}; };
struct SeqOperator: public Operator { struct SeqOperator: public Operator {
virtual int Match(const std::string& str, const RegEx& regex) const; virtual int Match(const std::string& str, const RegEx& regex) const;
virtual int Match(std::istream& in, const RegEx& regex) const; virtual int Match(std::istream& in, const RegEx& regex) const;
}; };
public: public:
friend struct Operator; friend struct Operator;
RegEx(); RegEx();
RegEx(char ch); RegEx(char ch);
RegEx(char a, char z); RegEx(char a, char z);
RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ); RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ);
RegEx(const RegEx& rhs); RegEx(const RegEx& rhs);
~RegEx(); ~RegEx();
RegEx& operator = (const RegEx& rhs); RegEx& operator = (const RegEx& rhs);
bool Matches(char ch) const; bool Matches(char ch) const;
bool Matches(const std::string& str) const; bool Matches(const std::string& str) const;
bool Matches(std::istream& in) const; bool Matches(std::istream& in) const;
bool Matches(Stream& in) const; bool Matches(Stream& in) const;
int Match(const std::string& str) const; int Match(const std::string& str) const;
int Match(std::istream& in) const; int Match(std::istream& in) const;
int Match(Stream& in) const; int Match(Stream& in) const;
friend RegEx operator ! (const RegEx& ex); friend RegEx operator ! (const RegEx& ex);
friend RegEx operator || (const RegEx& ex1, const RegEx& ex2); friend RegEx operator || (const RegEx& ex1, const RegEx& ex2);
friend RegEx operator && (const RegEx& ex1, const RegEx& ex2); friend RegEx operator && (const RegEx& ex1, const RegEx& ex2);
friend RegEx operator + (const RegEx& ex1, const RegEx& ex2); friend RegEx operator + (const RegEx& ex1, const RegEx& ex2);
private: private:
RegEx(REGEX_OP op); RegEx(REGEX_OP op);
void SetOp(); void SetOp();
private: private:
REGEX_OP m_op; REGEX_OP m_op;
Operator *m_pOp; Operator *m_pOp;
char m_a, m_z; char m_a, m_z;
std::vector <RegEx> m_params; std::vector <RegEx> m_params;
}; };
} }
#include "crt.h" #include "crt.h"
#include "scalar.h" #include "scalar.h"
#include "scanner.h" #include "scanner.h"
#include "token.h" #include "token.h"
#include "exceptions.h" #include "exceptions.h"
#include "node.h" #include "node.h"
#include <sstream> #include <sstream>
namespace YAML namespace YAML
{ {
Scalar::Scalar() Scalar::Scalar()
{ {
} }
Scalar::~Scalar() Scalar::~Scalar()
{ {
} }
void Scalar::Parse(Scanner *pScanner, const ParserState& state) void Scalar::Parse(Scanner *pScanner, const ParserState& state)
{ {
Token& token = pScanner->peek(); Token& token = pScanner->peek();
m_data = token.value; m_data = token.value;
pScanner->pop(); pScanner->pop();
} }
void Scalar::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) void Scalar::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine)
{ {
out << "\""; out << "\"";
for(unsigned i=0;i<m_data.size();i++) { for(unsigned i=0;i<m_data.size();i++) {
switch(m_data[i]) { switch(m_data[i]) {
case '\\': out << "\\\\"; break; case '\\': out << "\\\\"; break;
case '\t': out << "\\t"; break; case '\t': out << "\\t"; break;
case '\n': out << "\\n"; break; case '\n': out << "\\n"; break;
case '\r': out << "\\r"; break; case '\r': out << "\\r"; break;
default: out << m_data[i]; break; default: out << m_data[i]; break;
} }
} }
out << "\"\n"; out << "\"\n";
} }
void Scalar::Read(std::string& s) void Scalar::Read(std::string& s)
{ {
s = m_data; s = m_data;
} }
void Scalar::Read(int& i) void Scalar::Read(int& i)
{ {
std::stringstream data(m_data); std::stringstream data(m_data);
data >> i; data >> i;
if(!data) if(!data)
throw InvalidScalar(); throw InvalidScalar();
} }
void Scalar::Read(unsigned& u) void Scalar::Read(unsigned& u)
{ {
std::stringstream data(m_data); std::stringstream data(m_data);
data >> u; data >> u;
if(!data) if(!data)
throw InvalidScalar(); throw InvalidScalar();
} }
void Scalar::Read(long& l) void Scalar::Read(long& l)
{ {
std::stringstream data(m_data); std::stringstream data(m_data);
data >> l; data >> l;
if(!data) if(!data)
throw InvalidScalar(); throw InvalidScalar();
} }
void Scalar::Read(float& f) void Scalar::Read(float& f)
{ {
std::stringstream data(m_data); std::stringstream data(m_data);
data >> f; data >> f;
if(!data) if(!data)
throw InvalidScalar(); throw InvalidScalar();
} }
void Scalar::Read(double& d) void Scalar::Read(double& d)
{ {
std::stringstream data(m_data); std::stringstream data(m_data);
data >> d; data >> d;
if(!data) if(!data)
throw InvalidScalar(); throw InvalidScalar();
} }
void Scalar::Read(char& c) void Scalar::Read(char& c)
{ {
std::stringstream data(m_data); std::stringstream data(m_data);
data >> c; data >> c;
if(!data) if(!data)
throw InvalidScalar(); throw InvalidScalar();
} }
int Scalar::Compare(Content *pContent) int Scalar::Compare(Content *pContent)
{ {
return -pContent->Compare(this); return -pContent->Compare(this);
} }
int Scalar::Compare(Scalar *pScalar) int Scalar::Compare(Scalar *pScalar)
{ {
if(m_data < pScalar->m_data) if(m_data < pScalar->m_data)
return -1; return -1;
else if(m_data > pScalar->m_data) else if(m_data > pScalar->m_data)
return 1; return 1;
else else
return 0; return 0;
} }
} }
#pragma once #pragma once
#include "content.h" #include "content.h"
#include <string> #include <string>
namespace YAML namespace YAML
{ {
class Scalar: public Content class Scalar: public Content
{ {
public: public:
Scalar(); Scalar();
virtual ~Scalar(); virtual ~Scalar();
virtual void Parse(Scanner *pScanner, const ParserState& state); virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine); virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine);
virtual bool IsScalar() const { return true; } virtual bool IsScalar() const { return true; }
// extraction // extraction
virtual void Read(std::string& s); virtual void Read(std::string& s);
virtual void Read(int& i); virtual void Read(int& i);
virtual void Read(unsigned& u); virtual void Read(unsigned& u);
virtual void Read(long& l); virtual void Read(long& l);
virtual void Read(float& f); virtual void Read(float& f);
virtual void Read(double& d); virtual void Read(double& d);
virtual void Read(char& c); virtual void Read(char& c);
// ordering // ordering
virtual int Compare(Content *pContent); virtual int Compare(Content *pContent);
virtual int Compare(Scalar *pScalar); virtual int Compare(Scalar *pScalar);
virtual int Compare(Sequence *pSeq) { return -1; } virtual int Compare(Sequence *pSeq) { return -1; }
virtual int Compare(Map *pMap) { return -1; } virtual int Compare(Map *pMap) { return -1; }
protected: protected:
std::string m_data; std::string m_data;
}; };
} }
#include "crt.h" #include "crt.h"
#include "scanner.h" #include "scanner.h"
#include "token.h" #include "token.h"
#include "exceptions.h" #include "exceptions.h"
#include "exp.h" #include "exp.h"
#include <cassert> #include <cassert>
namespace YAML namespace YAML
{ {
Scanner::Scanner(std::istream& in) Scanner::Scanner(std::istream& in)
: INPUT(in), m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false), m_flowLevel(0) : INPUT(in), m_startedStream(false), m_endedStream(false), m_simpleKeyAllowed(false), m_flowLevel(0)
{ {
} }
Scanner::~Scanner() Scanner::~Scanner()
{ {
} }
// empty // empty
// . Returns true if there are no more tokens to be read // . Returns true if there are no more tokens to be read
bool Scanner::empty() bool Scanner::empty()
{ {
EnsureTokensInQueue(); EnsureTokensInQueue();
return m_tokens.empty(); return m_tokens.empty();
} }
// pop // pop
// . Simply removes the next token on the queue. // . Simply removes the next token on the queue.
void Scanner::pop() void Scanner::pop()
{ {
EnsureTokensInQueue(); EnsureTokensInQueue();
if(!m_tokens.empty()) if(!m_tokens.empty())
m_tokens.pop(); m_tokens.pop();
} }
// peek // peek
// . Returns (but does not remove) the next token on the queue. // . Returns (but does not remove) the next token on the queue.
Token& Scanner::peek() Token& Scanner::peek()
{ {
EnsureTokensInQueue(); EnsureTokensInQueue();
assert(!m_tokens.empty()); // should we be asserting here? I mean, we really just be checking assert(!m_tokens.empty()); // should we be asserting here? I mean, we really just be checking
// if it's empty before peeking. // if it's empty before peeking.
return m_tokens.front(); return m_tokens.front();
} }
// EnsureTokensInQueue // EnsureTokensInQueue
// . Scan until there's a valid token at the front of the queue, // . Scan until there's a valid token at the front of the queue,
// or we're sure the queue is empty. // or we're sure the queue is empty.
void Scanner::EnsureTokensInQueue() void Scanner::EnsureTokensInQueue()
{ {
while(1) { while(1) {
if(!m_tokens.empty()) { if(!m_tokens.empty()) {
Token& token = m_tokens.front(); Token& token = m_tokens.front();
// if this guy's valid, then we're done // if this guy's valid, then we're done
if(token.status == TS_VALID) if(token.status == TS_VALID)
return; return;
// here's where we clean up the impossible tokens // here's where we clean up the impossible tokens
if(token.status == TS_INVALID) { if(token.status == TS_INVALID) {
m_tokens.pop(); m_tokens.pop();
continue; continue;
} }
// note: what's left are the unverified tokens // note: what's left are the unverified tokens
} }
// no token? maybe we've actually finished // no token? maybe we've actually finished
if(m_endedStream) if(m_endedStream)
return; return;
// no? then scan... // no? then scan...
ScanNextToken(); ScanNextToken();
} }
} }
// ScanNextToken // ScanNextToken
// . The main scanning function; here we branch out and // . The main scanning function; here we branch out and
// scan whatever the next token should be. // scan whatever the next token should be.
void Scanner::ScanNextToken() void Scanner::ScanNextToken()
{ {
if(m_endedStream) if(m_endedStream)
return; return;
if(!m_startedStream) if(!m_startedStream)
return StartStream(); return StartStream();
// get rid of whitespace, etc. (in between tokens it should be irrelevent) // get rid of whitespace, etc. (in between tokens it should be irrelevent)
ScanToNextToken(); ScanToNextToken();
// check the latest simple key // check the latest simple key
VerifySimpleKey(); VerifySimpleKey();
// maybe need to end some blocks // maybe need to end some blocks
PopIndentTo(INPUT.column); PopIndentTo(INPUT.column);
// ***** // *****
// And now branch based on the next few characters! // And now branch based on the next few characters!
// ***** // *****
// end of stream // end of stream
if(INPUT.peek() == EOF) if(INPUT.peek() == EOF)
return EndStream(); return EndStream();
if(INPUT.column == 0 && INPUT.peek() == Keys::Directive) if(INPUT.column == 0 && INPUT.peek() == Keys::Directive)
return ScanDirective(); return ScanDirective();
// document token // document token
if(INPUT.column == 0 && Exp::DocStart.Matches(INPUT)) if(INPUT.column == 0 && Exp::DocStart.Matches(INPUT))
return ScanDocStart(); return ScanDocStart();
if(INPUT.column == 0 && Exp::DocEnd.Matches(INPUT)) if(INPUT.column == 0 && Exp::DocEnd.Matches(INPUT))
return ScanDocEnd(); return ScanDocEnd();
// flow start/end/entry // flow start/end/entry
if(INPUT.peek() == Keys::FlowSeqStart || INPUT.peek() == Keys::FlowMapStart) if(INPUT.peek() == Keys::FlowSeqStart || INPUT.peek() == Keys::FlowMapStart)
return ScanFlowStart(); return ScanFlowStart();
if(INPUT.peek() == Keys::FlowSeqEnd || INPUT.peek() == Keys::FlowMapEnd) if(INPUT.peek() == Keys::FlowSeqEnd || INPUT.peek() == Keys::FlowMapEnd)
return ScanFlowEnd(); return ScanFlowEnd();
if(INPUT.peek() == Keys::FlowEntry) if(INPUT.peek() == Keys::FlowEntry)
return ScanFlowEntry(); return ScanFlowEntry();
// block/map stuff // block/map stuff
if(Exp::BlockEntry.Matches(INPUT)) if(Exp::BlockEntry.Matches(INPUT))
return ScanBlockEntry(); return ScanBlockEntry();
if((m_flowLevel == 0 ? Exp::Key : Exp::KeyInFlow).Matches(INPUT)) if((m_flowLevel == 0 ? Exp::Key : Exp::KeyInFlow).Matches(INPUT))
return ScanKey(); return ScanKey();
if((m_flowLevel == 0 ? Exp::Value : Exp::ValueInFlow).Matches(INPUT)) if((m_flowLevel == 0 ? Exp::Value : Exp::ValueInFlow).Matches(INPUT))
return ScanValue(); return ScanValue();
// alias/anchor // alias/anchor
if(INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor) if(INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor)
return ScanAnchorOrAlias(); return ScanAnchorOrAlias();
// tag // tag
if(INPUT.peek() == Keys::Tag) if(INPUT.peek() == Keys::Tag)
return ScanTag(); return ScanTag();
// special scalars // special scalars
if(m_flowLevel == 0 && (INPUT.peek() == Keys::LiteralScalar || INPUT.peek() == Keys::FoldedScalar)) if(m_flowLevel == 0 && (INPUT.peek() == Keys::LiteralScalar || INPUT.peek() == Keys::FoldedScalar))
return ScanBlockScalar(); return ScanBlockScalar();
if(INPUT.peek() == '\'' || INPUT.peek() == '\"') if(INPUT.peek() == '\'' || INPUT.peek() == '\"')
return ScanQuotedScalar(); return ScanQuotedScalar();
// plain scalars // plain scalars
if((m_flowLevel == 0 ? Exp::PlainScalar : Exp::PlainScalarInFlow).Matches(INPUT)) if((m_flowLevel == 0 ? Exp::PlainScalar : Exp::PlainScalarInFlow).Matches(INPUT))
return ScanPlainScalar(); return ScanPlainScalar();
// don't know what it is! // don't know what it is!
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::UNKNOWN_TOKEN); throw ParserException(INPUT.line, INPUT.column, ErrorMsg::UNKNOWN_TOKEN);
} }
// ScanToNextToken // ScanToNextToken
// . Eats input until we reach the next token-like thing. // . Eats input until we reach the next token-like thing.
void Scanner::ScanToNextToken() void Scanner::ScanToNextToken()
{ {
while(1) { while(1) {
// first eat whitespace // first eat whitespace
while(IsWhitespaceToBeEaten(INPUT.peek())) while(IsWhitespaceToBeEaten(INPUT.peek()))
INPUT.eat(1); INPUT.eat(1);
// then eat a comment // then eat a comment
if(Exp::Comment.Matches(INPUT)) { if(Exp::Comment.Matches(INPUT)) {
// eat until line break // eat until line break
while(INPUT && !Exp::Break.Matches(INPUT)) while(INPUT && !Exp::Break.Matches(INPUT))
INPUT.eat(1); INPUT.eat(1);
} }
// if it's NOT a line break, then we're done! // if it's NOT a line break, then we're done!
if(!Exp::Break.Matches(INPUT)) if(!Exp::Break.Matches(INPUT))
break; break;
// otherwise, let's eat the line break and keep going // otherwise, let's eat the line break and keep going
int n = Exp::Break.Match(INPUT); int n = Exp::Break.Match(INPUT);
INPUT.eat(n); 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();
// new line - we may be able to accept a simple key now // new line - we may be able to accept a simple key now
if(m_flowLevel == 0) if(m_flowLevel == 0)
m_simpleKeyAllowed = true; m_simpleKeyAllowed = true;
} }
} }
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Misc. helpers // Misc. helpers
// IsWhitespaceToBeEaten // IsWhitespaceToBeEaten
// . We can eat whitespace if: // . We can eat whitespace if:
// 1. It's a space // 1. It's a space
// 2. It's a tab, and we're either: // 2. It's a tab, and we're either:
// a. In the flow context // a. In the flow context
// b. In the block context but not where a simple key could be allowed // 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 ':') // (i.e., not at the beginning of a line, or following '-', '?', or ':')
bool Scanner::IsWhitespaceToBeEaten(char ch) bool Scanner::IsWhitespaceToBeEaten(char ch)
{ {
if(ch == ' ') if(ch == ' ')
return true; return true;
if(ch == '\t' && (m_flowLevel >= 0 || !m_simpleKeyAllowed)) if(ch == '\t' && (m_flowLevel >= 0 || !m_simpleKeyAllowed))
return true; return true;
return false; return false;
} }
// StartStream // StartStream
// . Set the initial conditions for starting a stream. // . Set the initial conditions for starting a stream.
void Scanner::StartStream() void Scanner::StartStream()
{ {
m_startedStream = true; m_startedStream = true;
m_simpleKeyAllowed = true; m_simpleKeyAllowed = true;
m_indents.push(-1); m_indents.push(-1);
} }
// EndStream // EndStream
// . Close out the stream, finish up, etc. // . Close out the stream, finish up, etc.
void Scanner::EndStream() void Scanner::EndStream()
{ {
// force newline // force newline
if(INPUT.column > 0) if(INPUT.column > 0)
INPUT.column = 0; INPUT.column = 0;
PopIndentTo(-1); PopIndentTo(-1);
VerifyAllSimpleKeys(); VerifyAllSimpleKeys();
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
m_endedStream = true; m_endedStream = true;
} }
// 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).
// . Returns the token it generates (if any). // . Returns the token it generates (if any).
Token *Scanner::PushIndentTo(int column, bool sequence) Token *Scanner::PushIndentTo(int column, bool sequence)
{ {
// are we in flow? // are we in flow?
if(m_flowLevel > 0) if(m_flowLevel > 0)
return 0; return 0;
// is this actually an indentation? // is this actually an indentation?
if(column <= m_indents.top()) if(column <= m_indents.top())
return 0; return 0;
// now push // now push
m_indents.push(column); m_indents.push(column);
if(sequence) if(sequence)
m_tokens.push(Token(TT_BLOCK_SEQ_START, INPUT.line, INPUT.column)); m_tokens.push(Token(TT_BLOCK_SEQ_START, INPUT.line, INPUT.column));
else else
m_tokens.push(Token(TT_BLOCK_MAP_START, INPUT.line, INPUT.column)); m_tokens.push(Token(TT_BLOCK_MAP_START, INPUT.line, INPUT.column));
return &m_tokens.back(); return &m_tokens.back();
} }
// PopIndentTo // PopIndentTo
// . Pops indentations off the stack until we reach 'column' indentation, // . Pops indentations off the stack until we reach 'column' indentation,
// and enqueues the proper token each time. // and enqueues the proper token each time.
void Scanner::PopIndentTo(int column) void Scanner::PopIndentTo(int column)
{ {
// are we in flow? // are we in flow?
if(m_flowLevel > 0) if(m_flowLevel > 0)
return; return;
// now pop away // now pop away
while(!m_indents.empty() && m_indents.top() > column) { while(!m_indents.empty() && m_indents.top() > column) {
m_indents.pop(); m_indents.pop();
m_tokens.push(Token(TT_BLOCK_END, INPUT.line, INPUT.column)); m_tokens.push(Token(TT_BLOCK_END, INPUT.line, INPUT.column));
} }
} }
} }
#pragma once #pragma once
#include <ios> #include <ios>
#include <string> #include <string>
#include <queue> #include <queue>
#include <stack> #include <stack>
#include <set> #include <set>
#include "stream.h" #include "stream.h"
#include "token.h" #include "token.h"
namespace YAML namespace YAML
{ {
class Scanner class Scanner
{ {
public: public:
Scanner(std::istream& in); Scanner(std::istream& in);
~Scanner(); ~Scanner();
// token queue management (hopefully this looks kinda stl-ish) // token queue management (hopefully this looks kinda stl-ish)
bool empty(); bool empty();
void pop(); void pop();
Token& peek(); Token& peek();
private: private:
// scanning // scanning
void EnsureTokensInQueue(); void EnsureTokensInQueue();
void ScanNextToken(); void ScanNextToken();
void ScanToNextToken(); void ScanToNextToken();
void StartStream(); void StartStream();
void EndStream(); void EndStream();
Token *PushIndentTo(int column, bool sequence); Token *PushIndentTo(int column, bool sequence);
void PopIndentTo(int column); void PopIndentTo(int column);
// checking input // checking input
void InsertSimpleKey(); void InsertSimpleKey();
bool VerifySimpleKey(); bool VerifySimpleKey();
void VerifyAllSimpleKeys(); void VerifyAllSimpleKeys();
bool IsWhitespaceToBeEaten(char ch); bool IsWhitespaceToBeEaten(char ch);
struct SimpleKey { struct SimpleKey {
SimpleKey(int pos_, int line_, int column_, int flowLevel_); SimpleKey(int pos_, int line_, int column_, int flowLevel_);
void Validate(); void Validate();
void Invalidate(); void Invalidate();
int pos, line, column, flowLevel; int pos, line, column, flowLevel;
Token *pMapStart, *pKey; Token *pMapStart, *pKey;
}; };
// and the tokens // and the tokens
void ScanDirective(); void ScanDirective();
void ScanDocStart(); void ScanDocStart();
void ScanDocEnd(); void ScanDocEnd();
void ScanBlockSeqStart(); void ScanBlockSeqStart();
void ScanBlockMapSTart(); void ScanBlockMapSTart();
void ScanBlockEnd(); void ScanBlockEnd();
void ScanBlockEntry(); void ScanBlockEntry();
void ScanFlowStart(); void ScanFlowStart();
void ScanFlowEnd(); void ScanFlowEnd();
void ScanFlowEntry(); void ScanFlowEntry();
void ScanKey(); void ScanKey();
void ScanValue(); void ScanValue();
void ScanAnchorOrAlias(); void ScanAnchorOrAlias();
void ScanTag(); void ScanTag();
void ScanPlainScalar(); void ScanPlainScalar();
void ScanQuotedScalar(); void ScanQuotedScalar();
void ScanBlockScalar(); void ScanBlockScalar();
private: private:
// the stream // the stream
Stream INPUT; Stream INPUT;
// the output (tokens) // the output (tokens)
std::queue <Token> m_tokens; std::queue <Token> m_tokens;
// state info // state info
bool m_startedStream, m_endedStream; bool m_startedStream, m_endedStream;
bool m_simpleKeyAllowed; bool m_simpleKeyAllowed;
int m_flowLevel; // number of unclosed '[' and '{' indicators int m_flowLevel; // number of unclosed '[' and '{' indicators
bool m_isLastKeyValid; bool m_isLastKeyValid;
std::stack <SimpleKey> m_simpleKeys; std::stack <SimpleKey> m_simpleKeys;
std::stack <int> m_indents; std::stack <int> m_indents;
}; };
} }
#include "crt.h" #include "crt.h"
#include "scanscalar.h" #include "scanscalar.h"
#include "scanner.h" #include "scanner.h"
#include "exp.h" #include "exp.h"
#include "exceptions.h" #include "exceptions.h"
#include "token.h" #include "token.h"
namespace YAML namespace YAML
{ {
// ScanScalar // ScanScalar
// . This is where the scalar magic happens. // . This is where the scalar magic happens.
// //
// . We do the scanning in three phases: // . We do the scanning in three phases:
// 1. Scan until newline // 1. Scan until newline
// 2. Eat newline // 2. Eat newline
// 3. Scan leading blanks. // 3. Scan leading blanks.
// //
// . Depending on the parameters given, we store or stop // . Depending on the parameters given, we store or stop
// and different places in the above flow. // and different places in the above flow.
std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) std::string ScanScalar(Stream& INPUT, ScanScalarParams& params)
{ {
bool foundNonEmptyLine = false, pastOpeningBreak = false; bool foundNonEmptyLine = false, pastOpeningBreak = false;
bool emptyLine = false, moreIndented = false; bool emptyLine = false, moreIndented = false;
std::string scalar; std::string scalar;
params.leadingSpaces = false; params.leadingSpaces = false;
while(INPUT) { while(INPUT) {
// ******************************** // ********************************
// Phase #1: scan until line ending // Phase #1: scan until line ending
while(!params.end.Matches(INPUT) && !Exp::Break.Matches(INPUT)) { while(!params.end.Matches(INPUT) && !Exp::Break.Matches(INPUT)) {
if(INPUT.peek() == EOF) if(INPUT.peek() == EOF)
break; break;
// document indicator? // document indicator?
if(INPUT.column == 0 && Exp::DocIndicator.Matches(INPUT)) { if(INPUT.column == 0 && Exp::DocIndicator.Matches(INPUT)) {
if(params.onDocIndicator == BREAK) if(params.onDocIndicator == BREAK)
break; break;
else if(params.onDocIndicator == THROW) else if(params.onDocIndicator == THROW)
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::DOC_IN_SCALAR); throw ParserException(INPUT.line, INPUT.column, ErrorMsg::DOC_IN_SCALAR);
} }
foundNonEmptyLine = true; foundNonEmptyLine = true;
pastOpeningBreak = true; pastOpeningBreak = true;
// escaped newline? (only if we're escaping on slash) // escaped newline? (only if we're escaping on slash)
if(params.escape == '\\' && Exp::EscBreak.Matches(INPUT)) { if(params.escape == '\\' && Exp::EscBreak.Matches(INPUT)) {
int n = Exp::EscBreak.Match(INPUT); int n = Exp::EscBreak.Match(INPUT);
INPUT.eat(n); INPUT.eat(n);
continue; continue;
} }
// escape this? // escape this?
if(INPUT.peek() == params.escape) { if(INPUT.peek() == params.escape) {
scalar += Exp::Escape(INPUT); scalar += Exp::Escape(INPUT);
continue; continue;
} }
// otherwise, just add the damn character // otherwise, just add the damn character
scalar += INPUT.get(); scalar += INPUT.get();
} }
// eof? if we're looking to eat something, then we throw // eof? if we're looking to eat something, then we throw
if(INPUT.peek() == EOF) { if(INPUT.peek() == EOF) {
if(params.eatEnd) if(params.eatEnd)
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::EOF_IN_SCALAR); throw ParserException(INPUT.line, INPUT.column, ErrorMsg::EOF_IN_SCALAR);
break; break;
} }
// doc indicator? // doc indicator?
if(params.onDocIndicator == BREAK && INPUT.column == 0 && Exp::DocIndicator.Matches(INPUT)) if(params.onDocIndicator == BREAK && INPUT.column == 0 && Exp::DocIndicator.Matches(INPUT))
break; break;
// are we done via character match? // are we done via character match?
int n = params.end.Match(INPUT); int n = params.end.Match(INPUT);
if(n >= 0) { if(n >= 0) {
if(params.eatEnd) if(params.eatEnd)
INPUT.eat(n); INPUT.eat(n);
break; break;
} }
// ******************************** // ********************************
// Phase #2: eat line ending // Phase #2: eat line ending
n = Exp::Break.Match(INPUT); n = Exp::Break.Match(INPUT);
INPUT.eat(n); INPUT.eat(n);
// ******************************** // ********************************
// Phase #3: scan initial spaces // Phase #3: scan initial spaces
// first the required indentation // first the required indentation
while(INPUT.peek() == ' ' && (INPUT.column < params.indent || (params.detectIndent && !foundNonEmptyLine))) while(INPUT.peek() == ' ' && (INPUT.column < params.indent || (params.detectIndent && !foundNonEmptyLine)))
INPUT.eat(1); INPUT.eat(1);
// update indent if we're auto-detecting // update indent if we're auto-detecting
if(params.detectIndent && !foundNonEmptyLine) if(params.detectIndent && !foundNonEmptyLine)
params.indent = std::max(params.indent, INPUT.column); params.indent = std::max(params.indent, INPUT.column);
// and then the rest of the whitespace // and then the rest of the whitespace
while(Exp::Blank.Matches(INPUT)) { while(Exp::Blank.Matches(INPUT)) {
// we check for tabs that masquerade as indentation // we check for tabs that masquerade as indentation
if(INPUT.peek() == '\t'&& INPUT.column < params.indent && params.onTabInIndentation == THROW) if(INPUT.peek() == '\t'&& INPUT.column < params.indent && params.onTabInIndentation == THROW)
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::TAB_IN_INDENTATION); throw ParserException(INPUT.line, INPUT.column, ErrorMsg::TAB_IN_INDENTATION);
if(!params.eatLeadingWhitespace) if(!params.eatLeadingWhitespace)
break; break;
INPUT.eat(1); INPUT.eat(1);
} }
// was this an empty line? // was this an empty line?
bool nextEmptyLine = Exp::Break.Matches(INPUT); bool nextEmptyLine = Exp::Break.Matches(INPUT);
bool nextMoreIndented = (INPUT.peek() == ' '); bool nextMoreIndented = (INPUT.peek() == ' ');
// for block scalars, we always start with a newline, so we should ignore it (not fold or keep) // for block scalars, we always start with a newline, so we should ignore it (not fold or keep)
bool useNewLine = pastOpeningBreak; bool useNewLine = pastOpeningBreak;
// and for folded scalars, we don't fold the very last newline to a space // and for folded scalars, we don't fold the very last newline to a space
if(params.fold && !emptyLine && INPUT.column < params.indent) if(params.fold && !emptyLine && INPUT.column < params.indent)
useNewLine = false; useNewLine = false;
if(useNewLine) { if(useNewLine) {
if(params.fold && !emptyLine && !nextEmptyLine && !moreIndented && !nextMoreIndented) if(params.fold && !emptyLine && !nextEmptyLine && !moreIndented && !nextMoreIndented)
scalar += " "; scalar += " ";
else else
scalar += "\n"; scalar += "\n";
} }
emptyLine = nextEmptyLine; emptyLine = nextEmptyLine;
moreIndented = nextMoreIndented; moreIndented = nextMoreIndented;
pastOpeningBreak = true; pastOpeningBreak = true;
// are we done via indentation? // are we done via indentation?
if(!emptyLine && INPUT.column < params.indent) { if(!emptyLine && INPUT.column < params.indent) {
params.leadingSpaces = true; params.leadingSpaces = true;
break; break;
} }
} }
// post-processing // post-processing
if(params.trimTrailingSpaces) { if(params.trimTrailingSpaces) {
unsigned pos = scalar.find_last_not_of(' '); unsigned pos = scalar.find_last_not_of(' ');
if(pos < scalar.size()) if(pos < scalar.size())
scalar.erase(pos + 1); scalar.erase(pos + 1);
} }
if(params.chomp <= 0) { if(params.chomp <= 0) {
unsigned pos = scalar.find_last_not_of('\n'); unsigned pos = scalar.find_last_not_of('\n');
if(params.chomp == 0 && pos + 1 < scalar.size()) if(params.chomp == 0 && pos + 1 < scalar.size())
scalar.erase(pos + 2); scalar.erase(pos + 2);
else if(params.chomp == -1 && pos < scalar.size()) else if(params.chomp == -1 && pos < scalar.size())
scalar.erase(pos + 1); scalar.erase(pos + 1);
} }
return scalar; return scalar;
} }
} }
#pragma once #pragma once
#include <string> #include <string>
#include "regex.h" #include "regex.h"
#include "stream.h" #include "stream.h"
namespace YAML namespace YAML
{ {
enum CHOMP { STRIP = -1, CLIP, KEEP }; enum CHOMP { STRIP = -1, CLIP, KEEP };
enum ACTION { NONE, BREAK, THROW }; enum ACTION { NONE, BREAK, THROW };
struct ScanScalarParams { struct ScanScalarParams {
ScanScalarParams(): eatEnd(false), indent(0), detectIndent(false), eatLeadingWhitespace(0), escape(0), fold(false), ScanScalarParams(): eatEnd(false), indent(0), detectIndent(false), eatLeadingWhitespace(0), escape(0), fold(false),
trimTrailingSpaces(0), chomp(CLIP), onDocIndicator(NONE), onTabInIndentation(NONE), leadingSpaces(false) {} trimTrailingSpaces(0), chomp(CLIP), onDocIndicator(NONE), onTabInIndentation(NONE), leadingSpaces(false) {}
// input: // input:
RegEx end; // what condition ends this scalar? RegEx end; // what condition ends this scalar?
bool eatEnd; // should we eat that condition when we see it? bool eatEnd; // should we eat that condition when we see it?
int indent; // what level of indentation should be eaten and ignored? int indent; // what level of indentation should be eaten and ignored?
bool detectIndent; // should we try to autodetect the indent? bool detectIndent; // should we try to autodetect the indent?
bool eatLeadingWhitespace; // should we continue eating this delicious indentation after 'indent' spaces? bool eatLeadingWhitespace; // should we continue eating this delicious indentation after 'indent' spaces?
char escape; // what character do we escape on (i.e., slash or single quote) (0 for none) char escape; // what character do we escape on (i.e., slash or single quote) (0 for none)
bool fold; // do we fold line ends? bool fold; // do we fold line ends?
bool trimTrailingSpaces; // do we remove all trailing spaces (at the very end) bool trimTrailingSpaces; // do we remove all trailing spaces (at the very end)
CHOMP chomp; // do we strip, clip, or keep trailing newlines (at the very end) CHOMP chomp; // do we strip, clip, or keep trailing newlines (at the very end)
// Note: strip means kill all, clip means keep at most one, keep means keep all // Note: strip means kill all, clip means keep at most one, keep means keep all
ACTION onDocIndicator; // what do we do if we see a document indicator? ACTION onDocIndicator; // what do we do if we see a document indicator?
ACTION onTabInIndentation; // what do we do if we see a tab where we should be seeing indentation spaces ACTION onTabInIndentation; // what do we do if we see a tab where we should be seeing indentation spaces
// output: // output:
bool leadingSpaces; bool leadingSpaces;
}; };
std::string ScanScalar(Stream& INPUT, ScanScalarParams& info); std::string ScanScalar(Stream& INPUT, ScanScalarParams& info);
} }
This diff is collapsed.
This diff is collapsed.
#pragma once #pragma once
#include "content.h" #include "content.h"
#include <vector> #include <vector>
namespace YAML namespace YAML
{ {
class Node; class Node;
class Sequence: public Content class Sequence: public Content
{ {
public: public:
Sequence(); Sequence();
virtual ~Sequence(); virtual ~Sequence();
void Clear(); void Clear();
virtual bool GetBegin(std::vector <Node *>::const_iterator& it) const; virtual bool GetBegin(std::vector <Node *>::const_iterator& it) const;
virtual bool GetEnd(std::vector <Node *>::const_iterator& it) const; virtual bool GetEnd(std::vector <Node *>::const_iterator& it) const;
virtual Node *GetNode(unsigned i) const; virtual Node *GetNode(unsigned i) const;
virtual unsigned GetSize() const; virtual unsigned GetSize() const;
virtual void Parse(Scanner *pScanner, const ParserState& state); virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine); virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine);
virtual bool IsSequence() const { return true; } virtual bool IsSequence() const { return true; }
// ordering // ordering
virtual int Compare(Content *pContent); virtual int Compare(Content *pContent);
virtual int Compare(Scalar *pScalar) { return 1; } virtual int Compare(Scalar *pScalar) { return 1; }
virtual int Compare(Sequence *pSeq); virtual int Compare(Sequence *pSeq);
virtual int Compare(Map *pMap) { return -1; } virtual int Compare(Map *pMap) { return -1; }
private: private:
void ParseBlock(Scanner *pScanner, const ParserState& state); void ParseBlock(Scanner *pScanner, const ParserState& state);
void ParseImplicit(Scanner *pScanner, const ParserState& state); void ParseImplicit(Scanner *pScanner, const ParserState& state);
void ParseFlow(Scanner *pScanner, const ParserState& state); void ParseFlow(Scanner *pScanner, const ParserState& state);
protected: protected:
std::vector <Node *> m_data; std::vector <Node *> m_data;
}; };
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment