mxmlextrema_as3parser/parser/
context.rs

1use crate::ns::*;
2
3/// Context used to control the parsing of an expression.
4#[derive(Clone)]
5pub struct ParserExpressionContext {
6    pub min_precedence: OperatorPrecedence,
7    pub allow_in: bool,
8    pub allow_assignment: bool,
9}
10
11impl Default for ParserExpressionContext {
12    fn default() -> Self {
13        Self {
14            min_precedence: OperatorPrecedence::List,
15            allow_in: true,
16            allow_assignment: true,
17        }
18    }
19}
20
21#[derive(Clone)]
22pub enum ParserDirectiveContext {
23    Default,
24    TopLevel,
25    PackageBlock,
26    ClassBlock {
27        name: String,
28    },
29    InterfaceBlock,
30    EnumBlock,
31    ConstructorBlock {
32        super_statement_found: Rc<Cell<bool>>,
33    },
34    WithControl {
35        super_statement_found: Option<Rc<Cell<bool>>>,
36        to_be_labeled: Option<String>,
37        control_context: ParserControlFlowContext,
38        labels: HashMap<String, ParserControlFlowContext>,
39    },
40}
41
42impl ParserDirectiveContext {
43    pub fn may_contain_super_statement(&self) -> bool {
44        matches!(self, Self::ConstructorBlock { .. }) || matches!(self, Self::WithControl { .. })
45    }
46
47    pub fn super_statement_found(&self) -> bool {
48        match self {
49            Self::ConstructorBlock { super_statement_found } => super_statement_found.get(),
50            Self::WithControl { super_statement_found, .. } => super_statement_found.as_ref().or(Some(&Rc::new(Cell::new(false)))).unwrap().get(),
51            _ => false,
52        }
53    }
54
55    pub fn set_super_statement_found(&self, value: bool) {
56        match self {
57            Self::ConstructorBlock { super_statement_found } => { super_statement_found.set(value) },
58            Self::WithControl { super_statement_found, .. } => {
59                if let Some(found) = super_statement_found.as_ref() {
60                    found.set(value);
61                }
62            },
63            _ => {},
64        }
65    }
66
67    pub fn function_name_is_constructor(&self, name: &(String, Location)) -> bool {
68        if let ParserDirectiveContext::ClassBlock { name: ref name_1 } = self {
69            &name.0 == name_1
70        } else {
71            false
72        }
73    }
74
75    pub fn is_top_level_or_package(&self) -> bool {
76        matches!(self, ParserDirectiveContext::TopLevel) || matches!(self, ParserDirectiveContext::PackageBlock)
77    }
78
79    pub fn is_type_block(&self) -> bool {
80        match self {
81            Self::ClassBlock { .. } |
82            Self::InterfaceBlock |
83            Self::EnumBlock => true,
84            _ => false,
85        }
86    }
87
88    pub fn clone_control(&self) -> Self {
89        match self {
90            Self::WithControl { .. } => self.clone(),
91            _ => Self::Default,
92        }
93    }
94
95    pub fn override_control_context(&self, label_only: bool, mut context: ParserControlFlowContext) -> Self {
96        let mut prev_context = None;
97        let mut label = None;
98        let mut super_statement_found: Option<Rc<Cell<bool>>> = None;
99        let mut labels = match self {
100            Self::WithControl { control_context, labels, to_be_labeled: label1, super_statement_found: super_found_1 } => {
101                prev_context = Some(control_context.clone());
102                label = label1.clone();
103                super_statement_found = super_found_1.clone();
104                labels.clone()
105            },
106            _ => HashMap::new(),
107        };
108        if let Some(label) = label.clone() {
109            labels.insert(label, context.clone());
110        }
111        if label_only {
112            context = prev_context.unwrap_or(ParserControlFlowContext {
113                breakable: false,
114                iteration: false,
115            });
116        }
117        Self::WithControl { control_context: context, labels, to_be_labeled: None, super_statement_found }
118    }
119
120    pub fn put_label(&self, label: String) -> Self {
121        match self {
122            Self::WithControl { control_context, labels, to_be_labeled: _, super_statement_found } => Self::WithControl {
123                to_be_labeled: Some(label),
124                control_context: control_context.clone(),
125                labels: labels.clone(),
126                super_statement_found: super_statement_found.clone(),
127            },
128            _ => Self::WithControl {
129                to_be_labeled: Some(label),
130                control_context: ParserControlFlowContext {
131                    breakable: false,
132                    iteration: false,
133                },
134                labels: HashMap::new(),
135                super_statement_found: match self {
136                    Self::ConstructorBlock { super_statement_found } => Some(super_statement_found.clone()),
137                    _ => None,
138                },
139            },
140        }
141    }
142
143    pub fn is_label_defined(&self, label: String) -> bool {
144        self.resolve_label(label).is_some()
145    }
146
147    pub fn resolve_label(&self, label: String) -> Option<ParserControlFlowContext> {
148        if let Self::WithControl { labels, .. } = &self { labels.get(&label).map(|c| c.clone()) } else { None }
149    }
150
151    pub fn is_break_allowed(&self, label: Option<String>) -> bool {
152        if let Some(label) = label {
153            let context = self.resolve_label(label);
154            if let Some(context) = context { context.breakable } else { false }
155        } else {
156            if let Self::WithControl { control_context, .. } = &self { control_context.breakable } else { false }
157        }
158    }
159
160    pub fn is_continue_allowed(&self, label: Option<String>) -> bool {
161        if let Some(label) = label {
162            let context = self.resolve_label(label);
163            if let Some(context) = context { context.iteration } else { false }
164        } else {
165            if let Self::WithControl { control_context, .. } = &self { control_context.iteration } else { false }
166        }
167    }
168}
169
170#[derive(Clone)]
171pub struct ParserControlFlowContext {
172    pub breakable: bool,
173    pub iteration: bool,
174}