Шаг 2. Если множество первых символов содержит нетерминал В, то включить в него символы множества ПЕРВ(В), определенное на шаге 0.
| ПЕРВ(1) 2 | using |
| ПЕРВ(2) 2 | public |
| ПЕРВ(3) 2 | ; |
| ПЕРВ(4) 2 | |
| ПЕРВ(5) 2 | ID |
| ПЕРВ(6) 2 | . |
| ПЕРВ(7) 2 | |
| ПЕРВ(8) 2 | class |
| ПЕРВ(9) 2 | public |
| ПЕРВ(10) 2 | ; |
| ПЕРВ(11) 2 | |
| ПЕРВ(12) 2 | uint |
| ПЕРВ(13) 2 | bool |
| ПЕРВ(14) 2 | const |
| ПЕРВ(15) 2 | ID |
| ПЕРВ(16) 2 | ( |
| ПЕРВ(17) 2 | , |
| ПЕРВ(18) 2 | = |
| ПЕРВ(19) 2 | |
| ПЕРВ(20) 2 | ID |
| ПЕРВ(21) 2 | , |
| ПЕРВ(22) 2 | = |
| ПЕРВ(23) 2 | |
| ПЕРВ(24) 2 | for break continue write read ID |
| ПЕРВ(25) 2 | ; |
| ПЕРВ(26) 2 | |
| ПЕРВ(27) 2 | for |
| ПЕРВ(28) 2 | break |
| ПЕРВ(29) 2 | continue |
| ПЕРВ(30) 2 | write |
| ПЕРВ(31) 2 | read |
| ПЕРВ(32) 2 | ID |
| ПЕРВ(33) 2 | = |
| ПЕРВ(34) 2 | * |
| ПЕРВ(35) 2 | / |
| ПЕРВ(36) 2 | ( |
| ПЕРВ(37) 2 | ID |
| ПЕРВ(38) 2 | NUM |
| ПЕРВ(39) 2 | + |
| ПЕРВ(40) 2 | - |
| ПЕРВ(41) 2 | |
| ПЕРВ(42) 2 | ( |
| ПЕРВ(43) 2 | ( ID NUM |
| ПЕРВ(44) 2 | > |
| ПЕРВ(45) 2 | < |
| ПЕРВ(46) 2 | = |
| ПЕРВ(47) 2 |
Шаг 3. Если ПЕРВ(n)i+1 ≠ ПЕРВ(n)i, то i = i + 1 и перейти к шагу 2, иначе закончить.
Построение множества ПЕРВ(А). Множества ПЕРВ(А) необходимо для определения множеств СЛЕД(А).
Шаг 1. Для построения множества ПЕРВ(А) = FIRST(1, A), где А - нетерминал в правой части правил, определим множества первых символов, стоящих в начале правых частей правил, для каждого нетерминала в левой части правил.
| ПЕРВ(<S>) | using public |
| ПЕРВ(<NEXT>) | ; |
| ПЕРВ(<USING_LIST>) | ID |
| ПЕРВ(<NEXT_USING>) | . |
| ПЕРВ(<CLASS>) | class |
| ПЕРВ(<CLASS_BODY>) | public |
| ПЕРВ(<NEXT_BODY>) | ; |
| ПЕРВ(<DEF>) | uint bool const |
| ПЕРВ(<DEF_LIST>) | ID |
| ПЕРВ(<NEXT_DEF>) | ( , = |
| ПЕРВ(<VAR_LIST>) | ID |
| ПЕРВ(<NEXT_VAR>) | , = |
| ПЕРВ(<OPER_LIST>) | <OPERATOR> |
| ПЕРВ(<NEXT_OPER>) | ; |
| ПЕРВ(<OPERATOR>) | for break continue write read ID |
| ПЕРВ(<LET>) | = * / |
| ПЕРВ(<EXPR>) | ( ID NUM |
| ПЕРВ(<OPERATION>) | + - |
| ПЕРВ(<COND>) | <EXPR> ( |
| ПЕРВ(<RELATION>) | > < = |
Шаг 2. Если множество первых символов содержит нетерминал В, то включить в него символы множества ПЕРВ(В), i=0.
| ПЕРВ(<S>)0 | using public |
| ПЕРВ(<NEXT>)0 | ; |
| ПЕРВ(<USING_LIST>)0 | ID |
| ПЕРВ(<NEXT_USING>)0 | . |
| ПЕРВ(<CLASS>)0 | class |
| ПЕРВ(<CLASS_BODY>)0 | public |
| ПЕРВ(<NEXT_BODY>)0 | ; |
| ПЕРВ(<DEF>)0 | uint bool const |
| ПЕРВ(<DEF_LIST>)0 | ID |
| ПЕРВ(<NEXT_DEF>)0 | ( , = |
| ПЕРВ(<VAR_LIST>)0 | ID |
| ПЕРВ(<NEXT_VAR>)0 | , = |
| ПЕРВ(<OPER_LIST>)0 | for break continue write read ID |
| ПЕРВ(<NEXT_OPER>)0 | ; |
| ПЕРВ(<OPERATOR>)0 | for break continue write read ID |
| ПЕРВ(<LET>)0 | = * / |
| ПЕРВ(<EXPR>)0 | ( ID NUM |
| ПЕРВ(<OPERATION>)0 | + - |
| ПЕРВ(<COND>)0 | ( ID NUM |
| ПЕРВ(<RELATION>)0 | > < = |
Шаг 3. Выполнение шага 2 привело к изменению множеств ПЕРВ(А), поэтому повторим шаг 2.
Шаг 2. Если множество первых символов содержит нетерминал В, то включить в него символы множества ПЕРВ(В), i=1.
| ПЕРВ(<S>)1 | using public |
| ПЕРВ(<NEXT>)1 | ; |
| ПЕРВ(<USING_LIST>)1 | ID |
| ПЕРВ(<NEXT_USING>)1 | . |
| ПЕРВ(<CLASS>)1 | class |
| ПЕРВ(<CLASS_BODY>)1 | public |
| ПЕРВ(<NEXT_BODY>)1 | ; |
| ПЕРВ(<DEF>)1 | uint bool const |
| ПЕРВ(<DEF_LIST>)1 | ID |
| ПЕРВ(<NEXT_DEF>)1 | ( , = |
| ПЕРВ(<VAR_LIST>)1 | ID |
| ПЕРВ(<NEXT_VAR>)1 | , = |
| ПЕРВ(<OPER_LIST>)1 | for break continue write read ID |
| ПЕРВ(<NEXT_OPER>)1 | ; |
| ПЕРВ(<OPERATOR>)1 | for break continue write read ID |
| ПЕРВ(<LET>)1 | = * / |
| ПЕРВ(<EXPR>)1 | ( ID NUM |
| ПЕРВ(<OPERATION>)1 | + - |
| ПЕРВ(<COND>)1 | ( ID NUM |
| ПЕРВ(<RELATION>)1 | > < = |
Шаг 3. Дальнейшее выполнения шага 2 не приведет к изменению множеств ПЕРВ(А), поэтому закончим.
Построение множества СЛЕД(А). Множества СЛЕД(А) строятся для всех нетрминальных символов грамматики методом последовательного приближения.
Шаг 1. Внесем во множество последующих символов СЛЕД(А) = FOLLOW(1, A) для каждого нетерминала А все символы, которые в правых частях правил встречаются непосредственно за символом А; i=0.
| СЛЕД(<S>)0 | |
| СЛЕД(<NEXT>)0 | |
| СЛЕД(<USING_LIST>)0 | <NEXT> |
| СЛЕД(<NEXT_USING>)0 | |
| СЛЕД(<CLASS>)0 | <NEXT> |
| СЛЕД(<CLASS_BODY>)0 | } |
| СЛЕД(<NEXT_BODY>)0 | |
| СЛЕД(<DEF>)0 | <NEXT_BODY> |
| СЛЕД(<DEF_LIST>)0 | |
| СЛЕД(<NEXT_DEF>)0 | |
| СЛЕД(<VAR_LIST>)0 | ) |
| СЛЕД(<NEXT_VAR>)0 | |
| СЛЕД(<OPER_LIST>)0 | } |
| СЛЕД(<NEXT_OPER>)0 | |
| СЛЕД(<OPERATOR>)0 | <NEXT_OPER> |
| СЛЕД(<LET>)0 | ) |
| СЛЕД(<EXPR>)0 | <VAR_LIST> ; ) <RELATION> |
| СЛЕД(<OPERATION>)0 | |
| СЛЕД(<COND>)0 | ; ) |
| СЛЕД(<RELATION>)0 |
Шаг 2. Внесем пустую цепочку (или символ конца строки) во множество последующих символов для целевого символа <S>.
| СЛЕД(<S>)0 | # |
| СЛЕД(<NEXT>)0 | |
| СЛЕД(<USING_LIST>)0 | <NEXT> |
| СЛЕД(<NEXT_USING>)0 | |
| СЛЕД(<CLASS>)0 | <NEXT> |
| СЛЕД(<CLASS_BODY>)0 | } |
| СЛЕД(<NEXT_BODY>)0 | |
| СЛЕД(<DEF>)0 | <NEXT_BODY> |
| СЛЕД(<DEF_LIST>)0 | |
| СЛЕД(<NEXT_DEF>)0 | |
| СЛЕД(<VAR_LIST>)0 | ) |
| СЛЕД(<NEXT_VAR>)0 | |
| СЛЕД(<OPER_LIST>)0 | } |
| СЛЕД(<NEXT_OPER>)0 | |
| СЛЕД(<OPERATOR>)0 | <NEXT_OPER> |
| СЛЕД(<LET>)0 | ) |
| СЛЕД(<EXPR>)0 | <VAR_LIST> ; ) <RELATION> |
| СЛЕД(<OPERATION>)0 | |
| СЛЕД(<COND>)0 | ; ) |
| СЛЕД(<RELATION>)0 |
Шаг 3. Для всех нетерминальных символов A включить во множества СЛЕД(A) множества ПЕРВ(В), где B Î СЛЕД(A).
| СЛЕД(<S>)1 | # |
| СЛЕД(<NEXT>)1 | |
| СЛЕД(<USING_LIST>)1 | ; |
| СЛЕД(<NEXT_USING>)1 | |
| СЛЕД(<CLASS>)1 | ; |
| СЛЕД(<CLASS_BODY>)1 | } |
| СЛЕД(<NEXT_BODY>)1 | |
| СЛЕД(<DEF>)1 | ; |
| СЛЕД(<DEF_LIST>)1 | |
| СЛЕД(<NEXT_DEF>)1 | |
| СЛЕД(<VAR_LIST>)1 | ) |
| СЛЕД(<NEXT_VAR>)1 | |
| СЛЕД(<OPER_LIST>)1 | } |
| СЛЕД(<NEXT_OPER>)1 | |
| СЛЕД(<OPERATOR>)1 | ; |
| СЛЕД(<LET>)1 | ) |
| СЛЕД(<EXPR>)1 | ID ; ) < > = |
| СЛЕД(<OPERATION>)1 | |
| СЛЕД(<COND>)1 | ; ) |
| СЛЕД(<RELATION>)1 |
Шаг 4. Для всех нетерминальных символов A включить во множества СЛЕД(A) множества СЛЕД (В), где B Î СЛЕД(A), если существует правило B=e.