@@ -164,21 +164,35 @@ export
164164symbol : Lexer
165165symbol = some (pred (\x => not (isAlphaNum x) && not (isSpace x)))
166166
167−strChar : Lexer
168−strChar = (is '\\' <+> any) <|> isNot '"'
167+||| Recognise zero or more occurrences of a sub-lexer between
168+||| delimiting lexers
169+export
170+surround : (start : Lexer) -> (end : Lexer) -> (l : Lexer) -> Lexer
171+surround start end l = start <+> manyTill l end
172+
173+||| Recognise zero or more occurrences of a sub-lexer surrounded
174+||| by the same quote lexer on both sides (useful for strings)
175+export
176+quote : (q : Lexer) -> (l : Lexer) -> Lexer
177+quote q l = surround q q l
178+
179+||| Recognise an escape character (often '\\') followed by a sub-lexer
180+export
181+escape : (esc : Char) -> Lexer -> Lexer
182+escape esc l = is esc <+> l
169183
170184||| Recognise a string literal, including escaped characters.
171185||| (Note: doesn't yet handle escape sequences such as \123)
172186export
173187stringLit : Lexer
174−stringLit = is '"' <+> many strChar <+> is '"'
188+stringLit = quote (is '"') (escape '\\' any <|> any)
175189
176190||| Recognise a character literal, including escaped characters.
177191||| (Note: doesn't yet handle escape sequences such as \123)
178192export
179193charLit : Lexer
180194charLit = let q = '\'' in
181− is q <+> ((is '\\' <+> any) <|> isNot q) <+> is q
195+ is q <+> (escape '\\' any <|> isNot q) <+> is q
182196
183197||| Recognise an integer literal (possibly with a '-' prefix)
184198export