diff --git a/exceptions.h b/exceptions.h index 3540519d8b..f8968b7272 100644 --- a/exceptions.h +++ b/exceptions.h @@ -18,6 +18,8 @@ namespace YAML class RequiredSimpleKeyNotFound: public Exception {}; class ZeroIndentationInBlockScalar: public Exception {}; class UnexpectedCharacterInBlockScalar: public Exception {}; + class AnchorNotFound: public Exception {}; + class IllegalCharacterInAnchor: public Exception {}; class UnknownEscapeSequence: public Exception { public: diff --git a/exp.h b/exp.h index 3dcbdb2fba..cc308be8f6 100644 --- a/exp.h +++ b/exp.h @@ -16,6 +16,8 @@ namespace YAML const RegEx Break = RegEx('\n'); const RegEx BlankOrBreak = Blank || Break; const RegEx Digit = RegEx('0', '9'); + const RegEx Alpha = RegEx('a', 'z') || RegEx('A', 'Z'); + const RegEx AlphaNumeric = Alpha || Digit; const RegEx Hex = Digit || RegEx('A', 'F') || RegEx('a', 'f'); // actual tags @@ -28,6 +30,7 @@ namespace YAML const RegEx Value = RegEx(':'), ValueInFlow = RegEx(':') + BlankOrBreak; const RegEx Comment = RegEx('#'); + const RegEx AnchorEnd = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak; // Plain scalar rules: // . Cannot start with a blank. diff --git a/scanner.cpp b/scanner.cpp index 7c77b52291..bc7d2b598b 100644 --- a/scanner.cpp +++ b/scanner.cpp @@ -148,9 +148,9 @@ namespace YAML m_limboTokens.erase(pToken); } - /////////////////////////////////////////////////////////////////////// - // The main scanning function - + // ScanNextToken + // . The main scanning function; here we branch out and + // scan whatever the next token should be. void Scanner::ScanNextToken() { if(m_endedStream) @@ -159,21 +159,31 @@ namespace YAML if(!m_startedStream) return ScanAndEnqueue(new StreamStartToken); + // get rid of whitespace, etc. (in between tokens it should be irrelevent) ScanToNextToken(); + + // check the latest simple key ValidateSimpleKey(); + + // maybe need to end some blocks PopIndentTo(m_column); + // ***** + // And now branch based on the next few characters! + // ***** + + // end of stream if(INPUT.peek() == EOF) return ScanAndEnqueue(new StreamEndToken); - // are we at a document token? + // document token if(IsDocumentStart()) return ScanAndEnqueue(new DocumentStartToken); if(IsDocumentEnd()) return ScanAndEnqueue(new DocumentEndToken); - // are we at a flow start/end/entry? + // flow start/end/entry if(INPUT.peek() == Keys::FlowSeqStart) return ScanAndEnqueue(new FlowSeqStartToken); @@ -189,7 +199,7 @@ namespace YAML if(INPUT.peek() == Keys::FlowEntry) return ScanAndEnqueue(new FlowEntryToken); - // block/map stuff? + // block/map stuff if(IsBlockEntry()) return ScanAndEnqueue(new BlockEntryToken); @@ -199,7 +209,10 @@ namespace YAML if(IsValue()) return ScanAndEnqueue(new ValueToken); - // TODO: alias/anchor/tag + if(INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor) + return ScanAndEnqueue(new AnchorToken); + + // TODO: tag // special scalars if(m_flowLevel == 0 && (INPUT.peek() == Keys::LiteralScalar || INPUT.peek() == Keys::FoldedScalar)) diff --git a/scantoken.cpp b/scantoken.cpp index 3b8d7efb85..c81feb8de2 100644 --- a/scantoken.cpp +++ b/scantoken.cpp @@ -191,6 +191,36 @@ namespace YAML return pToken; } + // AnchorToken + template <> AnchorToken *Scanner::ScanToken(AnchorToken *pToken) + { + // insert a potential simple key + if(m_simpleKeyAllowed) + InsertSimpleKey(); + m_simpleKeyAllowed = false; + + // eat the indicator + char indicator = GetChar(); + pToken->alias = (indicator == Keys::Alias); + + // now eat the content + std::string tag; + while(Exp::AlphaNumeric.Matches(INPUT)) + tag += GetChar(); + + // we need to have read SOMETHING! + if(tag.empty()) + throw AnchorNotFound(); + + // and needs to end correctly + if(INPUT.peek() != EOF && !Exp::AnchorEnd.Matches(INPUT)) + throw IllegalCharacterInAnchor(); + + // and we're done + pToken->value = tag; + return pToken; + } + // PlainScalarToken // . We scan these in passes of two steps each: First, grab all non-whitespace // characters we can, and then grab all whitespace characters we can. diff --git a/test.yaml b/test.yaml index 8a9714cfc8..9dfb8de769 100644 --- a/test.yaml +++ b/test.yaml @@ -1,97 +1,13 @@ ---- -model: - file: data/models/compound.model - textures: data/materials/compound -rooms: - - name: "Room #1" - pos: [0, 0, 0] - size: [1000, 1000, 500] - height: 500 - stairtype: none - display: [] - pathfinding: - tilesize: 50 - size: [24, 24] - map: | - ----------------------- - -+++++++++++++++++++++- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+--------------------- - -+--------------------- - -+--------------------- - -+--------------------- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+++++++++++++++++++++- - ----------------------- - - name: Doorway - pos: [1000, 400, 0] - size: [50, 200, 500] - height: 500 - stairtype: none - display: [] - pathfinding: - tilesize: 50 - size: [5, 9] - map: | - ----- - -+++- - ----- - ----- - ----- - ----- - ----- - -+++- - ----- - - name: "Room #2" - pos: [1050, 0, 0] - size: [1000, 1000, 500] - height: 500 - stairtype: none - display: [] - pathfinding: - tilesize: 50 - size: [24, 24] - map: | - ----------------------- - -+++++++++++++++++++++- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - ---------------------+- - ---------------------+- - ---------------------+- - ---------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+-------------------+- - -+++++++++++++++++++++- - ----------------------- -exits: - - room1: "Room #1" - room2: "Room #2" - dir: e - pos: [400, 600] +people: + - &jsb + name: Jesse + age: 23 + - &dab + name: Daniel + age: 25 + - &ncb + name: Naftali + age: 21 +students: + - *jsb + - *ncb \ No newline at end of file diff --git a/token.h b/token.h index 1ab6571cb9..93e83a6e07 100644 --- a/token.h +++ b/token.h @@ -31,6 +31,12 @@ namespace YAML struct KeyToken: public Token {}; struct ValueToken: public Token {}; + struct AnchorToken: public Token { + bool alias; + std::string value; + + virtual void Write(std::ostream& out) const { out << (alias ? '*' : '&') << value; } + }; struct ScalarToken: public Token { std::string value;