regen/dynamic/
dyn_node.rs1use super::{DynTok, DynToken};
2use crate::core::{Language, ParamDataType, ParamDecorType, RuleValue};
3use crate::sdk::{TokenBlocks, TokenStream};
4use crate::{list, optional, required};
5
6pub enum DynAstNode {
8 Exterior(DynToken),
12 Interior(String , Vec<DynAstNode>),
16 InteriorVec(String , Vec<DynAstNode>),
20}
21
22macro_rules! impl_dyn_ast_parse_param {
23 ($param:ident, $ts:ident, $children:ident, $parse_expr:expr) => {
24 match &$param.param_type.decor {
25 ParamDecorType::None => $children.push(required!($ts, $parse_expr)?),
26 ParamDecorType::Optional => {
27 if let Some(n) = optional!($ts, $parse_expr) {
28 $children.push(n);
29 }
30 }
31 ParamDecorType::Vec(optional) => {
32 let v = if *optional {
33 let mut v = vec![];
34 list!($ts, v, $parse_expr)
35 } else {
36 let mut v = vec![required!($ts, $parse_expr)?];
37 list!($ts, v, $parse_expr)
38 };
39 $children.push(DynAstNode::InteriorVec($param.type_name.clone(), v))
40 }
41 }
42 };
43}
44
45impl DynAstNode {
46 pub fn parse_rule(
50 ts: &mut TokenStream<DynTok>,
51 lang: &Language,
52 rule_name: &str,
53 ) -> Option<Self> {
54 let rule = lang.rules.get(rule_name).unwrap();
55 match &rule.value {
56 RuleValue::Union(rules) => {
57 if !ts.push() {
58 return None;
59 };
60 for rule in rules {
61 let n = Self::parse_rule(ts, lang, rule);
62 if n.is_some() {
63 ts.pop();
64 return n;
65 }
66 ts.restore();
67 }
68 ts.pop();
69 None
70 }
71 RuleValue::Function(params) => {
72 let mut children = Vec::new();
73 for param in params {
74 let type_name = ¶m.type_name;
75
76 match ¶m.param_type.data {
77 ParamDataType::Rule => {
78 impl_dyn_ast_parse_param!(
79 param,
80 ts,
81 children,
82 Self::parse_rule(ts, lang, type_name)
83 )
84 }
85 ParamDataType::String => {
86 impl_dyn_ast_parse_param!(
87 param,
88 ts,
89 children,
90 Self::parse_token(ts, type_name)
91 )
92 }
93 ParamDataType::Flag(lit) => impl_dyn_ast_parse_param!(
94 param,
95 ts,
96 children,
97 Self::parse_token_lit(ts, type_name, lit)
98 ),
99 }
100 }
101 Some(DynAstNode::Interior(rule_name.to_string(), children))
102 }
103 }
104 }
105
106 fn parse_token(ts: &mut TokenStream<DynTok>, token_name: &str) -> Option<Self> {
108 let token_type = format!("T{}", token_name);
109 ts.consume()
110 .filter(|token| token.token_type == token_type)
111 .cloned()
112 .map(DynAstNode::Exterior)
113 }
114
115 fn parse_token_lit(
117 ts: &mut TokenStream<DynTok>,
118 token_name: &str,
119 literal: &str,
120 ) -> Option<Self> {
121 let token_type = format!("T{}", token_name);
122 ts.consume()
123 .filter(|token| token.token_type == token_type && token.value == literal)
124 .cloned()
125 .map(DynAstNode::Exterior)
126 }
127
128 pub fn apply_semantic(
130 &self,
131 lang: &Language,
132 tbs: &mut TokenBlocks<DynTok>,
133 ovr: &Option<DynTok>,
134 ) {
135 match self {
136 DynAstNode::Exterior(token) => {
137 if let Some(ovr) = ovr {
138 tbs.set(token, ovr.clone());
139 }
140 }
141 DynAstNode::Interior(rule_name, children)
142 | DynAstNode::InteriorVec(rule_name, children) => {
143 let rule = lang.rules.get(rule_name).unwrap();
144 let params = match &rule.value {
146 RuleValue::Union(_) => panic!("Union rules should not be in dynamic AST"),
147 RuleValue::Function(params) => params,
148 };
149 let semantic_override = params
150 .iter()
151 .map(|param| match ¶m.semantic {
152 None => ovr.clone(),
153 Some(s) => Some(format!("S{}", s)),
154 })
155 .collect::<Vec<_>>();
156
157 for (ovr, child) in semantic_override.iter().zip(children.iter()) {
158 child.apply_semantic(lang, tbs, ovr);
159 }
160 }
161 }
162 }
163}