microcad_lang/parse/
workbench.rs1use crate::{find_rule, find_rule_exact, parse::*, parser::*, rc::*, syntax::*};
5
6impl Parse for Refer<WorkbenchKind> {
7 fn parse(pair: Pair) -> ParseResult<Self> {
8 match pair.as_str() {
9 "part" => Ok(Refer::new(WorkbenchKind::Part, pair.into())),
10 "sketch" => Ok(Refer::new(WorkbenchKind::Sketch, pair.into())),
11 "op" => Ok(Refer::new(WorkbenchKind::Operation, pair.into())),
12 _ => Err(ParseError::UnexpectedToken),
13 }
14 }
15}
16
17impl Parse for Rc<WorkbenchDefinition> {
18 fn parse(pair: Pair) -> ParseResult<Self> {
19 Ok(WorkbenchDefinition {
20 doc: find_rule!(pair, doc_block)?,
21 visibility: find_rule!(pair, visibility)?,
22 attribute_list: find_rule!(pair, attribute_list)?,
23 kind: find_rule_exact!(pair, workbench_kind)?,
24 id: find_rule!(pair, identifier)?,
25 plan: find_rule!(pair, parameter_list)?,
26 body: {
27 let body = crate::find_rule!(pair, body)?;
28 check_statements(&body)?;
29 body
30 },
31 src_ref: pair.into(),
32 }
33 .into())
34 }
35}
36
37fn check_statements(body: &Body) -> ParseResult<()> {
38 if let (Some(first_init), Some(last_init)) = (
39 body.iter()
40 .position(|stmt| matches!(stmt, Statement::Init(_))),
41 body.iter()
42 .rposition(|stmt| matches!(stmt, Statement::Init(_))),
43 ) {
44 for (n, stmt) in body.iter().enumerate() {
45 match stmt {
46 Statement::Init(_) => (),
48
49 Statement::Module(_) | Statement::Workbench(_) | Statement::Return(_) => {
51 return Err(ParseError::IllegalWorkbenchStatement(stmt.src_ref()));
52 }
53
54 Statement::Use(_) => {
56 if n > first_init && n < last_init {
57 return Err(ParseError::CodeBetweenInitializers(stmt.src_ref()));
58 }
59 }
60
61 Statement::Assignment(a_stmt) => match a_stmt.assignment.qualifier {
63 Qualifier::Const => {
64 return Err(ParseError::IllegalWorkbenchStatement(stmt.src_ref()))
65 }
66 Qualifier::Value => {
67 if n > first_init {
68 return Err(ParseError::CodeBetweenInitializers(a_stmt.src_ref()));
69 }
70 }
71 Qualifier::Prop => {
72 if n < last_init {
73 if n > first_init {
74 return Err(ParseError::CodeBetweenInitializers(a_stmt.src_ref()));
75 }
76 return Err(ParseError::StatementNotAllowedPriorInitializers(
77 a_stmt.src_ref(),
78 ));
79 }
80 }
81 },
82
83 Statement::If(_)
85 | Statement::InnerAttribute(_)
86 | Statement::Expression(_)
87 | Statement::Function(_) => {
88 if n < last_init {
90 if n > first_init {
91 return Err(ParseError::CodeBetweenInitializers(stmt.src_ref()));
92 }
93 return Err(ParseError::StatementNotAllowedPriorInitializers(
94 stmt.src_ref(),
95 ));
96 }
97 }
98 }
99 }
100 }
101 Ok(())
102}