Skip to content

Commit 9362db1

Browse files
committed
add emmylua_parser test
1 parent 257c63a commit 9362db1

File tree

10 files changed

+303
-119
lines changed

10 files changed

+303
-119
lines changed

Cargo.lock

+48-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ lazy_static = "1.4.0"
1010
encoding_rs = "0.8"
1111
tokio = { version = "1.40.0", features = ["full"] }
1212
notify = { version = "6.1.1", features = ["serde"] }
13+
emmylua_parser = "0.3"
14+
rowan = { version = "0.15.16" }

crates/basic/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ lazy_static.workspace = true
99
encoding_rs.workspace = true
1010
tokio.workspace = true
1111
notify.workspace = true
12-
12+
emmylua_parser.workspace = true
13+
rowan.workspace = true
1314

1415
[build-dependencies]
1516
cc = "1.0"

crates/basic/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod codestyle;
33
mod lpeglabel;
44
mod lua_seri;
55
mod override_lua;
6+
mod parser;
67

78
#[macro_use]
89
extern crate lazy_static;
@@ -20,11 +21,12 @@ pub fn lua_preload(lua: &Lua) -> LuaResult<()> {
2021
// codestyle
2122
codestyle::register_code_format_module(lua)?;
2223

24+
parser::register_parser_module(lua)?;
25+
2326
add_package_path(
2427
&lua,
2528
vec![
2629
"resources/?.lua;resources/?/init.lua;",
27-
// "resources/override_script/?.lua;resources/override_script/?/init.lua;",
2830
"resources/script/?.lua;resources/script/?/init.lua",
2931
],
3032
)?;

crates/basic/src/parser/lua_node.rs

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
use emmylua_parser::{LuaSyntaxKind, LuaSyntaxNode, LuaSyntaxToken, LuaTokenKind};
2+
use mlua::prelude::*;
3+
4+
pub enum LuaNodeWrapper {
5+
Node(LuaSyntaxNode),
6+
Token(LuaSyntaxToken),
7+
}
8+
9+
impl LuaNodeWrapper {
10+
pub fn new(node: LuaSyntaxNode) -> Self {
11+
Self::Node(node)
12+
}
13+
14+
pub fn from_node_or_token(
15+
node_or_token: rowan::NodeOrToken<LuaSyntaxNode, LuaSyntaxToken>,
16+
) -> Self {
17+
match node_or_token {
18+
rowan::NodeOrToken::Node(node) => Self::Node(node),
19+
rowan::NodeOrToken::Token(token) => Self::Token(token),
20+
}
21+
}
22+
}
23+
24+
impl LuaUserData for LuaNodeWrapper {
25+
fn add_fields<F: LuaUserDataFields<Self>>(fields: &mut F) {
26+
fields.add_field_method_get("isNode", |_, this| match this {
27+
LuaNodeWrapper::Node(_) => Ok(true),
28+
LuaNodeWrapper::Token(_) => Ok(false),
29+
});
30+
fields.add_field_method_get("isToken", |_, this| match this {
31+
LuaNodeWrapper::Node(_) => Ok(false),
32+
LuaNodeWrapper::Token(_) => Ok(true),
33+
});
34+
fields.add_field_method_get("kind", |_, this| match this {
35+
LuaNodeWrapper::Node(node) => {
36+
let kind: LuaSyntaxKind = node.kind().into();
37+
Ok(kind as u16)
38+
}
39+
LuaNodeWrapper::Token(token) => {
40+
let kind: LuaTokenKind = token.kind().into();
41+
Ok(kind as u16)
42+
}
43+
});
44+
fields.add_field_method_get("kindText", |_, this| {
45+
let text = match this {
46+
LuaNodeWrapper::Node(node) => {
47+
let kind: LuaSyntaxKind = node.kind().into();
48+
format!("{:?}", kind)
49+
}
50+
LuaNodeWrapper::Token(token) => {
51+
let kind: LuaTokenKind = token.kind().into();
52+
format!("{:?}", kind)
53+
}
54+
};
55+
56+
Ok(text)
57+
});
58+
}
59+
60+
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
61+
methods.add_method("getText", |_, this, ()| {
62+
let text = match this {
63+
LuaNodeWrapper::Node(node) => node.text().to_string(),
64+
LuaNodeWrapper::Token(token) => token.text().to_string(),
65+
};
66+
Ok(text)
67+
});
68+
methods.add_method("getRange", |lua, this, ()| {
69+
let range = match this {
70+
LuaNodeWrapper::Node(node) => node.text_range(),
71+
LuaNodeWrapper::Token(token) => token.text_range(),
72+
};
73+
let table = lua.create_table()?;
74+
let line: u32 = range.start().into();
75+
let col: u32 = range.start().into();
76+
table.set("start", line)?;
77+
table.set("end", col)?;
78+
Ok(table)
79+
});
80+
methods.add_method("getChildren", |lua, this, ()| {
81+
let children = match this {
82+
LuaNodeWrapper::Node(node) => node
83+
.children_with_tokens()
84+
.filter_map(|it| match it {
85+
rowan::NodeOrToken::Node(node) => Some(LuaNodeWrapper::Node(node)),
86+
rowan::NodeOrToken::Token(token) => Some(LuaNodeWrapper::Token(token)),
87+
})
88+
.collect(),
89+
LuaNodeWrapper::Token(_) => vec![],
90+
};
91+
92+
Ok(children)
93+
});
94+
95+
methods.add_method("dump", |_, this, ()| {
96+
let dump = match this {
97+
LuaNodeWrapper::Node(node) => format!("{:#?}", node),
98+
LuaNodeWrapper::Token(token) => format!("{:#?}", token),
99+
};
100+
Ok(dump)
101+
});
102+
103+
methods.add_method("getParent", |_, this, ()| {
104+
let parent = match this {
105+
LuaNodeWrapper::Node(node) => node.parent().map(LuaNodeWrapper::Node),
106+
LuaNodeWrapper::Token(token) => token.parent().map(LuaNodeWrapper::Node),
107+
};
108+
Ok(parent)
109+
});
110+
111+
methods.add_method("getPrevSibling", |_, this, ()| {
112+
let prev_sibling = match this {
113+
LuaNodeWrapper::Node(node) => node.prev_sibling().map(LuaNodeWrapper::Node),
114+
LuaNodeWrapper::Token(token) => match token.prev_sibling_or_token() {
115+
Some(rowan::NodeOrToken::Node(node)) => Some(LuaNodeWrapper::Node(node)),
116+
Some(rowan::NodeOrToken::Token(token)) => Some(LuaNodeWrapper::Token(token)),
117+
None => None,
118+
},
119+
};
120+
Ok(prev_sibling)
121+
});
122+
123+
methods.add_method("getNextSibling", |_, this, ()| {
124+
let next_sibling = match this {
125+
LuaNodeWrapper::Node(node) => node.next_sibling().map(LuaNodeWrapper::Node),
126+
LuaNodeWrapper::Token(token) => match token.next_sibling_or_token() {
127+
Some(rowan::NodeOrToken::Node(node)) => Some(LuaNodeWrapper::Node(node)),
128+
Some(rowan::NodeOrToken::Token(token)) => Some(LuaNodeWrapper::Token(token)),
129+
None => None,
130+
},
131+
};
132+
Ok(next_sibling)
133+
});
134+
135+
methods.add_method("getDescendants", |_, this, ()| {
136+
let descendants = match this {
137+
LuaNodeWrapper::Node(node) => node
138+
.descendants_with_tokens()
139+
.map(LuaNodeWrapper::from_node_or_token)
140+
.collect(),
141+
LuaNodeWrapper::Token(_) => vec![],
142+
};
143+
Ok(descendants)
144+
});
145+
146+
methods.add_method("getAncestors", |_, this, ()| {
147+
let ancestors: Vec<LuaNodeWrapper> = match this {
148+
LuaNodeWrapper::Node(node) => node.ancestors().map(LuaNodeWrapper::Node).collect(),
149+
LuaNodeWrapper::Token(token) => {
150+
token.parent_ancestors().map(LuaNodeWrapper::Node).collect()
151+
}
152+
};
153+
154+
Ok(ancestors)
155+
});
156+
}
157+
}

