Collected pos, line, and column into a Mark struct

This commit is contained in:
Jesse Beder 2009-07-27 02:56:18 +00:00
parent 9b78bd459b
commit b1ce042535
17 changed files with 145 additions and 137 deletions

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "mark.h"
#include <exception> #include <exception>
#include <string> #include <string>
#include <sstream> #include <sstream>
@ -60,16 +61,16 @@ namespace YAML
class Exception: public std::exception { class Exception: public std::exception {
public: public:
Exception(int line_, int column_, const std::string& msg_) Exception(const Mark& mark_, const std::string& msg_)
: line(line_), column(column_), msg(msg_) { : mark(mark_), msg(msg_) {
std::stringstream output; std::stringstream output;
output << "Error at line " << line+1 << ", column " << column+1 << ": " << msg; output << "Error at line " << mark.line+1 << ", column " << mark.column+1 << ": " << msg;
what_ = output.str(); what_ = output.str();
} }
virtual ~Exception() throw() {} virtual ~Exception() throw() {}
virtual const char *what() const throw() { return what_.c_str(); } virtual const char *what() const throw() { return what_.c_str(); }
int line, column; Mark mark;
std::string msg; std::string msg;
private: private:
@ -78,53 +79,53 @@ namespace YAML
class ParserException: public Exception { class ParserException: public Exception {
public: public:
ParserException(int line_, int column_, const std::string& msg_) ParserException(const Mark& mark_, const std::string& msg_)
: Exception(line_, column_, msg_) {} : Exception(mark_, msg_) {}
}; };
class RepresentationException: public Exception { class RepresentationException: public Exception {
public: public:
RepresentationException(int line_, int column_, const std::string& msg_) RepresentationException(const Mark& mark_, const std::string& msg_)
: Exception(line_, column_, msg_) {} : Exception(mark_, msg_) {}
}; };
// representation exceptions // representation exceptions
class InvalidScalar: public RepresentationException { class InvalidScalar: public RepresentationException {
public: public:
InvalidScalar(int line_, int column_) InvalidScalar(const Mark& mark_)
: RepresentationException(line_, column_, ErrorMsg::INVALID_SCALAR) {} : RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
}; };
class KeyNotFound: public RepresentationException { class KeyNotFound: public RepresentationException {
public: public:
KeyNotFound(int line_, int column_) KeyNotFound(const Mark& mark_)
: RepresentationException(line_, column_, ErrorMsg::KEY_NOT_FOUND) {} : RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND) {}
}; };
template <typename T> template <typename T>
class TypedKeyNotFound: public KeyNotFound { class TypedKeyNotFound: public KeyNotFound {
public: public:
TypedKeyNotFound(int line_, int column_, const T& key_) TypedKeyNotFound(const Mark& mark_, const T& key_)
: KeyNotFound(line_, column_), key(key_) {} : KeyNotFound(mark_), key(key_) {}
~TypedKeyNotFound() throw() {} ~TypedKeyNotFound() throw() {}
T key; T key;
}; };
template <typename T> template <typename T>
TypedKeyNotFound <T> MakeTypedKeyNotFound(int line, int column, const T& key) { TypedKeyNotFound <T> MakeTypedKeyNotFound(const Mark& mark, const T& key) {
return TypedKeyNotFound <T> (line, column, key); return TypedKeyNotFound <T> (mark, key);
} }
class BadDereference: public RepresentationException { class BadDereference: public RepresentationException {
public: public:
BadDereference() BadDereference()
: RepresentationException(-1, -1, ErrorMsg::BAD_DEREFERENCE) {} : RepresentationException(Mark::null(), ErrorMsg::BAD_DEREFERENCE) {}
}; };
class EmitterException: public Exception { class EmitterException: public Exception {
public: public:
EmitterException(const std::string& msg_) EmitterException(const std::string& msg_)
: Exception(-1, -1, msg_) {} : Exception(Mark::null(), msg_) {}
}; };
} }

View File

