diff --git a/document.cpp b/document.cpp index 2ae9cc9712..ca07e66212 100644 --- a/document.cpp +++ b/document.cpp @@ -34,10 +34,7 @@ namespace YAML std::ifstream fin(fileName.c_str()); Scanner scanner(fin); - try { - scanner.Scan(); - } catch(const Exception& e) { - } + scanner.Scan(); getchar(); // if(!scanner) // return; diff --git a/scanner.cpp b/scanner.cpp index 7f49977f95..19695bb72f 100644 --- a/scanner.cpp +++ b/scanner.cpp @@ -37,6 +37,16 @@ namespace YAML return ch; } + // GetChar + // . Extracts 'n' characters from the stream and updates our position + std::string Scanner::GetChar(int n) + { + std::string ret; + for(int i=0;i PlainScalarToken *Scanner::ScanToken(PlainScalarToken *pToken) { // TODO: "save simple key" @@ -230,20 +234,21 @@ namespace YAML if(m_flowLevel == 0 && Exp::EndScalar.Matches(INPUT)) break; + // join whitespace if(leadingBlanks) { - if(!leadingBreaks.empty() && leadingBreaks[0] == '\n') { + if(Exp::Break.Matches(leadingBreaks)) { // fold line break? if(trailingBreaks.empty()) scalar += ' '; - else { + else scalar += trailingBreaks; - trailingBreaks = ""; - } } else { scalar += leadingBreaks + trailingBreaks; - leadingBreaks = ""; - trailingBreaks = ""; } + + leadingBlanks = false; + leadingBreaks = ""; + trailingBreaks = ""; } else if(!whitespace.empty()) { scalar += whitespace; whitespace = ""; @@ -260,7 +265,8 @@ namespace YAML // now eat blanks while(INPUT && Exp::BlankOrBreak.Matches(INPUT)) { if(Exp::Blank.Matches(INPUT)) { - if(leadingBlanks && m_column <= m_indents.top()) + // can't use tabs as indentation! only spaces! + if(INPUT.peek() == '\t' && leadingBlanks && m_column <= m_indents.top()) throw IllegalTabInScalar(); // maybe store this character @@ -269,13 +275,17 @@ namespace YAML else Eat(1); } else { + // we know it's a line break; see how many characters to read + int n = Exp::Break.Match(INPUT); + std::string line = GetChar(n); + // where to store this character? if(!leadingBlanks) { leadingBlanks = true; whitespace = ""; - leadingBreaks += GetChar(); + leadingBreaks += line; } else - trailingBreaks += GetChar(); + trailingBreaks += line; } } @@ -285,10 +295,16 @@ namespace YAML } // now modify our token - pToken->SetValue(scalar); + pToken->value = scalar; if(leadingBlanks) m_simpleKeyAllowed = true; return pToken; } + + // QuotedScalarToken + template <> QuotedScalarToken *Scanner::ScanToken(QuotedScalarToken *pToken) + { + return pToken; + } } diff --git a/test.yaml b/test.yaml index d3ad2c7190..64d38a7a81 100644 --- a/test.yaml +++ b/test.yaml @@ -1,5 +1,10 @@ --- -- milk +- green + eggs, + and + ham! - eggs # this is really important! -- cheese and bread +- - cheddar cheese + - american cheese +- bread ... \ No newline at end of file diff --git a/token.h b/token.h index ece11d8619..acaebb7c1e 100644 --- a/token.h +++ b/token.h @@ -1,32 +1,40 @@ #pragma once +#include + namespace YAML { - class Token { public: virtual ~Token() {} }; + struct Token { + virtual ~Token() {} + virtual void Write(std::ostream& out) const {} - class StreamStartToken: public Token {}; - class StreamEndToken: public Token {}; - class DocumentStartToken: public Token {}; - class DocumentEndToken: public Token {}; - - class BlockSeqStartToken: public Token {}; - class BlockMapStartToken: public Token {}; - class BlockEndToken: public Token {}; - class BlockEntryToken: public Token {}; - - class FlowSeqStartToken: public Token {}; - class FlowMapStartToken: public Token {}; - class FlowSeqEndToken: public Token {}; - class FlowMapEndToken: public Token {}; - class FlowEntryToken: public Token {}; - - class KeyToken: public Token {}; - class ValueToken: public Token {}; - - class PlainScalarToken: public Token { - public: - void SetValue(const std::string& value) { m_value = value; } - protected: - std::string m_value; + friend std::ostream& operator << (std::ostream& out, const Token& token) { token.Write(out); return out; } }; + + struct StreamStartToken: public Token {}; + struct StreamEndToken: public Token {}; + struct DocumentStartToken: public Token {}; + struct DocumentEndToken: public Token {}; + + struct BlockSeqStartToken: public Token {}; + struct BlockMapStartToken: public Token {}; + struct BlockEndToken: public Token {}; + struct BlockEntryToken: public Token {}; + + struct FlowSeqStartToken: public Token {}; + struct FlowMapStartToken: public Token {}; + struct FlowSeqEndToken: public Token {}; + struct FlowMapEndToken: public Token {}; + struct FlowEntryToken: public Token {}; + + struct KeyToken: public Token {}; + struct ValueToken: public Token {}; + + struct ScalarToken: public Token { + std::string value; + virtual void Write(std::ostream& out) const { out << value; } + }; + + struct PlainScalarToken: public ScalarToken {}; + struct QuotedScalarToken: public ScalarToken {}; }