00001 #include "scanner.h" 00002 #include "token.h" 00003 #include "yaml-cpp-pm/exceptions.h" 00004 #include "exp.h" 00005 00006 namespace YAML_PM 00007 { 00008 Scanner::SimpleKey::SimpleKey(const Mark& mark_, int flowLevel_) 00009 : mark(mark_), flowLevel(flowLevel_), pIndent(0), pMapStart(0), pKey(0) 00010 { 00011 } 00012 00013 void Scanner::SimpleKey::Validate() 00014 { 00015 // Note: pIndent will *not* be garbage here; 00016 // we "garbage collect" them so we can 00017 // always refer to them 00018 if(pIndent) 00019 pIndent->status = IndentMarker::VALID; 00020 if(pMapStart) 00021 pMapStart->status = Token::VALID; 00022 if(pKey) 00023 pKey->status = Token::VALID; 00024 } 00025 00026 void Scanner::SimpleKey::Invalidate() 00027 { 00028 if(pIndent) 00029 pIndent->status = IndentMarker::INVALID; 00030 if(pMapStart) 00031 pMapStart->status = Token::INVALID; 00032 if(pKey) 00033 pKey->status = Token::INVALID; 00034 } 00035 00036 // CanInsertPotentialSimpleKey 00037 bool Scanner::CanInsertPotentialSimpleKey() const 00038 { 00039 if(!m_simpleKeyAllowed) 00040 return false; 00041 00042 return !ExistsActiveSimpleKey(); 00043 } 00044 00045 // ExistsActiveSimpleKey 00046 // . Returns true if there's a potential simple key at our flow level 00047 // (there's allowed at most one per flow level, i.e., at the start of the flow start token) 00048 bool Scanner::ExistsActiveSimpleKey() const 00049 { 00050 if(m_simpleKeys.empty()) 00051 return false; 00052 00053 const SimpleKey& key = m_simpleKeys.top(); 00054 return key.flowLevel == GetFlowLevel(); 00055 } 00056 00057 // InsertPotentialSimpleKey 00058 // . If we can, add a potential simple key to the queue, 00059 // and save it on a stack. 00060 void Scanner::InsertPotentialSimpleKey() 00061 { 00062 if(!CanInsertPotentialSimpleKey()) 00063 return; 00064 00065 SimpleKey key(INPUT.mark(), GetFlowLevel()); 00066 00067 // first add a map start, if necessary 00068 if(InBlockContext()) { 00069 key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP); 00070 if(key.pIndent) { 00071 key.pIndent->status = IndentMarker::UNKNOWN; 00072 key.pMapStart = key.pIndent->pStartToken; 00073 key.pMapStart->status = Token::UNVERIFIED; 00074 } 00075 } 00076 00077 // then add the (now unverified) key 00078 m_tokens.push(Token(Token::KEY, INPUT.mark())); 00079 key.pKey = &m_tokens.back(); 00080 key.pKey->status = Token::UNVERIFIED; 00081 00082 m_simpleKeys.push(key); 00083 } 00084 00085 // InvalidateSimpleKey 00086 // . Automatically invalidate the simple key in our flow level 00087 void Scanner::InvalidateSimpleKey() 00088 { 00089 if(m_simpleKeys.empty()) 00090 return; 00091 00092 // grab top key 00093 SimpleKey& key = m_simpleKeys.top(); 00094 if(key.flowLevel != GetFlowLevel()) 00095 return; 00096 00097 key.Invalidate(); 00098 m_simpleKeys.pop(); 00099 } 00100 00101 // VerifySimpleKey 00102 // . Determines whether the latest simple key to be added is valid, 00103 // and if so, makes it valid. 00104 bool Scanner::VerifySimpleKey() 00105 { 00106 if(m_simpleKeys.empty()) 00107 return false; 00108 00109 // grab top key 00110 SimpleKey key = m_simpleKeys.top(); 00111 00112 // only validate if we're in the correct flow level 00113 if(key.flowLevel != GetFlowLevel()) 00114 return false; 00115 00116 m_simpleKeys.pop(); 00117 00118 bool isValid = true; 00119 00120 // needs to be less than 1024 characters and inline 00121 if(INPUT.line() != key.mark.line || INPUT.pos() - key.mark.pos > 1024) 00122 isValid = false; 00123 00124 // invalidate key 00125 if(isValid) 00126 key.Validate(); 00127 else 00128 key.Invalidate(); 00129 00130 return isValid; 00131 } 00132 00133 void Scanner::PopAllSimpleKeys() 00134 { 00135 while(!m_simpleKeys.empty()) 00136 m_simpleKeys.pop(); 00137 } 00138 } 00139