@ -1,14 +1,15 @@
#pragma once #pragma once
#include "conversion.h"
#include "exceptions.h"
#include "iterator.h"
#include "mark.h"
#include "noncopyable.h"
#include "parserstate.h"
#include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include "parserstate.h"
#include "exceptions.h"
#include "iterator.h"
#include "conversion.h"
#include "noncopyable.h"
#include <iostream>
namespace YAML namespace YAML
{ {
@ -30,8 +31,7 @@ namespace YAML
CONTENT_TYPE GetType() const; CONTENT_TYPE GetType() const;
// file location of start of this node // file location of start of this node
int GetLine() const { return m_line; } const Mark GetMark() const { return m_mark; }
int GetColumn() const { return m_column; }
// accessors // accessors
Iterator begin() const; Iterator begin() const;
@ -85,7 +85,7 @@ namespace YAML
void ParseAlias(Scanner *pScanner, const ParserState& state); void ParseAlias(Scanner *pScanner, const ParserState& state);
private: private:
int m_line, m_column; Mark m_mark;
std::string m_anchor, m_tag; std::string m_anchor, m_tag;
Content *m_pContent; Content *m_pContent;
bool m_alias; bool m_alias;

View File

@ -15,7 +15,7 @@ namespace YAML
template <typename T> template <typename T>
inline void operator >> (const Node& node, T& value) { inline void operator >> (const Node& node, T& value) {
if(!node.Read(value)) if(!node.Read(value))
throw InvalidScalar(node.m_line, node.m_column); throw InvalidScalar(node.m_mark);
} }
template <typename T> template <typename T>
@ -51,7 +51,7 @@ namespace YAML
} }
} }
throw MakeTypedKeyNotFound(m_line, m_column, key); throw MakeTypedKeyNotFound(m_mark, key);
} }
template <typename T> template <typename T>

View File

@ -7,7 +7,7 @@ namespace YAML
{ {
namespace Exp namespace Exp
{ {
unsigned ParseHex(const std::string& str, int line, int column) unsigned ParseHex(const std::string& str, const Mark& mark)
{ {
unsigned value = 0; unsigned value = 0;
for(unsigned i=0;i<str.size();i++) { for(unsigned i=0;i<str.size();i++) {
@ -20,7 +20,7 @@ namespace YAML
else if('0' <= ch && ch <= '9') else if('0' <= ch && ch <= '9')
digit = ch - '0'; digit = ch - '0';
else else
throw ParserException(line, column, ErrorMsg::INVALID_HEX); throw ParserException(mark, ErrorMsg::INVALID_HEX);
value = (value << 4) + digit; value = (value << 4) + digit;
} }
@ -44,13 +44,13 @@ namespace YAML
str += in.get(); str += in.get();
// get the value // get the value
unsigned value = ParseHex(str, in.line, in.column); unsigned value = ParseHex(str, in.mark());
// legal unicode? // legal unicode?
if((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) { if((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
std::stringstream msg; std::stringstream msg;
msg << ErrorMsg::INVALID_UNICODE << value; msg << ErrorMsg::INVALID_UNICODE << value;
throw ParserException(in.line, in.column, msg.str()); throw ParserException(in.mark(), msg.str());
} }
// now break it up into chars // now break it up into chars
@ -107,7 +107,7 @@ namespace YAML
} }
std::stringstream msg; std::stringstream msg;
throw ParserException(in.line, in.column, ErrorMsg::INVALID_ESCAPE + ch); throw ParserException(in.mark(), ErrorMsg::INVALID_ESCAPE + ch);
} }
} }
} }

View File

