Modify library for new parser
This commit is contained in:
parent
5fed0984a7
commit
589d66a90f
5033
Cargo.lock
generated
5033
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
46
Cargo.toml
46
Cargo.toml
@ -1,46 +0,0 @@
|
||||
[package]
|
||||
name = "dust-lang"
|
||||
version = "0.1.2"
|
||||
description = "Data-oriented programming language and interactive shell."
|
||||
authors = ["jeff <dev@jeffa.io.com>"]
|
||||
repository = "https://git.jeffa.io/jeff/dust.git"
|
||||
homepage = "https://git.jeffa.io/jeff/dust"
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
edition = "2018"
|
||||
default-run = "dust"
|
||||
|
||||
[[bin]]
|
||||
name = "dust"
|
||||
|
||||
[[bin]]
|
||||
name = "gui"
|
||||
|
||||
[lib]
|
||||
name = "dust_lib"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
rand = "0.8.5"
|
||||
chrono = "0.4.26"
|
||||
trash = "3.0.3"
|
||||
rayon = "1.7.0"
|
||||
serde = { version = "1.0.171", features = ["derive"] }
|
||||
sysinfo = "0.29.6"
|
||||
toml = "0.7.6"
|
||||
toml_edit = "0.19.14"
|
||||
comfy-table = "7.0.1"
|
||||
clap = { version = "4.3.19", features = ["derive"] }
|
||||
git2 = "0.17.2"
|
||||
csv = "1.2.2"
|
||||
json = "0.12.4"
|
||||
reqwest = { version = "0.11.18", features = ["blocking", "json"] }
|
||||
serde_json = "1.0.104"
|
||||
egui_extras = "0.22.0"
|
||||
rustyline = { version = "12.0.0", features = ["with-file-history", "derive"] }
|
||||
ansi_term = "0.12.1"
|
||||
iced = "0.10.0"
|
||||
egui = "0.22.0"
|
||||
eframe = "0.22.0"
|
||||
env_logger = "0.10.0"
|
||||
once_cell = "1.18.0"
|
40
build.rs
Normal file
40
build.rs
Normal file
@ -0,0 +1,40 @@
|
||||
fn main() {
|
||||
let src_dir = std::path::Path::new("src");
|
||||
|
||||
let mut c_config = cc::Build::new();
|
||||
c_config.include(&src_dir);
|
||||
c_config
|
||||
.flag_if_supported("-Wno-unused-parameter")
|
||||
.flag_if_supported("-Wno-unused-but-set-variable")
|
||||
.flag_if_supported("-Wno-trigraphs");
|
||||
let parser_path = src_dir.join("parser.c");
|
||||
c_config.file(&parser_path);
|
||||
|
||||
// If your language uses an external scanner written in C,
|
||||
// then include this block of code:
|
||||
|
||||
/*
|
||||
let scanner_path = src_dir.join("scanner.c");
|
||||
c_config.file(&scanner_path);
|
||||
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
|
||||
*/
|
||||
|
||||
c_config.compile("parser");
|
||||
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
|
||||
|
||||
// If your language uses an external scanner written in C++,
|
||||
// then include this block of code:
|
||||
|
||||
/*
|
||||
let mut cpp_config = cc::Build::new();
|
||||
cpp_config.cpp(true);
|
||||
cpp_config.include(&src_dir);
|
||||
cpp_config
|
||||
.flag_if_supported("-Wno-unused-parameter")
|
||||
.flag_if_supported("-Wno-unused-but-set-variable");
|
||||
let scanner_path = src_dir.join("scanner.cc");
|
||||
cpp_config.file(&scanner_path);
|
||||
cpp_config.compile("scanner");
|
||||
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
|
||||
*/
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
use dust_lib::eval;
|
||||
use iced::widget::{column, container, text_input, Column};
|
||||
use iced::{executor, Application, Command, Element, Settings, Theme};
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
static INPUT_ID: Lazy<text_input::Id> = Lazy::new(text_input::Id::unique);
|
||||
|
||||
pub fn main() -> iced::Result {
|
||||
DustGui::run(Settings::default())
|
||||
}
|
||||
|
||||
struct DustGui {
|
||||
text_buffer: String,
|
||||
results: Vec<String>,
|
||||
}
|
||||
|
||||
impl Application for DustGui {
|
||||
type Executor = executor::Default;
|
||||
|
||||
type Message = Message;
|
||||
|
||||
type Theme = Theme;
|
||||
|
||||
type Flags = ();
|
||||
|
||||
fn new(_flags: Self::Flags) -> (Self, iced::Command<Self::Message>) {
|
||||
(
|
||||
DustGui {
|
||||
text_buffer: String::new(),
|
||||
results: Vec::new(),
|
||||
},
|
||||
Command::none(),
|
||||
)
|
||||
}
|
||||
|
||||
fn title(&self) -> String {
|
||||
"Dust".to_string()
|
||||
}
|
||||
|
||||
fn update(&mut self, message: Self::Message) -> iced::Command<Self::Message> {
|
||||
match message {
|
||||
Message::TextInput(input) => {
|
||||
self.text_buffer = input;
|
||||
|
||||
Command::none()
|
||||
}
|
||||
Message::Evaluate => {
|
||||
let eval_result = eval(&self.text_buffer);
|
||||
|
||||
match eval_result {
|
||||
Ok(result) => self.results.push(result.to_string()),
|
||||
Err(error) => self.results.push(error.to_string()),
|
||||
}
|
||||
|
||||
Command::batch(vec![])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn view(&self) -> Element<'_, Self::Message, iced::Renderer<Self::Theme>> {
|
||||
let input = text_input("What needs to be done?", &self.text_buffer)
|
||||
.id(INPUT_ID.clone())
|
||||
.on_input(Message::TextInput)
|
||||
.on_submit(Message::Evaluate)
|
||||
.padding(15)
|
||||
.size(30);
|
||||
|
||||
let result_display: Column<Message> = {
|
||||
let mut text_widgets = Vec::new();
|
||||
|
||||
for _result in &self.results {
|
||||
// text_widgets.push(text(result).style().into());
|
||||
}
|
||||
|
||||
text_widgets.reverse();
|
||||
|
||||
Column::with_children(text_widgets)
|
||||
};
|
||||
|
||||
container(column![input, result_display]).into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum Message {
|
||||
TextInput(String),
|
||||
Evaluate,
|
||||
}
|
@ -14,6 +14,13 @@ pub type Result<T> = std::result::Result<T, Error>;
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
UnexpectedSourceNode {
|
||||
expected: &'static str,
|
||||
actual: &'static str,
|
||||
},
|
||||
|
||||
ExpectedFieldName,
|
||||
|
||||
/// Dust's internal type checking failed to identify a type mismatch. This should never happen, /// the error prompts the user to report the bug.
|
||||
TypeCheckFailure {
|
||||
tool_info: ToolInfo<'static>,
|
||||
@ -628,6 +635,8 @@ impl fmt::Display for Error {
|
||||
macro_info.identifier,
|
||||
macro_info.inputs
|
||||
),
|
||||
UnexpectedSourceNode { expected, actual } => write!(f, "Unexpected source node. Expected {expected}, but found {actual}."),
|
||||
ExpectedFieldName => write!(f, "Expected a field name for this node, but none was found."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
120
src/interface.rs
120
src/interface.rs
@ -1,6 +1,10 @@
|
||||
//! The top level of Dust's API with functions in interpret Dust code.
|
||||
|
||||
use crate::{token, tree, Result, Value, VariableMap};
|
||||
use std::ops::Range;
|
||||
|
||||
use tree_sitter::{Parser, TreeCursor};
|
||||
|
||||
use crate::{language, token, tree, Error, Result, Value, VariableMap};
|
||||
|
||||
/// Evaluate the given expression string.
|
||||
///
|
||||
@ -12,9 +16,10 @@ use crate::{token, tree, Result, Value, VariableMap};
|
||||
/// ```
|
||||
///
|
||||
/// *See the [crate doc](index.html) for more examples and explanations of the expression format.*
|
||||
pub fn eval(string: &str) -> Result<Value> {
|
||||
pub fn eval(source: &str) -> Result<Value> {
|
||||
let mut context = VariableMap::new();
|
||||
eval_with_context(string, &mut context)
|
||||
|
||||
eval_with_context(source, &mut context)
|
||||
}
|
||||
|
||||
/// Evaluate the given expression string with the given context.
|
||||
@ -30,32 +35,93 @@ pub fn eval(string: &str) -> Result<Value> {
|
||||
/// assert_eq!(eval_with_context("one + two + three", &mut context), Ok(Value::from(6)));
|
||||
/// ```
|
||||
pub fn eval_with_context(input: &str, context: &mut VariableMap) -> Result<Value> {
|
||||
let without_comments = input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let split = line.split_once('#');
|
||||
let mut parser = Parser::new();
|
||||
|
||||
if let Some((code, _comment)) = split {
|
||||
code
|
||||
parser.set_language(language()).unwrap();
|
||||
|
||||
let tree = parser.parse(input, None).unwrap();
|
||||
let sexp = tree.root_node().to_sexp();
|
||||
|
||||
println!("{sexp}");
|
||||
|
||||
let mut cursor = tree.walk();
|
||||
|
||||
cursor.goto_first_child();
|
||||
|
||||
let statement = Statement::from_cursor(cursor);
|
||||
|
||||
println!("{statement:?}");
|
||||
|
||||
Ok(Value::Empty)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct EvalTree {
|
||||
root: Source,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Source {
|
||||
Comment(String),
|
||||
Statement(Statement),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Statement {
|
||||
Closed(Expression),
|
||||
}
|
||||
|
||||
impl Statement {
|
||||
fn from_cursor(mut cursor: TreeCursor) -> Result<Self> {
|
||||
let node = cursor.node();
|
||||
|
||||
cursor.goto_first_child();
|
||||
|
||||
if node.kind() == "statement" {
|
||||
Ok(Statement::Closed(Expression::from_cursor(cursor)?))
|
||||
} else {
|
||||
line
|
||||
}
|
||||
Err(Error::UnexpectedSourceNode {
|
||||
expected: "statement",
|
||||
actual: node.kind(),
|
||||
})
|
||||
.collect::<String>();
|
||||
|
||||
let split = without_comments.split_once("->");
|
||||
|
||||
if let Some((left, right)) = split {
|
||||
let left_result = tree::tokens_to_operator_tree(token::tokenize(left)?)?
|
||||
.eval_with_context_mut(context)?;
|
||||
|
||||
context.set_value("input", left_result)?;
|
||||
|
||||
let right_result = eval_with_context(right, context)?;
|
||||
|
||||
Ok(right_result)
|
||||
} else {
|
||||
tree::tokens_to_operator_tree(token::tokenize(&without_comments)?)?
|
||||
.eval_with_context_mut(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Expression {
|
||||
Identifier(&'static str),
|
||||
Value(Range<usize>),
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
fn from_cursor(mut cursor: TreeCursor) -> Result<Self> {
|
||||
let parent = cursor.node();
|
||||
|
||||
cursor.goto_first_child();
|
||||
|
||||
let child = cursor.node();
|
||||
|
||||
if parent.kind() == "expression" {
|
||||
if child.kind() == "identifier" {
|
||||
if let Some(name) = cursor.field_name() {
|
||||
Ok(Expression::Identifier(name))
|
||||
} else {
|
||||
Err(Error::ExpectedFieldName)
|
||||
}
|
||||
} else if child.kind() == "value" {
|
||||
Ok(Self::Value(child.byte_range()))
|
||||
} else {
|
||||
Err(Error::UnexpectedSourceNode {
|
||||
expected: "identifier or value",
|
||||
actual: child.kind(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
Err(Error::UnexpectedSourceNode {
|
||||
expected: "expression",
|
||||
actual: parent.kind(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
37
src/lib.rs
37
src/lib.rs
@ -3,7 +3,6 @@
|
||||
//!
|
||||
//! Using this library is simple and straightforward, see the [inferface] module for instructions on
|
||||
//! interpreting Dust code. Most of the language's features are implemented in the [tools] module.
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
pub use crate::{
|
||||
error::*,
|
||||
@ -26,3 +25,39 @@ mod operator;
|
||||
mod token;
|
||||
mod tree;
|
||||
mod value;
|
||||
|
||||
use tree_sitter::Language;
|
||||
|
||||
extern "C" {
|
||||
fn tree_sitter_dust() -> Language;
|
||||
}
|
||||
|
||||
/// Get the tree-sitter [Language][] for this grammar.
|
||||
///
|
||||
/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
|
||||
pub fn language() -> Language {
|
||||
unsafe { tree_sitter_dust() }
|
||||
}
|
||||
|
||||
/// The content of the [`node-types.json`][] file for this grammar.
|
||||
///
|
||||
/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
|
||||
pub const NODE_TYPES: &'static str = include_str!("../../../src/node-types.json");
|
||||
|
||||
// Uncomment these to include any queries that this grammar contains
|
||||
|
||||
// pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm");
|
||||
// pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm");
|
||||
// pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
|
||||
// pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm");
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn test_can_load_grammar() {
|
||||
let mut parser = tree_sitter::Parser::new();
|
||||
parser
|
||||
.set_language(super::language())
|
||||
.expect("Error loading dust language");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user