(rules_with_context: &'r mut SpeechRulesWithContext<'c,'s,'m>,
lex_state: &mut LexState<'b>,
mathml: Element<'c>)
| 201 | } |
| 202 | |
| 203 | fn build_intent<'b, 'r, 'c, 's:'c, 'm:'c>(rules_with_context: &'r mut SpeechRulesWithContext<'c,'s,'m>, |
| 204 | lex_state: &mut LexState<'b>, |
| 205 | mathml: Element<'c>) -> Result<Element<'m>> { |
| 206 | // intent := self-property-list | expression |
| 207 | // self-property-list := property+ S |
| 208 | // expression := S ( term property* | application ) S |
| 209 | // term := concept-or-literal | number | reference |
| 210 | // concept-or-literal := NCName |
| 211 | // number := '-'? \d+ ( '.' \d+ )? |
| 212 | // reference := '$' NCName |
| 213 | // application := expression '(' arguments? S ')' |
| 214 | // |
| 215 | // When we flatten intent we have this implementation looking for Tokens or '(' [for application] |
| 216 | // Essentially, the grammar we deal with here is: |
| 217 | // intent := property+ | (concept-or-literal | number | reference) property* '('? |
| 218 | // debug!(" start build_intent: state: {}", lex_state); |
| 219 | let doc = rules_with_context.get_document(); |
| 220 | let mut intent; |
| 221 | match lex_state.token { |
| 222 | Token::Property(_) => { |
| 223 | // We only have a property -- we want to keep this tag/element |
| 224 | // There are two paths: |
| 225 | // 1. If there is a function call, then the children are dealt with there |
| 226 | // 2. If there is *no* function call, then the children are kept, which means we return to pattern matching |
| 227 | // Note: to avoid infinite loop, we need to remove the 'intent' so we don't end up back here; we put it back later |
| 228 | let properties = get_properties(lex_state)?; // advance state to see if funcall |
| 229 | if lex_state.is_terminal("(") { |
| 230 | intent = create_mathml_element(&doc, name(&mathml)); |
| 231 | intent.set_attribute_value(INTENT_PROPERTY, &properties); |
| 232 | } else { |
| 233 | let saved_intent = mathml.attribute_value("intent").unwrap(); |
| 234 | mathml.remove_attribute("intent"); |
| 235 | mathml.set_attribute_value(INTENT_PROPERTY, &properties); // needs to be set before the pattern match |
| 236 | intent = rules_with_context.match_pattern::<Element<'m>>(mathml)?; |
| 237 | mathml.set_attribute_value("intent", saved_intent); |
| 238 | } |
| 239 | return Ok(intent); // if we start with properties, then there can only be properties |
| 240 | }, |
| 241 | Token::ConceptOrLiteral(word) | Token::Number(word) => { |
| 242 | let leaf_name = if let Token::Number(_) = lex_state.token {"mn"} else {"mi"}; |
| 243 | intent = create_mathml_element(&doc, leaf_name); |
| 244 | intent.set_text(word); // '-' and '_' get removed by the rules. |
| 245 | lex_state.get_next()?; |
| 246 | if let Token::Property(_) = lex_state.token { |
| 247 | let properties = get_properties(lex_state)?; |
| 248 | intent.set_attribute_value(INTENT_PROPERTY, &properties); |
| 249 | } |
| 250 | }, |
| 251 | Token::ArgRef(word) => { |
| 252 | intent = match find_arg(rules_with_context, &word[1..], mathml, true, false)? { |
| 253 | Some(e) => { |
| 254 | lex_state.get_next()?; |
| 255 | e |
| 256 | }, |
| 257 | None => bail!("intent arg '{}' not found", word), |
| 258 | }; |
| 259 | if let Token::Property(_) = lex_state.token { |
| 260 | let properties = get_properties(lex_state)?; |
no test coverage detected