Parser: first scraches

This commit is contained in:
Aleksey Kladov 2018-01-01 22:13:04 +03:00
parent cb362626f3
commit 46422f722b
9 changed files with 97 additions and 17 deletions

View File

@ -62,5 +62,6 @@ Grammar(
],
nodes: [
"FILE",
"STRUCT_ITEM"
]
)

View File

@ -40,6 +40,12 @@ fn mod_items(p: &mut Parser) {
fn item(p: &mut Parser) -> Result {
outer_attributes(p)?;
visibility(p)?;
if p.current_is(STRUCT_KW) {
p.start(STRUCT_ITEM);
p.bump();
p.finish();
return OK;
}
ERR
}

View File

@ -4,6 +4,7 @@
mod grammar;
mod parser;
#[derive(Debug)]
pub(crate) enum Event {
Start { kind: SyntaxKind },
Finish,

View File

@ -1,5 +1,6 @@
use {Token, SyntaxKind, TextUnit};
use super::Event;
use super::{Event};
use super::super::is_insignificant;
use syntax_kinds::{WHITESPACE, COMMENT};
pub struct Parser<'t> {
@ -16,9 +17,8 @@ pub(crate) fn new(text: &'t str, raw_tokens: &'t [Token]) -> Parser<'t> {
let mut non_ws_tokens = Vec::new();
let mut len = TextUnit::new(0);
for (idx, &token) in raw_tokens.iter().enumerate() {
match token.kind {
WHITESPACE | COMMENT => (),
_ => non_ws_tokens.push((idx, len)),
if !is_insignificant(token.kind) {
non_ws_tokens.push((idx, len))
}
len += token.len;
}
@ -50,15 +50,25 @@ pub(crate) fn finish(&mut self) {
self.event(Event::Finish);
}
pub(crate) fn bump(&mut self) -> Option<SyntaxKind> {
pub(crate) fn current(&self) -> Option<SyntaxKind> {
if self.is_eof() {
return None;
}
let idx = self.non_ws_tokens[self.pos].0;
self.pos += 1;
Some(self.raw_tokens[idx].kind)
}
pub(crate) fn current_is(&self, kind: SyntaxKind) -> bool {
self.current() == Some(kind)
}
pub(crate) fn bump(&mut self) -> Option<SyntaxKind> {
let kind = self.current()?;
self.pos += 1;
self.event(Event::Token { kind, n_raw_tokens: 1 });
Some(kind)
}
fn event(&mut self, event: Event) {
self.events.push(event)
}

View File

@ -8,17 +8,50 @@
pub fn parse(text: String, tokens: &[Token]) -> File {
let events = event_parser::parse(&text, tokens);
from_events_to_file(text, events)
from_events_to_file(text, tokens, events)
}
fn from_events_to_file(text: String, events: Vec<Event>) -> File {
fn from_events_to_file(
text: String,
tokens: &[Token],
events: Vec<Event>,
) -> File {
let mut builder = FileBuilder::new(text);
let mut idx = 0;
for event in events {
match event {
Event::Start { kind } => builder.start_internal(kind),
Event::Finish => builder.finish_internal(),
Event::Token { .. } => unimplemented!(),
Event::Finish => {
while idx < tokens.len() {
let token = tokens[idx];
if is_insignificant(token.kind) {
idx += 1;
builder.leaf(token.kind, token.len);
} else {
break;
}
}
builder.finish_internal()
},
Event::Token { kind, mut n_raw_tokens } => loop {
let token = tokens[idx];
if !is_insignificant(token.kind) {
n_raw_tokens -= 1;
}
idx += 1;
builder.leaf(token.kind, token.len);
if n_raw_tokens == 0 {
break;
}
},
}
}
builder.finish()
}
fn is_insignificant(kind: SyntaxKind) -> bool {
match kind {
WHITESPACE | COMMENT => true,
_ => false,
}
}

View File

@ -59,8 +59,9 @@
pub const DOC_COMMENT: SyntaxKind = SyntaxKind(55);
pub const SHEBANG: SyntaxKind = SyntaxKind(56);
pub const FILE: SyntaxKind = SyntaxKind(57);
pub const STRUCT_ITEM: SyntaxKind = SyntaxKind(58);
static INFOS: [SyntaxInfo; 58] = [
static INFOS: [SyntaxInfo; 59] = [
SyntaxInfo { name: "USE_KW" },
SyntaxInfo { name: "FN_KW" },
SyntaxInfo { name: "STRUCT_KW" },
@ -119,6 +120,7 @@
SyntaxInfo { name: "DOC_COMMENT" },
SyntaxInfo { name: "SHEBANG" },
SyntaxInfo { name: "FILE" },
SyntaxInfo { name: "STRUCT_ITEM" },
];
pub(crate) fn syntax_info(kind: SyntaxKind) -> &'static SyntaxInfo {

View File

@ -64,8 +64,14 @@ pub fn new(text: String) -> FileBuilder {
}
pub fn finish(self) -> File {
assert!(self.in_progress.is_empty());
assert!(self.pos == (self.text.len() as u32).into());
assert!(
self.in_progress.is_empty(),
"some nodes in FileBuilder are unfinished"
);
assert!(
self.pos == (self.text.len() as u32).into(),
"nodes in FileBuilder do not cover the whole file"
);
File {
text: self.text,
nodes: self.nodes,
@ -81,11 +87,17 @@ fn new_node(&mut self, data: NodeData) -> NodeIdx {
fn push_child(&mut self, mut child: NodeData) -> NodeIdx {
child.parent = Some(self.current_id());
let id = self.new_node(child);
if let Some(sibling) = self.current_sibling() {
fill(&mut sibling.next_sibling, id);
return id
{
let (parent, sibling) = *self.in_progress.last().unwrap();
let slot = if let Some(idx) = sibling {
&mut self.nodes[idx].next_sibling
} else {
&mut self.nodes[parent].first_child
};
fill(slot, id);
}
fill(&mut self.current_parent().first_child, id);
self.in_progress.last_mut().unwrap().1 = Some(id);
id
}

View File

@ -0,0 +1,3 @@
struct S {
}

View File

@ -0,0 +1,12 @@
FILE@[0; 13)
STRUCT_ITEM@[0; 7)
STRUCT_KW@[0; 6)
WHITESPACE@[6; 7)
ERROR@[7; 9)
IDENT@[7; 8)
WHITESPACE@[8; 9)
ERROR@[9; 12)
L_CURLY@[9; 10)
WHITESPACE@[10; 12)
ERROR@[12; 13)
R_CURLY@[12; 13)