[feaLib] Resolve references to glyph classes

This commit is contained in:
Sascha Brawer 2015-08-01 19:25:48 +02:00
parent a0bbd5fab9
commit 3936e334f1
2 changed files with 46 additions and 9 deletions

View File

@ -66,10 +66,19 @@ class Parser(object):
def parse_glyphclass_reference_(self):
result = set()
if self.next_token_type_ is Lexer.GLYPHCLASS:
self.advance_lexer_()
gc = self.resolve_glyphclass_(self.cur_token_)
if gc is None:
raise ParserError("Unknown glyph class @%s" % self.cur_token_,
self.cur_token_location_)
result.update(gc.glyphs)
return result
self.expect_symbol_("[")
while self.next_token_ != "]":
if self.next_token_type_ is Lexer.NAME:
self.advance_lexer_()
self.advance_lexer_()
if self.cur_token_type_ is Lexer.NAME:
if self.next_token_ == "-":
range_location_ = self.cur_token_location_
range_start = self.cur_token_
@ -80,6 +89,16 @@ class Parser(object):
range_end))
else:
result.add(self.cur_token_)
elif self.cur_token_type_ is Lexer.GLYPHCLASS:
gc = self.resolve_glyphclass_(self.cur_token_)
if gc is None:
raise ParserError(
"Unknown glyph class @%s" % self.cur_token_,
self.cur_token_location_)
result.update(gc.glyphs)
else:
raise ParserError("Expected glyph name, range, or reference",
self.cur_token_location_)
self.expect_symbol_("]")
return result

View File

@ -24,11 +24,26 @@ class ParserTest(unittest.TestCase):
self.assertEqual(gc.name, "dash")
self.assertEqual(gc.glyphs, {"endash", "emdash", "figuredash"})
def test_glyphclass_bad(self):
self.assertRaisesRegex(
ParserError, "Expected glyph name, range, or reference",
self.parse, "@bad = [a 123];")
def test_glyphclass_duplicate(self):
self.assertRaisesRegex(
ParserError, "Glyph class @dup already defined",
self.parse, "@dup = [a b]; @dup = [x];")
def test_glyphclass_empty(self):
[gc] = self.parse("@empty_set = [];").statements
self.assertEqual(gc.name, "empty_set")
self.assertEqual(gc.glyphs, set())
def test_glyphclass_equality(self):
[foo, bar] = self.parse("@foo = [a b]; @bar = @foo;").statements
self.assertEqual(foo.glyphs, {"a", "b"})
self.assertEqual(bar.glyphs, {"a", "b"})
def test_glyphclass_range_uppercase(self):
[gc] = self.parse("@swashes = [X.swash-Z.swash];").statements
self.assertEqual(gc.name, "swashes")
@ -72,13 +87,16 @@ class ParserTest(unittest.TestCase):
"a", "foo.09", "foo.10", "foo.11", "X.sc", "Y.sc", "Z.sc"
})
# TODO: self.parse("@foo = [a b]; @bar = [@foo];")
# TODO: self.parse("@foo = [a b]; @bar = @foo;")
def test_glyphclass_empty(self):
[gc] = self.parse("@empty_set = [];").statements
self.assertEqual(gc.name, "empty_set")
self.assertEqual(gc.glyphs, set())
def test_glyphclass_reference(self):
[vowels_lc, vowels_uc, vowels] = self.parse(
"@Vowels.lc = [a e i o u]; @Vowels.uc = [A E I O U]; " +
"@Vowels = [@Vowels.lc @Vowels.uc y Y];").statements
self.assertEqual(vowels_lc.glyphs, set(list("aeiou")))
self.assertEqual(vowels_uc.glyphs, set(list("AEIOU")))
self.assertEqual(vowels.glyphs, set(list("aeiouyAEIOUY")))
self.assertRaisesRegex(
ParserError, "Unknown glyph class @unknown",
self.parse, "@bad = [@unknown];")
def test_languagesystem(self):
[langsys] = self.parse("languagesystem latn DEU;").statements