@ -58,11 +58,11 @@ namespace YAML
while(1) { while(1) {
if(pScanner->empty()) if(pScanner->empty())
throw ParserException(-1, -1, ErrorMsg::END_OF_MAP); throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
Token token = pScanner->peek(); Token token = pScanner->peek();
if(token.type != TT_KEY && token.type != TT_BLOCK_END) if(token.type != TT_KEY && token.type != TT_BLOCK_END)
throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP); throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
pScanner->pop(); pScanner->pop();
if(token.type == TT_BLOCK_END) if(token.type == TT_BLOCK_END)
@ -91,7 +91,7 @@ namespace YAML
while(1) { while(1) {
if(pScanner->empty()) if(pScanner->empty())
throw ParserException(-1, -1, ErrorMsg::END_OF_MAP_FLOW); throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
Token& token = pScanner->peek(); Token& token = pScanner->peek();
// first check for end // first check for end
@ -102,7 +102,7 @@ namespace YAML
// now it better be a key // now it better be a key
if(token.type != TT_KEY) if(token.type != TT_KEY)
throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP_FLOW); throw ParserException(token.mark, ErrorMsg::END_OF_MAP_FLOW);
pScanner->pop(); pScanner->pop();
@ -122,7 +122,7 @@ namespace YAML
if(nextToken.type == TT_FLOW_ENTRY) if(nextToken.type == TT_FLOW_ENTRY)
pScanner->pop(); pScanner->pop();
else if(nextToken.type != TT_FLOW_MAP_END) else if(nextToken.type != TT_FLOW_MAP_END)
throw ParserException(nextToken.line, nextToken.column, ErrorMsg::END_OF_MAP_FLOW); throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
// assign the map with the actual pointers // assign the map with the actual pointers
m_data[pKey.release()] = pValue.release(); m_data[pKey.release()] = pValue.release();

View File

@ -47,8 +47,7 @@ namespace YAML
return; return;
// save location // save location
m_line = pScanner->peek().line; m_mark = pScanner->peek().mark;
m_column = pScanner->peek().column;
ParseHeader(pScanner, state); ParseHeader(pScanner, state);
@ -119,7 +118,7 @@ namespace YAML
{ {
Token& token = pScanner->peek(); Token& token = pScanner->peek();
if(m_tag != "") if(m_tag != "")
throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_TAGS); throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
m_tag = state.TranslateTag(token.value); m_tag = state.TranslateTag(token.value);
@ -132,7 +131,7 @@ namespace YAML
{ {
Token& token = pScanner->peek(); Token& token = pScanner->peek();
if(m_anchor != "") if(m_anchor != "")
throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_ANCHORS); throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
m_anchor = token.value; m_anchor = token.value;
m_alias = false; m_alias = false;
@ -143,9 +142,9 @@ namespace YAML
{ {
Token& token = pScanner->peek(); Token& token = pScanner->peek();
if(m_anchor != "") if(m_anchor != "")
throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_ALIASES); throw ParserException(token.mark, ErrorMsg::MULTIPLE_ALIASES);
if(m_tag != "") if(m_tag != "")
throw ParserException(token.line, token.column, ErrorMsg::ALIAS_CONTENT); throw ParserException(token.mark, ErrorMsg::ALIAS_CONTENT);
m_anchor = token.value; m_anchor = token.value;
m_alias = true; m_alias = true;

View File

@ -98,17 +98,17 @@ namespace YAML
void Parser::HandleYamlDirective(Token *pToken) void Parser::HandleYamlDirective(Token *pToken)
{ {
if(pToken->params.size() != 1) if(pToken->params.size() != 1)
throw ParserException(pToken->line, pToken->column, ErrorMsg::YAML_DIRECTIVE_ARGS); throw ParserException(pToken->mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
std::stringstream str(pToken->params[0]); std::stringstream str(pToken->params[0]);
str >> m_state.version.major; str >> m_state.version.major;
str.get(); str.get();
str >> m_state.version.minor; str >> m_state.version.minor;
if(!str || str.peek() != EOF) if(!str || str.peek() != EOF)
throw ParserException(pToken->line, pToken->column, ErrorMsg::YAML_VERSION + pToken->params[0]); throw ParserException(pToken->mark, ErrorMsg::YAML_VERSION + pToken->params[0]);
if(m_state.version.major > 1) if(m_state.version.major > 1)
throw ParserException(pToken->line, pToken->column, ErrorMsg::YAML_MAJOR_VERSION); throw ParserException(pToken->mark, ErrorMsg::YAML_MAJOR_VERSION);
// TODO: warning on major == 1, minor > 2? // TODO: warning on major == 1, minor > 2?
} }
@ -118,7 +118,7 @@ namespace YAML
void Parser::HandleTagDirective(Token *pToken) void Parser::HandleTagDirective(Token *pToken)
{ {
if(pToken->params.size() != 2) if(pToken->params.size() != 2)
throw ParserException(pToken->line, pToken->column, ErrorMsg::TAG_DIRECTIVE_ARGS); throw ParserException(pToken->mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
std::string handle = pToken->params[0], prefix = pToken->params[1]; std::string handle = pToken->params[0], prefix = pToken->params[1];
m_state.tags[handle] = prefix; m_state.tags[handle] = prefix;

View File

@ -98,7 +98,7 @@ namespace YAML
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!
@ -108,14 +108,14 @@ namespace YAML
if(!INPUT) if(!INPUT)
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
@ -158,7 +158,7 @@ namespace YAML
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.mark(), ErrorMsg::UNKNOWN_TOKEN);
} }
// ScanToNextToken // ScanToNextToken
@ -230,8 +230,8 @@ namespace YAML
void Scanner::EndStream() void Scanner::EndStream()
{ {
// force newline // force newline
if(INPUT.column > 0) if(INPUT.column() > 0)
INPUT.column = 0; INPUT.ResetColumn();
PopIndentTo(-1); PopIndentTo(-1);
VerifyAllSimpleKeys(); VerifyAllSimpleKeys();
@ -257,9 +257,9 @@ namespace YAML
// 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.mark()));
else else
m_tokens.push(Token(TT_BLOCK_MAP_START, INPUT.line, INPUT.column)); m_tokens.push(Token(TT_BLOCK_MAP_START, INPUT.mark()));
return &m_tokens.back(); return &m_tokens.back();
} }
@ -276,7 +276,7 @@ namespace YAML
// 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.mark()));
} }
} }
@ -309,13 +309,12 @@ namespace YAML
// . Does not parse any more tokens. // . Does not parse any more tokens.
void Scanner::ThrowParserException(const std::string& msg) const void Scanner::ThrowParserException(const std::string& msg) const
{ {
int line = -1, column = -1; Mark mark = Mark::null();
if(!m_tokens.empty()) { if(!m_tokens.empty()) {
const Token& token = m_tokens.front(); const Token& token = m_tokens.front();
line = token.line; mark = token.mark;
column = token.column;
} }
throw ParserException(line, column, msg); throw ParserException(mark, msg);
} }
void Scanner::ClearAnchors() void Scanner::ClearAnchors()

View File

@ -48,12 +48,13 @@ namespace YAML
bool IsWhitespaceToBeEaten(char ch); bool IsWhitespaceToBeEaten(char ch);
struct SimpleKey { struct SimpleKey {
SimpleKey(int pos_, int line_, int column_, int flowLevel_); SimpleKey(const Mark& mark_, int flowLevel_);
void Validate(); void Validate();
void Invalidate(); void Invalidate();
int pos, line, column, flowLevel; Mark mark;
int flowLevel;
Token *pMapStart, *pKey; Token *pMapStart, *pKey;
}; };

View File

@ -32,11 +32,11 @@ namespace YAML
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.mark(), ErrorMsg::DOC_IN_SCALAR);
} }
foundNonEmptyLine = true; foundNonEmptyLine = true;
@ -62,12 +62,12 @@ namespace YAML
// eof? if we're looking to eat something, then we throw // eof? if we're looking to eat something, then we throw
if(!INPUT) { if(!INPUT) {
if(params.eatEnd) if(params.eatEnd)
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::EOF_IN_SCALAR); throw ParserException(INPUT.mark(), 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?
@ -87,18 +87,18 @@ namespace YAML
// 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.mark(), ErrorMsg::TAB_IN_INDENTATION);
if(!params.eatLeadingWhitespace) if(!params.eatLeadingWhitespace)
break; break;
@ -113,7 +113,7 @@ namespace YAML
// 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) {
@ -128,7 +128,7 @@ namespace YAML
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;
} }

