diff --git a/exp.h b/exp.h index ea1804b49f..652e2bdad8 100644 --- a/exp.h +++ b/exp.h @@ -57,6 +57,7 @@ namespace YAML namespace Keys { + const char Directive = '%'; const char FlowSeqStart = '['; const char FlowSeqEnd = ']'; const char FlowMapStart = '{'; diff --git a/scanner.cpp b/scanner.cpp index 5e83907b3c..fb49bbd665 100644 --- a/scanner.cpp +++ b/scanner.cpp @@ -44,56 +44,6 @@ namespace YAML return false; } - // IsDocumentStart - bool Scanner::IsDocumentStart() - { - // needs to be at the start of a new line - if(INPUT.column != 0) - return false; - - return Exp::DocStart.Matches(INPUT); - } - - // IsDocumentEnd - bool Scanner::IsDocumentEnd() - { - // needs to be at the start of a new line - if(INPUT.column != 0) - return false; - - return Exp::DocEnd.Matches(INPUT); - } - - // IsBlockEntry - bool Scanner::IsBlockEntry() - { - return Exp::BlockEntry.Matches(INPUT); - } - - // IsKey - bool Scanner::IsKey() - { - if(m_flowLevel > 0) - return Exp::KeyInFlow.Matches(INPUT); - return Exp::Key.Matches(INPUT); - } - - // IsValue - bool Scanner::IsValue() - { - if(m_flowLevel > 0) - return Exp::ValueInFlow.Matches(INPUT); - return Exp::Value.Matches(INPUT); - } - - // IsPlainScalar - bool Scanner::IsPlainScalar() - { - if(m_flowLevel > 0) - return Exp::PlainScalarInFlow.Matches(INPUT); - return Exp::PlainScalar.Matches(INPUT); - } - // ScanAndEnqueue // . Scans the token, then pushes it in the queue. // . Note: we also use a set of "limbo tokens", i.e., tokens @@ -136,11 +86,14 @@ namespace YAML if(INPUT.peek() == EOF) return ScanAndEnqueue(new StreamEndToken); + if(INPUT.column == 0 && INPUT.peek() == Keys::Directive) + return ScanAndEnqueue(new DirectiveToken); + // document token - if(IsDocumentStart()) + if(INPUT.column == 0 && Exp::DocStart.Matches(INPUT)) return ScanAndEnqueue(new DocumentStartToken); - if(IsDocumentEnd()) + if(INPUT.column == 0 && Exp::DocEnd.Matches(INPUT)) return ScanAndEnqueue(new DocumentEndToken); // flow start/end/entry @@ -160,19 +113,22 @@ namespace YAML return ScanAndEnqueue(new FlowEntryToken); // block/map stuff - if(IsBlockEntry()) + if(Exp::BlockEntry.Matches(INPUT)) return ScanAndEnqueue(new BlockEntryToken); - if(IsKey()) + if((m_flowLevel == 0 ? Exp::Key : Exp::KeyInFlow).Matches(INPUT)) return ScanAndEnqueue(new KeyToken); - if(IsValue()) + if((m_flowLevel == 0 ? Exp::Value : Exp::ValueInFlow).Matches(INPUT)) return ScanAndEnqueue(new ValueToken); + // alias/anchor if(INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor) return ScanAndEnqueue(new AnchorToken); - // TODO: tag + // tag + if(INPUT.peek() == Keys::Tag) + return ScanAndEnqueue(new TagToken); // special scalars if(m_flowLevel == 0 && (INPUT.peek() == Keys::LiteralScalar || INPUT.peek() == Keys::FoldedScalar)) @@ -182,7 +138,7 @@ namespace YAML return ScanAndEnqueue(new QuotedScalarToken); // plain scalars - if(IsPlainScalar()) + if((m_flowLevel == 0 ? Exp::PlainScalar : Exp::PlainScalarInFlow).Matches(INPUT)) return ScanAndEnqueue(new PlainScalarToken); // don't know what it is! diff --git a/scanner.h b/scanner.h index fd5ad1a87c..cf402cabfd 100644 --- a/scanner.h +++ b/scanner.h @@ -34,12 +34,6 @@ namespace YAML void VerifyAllSimpleKeys(); bool IsWhitespaceToBeEaten(char ch); - bool IsDocumentStart(); - bool IsDocumentEnd(); - bool IsBlockEntry(); - bool IsKey(); - bool IsValue(); - bool IsPlainScalar(); struct SimpleKey { SimpleKey(int pos_, int line_, int column_, int flowLevel_); diff --git a/scantoken.cpp b/scantoken.cpp index e1d2f1be9e..f9ea4bff9b 100644 --- a/scantoken.cpp +++ b/scantoken.cpp @@ -35,6 +35,44 @@ namespace YAML return pToken; } + // DirectiveToken + // . Note: no semantic checking is done here (that's for the parser to do) + template <> DirectiveToken *Scanner::ScanToken(DirectiveToken *pToken) + { + // pop indents and simple keys + PopIndentTo(-1); + VerifyAllSimpleKeys(); + + m_simpleKeyAllowed = false; + + // eat indicator + INPUT.Eat(1); + + // read name + while(INPUT.peek() != EOF && !Exp::BlankOrBreak.Matches(INPUT)) + pToken->name += INPUT.GetChar(); + + // read parameters + while(1) { + // first get rid of whitespace + while(Exp::Blank.Matches(INPUT)) + INPUT.Eat(1); + + // break on newline or comment + if(INPUT.peek() == EOF || Exp::Break.Matches(INPUT) || Exp::Comment.Matches(INPUT)) + break; + + // now read parameter + std::string param; + while(INPUT.peek() != EOF && !Exp::BlankOrBreak.Matches(INPUT)) + param += INPUT.GetChar(); + + pToken->params.push_back(param); + } + + return pToken; + } + // DocumentStartToken template <> DocumentStartToken *Scanner::ScanToken(DocumentStartToken *pToken) { @@ -222,6 +260,34 @@ namespace YAML return pToken; } + // TagToken + template <> TagToken *Scanner::ScanToken(TagToken *pToken) + { + // insert a potential simple key + if(m_simpleKeyAllowed) + InsertSimpleKey(); + m_simpleKeyAllowed = false; + + // eat the indicator + INPUT.Eat(1); + + // read the handle + while(INPUT.peek() != EOF && INPUT.peek() != Keys::Tag && !Exp::BlankOrBreak.Matches(INPUT)) + pToken->handle += INPUT.GetChar(); + + // is there a suffix? + if(INPUT.peek() == Keys::Tag) { + // eat the indicator + INPUT.Eat(1); + + // then read it + while(INPUT.peek() != EOF && !Exp::BlankOrBreak.Matches(INPUT)) + pToken->suffix += INPUT.GetChar(); + } + + return pToken; + } + // PlainScalarToken template <> PlainScalarToken *Scanner::ScanToken(PlainScalarToken *pToken) { diff --git a/test.yaml b/test.yaml index 8a9714cfc8..6b1ccb21a4 100644 --- a/test.yaml +++ b/test.yaml @@ -1,97 +1,26 @@ --- -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] +Time: 2001-11-23 15:01:42 -5 +User: ed +Warning: + This is an error message + for the log file +--- +Time: 2001-11-23 15:02:31 -5 +User: ed +Warning: + A slightly different error + message. +--- +Date: 2001-11-23 15:03:17 -5 +User: ed +Fatal: + Unknown variable "bar" +Stack: + - file: TopClass.py + line: 23 + code: | + x = MoreObject("345\n") + - file: MoreClass.py + line: 58 + code: |- + foo = bar \ No newline at end of file diff --git a/token.h b/token.h index 70fd7fdffd..3a3bff51de 100644 --- a/token.h +++ b/token.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include namespace YAML { @@ -17,6 +19,13 @@ namespace YAML struct StreamStartToken: public Token {}; struct StreamEndToken: public Token {}; + struct DirectiveToken: public Token { + std::string name; + std::vector params; + + virtual void Write(std::ostream& out) const { out << name; for(unsigned i=0;i