rust/src/parser_api.rs

165 lines
4.7 KiB
Rust
Raw Normal View History

2018-07-31 22:38:19 +02:00
use {
parser_impl::ParserImpl,
SyntaxKind::{self, ERROR},
};
2018-07-31 22:38:19 +02:00
pub(crate) struct TokenSet {
pub tokens: &'static [SyntaxKind],
}
impl TokenSet {
pub fn contains(&self, kind: SyntaxKind) -> bool {
self.tokens.contains(&kind)
}
}
#[macro_export]
macro_rules! token_set {
($($t:ident),*) => {
TokenSet {
tokens: &[$($t),*],
}
};
($($t:ident),* ,) => {
token_set!($($t),*)
};
}
2018-02-11 15:58:22 +01:00
/// `Parser` struct provides the low-level API for
/// navigating through the stream of tokens and
/// constructing the parse tree. The actual parsing
/// happens in the `grammar` module.
///
/// However, the result of this `Parser` is not a real
/// tree, but rather a flat stream of events of the form
/// "start expression, consume number literal,
/// finish expression". See `Event` docs for more.
pub(crate) struct Parser<'t>(pub(super) ParserImpl<'t>);
impl<'t> Parser<'t> {
2018-02-11 15:58:22 +01:00
/// Returns the kind of the current token.
/// If parser has already reached the end of input,
/// the special `EOF` kind is returned.
pub(crate) fn current(&self) -> SyntaxKind {
self.nth(0)
}
2018-02-11 15:58:22 +01:00
/// Lookahead operation: returns the kind of the next nth
/// token.
pub(crate) fn nth(&self, n: u32) -> SyntaxKind {
self.0.nth(n)
}
2018-02-11 15:58:22 +01:00
/// Checks if the current token is `kind`.
pub(crate) fn at(&self, kind: SyntaxKind) -> bool {
self.current() == kind
}
2018-02-11 15:58:22 +01:00
/// Checks if the current token is contextual keyword with text `t`.
pub(crate) fn at_contextual_kw(&self, t: &str) -> bool {
self.0.at_kw(t)
}
2018-02-11 15:58:22 +01:00
/// Starts a new node in the syntax tree. All nodes and tokens
/// consumed between the `start` and the corresponding `Marker::complete`
/// belong to the same node.
pub(crate) fn start(&mut self) -> Marker {
Marker(self.0.start())
}
2018-02-11 15:58:22 +01:00
/// Advances the parser by one token.
pub(crate) fn bump(&mut self) {
self.0.bump();
}
2018-02-11 15:58:22 +01:00
/// Advances the parser by one token, remapping its kind.
/// This is useful to create contextual keywords from
/// identifiers. For example, the lexer creates an `union`
/// *identifier* token, but the parser remaps it to the
/// `union` keyword, and keyword is what ends up in the
/// final tree.
pub(crate) fn bump_remap(&mut self, kind: SyntaxKind) {
self.0.bump_remap(kind);
}
2018-02-11 15:58:22 +01:00
/// Emit error with the `message`
/// TODO: this should be much more fancy and support
/// structured errors with spans and notes, like rustc
/// does.
pub(crate) fn error<T: Into<String>>(&mut self, message: T) {
self.0.error(message.into())
}
2018-02-11 15:58:22 +01:00
/// Consume the next token if it is `kind`.
pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
if !self.at(kind) {
return false;
}
self.bump();
true
}
2018-02-11 15:58:22 +01:00
/// Consume the next token if it is `kind` or emit an error
/// otherwise.
pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
if self.eat(kind) {
return true;
}
self.error(format!("expected {:?}", kind));
false
}
/// Create an error node and consume the next token.
pub(crate) fn err_and_bump(&mut self, message: &str) {
let m = self.start();
self.error(message);
self.bump();
m.complete(self, ERROR);
}
}
2018-02-11 15:58:22 +01:00
/// See `Parser::start`.
pub(crate) struct Marker(u32);
impl Marker {
2018-02-11 15:58:22 +01:00
/// Finishes the syntax tree node and assigns `kind` to it.
pub(crate) fn complete(self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker {
let pos = self.0;
::std::mem::forget(self);
p.0.complete(pos, kind);
CompletedMarker(pos)
}
2018-02-11 15:58:22 +01:00
/// Abandons the syntax tree node. All its children
/// are attached to its parent instead.
pub(crate) fn abandon(self, p: &mut Parser) {
let pos = self.0;
::std::mem::forget(self);
p.0.abandon(pos);
}
}
impl Drop for Marker {
fn drop(&mut self) {
if !::std::thread::panicking() {
panic!("Marker must be either completed or abandoned");
}
}
}
pub(crate) struct CompletedMarker(u32);
impl CompletedMarker {
2018-02-11 15:58:22 +01:00
/// This one is tricky :-)
/// This method allows to create a new node which starts
/// *before* the current one. That is, parser could start
/// node `A`, then complete it, and then after parsing the
/// whole `A`, decide that it should have started some node
/// `B` before starting `A`. `precede` allows to do exactly
/// that. See also docs about `forward_parent` in `Event::Start`.
pub(crate) fn precede(self, p: &mut Parser) -> Marker {
Marker(p.0.precede(self.0))
}
}