View File

@ -25,7 +25,7 @@ namespace YAML
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
// store pos and eat indicator // store pos and eat indicator
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
INPUT.eat(1); INPUT.eat(1);
// read name // read name
@ -50,7 +50,7 @@ namespace YAML
params.push_back(param); params.push_back(param);
} }
Token token(TT_DIRECTIVE, line, column); Token token(TT_DIRECTIVE, mark);
token.value = name; token.value = name;
token.params = params; token.params = params;
m_tokens.push(token); m_tokens.push(token);
@ -64,9 +64,9 @@ namespace YAML
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
// eat // eat
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
INPUT.eat(3); INPUT.eat(3);
m_tokens.push(Token(TT_DOC_START, line, column)); m_tokens.push(Token(TT_DOC_START, mark));
} }
// DocEnd // DocEnd
@ -77,9 +77,9 @@ namespace YAML
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
// eat // eat
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
INPUT.eat(3); INPUT.eat(3);
m_tokens.push(Token(TT_DOC_END, line, column)); m_tokens.push(Token(TT_DOC_END, mark));
} }
// FlowStart // FlowStart
@ -91,26 +91,26 @@ namespace YAML
m_simpleKeyAllowed = true; m_simpleKeyAllowed = true;
// eat // eat
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
char ch = INPUT.get(); char ch = INPUT.get();
TOKEN_TYPE type = (ch == Keys::FlowSeqStart ? TT_FLOW_SEQ_START : TT_FLOW_MAP_START); TOKEN_TYPE type = (ch == Keys::FlowSeqStart ? TT_FLOW_SEQ_START : TT_FLOW_MAP_START);
m_tokens.push(Token(type, line, column)); m_tokens.push(Token(type, mark));
} }
// FlowEnd // FlowEnd
void Scanner::ScanFlowEnd() void Scanner::ScanFlowEnd()
{ {
if(m_flowLevel == 0) if(m_flowLevel == 0)
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::FLOW_END); throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);
m_flowLevel--; m_flowLevel--;
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
// eat // eat
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
char ch = INPUT.get(); char ch = INPUT.get();
TOKEN_TYPE type = (ch == Keys::FlowSeqEnd ? TT_FLOW_SEQ_END : TT_FLOW_MAP_END); TOKEN_TYPE type = (ch == Keys::FlowSeqEnd ? TT_FLOW_SEQ_END : TT_FLOW_MAP_END);
m_tokens.push(Token(type, line, column)); m_tokens.push(Token(type, mark));
} }
// FlowEntry // FlowEntry
@ -119,9 +119,9 @@ namespace YAML
m_simpleKeyAllowed = true; m_simpleKeyAllowed = true;
// eat // eat
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
INPUT.eat(1); INPUT.eat(1);
m_tokens.push(Token(TT_FLOW_ENTRY, line, column)); m_tokens.push(Token(TT_FLOW_ENTRY, mark));
} }
// BlockEntry // BlockEntry
@ -129,19 +129,19 @@ namespace YAML
{ {
// we better be in the block context! // we better be in the block context!
if(m_flowLevel > 0) if(m_flowLevel > 0)
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::BLOCK_ENTRY); throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY);
// can we put it here? // can we put it here?
if(!m_simpleKeyAllowed) if(!m_simpleKeyAllowed)
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::BLOCK_ENTRY); throw ParserException(INPUT.mark(), ErrorMsg::BLOCK_ENTRY);
PushIndentTo(INPUT.column, true); PushIndentTo(INPUT.column(), true);
m_simpleKeyAllowed = true; m_simpleKeyAllowed = true;
// eat // eat
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
INPUT.eat(1); INPUT.eat(1);
m_tokens.push(Token(TT_BLOCK_ENTRY, line, column)); m_tokens.push(Token(TT_BLOCK_ENTRY, mark));
} }
// Key // Key
@ -150,9 +150,9 @@ namespace YAML
// handle keys diffently in the block context (and manage indents) // handle keys diffently in the block context (and manage indents)
if(m_flowLevel == 0) { if(m_flowLevel == 0) {
if(!m_simpleKeyAllowed) if(!m_simpleKeyAllowed)
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::MAP_KEY); throw ParserException(INPUT.mark(), ErrorMsg::MAP_KEY);
PushIndentTo(INPUT.column, false); PushIndentTo(INPUT.column(), false);
} }
// can only put a simple key here if we're in block context // can only put a simple key here if we're in block context
@ -162,9 +162,9 @@ namespace YAML
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
// eat // eat
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
INPUT.eat(1); INPUT.eat(1);
m_tokens.push(Token(TT_KEY, line, column)); m_tokens.push(Token(TT_KEY, mark));
} }
// Value // Value
@ -178,9 +178,9 @@ namespace YAML
// handle values diffently in the block context (and manage indents) // handle values diffently in the block context (and manage indents)
if(m_flowLevel == 0) { if(m_flowLevel == 0) {
if(!m_simpleKeyAllowed) if(!m_simpleKeyAllowed)
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::MAP_VALUE); throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE);
PushIndentTo(INPUT.column, false); PushIndentTo(INPUT.column(), false);
} }
// can only put a simple key here if we're in block context // can only put a simple key here if we're in block context
@ -191,9 +191,9 @@ namespace YAML
} }
// eat // eat
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
INPUT.eat(1); INPUT.eat(1);
m_tokens.push(Token(TT_VALUE, line, column)); m_tokens.push(Token(TT_VALUE, mark));
} }
// AnchorOrAlias // AnchorOrAlias
@ -208,7 +208,7 @@ namespace YAML
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
// eat the indicator // eat the indicator
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
char indicator = INPUT.get(); char indicator = INPUT.get();
alias = (indicator == Keys::Alias); alias = (indicator == Keys::Alias);
@ -218,14 +218,14 @@ namespace YAML
// we need to have read SOMETHING! // we need to have read SOMETHING!
if(name.empty()) if(name.empty())
throw ParserException(INPUT.line, INPUT.column, alias ? ErrorMsg::ALIAS_NOT_FOUND : ErrorMsg::ANCHOR_NOT_FOUND); throw ParserException(INPUT.mark(), alias ? ErrorMsg::ALIAS_NOT_FOUND : ErrorMsg::ANCHOR_NOT_FOUND);
// and needs to end correctly // and needs to end correctly
if(INPUT && !Exp::AnchorEnd.Matches(INPUT)) if(INPUT && !Exp::AnchorEnd.Matches(INPUT))
throw ParserException(INPUT.line, INPUT.column, alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR); throw ParserException(INPUT.mark(), alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR);
// and we're done // and we're done
Token token(alias ? TT_ALIAS : TT_ANCHOR, line, column); Token token(alias ? TT_ALIAS : TT_ANCHOR, mark);
token.value = name; token.value = name;
m_tokens.push(token); m_tokens.push(token);
} }
@ -241,7 +241,7 @@ namespace YAML
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
// eat the indicator // eat the indicator
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
handle += INPUT.get(); handle += INPUT.get();
// read the handle // read the handle
@ -262,7 +262,7 @@ namespace YAML
handle = "!"; handle = "!";
} }
Token token(TT_TAG, line, column); Token token(TT_TAG, mark);
token.value = handle; token.value = handle;
token.params.push_back(suffix); token.params.push_back(suffix);
m_tokens.push(token); m_tokens.push(token);
@ -289,7 +289,7 @@ namespace YAML
if(m_simpleKeyAllowed) if(m_simpleKeyAllowed)
InsertSimpleKey(); InsertSimpleKey();
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
scalar = ScanScalar(INPUT, params); scalar = ScanScalar(INPUT, params);
// can have a simple key only if we ended the scalar by starting a new line // can have a simple key only if we ended the scalar by starting a new line
@ -297,9 +297,9 @@ namespace YAML
// finally, check and see if we ended on an illegal character // finally, check and see if we ended on an illegal character
//if(Exp::IllegalCharInScalar.Matches(INPUT)) //if(Exp::IllegalCharInScalar.Matches(INPUT))
// throw ParserException(INPUT.line, INPUT.column, ErrorMsg::CHAR_IN_SCALAR); // throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_SCALAR);
Token token(TT_SCALAR, line, column); Token token(TT_SCALAR, mark);
token.value = scalar; token.value = scalar;
m_tokens.push(token); m_tokens.push(token);
} }
@ -329,7 +329,7 @@ namespace YAML
if(m_simpleKeyAllowed) if(m_simpleKeyAllowed)
InsertSimpleKey(); InsertSimpleKey();
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
// now eat that opening quote // now eat that opening quote
INPUT.get(); INPUT.get();
@ -338,7 +338,7 @@ namespace YAML
scalar = ScanScalar(INPUT, params); scalar = ScanScalar(INPUT, params);
m_simpleKeyAllowed = false; m_simpleKeyAllowed = false;
Token token(TT_SCALAR, line, column); Token token(TT_SCALAR, mark);
token.value = scalar; token.value = scalar;
m_tokens.push(token); m_tokens.push(token);
} }
@ -356,7 +356,7 @@ namespace YAML
params.detectIndent = true; params.detectIndent = true;
// eat block indicator ('|' or '>') // eat block indicator ('|' or '>')
int line = INPUT.line, column = INPUT.column; Mark mark = INPUT.mark();
char indicator = INPUT.get(); char indicator = INPUT.get();
params.fold = (indicator == Keys::FoldedScalar); params.fold = (indicator == Keys::FoldedScalar);
@ -370,7 +370,7 @@ namespace YAML
params.chomp = STRIP; params.chomp = STRIP;
else if(Exp::Digit.Matches(ch)) { else if(Exp::Digit.Matches(ch)) {
if(ch == '0') if(ch == '0')
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::ZERO_INDENT_IN_BLOCK); throw ParserException(INPUT.mark(), ErrorMsg::ZERO_INDENT_IN_BLOCK);
params.indent = ch - '0'; params.indent = ch - '0';
params.detectIndent = false; params.detectIndent = false;
@ -388,7 +388,7 @@ namespace YAML
// if it's not a line break, then we ran into a bad character inline // if it's not a line break, then we ran into a bad character inline
if(INPUT && !Exp::Break.Matches(INPUT)) if(INPUT && !Exp::Break.Matches(INPUT))
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::CHAR_IN_BLOCK); throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_BLOCK);
// set the initial indentation // set the initial indentation
if(m_indents.top() >= 0) if(m_indents.top() >= 0)
@ -403,7 +403,7 @@ namespace YAML
// simple keys always ok after block scalars (since we're gonna start a new line anyways) // simple keys always ok after block scalars (since we're gonna start a new line anyways)
m_simpleKeyAllowed = true; m_simpleKeyAllowed = true;
Token token(TT_SCALAR, line, column); Token token(TT_SCALAR, mark);
token.value = scalar; token.value = scalar;
m_tokens.push(token); m_tokens.push(token);
} }

