diff --git a/Lib/fontTools/feaLib/parser.py b/Lib/fontTools/feaLib/parser.py index bda34e261..1008f16a3 100644 --- a/Lib/fontTools/feaLib/parser.py +++ b/Lib/fontTools/feaLib/parser.py @@ -826,8 +826,14 @@ class Parser(object): 'is not supported', location) + # If there are remaining glyphs to parse, this is an invalid GSUB statement + if len(new) != 0: + raise FeatureLibError( + 'Invalid substitution statement', + location + ) + # GSUB lookup type 6: Chaining contextual substitution. - assert len(new) == 0, new rule = self.ast.ChainContextSubstStatement( old_prefix, old, old_suffix, lookups, location=location) return rule diff --git a/Tests/feaLib/data/GSUB_error.fea b/Tests/feaLib/data/GSUB_error.fea new file mode 100644 index 000000000..ae175c501 --- /dev/null +++ b/Tests/feaLib/data/GSUB_error.fea @@ -0,0 +1,13 @@ +# Trigger a parser error in the function parse_substitute_ in order to improve the error message. +# Note that this is not a valid substitution, this test is made to trigger an error. + +languagesystem latn dflt; + +@base = [a e]; +@accents = [acute grave]; + +feature abvs { + lookup lookup1 { + sub @base @accents by @base; + } lookup1; +} abvs; diff --git a/Tests/feaLib/parser_test.py b/Tests/feaLib/parser_test.py index cb4e689b7..f2256b4c4 100644 --- a/Tests/feaLib/parser_test.py +++ b/Tests/feaLib/parser_test.py @@ -1502,6 +1502,13 @@ class ParserTest(unittest.TestCase): FeatureLibError, 'Expected "by", "from" or explicit lookup references', self.parse, "feature liga {substitute f f i;} liga;") + + def test_substitute_invalid_statement(self): + self.assertRaisesRegex( + FeatureLibError, + "Invalid substitution statement", + Parser(self.getpath("GSUB_error.fea"), GLYPHNAMES).parse + ) def test_subtable(self): doc = self.parse("feature test {subtable;} test;")