-
Notifications
You must be signed in to change notification settings - Fork 200
Square lenses
Square lenses let you manage symmetric patterns in files, such as XML/SGML syntax, or quoting string (double vs simple).
Square lenses are built using the square
operator with three parameters:
square LEFT BODY RIGHT
where LEFT
and RIGHT
must assume the same language and match the same string.
As a simple example, let's pretend we need to match an XML-like string such as the following:
<a>text</a>
where the opening and closing tags must match.
This is done using a key RE
for the LEFT
lens. We could write a square lens such as:
let xml = [ Util.del_str "<" (* start of opening tag *)
. square (key Rx.word) (* LEFT side of square lens matches tag name *)
(Util.del_str ">" (* BODY: end of opening tag *)
. store Rx.word (* get text value *)
. Util.del_str "</") (* start of closing tag *)
(del Rx.word "DEFAULT") (* RIGHT side of square lens matches closing tag *)
. Util.del_str ">" . Util.eol ] (* end closing tag and add newline *)
(* Sample tree produced by this lens *)
test xml get "<ab>text</ab>\n" = { "ab" = "text" }
Note that the "DEFAULT"
string provided for the RIGHT
lens does not matter, as it will never be used.
The XML
and Httpd
modules contain more complete examples of such lenses.
Another type of usage for square lenses is symmetric deletion, such as quotes. Let's say we want to parse a quoted string and use the quoted value as a key. Both single and double quotes are accepted for our string, so we need to make sure that the quotes match (and possibly allow for single quotes inside a double quoted string, and vice versa). A square lens can be used for that, with the LEFT
lens using a del RE STR
pattern:
let quote =
let quote_lns = del /["']/ "\"" (* Delete single or double quote *)
in [ square quote_lns (* LEFT: a single or double quote *)
(key Rx.word) (* BODY: a word used as a key *)
quote_lns ] (* RIGHT: a matching quote *)
(* Sample trees produced by this lens *)
test quote get "'abc'" = { "abc" }
test quote get "\"abc\"" = { "abc" }
The Quote
module provides useful wrapping definitions for quoting values in lenses.