diff --git a/Lib/fontTools/feaLib/parser.py b/Lib/fontTools/feaLib/parser.py index c8f0acca3..eefac24ee 100644 --- a/Lib/fontTools/feaLib/parser.py +++ b/Lib/fontTools/feaLib/parser.py @@ -935,9 +935,9 @@ class Parser(object): for n in new: if not list(n.glyphSet()): raise FeatureLibError("Empty class in replacement", location) - if not isinstance(n, self.ast.GlyphName) and len(n.glyphSet()) != count: + if len(n.glyphSet()) != 1 and len(n.glyphSet()) != count: raise FeatureLibError( - f'Expected a glyph class with {count} elements after "by", ' + f'Expected a glyph class with 1 or {count} elements after "by", ' f"but found a glyph class with {len(n.glyphSet())} elements", location, ) diff --git a/Tests/feaLib/parser_test.py b/Tests/feaLib/parser_test.py index 54c7c4426..2923f50ab 100644 --- a/Tests/feaLib/parser_test.py +++ b/Tests/feaLib/parser_test.py @@ -1642,13 +1642,20 @@ class ParserTest(unittest.TestCase): self.assertEqual(glyphstr([sub.glyph]), "[f_i f_l]") self.assertEqual(glyphstr(sub.replacement), "f [i l]") + def test_substitute_multiple_classes_mixed_singleton(self): + doc = self.parse("lookup Look {substitute [f_i f_l] by [f] [i l];} Look;") + sub = doc.statements[0].statements[0] + self.assertIsInstance(sub, ast.MultipleSubstStatement) + self.assertEqual(glyphstr([sub.glyph]), "[f_i f_l]") + self.assertEqual(glyphstr(sub.replacement), "f [i l]") + def test_substitute_multiple_classes_mismatch(self): self.assertRaisesRegex( FeatureLibError, - 'Expected a glyph class with 2 elements after "by", ' - "but found a glyph class with 1 elements", + 'Expected a glyph class with 1 or 3 elements after "by", ' + "but found a glyph class with 2 elements", self.parse, - "lookup Look {substitute [f_i f_l] by [f] [i l];} Look;", + "lookup Look {substitute [f_i f_l f_f_i] by [f f_f] [i l i];} Look;", ) def test_substitute_multiple_by_mutliple(self):