View File

@ -68,11 +68,11 @@ namespace YAML
while(1) { while(1) {
if(pScanner->empty()) if(pScanner->empty())
throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ); throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ);
Token token = pScanner->peek(); Token token = pScanner->peek();
if(token.type != TT_BLOCK_ENTRY && token.type != TT_BLOCK_END) if(token.type != TT_BLOCK_ENTRY && token.type != TT_BLOCK_END)
throw ParserException(token.line, token.column, ErrorMsg::END_OF_SEQ); throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
pScanner->pop(); pScanner->pop();
if(token.type == TT_BLOCK_END) if(token.type == TT_BLOCK_END)
@ -111,7 +111,7 @@ namespace YAML
while(1) { while(1) {
if(pScanner->empty()) if(pScanner->empty())
throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ_FLOW); throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW);
// first check for end // first check for end
if(pScanner->peek().type == TT_FLOW_SEQ_END) { if(pScanner->peek().type == TT_FLOW_SEQ_END) {
@ -129,7 +129,7 @@ namespace YAML
if(token.type == TT_FLOW_ENTRY) if(token.type == TT_FLOW_ENTRY)
pScanner->pop(); pScanner->pop();
else if(token.type != TT_FLOW_SEQ_END) else if(token.type != TT_FLOW_SEQ_END)
throw ParserException(token.line, token.column, ErrorMsg::END_OF_SEQ_FLOW); throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
} }
} }

