Một bộ phân tích LR (shift-reduce) hoạt động dựa trên một ngăn xếp chứa xen kẽ trạng thái và ký hiệu, cùng hai bảng: ACTION[i,a] (với i là trạng thái, a là ký hiệu kết thúc kể cả $) cho biết hành động shift (đẩy vào ngăn xếp và chuyển sang trạng thái mới), reduce theo một luật sinh (rút gọn), accept (chấp nhận), hoặc rỗng (báo lỗi); và GOTO[i,A] (với A là non-terminal) cho biết trạng thái cần chuyển tới sau khi rút gọn về A.
Thuật toán mô phỏng: ngăn xếp khởi tạo chỉ chứa trạng thái 0; con trỏ đọc token ở vị trí 0. Lặp lại: gọi i là trạng thái trên đỉnh ngăn xếp, a là token hiện tại.
sJ (shift tới trạng thái J): đẩy a rồi đẩy J vào ngăn xếp, dịch con trỏ sang token kế tiếp.rP (reduce theo luật sinh số P: A→X1…Xk): rút 2k phần tử khỏi đỉnh ngăn xếp (k cặp ký hiệu-trạng thái, nếu k=0 thì không rút gì), gọi t là trạng thái trên đỉnh ngăn xếp sau khi rút, đẩy A rồi đẩy GOTO[t,A] vào ngăn xếp; ghi nhận số hiệu luật sinh P vào danh sách các bước reduce đã thực hiện (con trỏ đọc không dịch chuyển).acc: dừng và kết luận chấp nhận.$).Cho trước bảng ACTION/GOTO đầy đủ của một văn phạm (đã mở rộng, luật sinh số 0 là luật mở rộng S′→S) cùng một xâu token vào (luôn kết thúc bằng token $), hãy mô phỏng và đưa ra kết quả.
Ví dụ: với bảng SLR(1) chuẩn của văn phạm biểu thức số học E -> E + T | T, T -> T * F | F, F -> ( E ) | id, xâu vào id + id * id $ được chấp nhận qua dãy rút gọn theo số hiệu luật sinh: 6 4 2 6 4 6 3 1 (tương ứng F->id, T->F, E->T, rồi F->id, T->F, rồi F->id, T->T*F, E->E+T).
Dòng 1: bốn số nguyên numStates numTerm numNT numProd — số trạng thái, số ký hiệu kết thúc (đã tính $), số ký hiệu chưa kết thúc, số luật sinh (đã tính luật mở rộng số 0).
Dòng 2: numTerm ký hiệu kết thúc cách nhau bởi dấu cách, theo đúng thứ tự dùng cho các cột của bảng ACTION (bao gồm $).
Dòng 3: numNT ký hiệu chưa kết thúc cách nhau bởi dấu cách, theo đúng thứ tự dùng cho các cột của bảng GOTO.
numProd dòng tiếp theo: luật sinh thứ 0,1,… theo thứ tự, dạng A -> X1 X2 ... Xk (luật số 0 luôn có dạng S' -> S).
numStates dòng tiếp theo: bảng ACTION, mỗi dòng là hàng ứng với trạng thái đó, gồm numTerm ô cách nhau bởi dấu cách theo đúng thứ tự cột ở dòng 2; mỗi ô là sJ (shift), rP (reduce luật P), acc, hoặc - (rỗng).
numStates dòng tiếp theo: bảng GOTO, mỗi dòng gồm numNT ô theo đúng thứ tự cột ở dòng 3; mỗi ô là số hiệu trạng thái hoặc -.
Dòng cuối cùng: xâu token vào, cách nhau bởi dấu cách, luôn kết thúc bằng token $.
Nếu chấp nhận: in hai dòng — dòng đầu accept; dòng thứ hai là danh sách số hiệu luật sinh đã dùng để reduce, theo đúng thứ tự thực hiện, cách nhau bởi dấu cách (nếu không có bước reduce nào thì in dòng rỗng).
Nếu từ chối: in một dòng reject k với k là vị trí (0-indexed) của token đang xét khi phát hiện lỗi.
Ví dụ:
Đầu vào:
12 6 3 7
$ ( ) * + id
E F T
E' -> E
E -> E + T
E -> T
T -> T * F
T -> F
F -> ( E )
F -> id
- s1 - - - s5
- s1 - - - s5
acc - - - s7 -
r4 - r4 r4 r4 -
r2 - r2 s8 r2 -
r6 - r6 r6 r6 -
- - s9 - s7 -
- s1 - - - s5
- s1 - - - s5
r5 - r5 r5 r5 -
r1 - r1 s8 r1 -
r3 - r3 r3 r3 -
2 3 4
6 3 4
- - -
- - -
- - -
- - -
- - -
- 3 10
- 11 -
- - -
- - -
- - -
id + id * id $
Đầu ra:
accept
6 4 2 6 4 6 3 1
Đầu vào:
12 6 3 7
$ ( ) * + id
E F T
E' -> E
E -> E + T
E -> T
T -> T * F
T -> F
F -> ( E )
F -> id
- s1 - - - s5
- s1 - - - s5
acc - - - s7 -
r4 - r4 r4 r4 -
r2 - r2 s8 r2 -
r6 - r6 r6 r6 -
- - s9 - s7 -
- s1 - - - s5
- s1 - - - s5
r5 - r5 r5 r5 -
r1 - r1 s8 r1 -
r3 - r3 r3 r3 -
2 3 4
6 3 4
- - -
- - -
- - -
- - -
- - -
- 3 10
- 11 -
- - -
- - -
- - -
id $
Đầu ra:
accept
6 4 2
Đang tải editor...