@@ -1629,7 +1629,7 @@ object Parser {
16291629 case str if Impl .matchesString(str) => str.asInstanceOf [Parser0 [String ]]
16301630 case _ =>
16311631 Impl .unmap0(pa) match {
1632- case Impl .Pure (_) | Impl .Index => emptyStringParser0
1632+ case Impl .Pure (_) | Impl .Index | Impl . GetCaret => emptyStringParser0
16331633 case notEmpty => Impl .StringP0 (notEmpty)
16341634 }
16351635 }
@@ -1683,6 +1683,11 @@ object Parser {
16831683 */
16841684 def index : Parser0 [Int ] = Impl .Index
16851685
1686+ /** return the current Caret (offset, line, column) this is a bit more expensive that just the
1687+ * index
1688+ */
1689+ def caret : Parser0 [Caret ] = Impl .GetCaret
1690+
16861691 /** succeeds when we are at the start
16871692 */
16881693 def start : Parser0 [Unit ] = Impl .StartParser
@@ -1717,7 +1722,7 @@ object Parser {
17171722 case p1 : Parser [_] => as(p1, b)
17181723 case _ =>
17191724 Impl .unmap0(pa) match {
1720- case Impl .Pure (_) | Impl .Index => pure(b)
1725+ case Impl .Pure (_) | Impl .Index | Impl . GetCaret => pure(b)
17211726 case notPure =>
17221727 Impl .Void0 (notPure).map(Impl .ConstFn (b))
17231728 }
@@ -1837,6 +1842,10 @@ object Parser {
18371842 var offset : Int = 0
18381843 var error : Eval [Chain [Expectation ]] = null
18391844 var capture : Boolean = true
1845+
1846+ // This is lazy because we don't want to trigger it
1847+ // unless someone uses GetCaret
1848+ lazy val locationMap : LocationMap = LocationMap (str)
18401849 }
18411850
18421851 // invariant: input must be sorted
@@ -1885,8 +1894,9 @@ object Parser {
18851894 final def doesBacktrack (p : Parser0 [Any ]): Boolean =
18861895 p match {
18871896 case Backtrack0 (_) | Backtrack (_) | AnyChar | CharIn (_, _, _) | Str (_) | IgnoreCase (_) |
1888- Length (_) | StartParser | EndParser | Index | Pure (_) | Fail () | FailWith (_) | Not (_) |
1889- StringIn (_) =>
1897+ Length (_) | StartParser | EndParser | Index | GetCaret | Pure (_) | Fail () | FailWith (
1898+ _
1899+ ) | Not (_) | StringIn (_) =>
18901900 true
18911901 case Map0 (p, _) => doesBacktrack(p)
18921902 case Map (p, _) => doesBacktrack(p)
@@ -1916,7 +1926,7 @@ object Parser {
19161926 // and by construction, a oneOf0 never always succeeds
19171927 final def alwaysSucceeds (p : Parser0 [Any ]): Boolean =
19181928 p match {
1919- case Index | Pure (_) => true
1929+ case Index | GetCaret | Pure (_) => true
19201930 case Map0 (p, _) => alwaysSucceeds(p)
19211931 case SoftProd0 (a, b) => alwaysSucceeds(a) && alwaysSucceeds(b)
19221932 case Prod0 (a, b) => alwaysSucceeds(a) && alwaysSucceeds(b)
@@ -1934,7 +1944,7 @@ object Parser {
19341944 def unmap0 (pa : Parser0 [Any ]): Parser0 [Any ] =
19351945 pa match {
19361946 case p1 : Parser [Any ] => unmap(p1)
1937- case Pure (_) | Index => Parser .unit
1947+ case GetCaret | Index | Pure (_) => Parser .unit
19381948 case s if alwaysSucceeds(s) => Parser .unit
19391949 case Map0 (p, _) =>
19401950 // we discard any allocations done by fn
@@ -2172,6 +2182,12 @@ object Parser {
21722182 override def parseMut (state : State ): Int = state.offset
21732183 }
21742184
2185+ case object GetCaret extends Parser0 [Caret ] {
2186+ override def parseMut (state : State ): Caret =
2187+ // This unsafe call is safe because the offset can never go too far
2188+ state.locationMap.toCaretUnsafe(state.offset)
2189+ }
2190+
21752191 final def backtrack [A ](pa : Parser0 [A ], state : State ): A = {
21762192 val offset = state.offset
21772193 val a = pa.parseMut(state)
0 commit comments