lib/scanner: add explicit key support to Scanner
This commit is contained in:
parent
4c61af7eb9
commit
8558dada84
|
@ -143,7 +143,10 @@ impl Scanner
|
|||
},
|
||||
|
||||
// Is it an explicit key?
|
||||
// TODO
|
||||
[EXPLICIT_KEY, ..] if self.context.is_flow() || isWhiteSpaceZ!(~base, 1) =>
|
||||
{
|
||||
self.explicit_key(base, tokens)
|
||||
},
|
||||
|
||||
// Is it a value?
|
||||
[VALUE, ..] if isWhiteSpaceZ!(~base, 1) || self.context.is_flow() =>
|
||||
|
@ -466,6 +469,69 @@ impl Scanner
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn explicit_key<'de>(&mut self, base: &mut &'de str, tokens: &mut Tokens<'de>) -> Result<()>
|
||||
{
|
||||
let block_context = self.context.is_block();
|
||||
/*
|
||||
* If in the block context we may need to add indentation
|
||||
* tokens to the stream, and we need an additional
|
||||
* check that keys are currently legal.
|
||||
*
|
||||
* This can occur, for example if you have the following
|
||||
* YAML:
|
||||
*
|
||||
* !!str ? 'whoops, tag is': 'in the wrong place'
|
||||
* ^^^^^^^
|
||||
* Invalid token sequence
|
||||
*
|
||||
* As node decorators (tags, anchors, aliases) must be
|
||||
* directly preceding the node
|
||||
*/
|
||||
if block_context
|
||||
{
|
||||
// Ensure that keys are legal
|
||||
if !self.simple_key_allowed
|
||||
{
|
||||
return Err(ScanError::InvalidKey);
|
||||
}
|
||||
|
||||
// Increase the indentation level, and push a
|
||||
// BlockMappingStart token to the queue, if
|
||||
// required
|
||||
roll_indent(
|
||||
&mut self.context,
|
||||
tokens,
|
||||
self.stats.read,
|
||||
self.stats.lines,
|
||||
self.stats.column,
|
||||
BLOCK_MAP,
|
||||
)?;
|
||||
}
|
||||
|
||||
// Remove any saved implicit key
|
||||
self.remove_saved_key()?;
|
||||
|
||||
/* Another key may follow an explicit key in the block
|
||||
* context, typically when this explicit key is a
|
||||
* mapping node, and the mapping starts inline with the
|
||||
* explicit key. E.g:
|
||||
*
|
||||
* ? my key: value
|
||||
* : value
|
||||
*
|
||||
* is equivalent to
|
||||
*
|
||||
* ? { my key: value }: value
|
||||
*/
|
||||
self.simple_key_allowed = block_context;
|
||||
|
||||
advance!(*base, :self.stats, 1);
|
||||
|
||||
enqueue!(Token::Key, :self.stats => tokens);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fetch a value token (':') from .base, adding to
|
||||
/// .tokens. Also handles unwinding any saved
|
||||
/// keys and indentation increases, as needed
|
||||
|
@ -1119,6 +1185,7 @@ const FLOW_SEQUENCE_START: u8 = b'[';
|
|||
const FLOW_SEQUENCE_END: u8 = b']';
|
||||
const FLOW_ENTRY: u8 = b',';
|
||||
const BLOCK_ENTRY: u8 = b'-';
|
||||
const EXPLICIT_KEY: u8 = b'?';
|
||||
|
||||
const COMMENTS: bool = true;
|
||||
const REQUIRED: bool = true;
|
||||
|
|
Loading…
Reference in a new issue