Introduce EOF token

This commit is contained in:
Aleksey Kladov 2018-01-07 21:09:05 +03:00
parent fc4d6cc298
commit 5562931e4f
3 changed files with 133 additions and 137 deletions

View file

@ -1,5 +1,6 @@
use super::parser::Parser; use super::parser::Parser;
use {SyntaxKind}; use {SyntaxKind};
use tree::EOF;
use syntax_kinds::*; use syntax_kinds::*;
// Items // // Items //
@ -18,11 +19,7 @@ pub(crate) fn file(p: &mut Parser) {
} }
fn item_first(p: &Parser) -> bool { fn item_first(p: &Parser) -> bool {
let current = match p.current() { match p.current() {
Some(c) => c,
None => return false,
};
match current {
STRUCT_KW | FN_KW => true, STRUCT_KW | FN_KW => true,
_ => false, _ => false,
} }
@ -79,7 +76,7 @@ fn visibility(_: &mut Parser) {
// Error recovery and high-order utils // // Error recovery and high-order utils //
fn node_if<F: FnOnce(&mut Parser)>(p: &mut Parser, first: SyntaxKind, node_kind: SyntaxKind, rest: F) -> bool { fn node_if<F: FnOnce(&mut Parser)>(p: &mut Parser, first: SyntaxKind, node_kind: SyntaxKind, rest: F) -> bool {
p.current_is(first) && { node(p, node_kind, |p| { p.bump(); rest(p); }); true } p.current() == first && { node(p, node_kind, |p| { p.bump(); rest(p); }); true }
} }
fn node<F: FnOnce(&mut Parser)>(p: &mut Parser, node_kind: SyntaxKind, rest: F) { fn node<F: FnOnce(&mut Parser)>(p: &mut Parser, node_kind: SyntaxKind, rest: F) {
@ -95,7 +92,7 @@ fn many<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) {
fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) { fn comma_list<F: Fn(&mut Parser) -> bool>(p: &mut Parser, f: F) {
many(p, |p| { many(p, |p| {
f(p); f(p);
if p.is_eof() { if p.current() == EOF {
false false
} else { } else {
p.expect(COMMA); p.expect(COMMA);
@ -119,7 +116,7 @@ where
f(p); f(p);
return true; return true;
} }
if p.is_eof() { if p.current() == EOF {
if skipped { if skipped {
p.finish(); p.finish();
} }
@ -131,18 +128,14 @@ where
.message(message) .message(message)
.emit(); .emit();
} }
p.bump().unwrap(); p.bump();
skipped = true; skipped = true;
} }
} }
impl<'p> Parser<'p> { impl<'p> Parser<'p> {
fn current_is(&self, kind: SyntaxKind) -> bool {
self.current() == Some(kind)
}
pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool { pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
if self.current_is(kind) { if self.current() == kind {
self.bump(); self.bump();
true true
} else { } else {
@ -154,7 +147,7 @@ impl<'p> Parser<'p> {
} }
fn optional(&mut self, kind: SyntaxKind) { fn optional(&mut self, kind: SyntaxKind) {
if self.current_is(kind) { if self.current() == kind {
self.bump(); self.bump();
} }
} }

View file

@ -2,8 +2,7 @@ use {Token, SyntaxKind, TextUnit};
use super::{Event}; use super::{Event};
use super::super::is_insignificant; use super::super::is_insignificant;
use syntax_kinds::{L_CURLY, R_CURLY, ERROR}; use syntax_kinds::{L_CURLY, R_CURLY, ERROR};
use tree::EOF;
pub(crate) const EOF: SyntaxKind = SyntaxKind(10000);
pub(crate) struct Parser<'t> { pub(crate) struct Parser<'t> {
@ -46,19 +45,22 @@ impl<'t> Parser<'t> {
} }
pub(crate) fn into_events(self) -> Vec<Event> { pub(crate) fn into_events(self) -> Vec<Event> {
assert!(self.is_eof()); assert!(self.curly_limit.is_none());
assert!(self.current() == EOF);
self.events self.events
} }
pub(crate) fn is_eof(&self) -> bool { pub(crate) fn current(&self) -> SyntaxKind {
if self.pos == self.tokens.len() { if self.pos == self.tokens.len() {
return true return EOF;
} }
let token = self.tokens[self.pos];
if let Some(limit) = self.curly_limit { if let Some(limit) = self.curly_limit {
let token = self.tokens[self.pos]; if limit == self.curly_level && token.kind == R_CURLY {
return limit == self.curly_level && token.kind == R_CURLY; return EOF
}
} }
false token.kind
} }
pub(crate) fn start(&mut self, kind: SyntaxKind) { pub(crate) fn start(&mut self, kind: SyntaxKind) {
@ -73,24 +75,17 @@ impl<'t> Parser<'t> {
ErrorBuilder::new(self) ErrorBuilder::new(self)
} }
pub(crate) fn current(&self) -> Option<SyntaxKind> { pub(crate) fn bump(&mut self) -> SyntaxKind {
if self.is_eof() { let kind = self.current();
return None;
}
let token = self.tokens[self.pos];
Some(token.kind)
}
pub(crate) fn bump(&mut self) -> Option<SyntaxKind> {
let kind = self.current()?;
match kind { match kind {
L_CURLY => self.curly_level += 1, L_CURLY => self.curly_level += 1,
R_CURLY => self.curly_level -= 1, R_CURLY => self.curly_level -= 1,
EOF => return EOF,
_ => (), _ => (),
} }
self.pos += 1; self.pos += 1;
self.event(Event::Token { kind, n_raw_tokens: 1 }); self.event(Event::Token { kind, n_raw_tokens: 1 });
Some(kind) kind
} }
pub(crate) fn lookahead(&self, kinds: &[SyntaxKind]) -> bool { pub(crate) fn lookahead(&self, kinds: &[SyntaxKind]) -> bool {
@ -114,7 +109,7 @@ impl<'t> Parser<'t> {
if !self.expect(R_CURLY) { if !self.expect(R_CURLY) {
self.start(ERROR); self.start(ERROR);
while self.curly_level > old_level { while self.curly_level > old_level {
if self.bump().is_none() { if self.bump() == EOF {
break; break;
} }
} }

View file

@ -10,8 +10,16 @@ pub use self::file_builder::{FileBuilder, Sink};
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SyntaxKind(pub(crate) u32); pub struct SyntaxKind(pub(crate) u32);
pub(crate) const EOF: SyntaxKind = SyntaxKind(10000);
pub(crate) const EOF_INFO: SyntaxInfo = SyntaxInfo {
name: "EOF"
};
impl SyntaxKind { impl SyntaxKind {
fn info(self) -> &'static SyntaxInfo { fn info(self) -> &'static SyntaxInfo {
if self == EOF {
return &EOF_INFO;
}
syntax_info(self) syntax_info(self)
} }
} }
@ -35,72 +43,72 @@ pub struct Token {
} }
pub struct File { pub struct File {
text: String, text: String,
nodes: Vec<NodeData>, nodes: Vec<NodeData>,
errors: Vec<SyntaxErrorData>, errors: Vec<SyntaxErrorData>,
} }
impl File { impl File {
pub fn root<'f>(&'f self) -> Node<'f> { pub fn root<'f>(&'f self) -> Node<'f> {
assert!(!self.nodes.is_empty()); assert!(!self.nodes.is_empty());
Node { file: self, idx: NodeIdx(0) } Node { file: self, idx: NodeIdx(0) }
} }
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Node<'f> { pub struct Node<'f> {
file: &'f File, file: &'f File,
idx: NodeIdx, idx: NodeIdx,
} }
impl<'f> Node<'f> { impl<'f> Node<'f> {
pub fn kind(&self) -> SyntaxKind { pub fn kind(&self) -> SyntaxKind {
self.data().kind self.data().kind
} }
pub fn range(&self) -> TextRange { pub fn range(&self) -> TextRange {
self.data().range self.data().range
} }
pub fn text(&self) -> &'f str { pub fn text(&self) -> &'f str {
&self.file.text.as_str()[self.range()] &self.file.text.as_str()[self.range()]
} }
pub fn parent(&self) -> Option<Node<'f>> { pub fn parent(&self) -> Option<Node<'f>> {
self.as_node(self.data().parent) self.as_node(self.data().parent)
} }
pub fn children(&self) -> Children<'f> { pub fn children(&self) -> Children<'f> {
Children { next: self.as_node(self.data().first_child) } Children { next: self.as_node(self.data().first_child) }
} }
pub fn errors(&self) -> SyntaxErrors<'f> { pub fn errors(&self) -> SyntaxErrors<'f> {
let pos = self.file.errors.iter().position(|e| e.node == self.idx); let pos = self.file.errors.iter().position(|e| e.node == self.idx);
let next = pos let next = pos
.map(|i| ErrorIdx(i as u32)) .map(|i| ErrorIdx(i as u32))
.map(|idx| SyntaxError { file: self.file, idx }); .map(|idx| SyntaxError { file: self.file, idx });
SyntaxErrors { next } SyntaxErrors { next }
} }
fn data(&self) -> &'f NodeData { fn data(&self) -> &'f NodeData {
&self.file.nodes[self.idx] &self.file.nodes[self.idx]
} }
fn as_node(&self, idx: Option<NodeIdx>) -> Option<Node<'f>> { fn as_node(&self, idx: Option<NodeIdx>) -> Option<Node<'f>> {
idx.map(|idx| Node { file: self.file, idx }) idx.map(|idx| Node { file: self.file, idx })
} }
} }
impl<'f> fmt::Debug for Node<'f> { impl<'f> fmt::Debug for Node<'f> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{:?}@{:?}", self.kind(), self.range()) write!(fmt, "{:?}@{:?}", self.kind(), self.range())
} }
} }
impl<'f> cmp::PartialEq<Node<'f>> for Node<'f> { impl<'f> cmp::PartialEq<Node<'f>> for Node<'f> {
fn eq(&self, other: &Node<'f>) -> bool { fn eq(&self, other: &Node<'f>) -> bool {
self.idx == other.idx && ::std::ptr::eq(self.file, other.file) self.idx == other.idx && ::std::ptr::eq(self.file, other.file)
} }
} }
impl<'f> cmp::Eq for Node<'f> { impl<'f> cmp::Eq for Node<'f> {
@ -108,66 +116,66 @@ impl<'f> cmp::Eq for Node<'f> {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct SyntaxError<'f> { pub struct SyntaxError<'f> {
file: &'f File, file: &'f File,
idx: ErrorIdx, idx: ErrorIdx,
} }
impl<'f> SyntaxError<'f> { impl<'f> SyntaxError<'f> {
pub fn message(&self) -> &'f str { pub fn message(&self) -> &'f str {
self.data().message.as_str() self.data().message.as_str()
} }
pub fn after_child(&self) -> Option<Node<'f>> { pub fn after_child(&self) -> Option<Node<'f>> {
let idx = self.data().after_child?; let idx = self.data().after_child?;
Some(Node { file: self.file, idx }) Some(Node { file: self.file, idx })
} }
fn data(&self) -> &'f SyntaxErrorData { fn data(&self) -> &'f SyntaxErrorData {
&self.file.errors[self.idx] &self.file.errors[self.idx]
} }
fn next(&self) -> Option<SyntaxError<'f>> { fn next(&self) -> Option<SyntaxError<'f>> {
let next_idx = self.idx.0 + 1; let next_idx = self.idx.0 + 1;
if !((next_idx as usize) < self.file.errors.len()) { if !((next_idx as usize) < self.file.errors.len()) {
return None; return None;
} }
let result = SyntaxError { let result = SyntaxError {
file: self.file, file: self.file,
idx: ErrorIdx(next_idx) idx: ErrorIdx(next_idx)
}; };
if result.data().node != self.data().node { if result.data().node != self.data().node {
return None; return None;
} }
Some(result) Some(result)
} }
} }
pub struct Children<'f> { pub struct Children<'f> {
next: Option<Node<'f>>, next: Option<Node<'f>>,
} }
impl<'f> Iterator for Children<'f> { impl<'f> Iterator for Children<'f> {
type Item = Node<'f>; type Item = Node<'f>;
fn next(&mut self) -> Option<Node<'f>> { fn next(&mut self) -> Option<Node<'f>> {
let next = self.next; let next = self.next;
self.next = next.and_then(|node| node.as_node(node.data().next_sibling)); self.next = next.and_then(|node| node.as_node(node.data().next_sibling));
next next
} }
} }
pub struct SyntaxErrors<'f> { pub struct SyntaxErrors<'f> {
next: Option<SyntaxError<'f>>, next: Option<SyntaxError<'f>>,
} }
impl<'f> Iterator for SyntaxErrors<'f> { impl<'f> Iterator for SyntaxErrors<'f> {
type Item = SyntaxError<'f>; type Item = SyntaxError<'f>;
fn next(&mut self) -> Option<SyntaxError<'f>> { fn next(&mut self) -> Option<SyntaxError<'f>> {
let next = self.next; let next = self.next;
self.next = next.as_ref().and_then(SyntaxError::next); self.next = next.as_ref().and_then(SyntaxError::next);
next next
} }
} }
@ -175,40 +183,40 @@ impl<'f> Iterator for SyntaxErrors<'f> {
struct NodeIdx(u32); struct NodeIdx(u32);
struct NodeData { struct NodeData {
kind: SyntaxKind, kind: SyntaxKind,
range: TextRange, range: TextRange,
parent: Option<NodeIdx>, parent: Option<NodeIdx>,
first_child: Option<NodeIdx>, first_child: Option<NodeIdx>,
next_sibling: Option<NodeIdx>, next_sibling: Option<NodeIdx>,
} }
impl ::std::ops::Index<NodeIdx> for Vec<NodeData> { impl ::std::ops::Index<NodeIdx> for Vec<NodeData> {
type Output = NodeData; type Output = NodeData;
fn index(&self, NodeIdx(idx): NodeIdx) -> &NodeData { fn index(&self, NodeIdx(idx): NodeIdx) -> &NodeData {
&self[idx as usize] &self[idx as usize]
} }
} }
impl ::std::ops::IndexMut<NodeIdx> for Vec<NodeData> { impl ::std::ops::IndexMut<NodeIdx> for Vec<NodeData> {
fn index_mut(&mut self, NodeIdx(idx): NodeIdx) -> &mut NodeData { fn index_mut(&mut self, NodeIdx(idx): NodeIdx) -> &mut NodeData {
&mut self[idx as usize] &mut self[idx as usize]
} }
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
struct ErrorIdx(u32); struct ErrorIdx(u32);
struct SyntaxErrorData { struct SyntaxErrorData {
node: NodeIdx, node: NodeIdx,
message: String, message: String,
after_child: Option<NodeIdx>, after_child: Option<NodeIdx>,
} }
impl ::std::ops::Index<ErrorIdx> for Vec<SyntaxErrorData> { impl ::std::ops::Index<ErrorIdx> for Vec<SyntaxErrorData> {
type Output = SyntaxErrorData; type Output = SyntaxErrorData;
fn index(&self, ErrorIdx(idx): ErrorIdx) -> &SyntaxErrorData { fn index(&self, ErrorIdx(idx): ErrorIdx) -> &SyntaxErrorData {
&self[idx as usize] &self[idx as usize]
} }
} }