3 (* An experiment in handling empty lines and comments in httpd.conf and
4 * similar. What makes this challenging is that httpd.conf allows
5 * continuation lines; the markers for continuation lines (backslash +
6 * newline) needs to be treated like any other whitespace. *)
8 (* The continuation sequence that indicates that we should consider the
9 * next line part of the current line *)
10 let cont = /\\\\\r?\n/
12 (* Whitespace within a line: space, tab, and the continuation sequence *)
13 let ws = /[ \t]/ | cont
15 (* Any possible character - '.' does not match \n *)
18 (* Newline sequence - both for Unix and DOS newlines *)
21 (* Whitespace at the end of a line *)
22 let eol = del (ws* . nl) "\n"
24 (* A complete line that is either just whitespace or a comment that only
25 * contains whitespace *)
26 let empty = [ del (ws* . /#?/ . ws* . nl) "\n" ]
28 (* A comment that is not just whitespace. We define it in terms of the
29 * things that are not allowed as part of such a comment:
30 * 1) Starts with whitespace or newline
31 * 2) Ends with whitespace, a backslash or \r
32 * 3) Unescaped newlines
35 let comment_start = del (ws* . "#" . ws* ) "# " in
36 let unesc_eol = /[^\]/ . nl in
37 (* As a complement, the above criteria can be written as
38 let line = any* - ((ws|nl) . any*
39 | any* . (ws|/[\r\\]/)
40 | any* . unesc_eol . any* )? in
41 * Printing this out with 'print_regexp line' and simplifying it while
42 * checking for equality with the ruby-fa bindings, we can write this
44 let w = /[^\t\n\r \\]/ in
48 let t = /[\t\n\r ]/ in
49 let line = ((r . s* . w|w|r) . (s|w)* . (b . (t? . (s|w)* ))*|(r.s* )?).w.(s*.w)* in
50 [ label "#comment" . comment_start . store line . eol ]
52 let lns = (comment|empty)*
54 test [eol] get " \n" = { }
55 test [eol] get " \t\n" = { }
56 test [eol] get "\\\n\n" = { }
59 test lns get "# \\\r\n \t \\\n\n" = { }
60 test lns get "# x\n" = { "#comment" = "x" }
61 test lns get "# x\\\n\n" = { "#comment" = "x" }
62 test lns get "# \\\r\n \tx \\\n\n" = { "#comment" = "x" }
63 test lns get " \t\\\n# x\n" = { "#comment" = "x" }
64 test lns get "# word\\\n word \n" = { "#comment" = "word\\\n word" }
65 (* Not valid as it is an incomplete 'line' *)
66 test lns get "# x\\\n" = *