mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-12 21:28:51 +00:00
Parser: first scraches
This commit is contained in:
parent
cb362626f3
commit
46422f722b
9 changed files with 97 additions and 17 deletions
|
@ -62,5 +62,6 @@ Grammar(
|
||||||
],
|
],
|
||||||
nodes: [
|
nodes: [
|
||||||
"FILE",
|
"FILE",
|
||||||
|
"STRUCT_ITEM"
|
||||||
]
|
]
|
||||||
)
|
)
|
|
@ -40,6 +40,12 @@ fn mod_items(p: &mut Parser) {
|
||||||
fn item(p: &mut Parser) -> Result {
|
fn item(p: &mut Parser) -> Result {
|
||||||
outer_attributes(p)?;
|
outer_attributes(p)?;
|
||||||
visibility(p)?;
|
visibility(p)?;
|
||||||
|
if p.current_is(STRUCT_KW) {
|
||||||
|
p.start(STRUCT_ITEM);
|
||||||
|
p.bump();
|
||||||
|
p.finish();
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
ERR
|
ERR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ use syntax_kinds::*;
|
||||||
mod grammar;
|
mod grammar;
|
||||||
mod parser;
|
mod parser;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub(crate) enum Event {
|
pub(crate) enum Event {
|
||||||
Start { kind: SyntaxKind },
|
Start { kind: SyntaxKind },
|
||||||
Finish,
|
Finish,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use {Token, SyntaxKind, TextUnit};
|
use {Token, SyntaxKind, TextUnit};
|
||||||
use super::Event;
|
use super::{Event};
|
||||||
|
use super::super::is_insignificant;
|
||||||
use syntax_kinds::{WHITESPACE, COMMENT};
|
use syntax_kinds::{WHITESPACE, COMMENT};
|
||||||
|
|
||||||
pub struct Parser<'t> {
|
pub struct Parser<'t> {
|
||||||
|
@ -16,9 +17,8 @@ impl<'t> Parser<'t> {
|
||||||
let mut non_ws_tokens = Vec::new();
|
let mut non_ws_tokens = Vec::new();
|
||||||
let mut len = TextUnit::new(0);
|
let mut len = TextUnit::new(0);
|
||||||
for (idx, &token) in raw_tokens.iter().enumerate() {
|
for (idx, &token) in raw_tokens.iter().enumerate() {
|
||||||
match token.kind {
|
if !is_insignificant(token.kind) {
|
||||||
WHITESPACE | COMMENT => (),
|
non_ws_tokens.push((idx, len))
|
||||||
_ => non_ws_tokens.push((idx, len)),
|
|
||||||
}
|
}
|
||||||
len += token.len;
|
len += token.len;
|
||||||
}
|
}
|
||||||
|
@ -50,15 +50,25 @@ impl<'t> Parser<'t> {
|
||||||
self.event(Event::Finish);
|
self.event(Event::Finish);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn bump(&mut self) -> Option<SyntaxKind> {
|
pub(crate) fn current(&self) -> Option<SyntaxKind> {
|
||||||
if self.is_eof() {
|
if self.is_eof() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let idx = self.non_ws_tokens[self.pos].0;
|
let idx = self.non_ws_tokens[self.pos].0;
|
||||||
self.pos += 1;
|
|
||||||
Some(self.raw_tokens[idx].kind)
|
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) {
|
fn event(&mut self, event: Event) {
|
||||||
self.events.push(event)
|
self.events.push(event)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,50 @@ use self::event_parser::Event;
|
||||||
|
|
||||||
pub fn parse(text: String, tokens: &[Token]) -> File {
|
pub fn parse(text: String, tokens: &[Token]) -> File {
|
||||||
let events = event_parser::parse(&text, tokens);
|
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 builder = FileBuilder::new(text);
|
||||||
|
let mut idx = 0;
|
||||||
for event in events {
|
for event in events {
|
||||||
match event {
|
match event {
|
||||||
Event::Start { kind } => builder.start_internal(kind),
|
Event::Start { kind } => builder.start_internal(kind),
|
||||||
Event::Finish => builder.finish_internal(),
|
Event::Finish => {
|
||||||
Event::Token { .. } => unimplemented!(),
|
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()
|
builder.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_insignificant(kind: SyntaxKind) -> bool {
|
||||||
|
match kind {
|
||||||
|
WHITESPACE | COMMENT => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,8 +59,9 @@ pub const COMMENT: SyntaxKind = SyntaxKind(54);
|
||||||
pub const DOC_COMMENT: SyntaxKind = SyntaxKind(55);
|
pub const DOC_COMMENT: SyntaxKind = SyntaxKind(55);
|
||||||
pub const SHEBANG: SyntaxKind = SyntaxKind(56);
|
pub const SHEBANG: SyntaxKind = SyntaxKind(56);
|
||||||
pub const FILE: SyntaxKind = SyntaxKind(57);
|
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: "USE_KW" },
|
||||||
SyntaxInfo { name: "FN_KW" },
|
SyntaxInfo { name: "FN_KW" },
|
||||||
SyntaxInfo { name: "STRUCT_KW" },
|
SyntaxInfo { name: "STRUCT_KW" },
|
||||||
|
@ -119,6 +120,7 @@ static INFOS: [SyntaxInfo; 58] = [
|
||||||
SyntaxInfo { name: "DOC_COMMENT" },
|
SyntaxInfo { name: "DOC_COMMENT" },
|
||||||
SyntaxInfo { name: "SHEBANG" },
|
SyntaxInfo { name: "SHEBANG" },
|
||||||
SyntaxInfo { name: "FILE" },
|
SyntaxInfo { name: "FILE" },
|
||||||
|
SyntaxInfo { name: "STRUCT_ITEM" },
|
||||||
];
|
];
|
||||||
|
|
||||||
pub(crate) fn syntax_info(kind: SyntaxKind) -> &'static SyntaxInfo {
|
pub(crate) fn syntax_info(kind: SyntaxKind) -> &'static SyntaxInfo {
|
||||||
|
|
|
@ -64,8 +64,14 @@ impl FileBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finish(self) -> File {
|
pub fn finish(self) -> File {
|
||||||
assert!(self.in_progress.is_empty());
|
assert!(
|
||||||
assert!(self.pos == (self.text.len() as u32).into());
|
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 {
|
File {
|
||||||
text: self.text,
|
text: self.text,
|
||||||
nodes: self.nodes,
|
nodes: self.nodes,
|
||||||
|
@ -81,11 +87,17 @@ impl FileBuilder {
|
||||||
fn push_child(&mut self, mut child: NodeData) -> NodeIdx {
|
fn push_child(&mut self, mut child: NodeData) -> NodeIdx {
|
||||||
child.parent = Some(self.current_id());
|
child.parent = Some(self.current_id());
|
||||||
let id = self.new_node(child);
|
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
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
tests/data/parser/0001_struct_item.rs
Normal file
3
tests/data/parser/0001_struct_item.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
struct S {
|
||||||
|
|
||||||
|
}
|
12
tests/data/parser/0001_struct_item.txt
Normal file
12
tests/data/parser/0001_struct_item.txt
Normal 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)
|
Loading…
Reference in a new issue