crates/basic/src/parser/lua_parser.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use emmylua_parser::{LuaParser, ParserConfig};
2+
use mlua::{prelude::*, Lua};
3+
4+
use super::lua_syntax_tree::LuaSyntaxTree;
5+
6+
fn parse(_: &Lua, text: String) -> LuaResult<LuaSyntaxTree> {
7+
let tree = LuaParser::parse(&text, ParserConfig::default());
8+
9+
Ok(LuaSyntaxTree::new(tree))
10+
}
11+
12+
pub fn lua_parser(lua: &Lua) -> LuaResult<LuaTable> {
13+
let parser = lua.create_table()?;
14+
parser.set("parse", lua.create_function(parse)?)?;
15+
Ok(parser)
16+
}
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use emmylua_parser::LuaSyntaxTree as EmmyLuaSyntaxTree;
2+
use mlua::prelude::*;
3+
use rowan::TextSize;
4+
5+
use super::lua_node::LuaNodeWrapper;
6+
7+
pub struct LuaSyntaxTree {
8+
tree: EmmyLuaSyntaxTree,
9+
}
10+
11+
impl LuaSyntaxTree {
12+
pub fn new(tree: EmmyLuaSyntaxTree) -> Self {
13+
Self { tree }
14+
}
15+
16+
pub fn get_root(&self) -> LuaNodeWrapper {
17+
LuaNodeWrapper::new(self.tree.get_red_root().clone())
18+
}
19+
20+
pub fn get_line_col(&self, offset: usize) -> Option<(usize, usize)> {
21+
let offset = TextSize::from(offset as u32);
22+
let (line, col) = self.tree.get_line_col(offset)?;
23+
Some((line, col))
24+
}
25+
26+
pub fn get_offset(&self, line: usize, col: usize) -> Option<usize> {
27+
let offset = self.tree.get_offset(line, col)?;
28+
Some(offset.into())
29+
}
30+
}
31+
32+
impl LuaUserData for LuaSyntaxTree {
33+
fn add_fields<F: LuaUserDataFields<Self>>(fields: &mut F) {}
34+
35+
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
36+
methods.add_method("getRoot", |_, this, ()| Ok(this.get_root()));
37+
// methods.add_method("get_chunk_node", |_, this, ()| Ok(this.get_chunk_node()));
38+
methods.add_method("getLineCol", |lua, this, offset: usize| {
39+
let (line, col) = this.get_line_col(offset).unwrap();
40+
let table = lua.create_table()?;
41+
table.set(1, line)?;
42+
table.set(2, col)?;
43+
Ok(table)
44+
});
45+
methods.add_method("getOffset", |_, this, (line, col): (usize, usize)| {
46+
Ok(this.get_offset(line, col))
47+
});
48+
}
49+
}

crates/basic/src/parser/mod.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
mod lua_parser;
2+
mod lua_syntax_tree;
3+
mod lua_node;
4+
5+
use mlua::{prelude::*, Lua};
6+
7+
use crate::add_preload_module;
8+
9+
10+
pub fn register_parser_module(lua: &Lua) -> LuaResult<()> {
11+
// lua.parser
12+
let lua_parser_loader =
13+
lua.create_function(|lua: &Lua, ()| Ok(lua_parser::lua_parser(lua)))?;
14+
add_preload_module(&lua, "lua.parser", lua_parser_loader)?;
15+
Ok(())
16+
}

resources/main.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ local fs = require 'bee.filesystem'
22
local util = require 'utility'
33
local version = require 'version'
44
require 'config.env'
5-
5+
require 'test'
66
local function getValue(value)
77
if value == 'true' or value == nil then
88
value = true

0 commit comments

Comments
 (0)