|
2 | 2 | local class = require("pl.class") |
3 | 3 | local epnf = require("epnf") |
4 | 4 |
|
| 5 | +-- UTF8 code points up to four-byte encodings |
| 6 | +local function f1 (s) |
| 7 | + return string.byte(s) |
| 8 | +end |
| 9 | +local function f2 (s) |
| 10 | + local c1, c2 = string.byte(s, 1, 2) |
| 11 | + return c1 * 64 + c2 - 12416 |
| 12 | +end |
| 13 | +local function f3 (s) |
| 14 | + local c1, c2, c3 = string.byte(s, 1, 3) |
| 15 | + return (c1 * 64 + c2) * 64 + c3 - 925824 |
| 16 | +end |
| 17 | +local function f4 (s) |
| 18 | + local c1, c2, c3, c4 = string.byte(s, 1, 4) |
| 19 | + return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 |
| 20 | +end |
| 21 | +local cont = "\128\191" |
| 22 | + |
5 | 23 | -- luacheck: push ignore |
6 | 24 | local ftlparser = epnf.define(function (_ENV) |
7 | 25 | local blank_inline = P" "^1 |
8 | 26 | local line_end = P"\r\n" + P"\n" |
9 | 27 | local blank_block = (blank_inline^-1 * line_end)^1 |
10 | 28 | local blank = (blank_inline + line_end)^1 |
11 | 29 | local digits = R"09"^1 |
| 30 | + local special_text_char = P"{" + P"}" |
| 31 | + local any_char = R("\0\127") / f1 + R("\194\223") * R(cont) / f2 + R("\224\239") * R(cont) * R(cont) / f3 + R("\240\244") * R(cont) * R(cont) * R(cont) / f4 |
| 32 | + local text_char = any_char - special_text_char - line_end |
| 33 | + local indented_char = text_char - P"{" - P"*" - P"." |
| 34 | + Identifier = R("az", "AZ") * (R("az", "AZ", "09") + P"_" + P"-")^0 |
| 35 | + InlineExpression = P"foo" |
| 36 | + SelectExpression = P"bar" |
| 37 | + local inline_placeable = P"{" * blank^-1 * (V"SelectExpression" + V"InlineExpression") * blank^-1 * P"}" |
| 38 | + local block_placeable = blank_block * blank_inline^-1 * inline_placeable |
| 39 | + local inline_text = text_char^1 |
| 40 | + local block_text = blank_block * blank_inline * indented_char * inline_text^-1 |
| 41 | + PatternElement = inline_text + block_text + inline_placeable + block_placeable |
| 42 | + Pattern = V"PatternElement"^1 |
| 43 | + Attribute = line_end * blank^-1 * P"." * V"Identifier" * blank_inline^-1 * "=" * blank_inline^-1 * V"Pattern" |
12 | 44 | local junk_line = (1-line_end)^0 * line_end |
13 | | - Pattern = P"bar" + P"qiz" |
14 | 45 | Junk = junk_line * (junk_line - P"#" - P"-" - R("az","AZ"))^0 |
15 | | - Attribute = line_end * blank^-1 * P"." * V"Identifier" * blank_inline^-1 * "=" * blank_inline^-1 * V"Pattern" |
16 | | - local comment_char = 1 - line_end |
| 46 | + local comment_char = any_char - line_end |
17 | 47 | CommentLine = (P"###" + P"##" + P"#") * (" " * comment_char^0)-1 * line_end |
18 | 48 | Term = P"-" * V"Identifier" * blank_inline^-1 * "=" * blank_inline^-1 * V"Pattern" * V"Attribute"^0 |
19 | | - Identifier = R("az", "AZ") * (R("az", "AZ", "09") + P"_" + P"-")^0 |
20 | 49 | Message = V"Identifier" * blank_inline^-1 * P"=" * blank_inline^-1 * ((V"Pattern" * V"Attribute"^0) + V"Attribute"^1) |
21 | 50 | Entry = (V"Message" * line_end) + (V"Term" * line_end) + V"CommentLine" |
22 | 51 | Resource = (V"Entry" + blank_block + V"Junk")^0 * EOF"unparsable input" |
23 | 52 | START("Resource") |
24 | 53 | end) |
25 | 54 | -- luacheck: pop |
26 | 55 |
|
27 | | --- TODO: Spec L33-L84, L86-L129 |
| 56 | +-- TODO: Spec L53-L82, L122-L129 |
28 | 57 |
|
29 | 58 | local FluentSyntax = class({ |
30 | 59 | parser = ftlparser, |
|
0 commit comments