Skip to content

Commit 1283904

Browse files
committed
Define parser based on EBNF: Pattern me 4 bytes cross-eyed...
1 parent 35feafe commit 1283904

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

fluent/syntax.lua

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,58 @@
22
local class = require("pl.class")
33
local epnf = require("epnf")
44

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+
523
-- luacheck: push ignore
624
local ftlparser = epnf.define(function (_ENV)
725
local blank_inline = P" "^1
826
local line_end = P"\r\n" + P"\n"
927
local blank_block = (blank_inline^-1 * line_end)^1
1028
local blank = (blank_inline + line_end)^1
1129
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"
1244
local junk_line = (1-line_end)^0 * line_end
13-
Pattern = P"bar" + P"qiz"
1445
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
1747
CommentLine = (P"###" + P"##" + P"#") * (" " * comment_char^0)-1 * line_end
1848
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
2049
Message = V"Identifier" * blank_inline^-1 * P"=" * blank_inline^-1 * ((V"Pattern" * V"Attribute"^0) + V"Attribute"^1)
2150
Entry = (V"Message" * line_end) + (V"Term" * line_end) + V"CommentLine"
2251
Resource = (V"Entry" + blank_block + V"Junk")^0 * EOF"unparsable input"
2352
START("Resource")
2453
end)
2554
-- luacheck: pop
2655

27-
-- TODO: Spec L33-L84, L86-L129
56+
-- TODO: Spec L53-L82, L122-L129
2857

2958
local FluentSyntax = class({
3059
parser = ftlparser,

spec/fluent_syntax_spec.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ describe('fluent.syntax', function ()
4646
assert.equals("Entry", syntax:parse("foo = bar\n .baz = quiz")[1].id)
4747
end)
4848

49+
it('should handle complex term entries', function ()
50+
assert.equals("Entry", syntax:parse("foo = türkçe\n görüşürüz")[1].id)
51+
end)
52+
4953
it('should handle simple comments', function ()
5054
assert.same("CommentLine", syntax:parse("# foo")[1][1].id)
5155
assert.same("CommentLine", syntax:parse("## foo")[1][1].id)

0 commit comments

Comments
 (0)