View File

@ -6,8 +6,8 @@
namespace YAML namespace YAML
{ {
Scanner::SimpleKey::SimpleKey(int pos_, int line_, int column_, int flowLevel_) Scanner::SimpleKey::SimpleKey(const Mark& mark_, int flowLevel_)
: pos(pos_), line(line_), column(column_), flowLevel(flowLevel_), pMapStart(0), pKey(0) : mark(mark_), flowLevel(flowLevel_), pMapStart(0), pKey(0)
{ {
} }
@ -32,15 +32,15 @@ namespace YAML
// and saves it on a stack. // and saves it on a stack.
void Scanner::InsertSimpleKey() void Scanner::InsertSimpleKey()
{ {
SimpleKey key(INPUT.pos, INPUT.line, INPUT.column, m_flowLevel); SimpleKey key(INPUT.mark(), m_flowLevel);
// first add a map start, if necessary // first add a map start, if necessary
key.pMapStart = PushIndentTo(INPUT.column, false); key.pMapStart = PushIndentTo(INPUT.column(), false);
if(key.pMapStart) if(key.pMapStart)
key.pMapStart->status = TS_UNVERIFIED; key.pMapStart->status = TS_UNVERIFIED;
// then add the (now unverified) key // then add the (now unverified) key
m_tokens.push(Token(TT_KEY, INPUT.line, INPUT.column)); m_tokens.push(Token(TT_KEY, INPUT.mark()));
key.pKey = &m_tokens.back(); key.pKey = &m_tokens.back();
key.pKey->status = TS_UNVERIFIED; key.pKey->status = TS_UNVERIFIED;
@ -78,7 +78,7 @@ namespace YAML
isValid = false; isValid = false;
// also needs to be less than 1024 characters and inline // also needs to be less than 1024 characters and inline
if(INPUT.line != key.line || INPUT.pos - key.pos > 1024) if(INPUT.line() != key.mark.line || INPUT.pos() - key.mark.pos > 1024)
isValid = false; isValid = false;
// invalidate key // invalidate key

View File

@ -179,7 +179,7 @@ namespace YAML
} }
Stream::Stream(std::istream& input) Stream::Stream(std::istream& input)
: pos(0), line(0), column(0), m_input(input), m_nPushedBack(0), : m_input(input), m_nPushedBack(0),
m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]), m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]),
m_nPrefetchedAvailable(0), m_nPrefetchedUsed(0) m_nPrefetchedAvailable(0), m_nPrefetchedUsed(0)
{ {
@ -248,11 +248,11 @@ namespace YAML
{ {
char ch = peek(); char ch = peek();
AdvanceCurrent(); AdvanceCurrent();
column++; m_mark.column++;
if(ch == '\n') { if(ch == '\n') {
column = 0; m_mark.column = 0;
line++; m_mark.line++;
} }
return ch; return ch;
@ -282,7 +282,7 @@ namespace YAML
if (!m_readahead.empty()) if (!m_readahead.empty())
{ {
m_readahead.pop_front(); m_readahead.pop_front();
++pos; m_mark.pos++;
} }
ReadAheadTo(0); ReadAheadTo(0);

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "noncopyable.h" #include "noncopyable.h"
#include "mark.h"
#include <deque> #include <deque>
#include <ios> #include <ios>
#include <string> #include <string>
@ -28,13 +29,19 @@ namespace YAML
void eat(int n = 1); void eat(int n = 1);
static char eof() { return 0x04; } static char eof() { return 0x04; }
const Mark mark() const { return m_mark; }
int pos() const { return m_mark.pos; }
int line() const { return m_mark.line; }
int column() const { return m_mark.column; }
void ResetColumn() { m_mark.column = 0; }
int pos, line, column;
private: private:
enum CharacterSet {utf8, utf16le, utf16be, utf32le, utf32be}; enum CharacterSet {utf8, utf16le, utf16be, utf32le, utf32be};
std::istream& m_input; std::istream& m_input;
Mark m_mark;
CharacterSet m_charSet; CharacterSet m_charSet;
unsigned char m_bufPushback[MAX_PARSER_PUSHBACK]; unsigned char m_bufPushback[MAX_PARSER_PUSHBACK];
mutable size_t m_nPushedBack; mutable size_t m_nPushedBack;

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "mark.h"
#include <ios> #include <ios>
#include <string> #include <string>
#include <vector> #include <vector>
@ -50,7 +51,7 @@ namespace YAML
}; };
struct Token { struct Token {
Token(TOKEN_TYPE type_, int line_, int column_): status(TS_VALID), type(type_), line(line_), column(column_) {} Token(TOKEN_TYPE type_, const Mark& mark_): status(TS_VALID), type(type_), mark(mark_) {}
friend std::ostream& operator << (std::ostream& out, const Token& token) { friend std::ostream& operator << (std::ostream& out, const Token& token) {
out << TokenNames[token.type] << std::string(": ") << token.value; out << TokenNames[token.type] << std::string(": ") << token.value;
@ -61,7 +62,7 @@ namespace YAML
TOKEN_STATUS status; TOKEN_STATUS status;
TOKEN_TYPE type; TOKEN_TYPE type;
int line, column; Mark mark;
std::string value; std::string value;
std::vector <std::string> params; std::vector <std::string> params;
}; };

View File

@ -217,7 +217,7 @@ namespace Test
out << YAML::Literal << "literal scalar\nthat may span\nmany, many\nlines and have \"whatever\" crazy\tsymbols that we like"; out << YAML::Literal << "literal scalar\nthat may span\nmany, many\nlines and have \"whatever\" crazy\tsymbols that we like";
out << YAML::EndSeq; out << YAML::EndSeq;
desiredOutput = "- simple scalar\n- 'explicit single-quoted scalar'\n- \"explicit double-quoted scalar\"\n- \"auto-detected\\xadouble-quoted scalar\"\n- a non-\"auto-detected\" double-quoted scalar\n- |\n literal scalar\n that may span\n many, many\n lines and have \"whatever\" crazy\tsymbols that we like"; desiredOutput = "- simple scalar\n- 'explicit single-quoted scalar'\n- \"explicit double-quoted scalar\"\n- \"auto-detected\\x0adouble-quoted scalar\"\n- a non-\"auto-detected\" double-quoted scalar\n- |\n literal scalar\n that may span\n many, many\n lines and have \"whatever\" crazy\tsymbols that we like";
} }
void AutoLongKeyScalar(YAML::Emitter& out, std::string& desiredOutput) void AutoLongKeyScalar(YAML::Emitter& out, std::string& desiredOutput)