blueprint_engine_parser/
lib.rs1use blueprint_engine_core::{BlueprintError, Result, SourceLocation, Span};
2use blueprint_starlark_syntax::codemap::CodeMap;
3use blueprint_starlark_syntax::dialect::{Dialect, DialectTypes};
4use blueprint_starlark_syntax::syntax::module::AstModuleFields;
5use blueprint_starlark_syntax::syntax::AstModule;
6
7pub use blueprint_starlark_syntax::syntax::ast::{
8 AssignOp, AssignTarget, AssignTargetP, AstArgument, AstExpr, AstLiteral, AstParameter,
9 AstPayload, AstStmt, Clause, Expr, ExprP, ForClause, Parameter, ParameterP, Stmt, StmtP,
10};
11pub use blueprint_starlark_syntax::syntax::def::{DefParam, DefParams};
12
13pub struct ParsedModule {
14 pub codemap: CodeMap,
15 pub statement: AstStmt,
16}
17
18impl ParsedModule {
19 pub fn statements(&self) -> &AstStmt {
20 &self.statement
21 }
22}
23
24pub fn parse(filename: &str, content: &str) -> Result<ParsedModule> {
25 let dialect = Dialect {
26 enable_f_strings: true,
27 enable_lambda: true,
28 enable_keyword_only_arguments: true,
29 enable_top_level_stmt: true,
30 enable_types: DialectTypes::Enable,
31 ..Dialect::Standard
32 };
33
34 match AstModule::parse(filename, content.to_owned(), &dialect) {
35 Ok(module) => {
36 let (codemap, statement, _dialect, _) = module.into_parts();
37 Ok(ParsedModule { codemap, statement })
38 }
39 Err(e) => {
40 let location = SourceLocation {
41 file: Some(filename.to_string()),
42 line: 1,
43 column: 1,
44 span: None,
45 };
46 Err(BlueprintError::ParseError {
47 location,
48 message: e.to_string(),
49 })
50 }
51 }
52}
53
54pub fn get_location(
55 codemap: &CodeMap,
56 span: blueprint_starlark_syntax::codemap::Span,
57) -> SourceLocation {
58 let file_span = codemap.file_span(span);
59 let loc = file_span.resolve();
60 SourceLocation {
61 file: Some(loc.file.clone()),
62 line: loc.span.begin.line + 1,
63 column: loc.span.begin.column + 1,
64 span: Some(Span {
65 start: span.begin().get() as usize,
66 end: span.end().get() as usize,
67 }),
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn test_parse_simple() {
77 let result = parse("test.star", "x = 1 + 2");
78 assert!(result.is_ok());
79 }
80
81 #[test]
82 fn test_parse_function() {
83 let code = r#"
84def hello(name):
85 print("Hello, " + name)
86"#;
87 let result = parse("test.star", code);
88 assert!(result.is_ok());
89 }
90
91 #[test]
92 fn test_parse_lambda() {
93 let result = parse("test.star", "f = lambda x: x * 2");
94 assert!(result.is_ok());
95 }
96
97 #[test]
98 fn test_parse_error() {
99 let result = parse("test.star", "x = ");
100 assert!(result.is_err());
101 }
102}