Что мы можем обобщить:
1. существует порядок. Элементы в последовательности не обязательны, но порядок строгий
Например, protected может и не быть. Но точно не может быть function protected
2. Часть элементов имеет только ограниченный набор значений (scope, type)
Я вижу, примерно, такую логику (ее нужно рисовать, как диаграмму):
1. определяем набор допустимых значений для scope (protected/public/private)
2. берем первое слово строки. смотрим, совпадает ли с одним из вариантов
3. если нет, то scope ставим по умолчанию (public например). А первое слово проверяем на совпадение с множестовм допустимых значений type (function/class/enum/interface).
4. если нет - ошибка парсинга
5. если ошибок не было и значение type еще не определено, значит до этого определялся scope. Поэтому, берем второе слово и проверяем его на множестово допустимых значений type
6. если type уже был определен, проверяем на множество для returnType
7. когда определим все три первых элемента (type, scope, returnType), берем 4й - это имя функции
8. берем значение в (скобках) и делим по делиметру "," - получим массив аргументов