Move the wasm lib, and cleanup rust directory and all references (#5585)
* git mv src/wasm-lib rust Signed-off-by: Jess Frazelle <github@jessfraz.com> * mv wasm-lib to workspace Signed-off-by: Jess Frazelle <github@jessfraz.com> * mv kcl-lib Signed-off-by: Jess Frazelle <github@jessfraz.com> * mv derive docs Signed-off-by: Jess Frazelle <github@jessfraz.com> * resolve file paths Signed-off-by: Jess Frazelle <github@jessfraz.com> * clippy Signed-off-by: Jess Frazelle <github@jessfraz.com> * move more shit Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix more paths Signed-off-by: Jess Frazelle <github@jessfraz.com> * make yarn build:wasm work Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix scripts Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixups Signed-off-by: Jess Frazelle <github@jessfraz.com> * better references Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix cargo ci Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix reference Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix more ci Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix tests Signed-off-by: Jess Frazelle <github@jessfraz.com> * cargo sort Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix script Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix Signed-off-by: Jess Frazelle <github@jessfraz.com> * fmt Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix a dep Signed-off-by: Jess Frazelle <github@jessfraz.com> * sort Signed-off-by: Jess Frazelle <github@jessfraz.com> * remove unused deps Signed-off-by: Jess Frazelle <github@jessfraz.com> * Revert "remove unused deps" This reverts commit fbabdb062e275fd5cbc1476f8480a1afee15d972. * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * deps; Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
162
rust/kcl-lib/src/parsing/mod.rs
Normal file
162
rust/kcl-lib/src/parsing/mod.rs
Normal file
@ -0,0 +1,162 @@
|
||||
use crate::{
|
||||
errors::{CompilationError, KclError, KclErrorDetails},
|
||||
parsing::{
|
||||
ast::types::{Node, Program},
|
||||
token::TokenStream,
|
||||
},
|
||||
source_range::SourceRange,
|
||||
ModuleId,
|
||||
};
|
||||
|
||||
pub(crate) mod ast;
|
||||
mod math;
|
||||
pub(crate) mod parser;
|
||||
pub(crate) mod token;
|
||||
|
||||
pub const PIPE_SUBSTITUTION_OPERATOR: &str = "%";
|
||||
pub const PIPE_OPERATOR: &str = "|>";
|
||||
|
||||
// `?` like behavior for `Result`s to return a ParseResult if there is an error.
|
||||
macro_rules! pr_try {
|
||||
($e: expr) => {
|
||||
match $e {
|
||||
Ok(a) => a,
|
||||
Err(e) => return e.into(),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// Parse the given KCL code into an AST. This is the top-level.
|
||||
pub fn top_level_parse(code: &str) -> ParseResult {
|
||||
let module_id = ModuleId::default();
|
||||
parse_str(code, module_id)
|
||||
}
|
||||
|
||||
/// Parse the given KCL code into an AST.
|
||||
pub fn parse_str(code: &str, module_id: ModuleId) -> ParseResult {
|
||||
let tokens = pr_try!(crate::parsing::token::lex(code, module_id));
|
||||
parse_tokens(tokens)
|
||||
}
|
||||
|
||||
/// Parse the supplied tokens into an AST.
|
||||
pub fn parse_tokens(mut tokens: TokenStream) -> ParseResult {
|
||||
let unknown_tokens = tokens.remove_unknown();
|
||||
|
||||
if !unknown_tokens.is_empty() {
|
||||
let source_ranges = unknown_tokens.iter().map(SourceRange::from).collect();
|
||||
let token_list = unknown_tokens.iter().map(|t| t.value.as_str()).collect::<Vec<_>>();
|
||||
let message = if token_list.len() == 1 {
|
||||
format!("found unknown token '{}'", token_list[0])
|
||||
} else {
|
||||
format!("found unknown tokens [{}]", token_list.join(", "))
|
||||
};
|
||||
return KclError::Lexical(KclErrorDetails { source_ranges, message }).into();
|
||||
}
|
||||
|
||||
// Important, to not call this before the unknown tokens check.
|
||||
if tokens.is_empty() {
|
||||
// Empty file should just do nothing.
|
||||
return Node::<Program>::default().into();
|
||||
}
|
||||
|
||||
// Check all the tokens are whitespace or comments.
|
||||
if tokens
|
||||
.iter()
|
||||
.all(|t| t.token_type.is_whitespace() || t.token_type.is_comment())
|
||||
{
|
||||
return Node::<Program>::default().into();
|
||||
}
|
||||
|
||||
parser::run_parser(tokens.as_slice())
|
||||
}
|
||||
|
||||
/// Result of parsing.
|
||||
///
|
||||
/// Will be a KclError if there was a lexing error or some unexpected error during parsing.
|
||||
/// TODO - lexing errors should be included with the parse errors.
|
||||
/// Will be Ok otherwise, including if there were parsing errors. Any errors or warnings will
|
||||
/// be in the ParseContext. If an AST was produced, then that will be in the Option.
|
||||
///
|
||||
/// Invariants:
|
||||
/// - if there are no errors, then the Option will be Some
|
||||
/// - if the Option is None, then there will be at least one error in the ParseContext.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct ParseResult(pub Result<(Option<Node<Program>>, Vec<CompilationError>), KclError>);
|
||||
|
||||
impl ParseResult {
|
||||
#[cfg(test)]
|
||||
#[track_caller]
|
||||
pub fn unwrap(self) -> Node<Program> {
|
||||
if self.0.is_err() || self.0.as_ref().unwrap().0.is_none() {
|
||||
eprint!("{self:#?}");
|
||||
}
|
||||
self.0.unwrap().0.unwrap()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn is_ok(&self) -> bool {
|
||||
match &self.0 {
|
||||
Ok((p, errs)) => p.is_some() && !errs.iter().any(|e| e.severity.is_err()),
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[track_caller]
|
||||
pub fn unwrap_errs(&self) -> impl Iterator<Item = &CompilationError> {
|
||||
self.0.as_ref().unwrap().1.iter().filter(|e| e.severity.is_err())
|
||||
}
|
||||
|
||||
/// Treat parsing errors as an Error.
|
||||
pub fn parse_errs_as_err(self) -> Result<Node<Program>, KclError> {
|
||||
let (p, errs) = self.0?;
|
||||
|
||||
if let Some(err) = errs.iter().find(|e| e.severity.is_err()) {
|
||||
return Err(KclError::Syntax(err.clone().into()));
|
||||
}
|
||||
match p {
|
||||
Some(p) => Ok(p),
|
||||
None => Err(KclError::internal("Unknown parsing error".to_owned())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Result<(Option<Node<Program>>, Vec<CompilationError>), KclError>> for ParseResult {
|
||||
fn from(r: Result<(Option<Node<Program>>, Vec<CompilationError>), KclError>) -> ParseResult {
|
||||
ParseResult(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(Option<Node<Program>>, Vec<CompilationError>)> for ParseResult {
|
||||
fn from(p: (Option<Node<Program>>, Vec<CompilationError>)) -> ParseResult {
|
||||
ParseResult(Ok(p))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Node<Program>> for ParseResult {
|
||||
fn from(p: Node<Program>) -> ParseResult {
|
||||
ParseResult(Ok((Some(p), vec![])))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KclError> for ParseResult {
|
||||
fn from(e: KclError) -> ParseResult {
|
||||
ParseResult(Err(e))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
macro_rules! parse_and_lex {
|
||||
($func_name:ident, $test_kcl_program:expr) => {
|
||||
#[test]
|
||||
fn $func_name() {
|
||||
let _ = crate::parsing::top_level_parse($test_kcl_program);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
parse_and_lex!(crash_eof_1, "{\"ގގ\0\0\0\"\".");
|
||||
parse_and_lex!(crash_eof_2, "(/=e\"\u{616}ݝ\"\"");
|
||||
}
|
Reference in New Issue
Block a user