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