@@ -212,6 +212,13 @@ enum HirFrame {
212212 /// This sentinel only exists to stop other things (like flattening
213213 /// literals) from reaching across repetition operators.
214214 Repetition ,
215+ /// This is pushed whenever a look-around expression is observed. After
216+ /// visiting the sub-expression in the look-around, the translator's stack
217+ /// is expected to have this sentinel at the top.
218+ ///
219+ /// This sentinel only exists to stop other things (like flattening
220+ /// literals) from reaching across look-around operators.
221+ LookAround ,
215222 /// This is pushed on to the stack upon first seeing any kind of capture,
216223 /// indicated by parentheses (including non-capturing groups). It is popped
217224 /// upon leaving a group.
@@ -298,6 +305,18 @@ impl HirFrame {
298305 }
299306 }
300307
308+ fn unwrap_lookaround ( self ) {
309+ match self {
310+ HirFrame :: LookAround => { }
311+ _ => {
312+ panic ! (
313+ "tried to unwrap look-around from HirFrame, got: {:?}" ,
314+ self
315+ )
316+ }
317+ }
318+ }
319+
301320 /// Assert that the current stack frame is a group indicator and return
302321 /// its corresponding flags (the flags that were active at the time the
303322 /// group was entered).
@@ -363,6 +382,7 @@ impl<'t, 'p> Visitor for TranslatorI<'t, 'p> {
363382 self . push ( HirFrame :: AlternationBranch ) ;
364383 }
365384 }
385+ Ast :: LookAround ( _) => self . push ( HirFrame :: LookAround ) ,
366386 _ => { }
367387 }
368388 Ok ( ( ) )
@@ -448,6 +468,7 @@ impl<'t, 'p> Visitor for TranslatorI<'t, 'p> {
448468 }
449469 Ast :: LookAround ( ref x) => {
450470 let expr = Box :: new ( self . pop ( ) . unwrap ( ) . unwrap_expr ( ) ) ;
471+ self . pop ( ) . unwrap ( ) . unwrap_lookaround ( ) ;
451472 self . push ( HirFrame :: Expr ( Hir :: lookaround ( match x. kind {
452473 ast:: LookAroundKind :: PositiveLookBehind => {
453474 hir:: LookAround :: PositiveLookBehind ( expr)
@@ -770,6 +791,9 @@ impl<'t, 'p> TranslatorI<'t, 'p> {
770791 HirFrame :: AlternationBranch => {
771792 unreachable ! ( "expected expr or concat, got alt branch marker" )
772793 }
794+ HirFrame :: LookAround => {
795+ unreachable ! ( "expected expr or concat, got look-around" )
796+ }
773797 }
774798 }
775799
@@ -801,6 +825,9 @@ impl<'t, 'p> TranslatorI<'t, 'p> {
801825 HirFrame :: AlternationBranch => {
802826 unreachable ! ( "expected expr or alt, got alt branch marker" )
803827 }
828+ HirFrame :: LookAround => {
829+ unreachable ! ( "expected expr or alt, got look-around" )
830+ }
804831 }
805832 }
806833
@@ -1612,6 +1639,15 @@ mod tests {
16121639 Hir :: look ( look)
16131640 }
16141641
1642+ fn hir_lookbehind ( expr : Hir , positive : bool ) -> Hir {
1643+ let lookaround = if positive {
1644+ hir:: LookAround :: PositiveLookBehind ( Box :: new ( expr) )
1645+ } else {
1646+ hir:: LookAround :: NegativeLookBehind ( Box :: new ( expr) )
1647+ } ;
1648+ Hir :: lookaround ( lookaround)
1649+ }
1650+
16151651 #[ test]
16161652 fn empty ( ) {
16171653 assert_eq ! ( t( "" ) , Hir :: empty( ) ) ;
@@ -1835,6 +1871,44 @@ mod tests {
18351871 assert_eq ! ( t( r"(?-u)\B" ) , hir_look( hir:: Look :: WordAsciiNegate ) ) ;
18361872 }
18371873
1874+ #[ test]
1875+ fn lookarounds ( ) {
1876+ assert_eq ! ( t( "(?<=a)" ) , hir_lookbehind( hir_lit( "a" ) , true ) ) ;
1877+ assert_eq ! ( t( "(?<!a)" ) , hir_lookbehind( hir_lit( "a" ) , false ) ) ;
1878+ assert_eq ! ( t( "(?<!)" ) , hir_lookbehind( Hir :: empty( ) , false ) ) ;
1879+ assert_eq ! (
1880+ t( "(?<=a|b)" ) ,
1881+ hir_lookbehind( hir_alt( vec![ hir_lit( "a" ) , hir_lit( "b" ) ] ) , true )
1882+ ) ;
1883+ assert_eq ! (
1884+ t( "(?<=a)|(?<!b)" ) ,
1885+ hir_alt( vec![
1886+ hir_lookbehind( hir_lit( "a" ) , true ) ,
1887+ hir_lookbehind( hir_lit( "b" ) , false )
1888+ ] )
1889+ ) ;
1890+ assert_eq ! (
1891+ t( "(?<=a)(?<!b)" ) ,
1892+ hir_cat( vec![
1893+ hir_lookbehind( hir_lit( "a" ) , true ) ,
1894+ hir_lookbehind( hir_lit( "b" ) , false )
1895+ ] )
1896+ ) ;
1897+ assert_eq ! (
1898+ t( "a(?<=ba(?<!c))" ) ,
1899+ hir_cat( vec![
1900+ hir_lit( "a" ) ,
1901+ hir_lookbehind(
1902+ hir_cat( vec![
1903+ hir_lit( "ba" ) ,
1904+ hir_lookbehind( hir_lit( "c" ) , false )
1905+ ] ) ,
1906+ true
1907+ )
1908+ ] )
1909+ ) ;
1910+ }
1911+
18381912 #[ test]
18391913 fn group ( ) {
18401914 assert_eq ! ( t( "(a)" ) , hir_capture( 1 , hir_lit( "a" ) ) ) ;
0 commit comments