Ejemplo n.º 1
0
	// Value
	void Scanner::ScanValue()
	{
		// and check that simple key
		bool isSimpleKey = VerifySimpleKey();
		m_canBeJSONFlow = false;
		
		if(isSimpleKey) {
			// can't follow a simple key with another simple key (dunno why, though - it seems fine)
			m_simpleKeyAllowed = false;
		} else {
			// handle values diffently in the block context (and manage indents)
			if(InBlockContext()) {
				if(!m_simpleKeyAllowed)
					throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE);

				PushIndentTo(INPUT.column(), IndentMarker::MAP);
			}

			// can only put a simple key here if we're in block context
			m_simpleKeyAllowed = InBlockContext();
		}

		// eat
		Mark mark = INPUT.mark();
		INPUT.eat(1);
		m_tokens.push(Token(Token::VALUE, mark));
	}
Ejemplo n.º 2
0
// ScanToNextToken
// . Eats input until we reach the next token-like thing.
void Scanner::ScanToNextToken() {
  while (1) {
    // first eat whitespace
    while (INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
      if (InBlockContext() && Exp::Tab().Matches(INPUT))
        m_simpleKeyAllowed = false;
      INPUT.eat(1);
    }

    // then eat a comment
    if (Exp::Comment().Matches(INPUT)) {
      // eat until line break
      while (INPUT && !Exp::Break().Matches(INPUT))
        INPUT.eat(1);
    }

    // if it's NOT a line break, then we're done!
    if (!Exp::Break().Matches(INPUT))
      break;

    // otherwise, let's eat the line break and keep going
    int n = Exp::Break().Match(INPUT);
    INPUT.eat(n);

    // oh yeah, and let's get rid of that simple key
    InvalidateSimpleKey();

    // new line - we may be able to accept a simple key now
    if (InBlockContext())
      m_simpleKeyAllowed = true;
  }
}
Ejemplo n.º 3
0
const RegEx& Scanner::GetValueRegex() const {
  if (InBlockContext()) {
    return Exp::Value();
  }

  return m_canBeJSONFlow ? Exp::ValueInJSONFlow() : Exp::ValueInFlow();
}
Ejemplo n.º 4
0
	// FlowEnd
	void Scanner::ScanFlowEnd()
	{
		if(InBlockContext())
			throw ParserException(INPUT.mark(), ErrorMsg::FLOW_END);

		// we might have a solo entry in the flow context
		if(InFlowContext()) {
			if(m_flows.top() == FLOW_MAP && VerifySimpleKey())
				m_tokens.push(Token(Token::VALUE, INPUT.mark()));
			else if(m_flows.top() == FLOW_SEQ)
				InvalidateSimpleKey();
		}

		m_simpleKeyAllowed = false;
		m_canBeJSONFlow = true;

		// eat
		Mark mark = INPUT.mark();
		char ch = INPUT.get();

		// check that it matches the start
		FLOW_MARKER flowType = (ch == Keys::FlowSeqEnd ? FLOW_SEQ : FLOW_MAP);
		if(m_flows.top() != flowType)
			throw ParserException(mark, ErrorMsg::FLOW_END);
		m_flows.pop();
		
		Token::TYPE type = (flowType ? Token::FLOW_SEQ_END : Token::FLOW_MAP_END);
		m_tokens.push(Token(type, mark));
	}
Ejemplo n.º 5
0
// Key
void Scanner::ScanKey() {
  // handle keys diffently in the block context (and manage indents)
  if (InBlockContext()) {
    if (!m_simpleKeyAllowed)
      throw ParserException(INPUT.mark(), ErrorMsg::MAP_KEY);

    PushIndentTo(INPUT.column(), IndentMarker::MAP);
  }

  // can only put a simple key here if we're in block context
  m_simpleKeyAllowed = InBlockContext();

  // eat
  Mark mark = INPUT.mark();
  INPUT.eat(1);
  m_tokens.push(Token(Token::KEY, mark));
}
Ejemplo n.º 6
0
	// InsertPotentialSimpleKey
	// . If we can, add a potential simple key to the queue,
	//   and save it on a stack.
	void Scanner::InsertPotentialSimpleKey()
	{
		if(!CanInsertPotentialSimpleKey())
			return;
		
		SimpleKey key(INPUT.mark(), GetFlowLevel());

		// first add a map start, if necessary
		if(InBlockContext()) {
			key.pIndent = PushIndentTo(INPUT.column(), IndentMarker::MAP);
			if(key.pIndent) {
				key.pIndent->status = IndentMarker::UNKNOWN;
				key.pMapStart = key.pIndent->pStartToken;
				key.pMapStart->status = Token::UNVERIFIED;
			}
		}

		// then add the (now unverified) key
		m_tokens.push(Token(Token::KEY, INPUT.mark()));
		key.pKey = &m_tokens.back();
		key.pKey->status = Token::UNVERIFIED;

		m_simpleKeys.push(key);
	}
Ejemplo n.º 7
0
void Scanner::ScanNextToken() {
  if (m_endedStream) {
    return;
  }

  if (!m_startedStream) {
    return StartStream();
  }

  // get rid of whitespace, etc. (in between tokens it should be irrelevent)
  ScanToNextToken();

  // maybe need to end some blocks
  PopIndentToHere();

  // *****
  // And now branch based on the next few characters!
  // *****

  // end of stream
  if (!INPUT) {
    return EndStream();
  }

  if (INPUT.column() == 0 && INPUT.peek() == Keys::Directive) {
    return ScanDirective();
  }

  // document token
  if (INPUT.column() == 0 && Exp::DocStart().Matches(INPUT)) {
    return ScanDocStart();
  }

  if (INPUT.column() == 0 && Exp::DocEnd().Matches(INPUT)) {
    return ScanDocEnd();
  }

  // flow start/end/entry
  if (INPUT.peek() == Keys::FlowSeqStart ||
      INPUT.peek() == Keys::FlowMapStart) {
    return ScanFlowStart();
  }

  if (INPUT.peek() == Keys::FlowSeqEnd || INPUT.peek() == Keys::FlowMapEnd) {
    return ScanFlowEnd();
  }

  if (INPUT.peek() == Keys::FlowEntry) {
    return ScanFlowEntry();
  }

  // block/map stuff
  if (Exp::BlockEntry().Matches(INPUT)) {
    return ScanBlockEntry();
  }

  if ((InBlockContext() ? Exp::Key() : Exp::KeyInFlow()).Matches(INPUT)) {
    return ScanKey();
  }

  if (GetValueRegex().Matches(INPUT)) {
    return ScanValue();
  }

  // alias/anchor
  if (INPUT.peek() == Keys::Alias || INPUT.peek() == Keys::Anchor) {
    return ScanAnchorOrAlias();
  }

  // tag
  if (INPUT.peek() == Keys::Tag) {
    return ScanTag();
  }

  // special scalars
  if (InBlockContext() && (INPUT.peek() == Keys::LiteralScalar ||
                           INPUT.peek() == Keys::FoldedScalar)) {
    return ScanBlockScalar();
  }

  if (INPUT.peek() == '\'' || INPUT.peek() == '\"') {
    return ScanQuotedScalar();
  }

  // plain scalars
  if ((InBlockContext() ? Exp::PlainScalar() : Exp::PlainScalarInFlow())
          .Matches(INPUT)) {
    return ScanPlainScalar();
  }

  // don't know what it is!
  throw ParserException(INPUT.mark(), ErrorMsg::UNKNOWN_TOKEN);
}