aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--cli/src/main.rs4
-rw-r--r--code/native/Cargo.toml2
-rw-r--r--code/native/src/lib.rs40
-rw-r--r--libeditor/Cargo.toml9
-rw-r--r--libeditor/src/lib.rs53
-rw-r--r--src/algo/walk.rs1
-rw-r--r--src/ast.rs2
-rw-r--r--src/lib.rs2
-rw-r--r--src/parser_impl/event.rs2
-rw-r--r--src/parser_impl/mod.rs8
-rw-r--r--src/syntax_kinds/generated.rs41
-rw-r--r--src/syntax_kinds/generated.rs.tera10
-rw-r--r--src/yellow/builder.rs10
-rw-r--r--tests/parser.rs2
15 files changed, 138 insertions, 50 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 0a9d1815e..d61613352 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,7 +5,7 @@ authors = ["Aleksey Kladov <[email protected]>"]
5license = "MIT OR Apache-2.0" 5license = "MIT OR Apache-2.0"
6 6
7[workspace] 7[workspace]
8members = [ "tools", "cli" ] 8members = [ "tools", "cli", "libeditor" ]
9 9
10[dependencies] 10[dependencies]
11unicode-xid = "0.1.0" 11unicode-xid = "0.1.0"
diff --git a/cli/src/main.rs b/cli/src/main.rs
index f6e7e2fed..0044841ed 100644
--- a/cli/src/main.rs
+++ b/cli/src/main.rs
@@ -52,7 +52,7 @@ fn main() -> Result<()> {
52fn parse() -> Result<String> { 52fn parse() -> Result<String> {
53 let text = read_stdin()?; 53 let text = read_stdin()?;
54 let start = Instant::now(); 54 let start = Instant::now();
55 let file = libsyntax2::parse(text); 55 let file = libsyntax2::parse(&text);
56 eprintln!("elapsed {:?}", start.elapsed()); 56 eprintln!("elapsed {:?}", start.elapsed());
57 let tree = libsyntax2::utils::dump_tree(&file); 57 let tree = libsyntax2::utils::dump_tree(&file);
58 Ok(tree) 58 Ok(tree)
@@ -74,7 +74,7 @@ fn render_test(file: &Path, line: usize) -> Result<(String, String)> {
74 None => bail!("No test found at line {} at {}", line, file.display()), 74 None => bail!("No test found at line {} at {}", line, file.display()),
75 Some((_start_line, test)) => test, 75 Some((_start_line, test)) => test,
76 }; 76 };
77 let file = libsyntax2::parse(test.text.clone()); 77 let file = libsyntax2::parse(&test.text);
78 let tree = libsyntax2::utils::dump_tree(&file); 78 let tree = libsyntax2::utils::dump_tree(&file);
79 Ok((test.text, tree)) 79 Ok((test.text, tree))
80} 80}
diff --git a/code/native/Cargo.toml b/code/native/Cargo.toml
index 1648dfb33..3a27051b2 100644
--- a/code/native/Cargo.toml
+++ b/code/native/Cargo.toml
@@ -16,4 +16,4 @@ neon-build = "0.2.0"
16 16
17[dependencies] 17[dependencies]
18neon = "0.2.0" 18neon = "0.2.0"
19libsyntax2 = { path = "../../" } 19libeditor = { path = "../../libeditor" }
diff --git a/code/native/src/lib.rs b/code/native/src/lib.rs
index 068767fab..aae7ad2f3 100644
--- a/code/native/src/lib.rs
+++ b/code/native/src/lib.rs
@@ -1,42 +1,20 @@
1#[macro_use] 1#[macro_use]
2extern crate neon; 2extern crate neon;
3extern crate libsyntax2; 3extern crate libeditor;
4 4
5use libsyntax2::{
6 TextRange,
7 File,
8 utils::dump_tree,
9 SyntaxKind::*,
10 algo,
11};
12use neon::prelude::*; 5use neon::prelude::*;
13 6
14pub struct Wrapper { 7pub struct Wrapper {
15 inner: File, 8 inner: libeditor::File,
16} 9}
17 10
18impl Wrapper {
19 fn highlight(&self) -> Vec<(TextRange, &'static str)> {
20 let mut res = Vec::new();
21 let syntax = self.inner.syntax();
22 for node in algo::walk::preorder(syntax.as_ref()) {
23 if node.kind() == ERROR {
24 res.push((node.range(), "error"))
25 }
26 }
27 res
28 }
29}
30
31
32
33declare_types! { 11declare_types! {
34 /// A class for generating greeting strings. 12 /// A class for generating greeting strings.
35 pub class RustFile for Wrapper { 13 pub class RustFile for Wrapper {
36 init(mut cx) { 14 init(mut cx) {
37 let text = cx.argument::<JsString>(0)?.value(); 15 let text = cx.argument::<JsString>(0)?.value();
38 Ok(Wrapper { 16 Ok(Wrapper {
39 inner: File::parse(&text) 17 inner: libeditor::File::new(&text)
40 }) 18 })
41 } 19 }
42 20
@@ -45,7 +23,7 @@ declare_types! {
45 let tree = { 23 let tree = {
46 let guard = cx.lock(); 24 let guard = cx.lock();
47 let wrapper = this.borrow(&guard); 25 let wrapper = this.borrow(&guard);
48 dump_tree(&wrapper.inner.syntax()) 26 wrapper.inner.syntax_tree()
49 }; 27 };
50 Ok(cx.string(tree.as_str()).upcast()) 28 Ok(cx.string(tree.as_str()).upcast())
51 } 29 }
@@ -55,15 +33,15 @@ declare_types! {
55 let highlights = { 33 let highlights = {
56 let guard = cx.lock(); 34 let guard = cx.lock();
57 let wrapper = this.borrow(&guard); 35 let wrapper = this.borrow(&guard);
58 wrapper.highlight() 36 wrapper.inner.highlight()
59 }; 37 };
60 let res = cx.empty_array(); 38 let res = cx.empty_array();
61 for (i, (range, tag)) in highlights.into_iter().enumerate() { 39 for (i, hl) in highlights.into_iter().enumerate() {
62 let start: u32 = range.start().into(); 40 let start: u32 = hl.range.start().into();
63 let end: u32 = range.end().into(); 41 let end: u32 = hl.range.end().into();
64 let start = cx.number(start); 42 let start = cx.number(start);
65 let end = cx.number(end); 43 let end = cx.number(end);
66 let tag = cx.string(tag); 44 let tag = cx.string(hl.tag);
67 let hl = cx.empty_array(); 45 let hl = cx.empty_array();
68 hl.set(&mut cx, 0, start)?; 46 hl.set(&mut cx, 0, start)?;
69 hl.set(&mut cx, 1, end)?; 47 hl.set(&mut cx, 1, end)?;
diff --git a/libeditor/Cargo.toml b/libeditor/Cargo.toml
new file mode 100644
index 000000000..1a532ce2f
--- /dev/null
+++ b/libeditor/Cargo.toml
@@ -0,0 +1,9 @@
1[package]
2name = "libeditor"
3version = "0.1.0"
4authors = ["Aleksey Kladov <[email protected]>"]
5publish = false
6
7[dependencies]
8libsyntax2 = { path = "../" }
9text_unit = "0.1.2"
diff --git a/libeditor/src/lib.rs b/libeditor/src/lib.rs
new file mode 100644
index 000000000..119bdb2d6
--- /dev/null
+++ b/libeditor/src/lib.rs
@@ -0,0 +1,53 @@
1extern crate libsyntax2;
2extern crate text_unit;
3
4use libsyntax2::{
5 algo::walk,
6 SyntaxKind::*,
7};
8use text_unit::TextRange;
9
10pub struct File {
11 inner: libsyntax2::File
12}
13
14pub struct HighlightedRange {
15 pub range: TextRange,
16 pub tag: &'static str,
17}
18
19impl File {
20 pub fn new(text: &str) -> File {
21 File {
22 inner: libsyntax2::File::parse(text)
23 }
24 }
25
26 pub fn highlight(&self) -> Vec<HighlightedRange> {
27 let syntax = self.inner.syntax();
28 let mut res = Vec::new();
29 for node in walk::preorder(syntax.as_ref()) {
30 let tag = match node.kind() {
31 ERROR => "error",
32 COMMENT | DOC_COMMENT => "comment",
33 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string",
34 ATTR => "attribute",
35 NAME_REF => "text",
36 NAME => "function",
37 INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal",
38 LIFETIME => "parameter",
39 k if k.is_keyword() => "keyword",
40 _ => continue,
41 };
42 res.push(HighlightedRange {
43 range: node.range(),
44 tag
45 })
46 }
47 res
48 }
49
50 pub fn syntax_tree(&self) -> String {
51 ::libsyntax2::utils::dump_tree(&self.inner.syntax())
52 }
53}
diff --git a/src/algo/walk.rs b/src/algo/walk.rs
index a50ec2a09..ad0f2d8fb 100644
--- a/src/algo/walk.rs
+++ b/src/algo/walk.rs
@@ -6,7 +6,6 @@ pub fn preorder<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = SyntaxNodeR
6 WalkEvent::Exit(_) => None, 6 WalkEvent::Exit(_) => None,
7 }) 7 })
8} 8}
9
10#[derive(Debug, Copy, Clone)] 9#[derive(Debug, Copy, Clone)]
11pub enum WalkEvent<'a> { 10pub enum WalkEvent<'a> {
12 Enter(SyntaxNodeRef<'a>), 11 Enter(SyntaxNodeRef<'a>),
diff --git a/src/ast.rs b/src/ast.rs
index 48e1d23ac..caf5fb7ef 100644
--- a/src/ast.rs
+++ b/src/ast.rs
@@ -9,7 +9,7 @@ pub struct File<R: TreeRoot = Arc<SyntaxRoot>> {
9impl File<Arc<SyntaxRoot>> { 9impl File<Arc<SyntaxRoot>> {
10 pub fn parse(text: &str) -> Self { 10 pub fn parse(text: &str) -> Self {
11 File { 11 File {
12 syntax: ::parse(text.to_owned()), 12 syntax: ::parse(text),
13 } 13 }
14 } 14 }
15} 15}
diff --git a/src/lib.rs b/src/lib.rs
index 8f25de9a4..611b87492 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -45,7 +45,7 @@ pub use {
45 yellow::{SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot}, 45 yellow::{SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot},
46}; 46};
47 47
48pub fn parse(text: String) -> SyntaxNode { 48pub fn parse(text: &str) -> SyntaxNode {
49 let tokens = tokenize(&text); 49 let tokens = tokenize(&text);
50 parser_impl::parse::<yellow::GreenBuilder>(text, &tokens) 50 parser_impl::parse::<yellow::GreenBuilder>(text, &tokens)
51} 51}
diff --git a/src/parser_impl/event.rs b/src/parser_impl/event.rs
index eb5d0a4be..66a0b6fc0 100644
--- a/src/parser_impl/event.rs
+++ b/src/parser_impl/event.rs
@@ -76,7 +76,7 @@ pub(crate) enum Event {
76 }, 76 },
77} 77}
78 78
79pub(super) fn process(builder: &mut impl Sink, tokens: &[Token], events: Vec<Event>) { 79pub(super) fn process<'a>(builder: &mut impl Sink<'a>, tokens: &[Token], events: Vec<Event>) {
80 let mut idx = 0; 80 let mut idx = 0;
81 81
82 let mut holes = Vec::new(); 82 let mut holes = Vec::new();
diff --git a/src/parser_impl/mod.rs b/src/parser_impl/mod.rs
index b58094be3..2791c8da5 100644
--- a/src/parser_impl/mod.rs
+++ b/src/parser_impl/mod.rs
@@ -14,10 +14,10 @@ use {
14 14
15use SyntaxKind::{self, EOF, TOMBSTONE}; 15use SyntaxKind::{self, EOF, TOMBSTONE};
16 16
17pub(crate) trait Sink { 17pub(crate) trait Sink<'a> {
18 type Tree; 18 type Tree;
19 19
20 fn new(text: String) -> Self; 20 fn new(text: &'a str) -> Self;
21 21
22 fn leaf(&mut self, kind: SyntaxKind, len: TextUnit); 22 fn leaf(&mut self, kind: SyntaxKind, len: TextUnit);
23 fn start_internal(&mut self, kind: SyntaxKind); 23 fn start_internal(&mut self, kind: SyntaxKind);
@@ -27,9 +27,9 @@ pub(crate) trait Sink {
27} 27}
28 28
29/// Parse a sequence of tokens into the representative node tree 29/// Parse a sequence of tokens into the representative node tree
30pub(crate) fn parse<S: Sink>(text: String, tokens: &[Token]) -> S::Tree { 30pub(crate) fn parse<'a, S: Sink<'a>>(text: &'a str, tokens: &[Token]) -> S::Tree {
31 let events = { 31 let events = {
32 let input = input::ParserInput::new(&text, tokens); 32 let input = input::ParserInput::new(text, tokens);
33 let parser_impl = ParserImpl::new(&input); 33 let parser_impl = ParserImpl::new(&input);
34 let mut parser_api = Parser(parser_impl); 34 let mut parser_api = Parser(parser_impl);
35 grammar::file(&mut parser_api); 35 grammar::file(&mut parser_api);
diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs
index 435be781c..cbcd0c4e1 100644
--- a/src/syntax_kinds/generated.rs
+++ b/src/syntax_kinds/generated.rs
@@ -169,6 +169,47 @@ pub enum SyntaxKind {
169use self::SyntaxKind::*; 169use self::SyntaxKind::*;
170 170
171impl SyntaxKind { 171impl SyntaxKind {
172 pub fn is_keyword(self) -> bool {
173 match self {
174 | USE_KW
175 | FN_KW
176 | STRUCT_KW
177 | ENUM_KW
178 | TRAIT_KW
179 | IMPL_KW
180 | TRUE_KW
181 | FALSE_KW
182 | AS_KW
183 | EXTERN_KW
184 | CRATE_KW
185 | MOD_KW
186 | PUB_KW
187 | SELF_KW
188 | SUPER_KW
189 | IN_KW
190 | WHERE_KW
191 | FOR_KW
192 | LOOP_KW
193 | WHILE_KW
194 | IF_KW
195 | ELSE_KW
196 | MATCH_KW
197 | CONST_KW
198 | STATIC_KW
199 | MUT_KW
200 | UNSAFE_KW
201 | TYPE_KW
202 | REF_KW
203 | LET_KW
204 | MOVE_KW
205 | AUTO_KW
206 | DEFAULT_KW
207 | UNION_KW
208 => true,
209 _ => false
210 }
211 }
212
172 pub(crate) fn info(self) -> &'static SyntaxInfo { 213 pub(crate) fn info(self) -> &'static SyntaxInfo {
173 match self { 214 match self {
174 SEMI => &SyntaxInfo { name: "SEMI" }, 215 SEMI => &SyntaxInfo { name: "SEMI" },
diff --git a/src/syntax_kinds/generated.rs.tera b/src/syntax_kinds/generated.rs.tera
index d719c8312..4e2ee56c3 100644
--- a/src/syntax_kinds/generated.rs.tera
+++ b/src/syntax_kinds/generated.rs.tera
@@ -24,6 +24,16 @@ pub enum SyntaxKind {
24use self::SyntaxKind::*; 24use self::SyntaxKind::*;
25 25
26impl SyntaxKind { 26impl SyntaxKind {
27 pub fn is_keyword(self) -> bool {
28 match self {
29{%- for kw in concat(a=keywords, b=contextual_keywords) %}
30 | {{kw | upper}}_KW
31{%- endfor %}
32 => true,
33 _ => false
34 }
35 }
36
27 pub(crate) fn info(self) -> &'static SyntaxInfo { 37 pub(crate) fn info(self) -> &'static SyntaxInfo {
28 match self { 38 match self {
29{%- for t in concat(a=single_byte_tokens, b=multi_byte_tokens) %} 39{%- for t in concat(a=single_byte_tokens, b=multi_byte_tokens) %}
diff --git a/src/yellow/builder.rs b/src/yellow/builder.rs
index b68ba789e..dbe646cd7 100644
--- a/src/yellow/builder.rs
+++ b/src/yellow/builder.rs
@@ -4,20 +4,18 @@ use {
4 SyntaxKind, TextRange, TextUnit, 4 SyntaxKind, TextRange, TextUnit,
5}; 5};
6 6
7pub(crate) struct GreenBuilder { 7pub(crate) struct GreenBuilder<'a> {
8 text: String, 8 text: &'a str,
9 stack: Vec<GreenNodeBuilder>, 9 stack: Vec<GreenNodeBuilder>,
10 pos: TextUnit, 10 pos: TextUnit,
11 root: Option<GreenNode>, 11 root: Option<GreenNode>,
12 errors: Vec<SyntaxError>, 12 errors: Vec<SyntaxError>,
13} 13}
14 14
15impl GreenBuilder {} 15impl<'a> Sink<'a> for GreenBuilder<'a> {
16
17impl Sink for GreenBuilder {
18 type Tree = SyntaxNode; 16 type Tree = SyntaxNode;
19 17
20 fn new(text: String) -> Self { 18 fn new(text: &'a str) -> Self {
21 GreenBuilder { 19 GreenBuilder {
22 text, 20 text,
23 stack: Vec::new(), 21 stack: Vec::new(),
diff --git a/tests/parser.rs b/tests/parser.rs
index 770610974..af2ae11bb 100644
--- a/tests/parser.rs
+++ b/tests/parser.rs
@@ -8,7 +8,7 @@ use testutils::dir_tests;
8#[test] 8#[test]
9fn parser_tests() { 9fn parser_tests() {
10 dir_tests(&["parser/inline", "parser/ok", "parser/err"], |text| { 10 dir_tests(&["parser/inline", "parser/ok", "parser/err"], |text| {
11 let file = parse(text.to_string()); 11 let file = parse(text);
12 dump_tree(&file) 12 dump_tree(&file)
13 }) 13 })
14} 14}