@@ -17,6 +17,7 @@ use regex::Regex;
1717use phf:: phf_set;
1818
1919const IMPLICIT_FUNCTION_NAME : & str = "apply-function" ;
20+
2021pub fn infer_intent < ' r , ' c , ' s : ' c , ' m : ' c > ( rules_with_context : & ' r mut SpeechRulesWithContext < ' c , ' s , ' m > , mathml : Element < ' c > ) -> Result < Element < ' m > > {
2122 match catch_errors_building_intent ( rules_with_context, mathml) {
2223 Ok ( intent) => return Ok ( intent) ,
@@ -47,7 +48,8 @@ pub fn infer_intent<'r, 'c, 's:'c, 'm:'c>(rules_with_context: &'r mut SpeechRule
4748 if let Some ( intent_str) = mathml. attribute_value ( INTENT_ATTR ) {
4849 // debug!("Before intent: {}", crate::pretty_print::mml_to_string(mathml));
4950 let mut lex_state = LexState :: init ( intent_str. trim ( ) ) ?;
50- let result = build_intent ( rules_with_context, & mut lex_state, mathml)
51+ let mut intent_offset = 0 ;
52+ let result = build_intent ( rules_with_context, & mut lex_state, mathml, & mut intent_offset)
5153 . with_context ( || format ! ( "occurs before '{}' in intent attribute value '{}'" , lex_state. remaining_str, intent_str) ) ?;
5254 if lex_state. token != Token :: None {
5355 bail ! ( "Error in intent value: extra unparsed intent '{}' in intent attribute value '{}'" , lex_state. remaining_str, intent_str) ;
@@ -183,7 +185,7 @@ pub fn add_fixity_children(intent: Element) -> Element {
183185 fn create_operator_element < ' a > ( intent_name : & str , fixity : & str , id : & str , id_inc : usize , doc : & Document < ' a > ) -> ChildOfElement < ' a > {
184186 let intent_name = intent_speech_for_name ( intent_name, & PreferenceManager :: get ( ) . borrow ( ) . pref_to_string ( "NavMode" ) , fixity) ;
185187 let element = create_mathml_element ( doc, & intent_name) ;
186- element. set_attribute_value ( "id" , & format ! ( "{id}-{id_inc}" ) ) ;
188+ element. set_attribute_value ( "id" , & format ! ( "{id}-fixity- {id_inc}" ) ) ;
187189 element. set_attribute_value ( MATHML_FROM_NAME_ATTR , "mo" ) ;
188190 return ChildOfElement :: Element ( element) ;
189191 }
@@ -368,7 +370,8 @@ impl<'i> LexState<'i> {
368370
369371fn build_intent < ' b , ' r , ' c , ' s : ' c , ' m : ' c > ( rules_with_context : & ' r mut SpeechRulesWithContext < ' c , ' s , ' m > ,
370372 lex_state : & mut LexState < ' b > ,
371- mathml : Element < ' c > ) -> Result < Element < ' m > > {
373+ mathml : Element < ' c > ,
374+ intent_offset : & mut u32 ) -> Result < Element < ' m > > {
372375 // intent := self-property-list | expression
373376 // self-property-list := property+ S
374377 // expression := S ( term property* | application ) S
@@ -384,7 +387,7 @@ fn build_intent<'b, 'r, 'c, 's:'c, 'm:'c>(rules_with_context: &'r mut SpeechRule
384387 // debug!(" start build_intent: state: {}", lex_state);
385388 let doc = rules_with_context. get_document ( ) ;
386389 let mut intent;
387- // debug!(" build_intent: start mathml name={}", name(mathml));
390+ debug ! ( " build_intent: start mathml name={}, intent_offset={} " , name( mathml) , intent_offset ) ;
388391 match lex_state. token {
389392 Token :: Property ( _) => {
390393 // We only have a property -- we want to keep this tag/element
@@ -419,7 +422,8 @@ fn build_intent<'b, 'r, 'c, 's:'c, 'm:'c>(rules_with_context: &'r mut SpeechRule
419422 if word == mathml. attribute_value ( INTENT_ATTR ) . unwrap_or_default ( ) { name ( mathml) } else { leaf_name} ) ;
420423 intent. set_text ( word) ; // '-' and '_' get removed by the rules.
421424 if let Some ( id) = mathml. attribute_value ( "id" ) {
422- intent. set_attribute_value ( "id" , id) ;
425+ intent. set_attribute_value ( "id" , & format ! ( "{}-literal-{}" , id, intent_offset) ) ;
426+ * intent_offset += 1 ;
423427 }
424428 lex_state. get_next ( ) ?;
425429 if let Token :: Property ( _) = lex_state. token {
@@ -428,7 +432,7 @@ fn build_intent<'b, 'r, 'c, 's:'c, 'm:'c>(rules_with_context: &'r mut SpeechRule
428432 }
429433 } ,
430434 Token :: ArgRef ( word) => {
431- intent = match find_arg ( rules_with_context, & word[ 1 ..] , mathml, true , false ) ? {
435+ intent = match find_arg ( rules_with_context, & word[ 1 ..] , mathml, intent_offset , true , false ) ? {
432436 Some ( e) => {
433437 lex_state. get_next ( ) ?;
434438 e
@@ -443,7 +447,7 @@ fn build_intent<'b, 'r, 'c, 's:'c, 'm:'c>(rules_with_context: &'r mut SpeechRule
443447 _ => bail ! ( "Illegal 'intent' syntax: found {}" , lex_state. token) ,
444448 } ;
445449 if lex_state. is_terminal ( "(" ) {
446- intent = build_function ( intent, rules_with_context, lex_state, mathml) ?;
450+ intent = build_function ( intent, rules_with_context, lex_state, mathml, intent_offset ) ?;
447451 }
448452 // debug!(" end build_intent: state: {} piece: {}", lex_state, mml_to_string(intent));
449453 add_fixity ( intent) ;
@@ -482,7 +486,8 @@ fn build_function<'b, 'r, 'c, 's:'c, 'm:'c>(
482486 function_name : Element < ' m > ,
483487 rules_with_context : & ' r mut SpeechRulesWithContext < ' c , ' s , ' m > ,
484488 lex_state : & mut LexState < ' b > ,
485- mathml : Element < ' c > ) -> Result < Element < ' m > > {
489+ mathml : Element < ' c > ,
490+ intent_offset : & mut u32 ) -> Result < Element < ' m > > {
486491 // debug!(" start build_function: name: {}, state: {}", name(function_name), lex_state);
487492 // application := intent '(' arguments? S ')' where 'function_name' is 'intent'
488493 assert ! ( lex_state. is_terminal( "(" ) ) ;
@@ -494,7 +499,7 @@ fn build_function<'b, 'r, 'c, 's:'c, 'm:'c>(
494499 // grammar requires at least one argument
495500 bail ! ( "Illegal 'intent' syntax: missing argument for intent name '{}'" , name( function_name) ) ;
496501 }
497- let children = build_arguments ( rules_with_context, lex_state, mathml) ?;
502+ let children = build_arguments ( rules_with_context, lex_state, mathml, intent_offset ) ?;
498503 function = lift_function_name ( rules_with_context. get_document ( ) , function, children) ;
499504
500505 if !lex_state. is_terminal ( ")" ) {
@@ -514,18 +519,19 @@ fn build_function<'b, 'r, 'c, 's:'c, 'm:'c>(
514519fn build_arguments < ' b , ' r , ' c , ' s : ' c , ' m : ' c > (
515520 rules_with_context : & ' r mut SpeechRulesWithContext < ' c , ' s , ' m > ,
516521 lex_state : & mut LexState < ' b > ,
517- mathml : Element < ' c > ) -> Result < Vec < Element < ' m > > > {
522+ mathml : Element < ' c > ,
523+ intent_offset : & mut u32 ) -> Result < Vec < Element < ' m > > > {
518524 // arguments := intent ( ',' intent )*'
519525 // debug!(" start build_args state: {}", lex_state);
520526
521527 // there is at least one arg
522528 let mut children = Vec :: with_capacity ( lex_state. remaining_str . len ( ) /3 + 1 ) ; // conservative estimate ('3' - "$x,");
523- children. push ( build_intent ( rules_with_context, lex_state, mathml) ? ) ; // arg before ','
529+ children. push ( build_intent ( rules_with_context, lex_state, mathml, intent_offset ) ? ) ; // arg before ','
524530 // debug!(" build_args: # children {}; state: {}", children.len(), lex_state);
525531
526532 while lex_state. is_terminal ( "," ) {
527533 lex_state. get_next ( ) ?;
528- children. push ( build_intent ( rules_with_context, lex_state, mathml) ? ) ; // arg before ','
534+ children. push ( build_intent ( rules_with_context, lex_state, mathml, intent_offset ) ? ) ; // arg before ','
529535 // debug!(" build_args, # children {}; state: {}", children.len(), lex_state);
530536 }
531537
@@ -566,7 +572,13 @@ fn lift_function_name<'m>(doc: Document<'m>, function_name: Element<'m>, childre
566572
567573/// look for @arg=name in mathml
568574/// if 'check_intent', then look at an @intent for this element (typically false for non-recursive calls)
569- fn find_arg < ' r , ' c , ' s : ' c , ' m : ' c > ( rules_with_context : & ' r mut SpeechRulesWithContext < ' c , ' s , ' m > , name : & str , mathml : Element < ' c > , skip_self : bool , no_check_inside : bool ) -> Result < Option < Element < ' m > > > {
575+ fn find_arg < ' r , ' c , ' s : ' c , ' m : ' c > (
576+ rules_with_context : & ' r mut SpeechRulesWithContext < ' c , ' s , ' m > ,
577+ name : & str ,
578+ mathml : Element < ' c > ,
579+ intent_offset : & mut u32 ,
580+ skip_self : bool ,
581+ no_check_inside : bool ) -> Result < Option < Element < ' m > > > {
570582 // debug!("Looking for '{}' in\n{}", name, mml_to_string(mathml));
571583 if !skip_self {
572584 if let Some ( arg_val) = mathml. attribute_value ( "arg" ) {
@@ -575,7 +587,7 @@ fn find_arg<'r, 'c, 's:'c, 'm:'c>(rules_with_context: &'r mut SpeechRulesWithCon
575587 // check to see if this mathml has an intent value -- if so the value is the value of its intent value
576588 if let Some ( intent_str) = mathml. attribute_value ( INTENT_ATTR ) {
577589 let mut lex_state = LexState :: init ( intent_str. trim ( ) ) ?;
578- return Ok ( Some ( build_intent ( rules_with_context, & mut lex_state, mathml) ? ) ) ;
590+ return Ok ( Some ( build_intent ( rules_with_context, & mut lex_state, mathml, intent_offset ) ? ) ) ;
579591 } else {
580592 return Ok ( Some ( rules_with_context. match_pattern :: < Element < ' m > > ( mathml) ? ) ) ;
581593 }
@@ -595,7 +607,7 @@ fn find_arg<'r, 'c, 's:'c, 'm:'c>(rules_with_context: &'r mut SpeechRulesWithCon
595607
596608 for child in mathml. children ( ) {
597609 let child = as_element ( child) ;
598- if let Some ( element) = find_arg ( rules_with_context, name, child, false , true ) ? {
610+ if let Some ( element) = find_arg ( rules_with_context, name, child, intent_offset , false , true ) ? {
599611 return Ok ( Some ( element) ) ;
600612 }
601613 }
0 commit comments