19. Phân tích cú pháp

Phân tích cú pháp là giai đoạn biến luồng mã thông báo thành cấu trúc cú pháp.

Trình mã thông báo nhận dạng các đơn vị từ vựng. Trình phân tích cú pháp nhận ra cấu trúc ngữ pháp. Nó quyết định xem một chuỗi mã thông báo có phải là chương trình Python hợp lệ hay không và khi nó hợp lệ sẽ xây dựng một cây cú pháp trừu tượng.

Đối với nguồn này:python def add(a, b): return a + b trình mã thông báo tạo ra các mã thông báo như:text NAME "def" NAME "add" LPAR "(" NAME "a" COMMA "," NAME "b" RPAR ")" COLON ":" NEWLINE "\n" INDENT " " NAME "return" NAME "a" PLUS "+" NAME "b" NEWLINE "\n" DEDENT "" ENDMARKER "" Trình phân tích cú pháp đưa ra cấu trúc mã thông báo đó:text Module FunctionDef name="add" arguments arg "a" arg "b" body Return BinOp Name "a" Add Name "b" Sự khác biệt là quan trọng. Token hóa biết điều đódef, add, (, a, Và:hiện hữu. Phân tích cú pháp biết rằng chúng cùng nhau tạo thành một định nghĩa hàm.

19.1 Vị trí trong Đường dẫn biên dịch

Phân tích cú pháp nằm giữa mã thông báo và biên dịch ngữ nghĩa.```text source bytes ↓ encoding detection ↓ tokenization ↓ parsing ↓ abstract syntax tree ↓ symbol table ↓ compiler ↓ code object ↓ bytecode execution


Trách nhim chính ca nó là:```text
recognize valid Python grammar
reject invalid syntax
group tokens into statements and expressions
apply operator precedence
handle indentation-based blocks
build AST nodes
produce useful syntax errors
```Tài liu tham kho ngôn ng Python hin th toàn b ng pháp được CPython s dng, bt ngun t`Grammar/python.gram`, đồng thi b qua các chi tiết trin khai liên quan đến vic to mã và khôi phc li. ([Tài liu Python][1])

## 19.2 CPython sử dụng trình phân tích cú pháp PEG

CPython hin đại s dng trình phân tích cú pháp PEG.

PEG có nghĩa là Phân tích ng pháp biu thc. CPython đã chuyn t trình phân tích cú pháp LL(1) cũ hơn sang trình phân tích cú pháp PEG trong Python 3.9. Trình phân tích cú pháp PEG cho phép din đạt trc tiếp hơn ng pháp ca Python và giúp CPython linh hot hơn khi thêm cú pháp.

Trình phân tích cú pháp PEG hot động bng cách th các la chn thay thế ng pháp theo th t. Phương án thay thế đầu tiên thành công s được chn.

Mt quy tc đơn gin hóa có th trông ging như:```text
statement:
    | function_def
    | class_def
    | if_stmt
    | while_stmt
    | simple_stmt
```Vi các mã thông báo đầu vào, trình phân tích cú pháp s c gng khp mt câu lnh. Nếu phương án đầu tiên tht bi, nó s th phương án tiếp theo, v.v.

S la chn có th t này khác vi mt s h thng ng pháp phi ng cnh trong đó các la chn thay thế không có th t. Trong PEG, trt t rt quan trng.

##19.3 Quy tắc ngữ pháp

Ng pháp xác định chui mã thông báo hp l.

Mt quy tc định nghĩa hàm đơn gin có th được hình dung như sau:```text
function_def:
    "def" NAME "(" parameters? ")" ":" block
```Điu này có nghĩa là:```text
the keyword def
then a function name
then an opening parenthesis
then optional parameters
then a closing parenthesis
then a colon
then a block
```Ng pháp CPython thc chi tiết hơn vì nó h tr trình trang trí, hàm không đồng b, chú thích, tham s ch v trí, tham s ch t khóa, giá tr mc định, tham s loi, chú thích tr v và khôi phc li.

Tuy nhiên, mô hình cơ bn vn là:```text
tokens are matched against grammar rules
rules call other rules
successful rules produce AST structure
failed rules produce backtracking or syntax errors
```## 19.4 Câu lệnh và biểu thức

Cú pháp Python có các câu lnh và biu thc.

Các câu lnh thc hin các hành động:```python
x = 1
return x
if x:
    print(x)
```Biu thc to ra các giá tr:```python
x + 1
f(a, b)
items[0]
lambda x: x + 1
```Trình phân tích cú pháp phi phân bit chúng vì không phi mi biu thc đều được phép  mi nơi và không phi mi câu lnh đều có th xut hin bên trong mt biu thc.

Có hiu lc:```python
if ready:
    run()
```Không hp l:```python
x = if ready: run()
```Có hiu lc:```python
value = a if ready else b
```Ng pháp mã hóa nhng khác bit này.`if`như mt tuyên b thuc v mt khu vc ng pháp. Biu thc điu kin thuc v người khác.

## 19,5 Block và Suites

Các khi Python được biu din bi`INDENT`Và`DEDENT`mã thông báo.

Trình phân tích cú pháp không đếm khong trng mt cách trc tiếp. Trình mã thông báo đã chuyn đổi tht l thành mã thông báo cu trúc.

Ví d:```python
if x:
    a = 1
    b = 2
c = 3
```Hình dng mã thông báo:```text
NAME      "if"
NAME      "x"
COLON     ":"
NEWLINE
INDENT
NAME      "a"
EQUAL
NUMBER    "1"
NEWLINE
NAME      "b"
EQUAL
NUMBER    "2"
NEWLINE
DEDENT
NAME      "c"
EQUAL
NUMBER    "3"
NEWLINE
ENDMARKER
```Trình phân tích cú pháp xem khi này như mt b:```text
If
    test: Name "x"
    body:
        Assign a = 1
        Assign b = 2
Module body:
    Assign c = 3
```Thiết kế này giúp vic x lý tht đầu dòng nm ngoài hu hết các quy tc ng pháp. Ng pháp có th nói là chn và da vào mã thông báo được to ra`INDENT`Và`DEDENT`mã thông báo.

## 19.6 Phân tích biểu thức và mức độ ưu tiên

Biu thc phân tích cú pháp yêu cu quyn ưu tiên.

Coi như:```python
x = 1 + 2 * 3
```Trình phân tích cú pháp phi to ra:```text
1 + (2 * 3)
```không:```text
(1 + 2) * 3
```Hình dng AST là:```text
Assign
    target: Name "x"
    value:
        BinOp Add
            left: Constant 1
            right:
                BinOp Mult
                    left: Constant 2
                    right: Constant 3
```Các quy tc ng pháp mã hóa mc độ ưu tiên bng cách xếp lp các biu thc.

Mt mô hình đơn gin hóa:```text
expression
    conditional expression

sum
    term
    sum "+" term
    sum "-" term

term
    factor
    term "*" factor
    term "/" factor

factor
    atom
    "-" factor
    "+" factor

atom
    NAME
    NUMBER
    STRING
    "(" expression ")"
```Các cu trúc có mc độ ưu tiên cao hơn xut hin sâu hơn trong ng pháp. Phép nhân liên kết cht ch hơn phép cng vì các quy tc cng s dng các biu thc cp nhân làm toán hng.

## 19.7 Tính liên kết

Quyn ưu tiên quyết định toán t nào liên kết cht ch hơn. Tính kết hp quyết định cách thc các toán t ca cùng mt nhóm ưu tiên.

Ví d:```python
x = a - b - c
```Điu này phân tích như sau:```text
(a - b) - c
```không:```text
a - (b - c)
```Phép tr là liên kết trái.

Nhưng lũy ​​tha hot động khác nhau:```python
x = a ** b ** c
```Điu này phân tích như sau:```text
a ** (b ** c)
```Ng pháp phi mã hóa điu này mt cách rõ ràng. Tính kết hp không phi là thuc tính thi gian chy. Nó được c định bng cu trúc phân tích trước khi bt đầu đánh giá.

## 19.8 Lệnh gọi, thuộc tính và đăng ký

Python có các dng biu thc hu t:```python
obj.attr
obj.method(x)
items[i]
items[i:j]
f(x)(y).z
```Nhng chui này cht ch.

Ví d:```python
result = client.session.get(url).json()["items"][0]
```Trình phân tích cú pháp nhóm nhóm này thành mt chui các thao tác trên biu thc chính:```text
Name "client"
    Attribute "session"
    Attribute "get"
    Call args=[Name "url"]
    Attribute "json"
    Call args=[]
    Subscript "items"
    Subscript 0
```Đây là lý do ti sao các lnh gi, thuc tính và ch s dưới liên kết cht ch hơn các toán t s hc:```python
x = f(a) + b.c
```Các cuc gi và thuc tính được phân tích cú pháp trước khi biu thc b sung được hình thành.

## 19.9 Phân tích bài tập

Cú pháp gán b hn chế hơn cú pháp biu thc.

Các mc tiêu phân công hp l bao gm:```python
x = 1
obj.attr = 1
items[0] = 1
a, b = pair
```Các mc tiêu chuyn nhượng không hp l bao gm:```python
1 = x
a + b = x
f() = x
```Trình phân tích cú pháp phi nhn ra rng vế trái ca phép gán không ch là bt k biu thc nào. Nó phi là mt mc tiêu hp l.

Điu này cũng nh hưởng đến bài tp tăng cường:```python
x += 1
obj.value *= 2
items[i] -= 3
```và bài tp có chú thích:```python
x: int = 1
name: str
```Trình phân tích cú pháp và trình to AST ca CPython phi duy trì s khác bit gia biu thc được s dng để đọc và mc tiêu được s dng để viết.

 cp độ AST, tên mang ng cnh:```text
Name id="x", ctx=Load
Name id="x", ctx=Store
Name id="x", ctx=Del
```Ví d:```python
x = x + 1
```bên trái`x`là`Store`. Bên phi`x`là`Load`.

## 19.10 Sự mơ hồ và lựa chọn có trật tự

Phân tích cú pháp PEG s dng các la chn thay thế được sp xếp.

Hãy xem xét cú pháp trong đó nhiu la chn ng pháp bt đầu tương t nhau. Trình phân tích cú pháp s th mt gii pháp thay thế trước tiên. Nếu thành công, kết qu đó s được s dng. Nếu tht bi, các la chn thay thế sau này có th được th.

Điu này mang li cho các tác gi ng pháp mt cách có kim soát để gii quyết s mơ h.

Ví d đơn gin:```text
small_stmt:
    | assignment
    | expression
```Phương án gán phi được xem xét trước phương án thay thế biu thc đơn gin, bi vì mt phép gán thường bt đầu bng mt mc tiêu ging như biu thc.

đầu vào:```python
x = 1
```Tin t`x`có th bt đầu mt biu thc, nhưng câu lnh đầy đủ là phép gán. Ng pháp phi được sp xếp và cu trúc sao cho bài tp s thành công.

PEG cũng h tr toán t ct trong ký hiu ng pháp CPython. Tài liu tham kho ngôn ng ghi chú`~`đim đánh du trong ng pháp dưới dng mt phn ct cam kết vi gii pháp thay thế hin ti và không thc hin được quy tc nếu gii pháp thay thế đó không thành công. ([Tài liu Python][1])

Vic ct gim rt hu ích cho hiu sut và chn đoán. Sau khi trình phân tích cú pháp đã thy đủ mã thông báo để biết cu trúc nào đang phân tích cú pháp, nó có th ngng xem xét các la chn thay thế không liên quan.

## 19.11 Nhìn về phía trước

Người phân tích cú pháp thường cn kim tra các mã thông báo sp ti trước khi quyết định phân tích cái gì.

Lookahead hi: Mã thông báo tiếp theo hoc chui mã thông báo tiếp theo có khp vi mu này không?

Ví d:```python
x: int
```Điu này có th bt đầu mt bài tp có chú thích.

Ví d:```python
x + y
```Đây là mt tuyên b biu hin.

C hai đều bt đầu bng`NAME`. Trình phân tích cú pháp cn nhiu ng cnh hơn mã thông báo đầu tiên.

Lookahead cũng giúp loi b cú pháp sm và chn thông báo li tt hơn.

Mt mô hình nhìn trước đơn gin hóa:```text
if next token is NAME and following token is ":":
    parse annotated assignment
else:
    parse expression statement
```Ng pháp CPython thc s s dng các cơ chế phong phú hơn, nhưng mô hình tinh thn vn ging nhau: mt s quyết định yêu cu xem xét trước mà không tiêu th mã thông báo vĩnh vin.

## 19.12 Quay lại

Trình phân tích cú pháp PEG có th quay li.

Quay li có nghĩa là trình phân tích cú pháp th mt đường dn ng pháp, không thành công, khôi phc v trí mã thông báo trước đó và th mt đường dn khác.

Mô hình ví d:```text
try parse async function definition
    if it fails:
        restore token position
try parse normal function definition
    if it fails:
        restore token position
try parse simple statement
```Vic quay lui làm cho vic biên son ng pháp tr nên linh hot hơn so vi trình phân tích cú pháp xem trước mt mã thông báo nghiêm ngt.

Nhưng vic quay li không hn chế có th tn kém. Trình phân tích cú pháp ca CPython s dng cu trúc ng pháp, các đon ct, ghi nh và các quy tc được nhm mc tiêu để duy trì hiu qu phân tích cú pháp.

## 19.13 AST Xây dựng

Phân tích cú pháp trong CPython không ch chp nhn hoc t chi cú pháp. Nó xây dng mt AST.

Ngun ví d:```python
x = 1 + 2
```Hình dng AST:```text
Module
    Assign
        targets:
            Name id="x", ctx=Store
        value:
            BinOp
                left: Constant 1
                op: Add
                right: Constant 2
``` cp độ Python:```python
import ast

tree = ast.parse("x = 1 + 2\n")
print(ast.dump(tree, indent=4))
```Điu này to ra mt cây có cu trúc.

AST vn không phi là mã byte. Nó là mt cây cú pháp vi các chú thích ng nghĩa như ng cnh ti/lưu tr và v trí ngun.

## 19.14 Vị trí nguồn

Các nút AST mang thông tin v trí ngun.

Điu này bao gm s dòng và độ lch ct. CPython hin đại cũng theo dõi v trí kết thúc ca nhiu nút.

Ví d:```python
import ast

tree = ast.parse("x = 1 + 2\n")
node = tree.body[0]

print(node.lineno)
print(node.col_offset)
print(node.end_lineno)
print(node.end_col_offset)
```H tr v trí ngun:```text
tracebacks
syntax errors
debuggers
coverage tools
profilers
AST tools
editor integrations
```Nếu không có v trí ngun chính xác, CPython vn có th thc thi mã, nhưng cht lượng chn đoán và công c s kém hơn nhiu.

## 19.15 Lỗi cú pháp

Khi phân tích cú pháp tht bi, CPython tăng`SyntaxError`hoc mt lp con như`IndentationError`.

Mt li cú pháp s báo cáo:```text
filename
line number
column offset
source text
message
```Ví d:```python
if x
    pass
```Trình phân tích cú pháp thy rng`if`câu lnh thiếu du hai chm.

Mt đim li hu ích gn nơi không th phân tích cú pháp:```text
SyntaxError: expected ':'
```Li phân tích cú pháp không phi lúc nào cũng đơn gin. Bi vì trình phân tích cú pháp có th quay li, nên nó phi nh v trí li hu ích nht thay vì ch v trí li thay thế cui cùng.

Li cú pháp tt là mt phn quan trng ca k thut phân tích cú pháp.

## 19.16 Quy tắc không hợp lệ và chẩn đoán tốt hơn

Ng pháp ca CPython bao gm các quy tc được s dng riêng để đưa ra thông báo li tt hơn.

Mt trình phân tích cú pháp có th t chi cú pháp xu mt cách tng quát:```text
SyntaxError: invalid syntax
```Nhưng CPython thường c gng phát hin nhng li ph biến:```python
if x = 1:
    pass
```Điu này có th to ra thông báo hu ích hơn li phân tích cú pháp chung.

Các quy tc ng pháp không hp l không nhm mc đích chp nhn các chương trình. Chúng được s dng để nhn ra các dng sai và nâng cao kh năng chn đoán tt hơn.

Mô hình thc tế:```text
normal grammar accepts valid Python
invalid rules recognize common invalid Python
error machinery reports a targeted message
```Điu này gi cho trình phân tích cú pháp luôn cht ch trong khi ci thin tri nghim người dùng.

## 19.17 Đầu ra của trình phân tích cú pháp chưa được xác thực đầy đủ

Phân tích cú pháp thành công có nghĩa là ngun khp vi ng pháp Python. Điu đó không có nghĩa là chương trình hoàn toàn hp l theo mi nghĩa sau này.

Mt s kim tra xy ra sau khi phân tích cú pháp.

Ví d:```python
return 1
``` cp độ mô-đun, điu này có hình dng cú pháp ging như mt câu lnh return, nhưng nó không hp l khi  bên ngoài mt hàm.

Mt ví d khác:```python
break
``` cp độ mô-đun, v mt ng pháp đây là mt câu lnh break, nhưng nó không hp l khi  bên ngoài vòng lp.

Nhng ràng buc này thường được kim tra trong quá trình xác thc AST, phân tích bng ký hiu hoc biên dch.

Các giai đon là riêng bit:```text
parser:
    Can these tokens form a syntax tree?

later compiler checks:
    Is this syntax legal in this context?
    Which names are local, global, free, or cell variables?
    Can this construct be compiled here?
```## 19.18`ast.parse`Công chúng`ast.parse()`hàm hiển thị bộ máy phân tích cú pháp của CPython ở cấp độ Python.

Ví d:```python
import ast

src = """
def add(a, b):
    return a + b
"""

tree = ast.parse(src)
print(ast.dump(tree, indent=4))
```Điu này hu ích cho:```text
linters
formatters
static analyzers
code generation tools
security scanners
refactoring tools
documentation tools
```Nhưng`ast.parse()`tr v AST, không phi mã thông báo và không phi mã byte.

Đối vi mã byte, hãy s dng`compile()`Và`dis`:

```python
import dis

code = compile("x = 1 + 2\n", "<input>", "exec")
dis.dis(code)
```Mi quan h là:```text
tokenize.tokenize()    source to tokens
ast.parse()            source to AST
compile()              source or AST to code object
dis.dis()              code object to bytecode display
```## 19.19 Chế độ phân tích cú pháp

Ngun Python có th được phân tích cú pháp  các chế độ khác nhau.

Các chế độ ph biến:

| Chế độ | Ý nghĩa |
| -------- | ---------------------------------------- |
|`exec`| Phân tích mt mô-đun hoc chui câu lnh |
|`eval`| Phân tích mt biu thc |
|`single`| Phân tích đầu vào tương tác |

Ví d:```python
compile("x = 1", "<input>", "exec")
compile("1 + 2", "<input>", "eval")
compile("print(1)", "<input>", "single")

evalchế độ từ chối các câu lệnh:```python compile("x = 1", "", "eval")


Chế độ phân tích cú pháp xác định ký hiu bt đầu ng pháp.

## 19.20 Chuỗi F và Trình phân tích cú pháp

CPython hin đại phân tích các biu thc chui f thông qua máy phân tích cú pháp.

Trước Python 3.12, phân tích cú pháp biu thc chui f có nhiu hành vi trong trường hp đặc bit hơn. Python 3.12 đã thay đổi chui f thông qua PEP 701, đưa chúng vào ng pháp đầy đủ hơn. Tài liu Python 3.12 lưu ý rng chui f được phân tích cú pháp bng trình phân tích cú pháp PEG, cho phép thông báo li chính xác hơn và hiu sut mã thông báo được ci thin do nhng thay đổi này. ([Tài liu Python][2])

Ví d:```python
name = "Ada"
text = f"hello {name.upper()}"
```Biu thc được nhúng:```python
name.upper()
```được phân tích cú pháp dưới dng cú pháp biu thc Python.

Điu này có nghĩa là chui f không ch là phép ni suy chui khi chy. Chúng cha cú pháp lng nhau phi được phân tích cú pháp và biu din theo cu trúc.

## 19.21 Tệp phân tích cú pháp trong CPython

Các vùng ngun quan trng liên quan đến trình phân tích cú pháp bao gm:```text
Grammar/python.gram
Parser/
Python/ast.c
Include/internal/
Lib/ast.py
Lib/test/test_grammar.py
Lib/test/test_syntax.py
```Ranh gii tp chính xác có th thay đổi, nhưng s phân chia khái nim vn n định:

| Khu vc | Vai trò |
| ---------------- | --------------------------------------------- |
| Ng pháp | Xác định cú pháp Python |
| Trình to trình phân tích cú pháp | To vic trin khai trình phân tích cú pháp t ng pháp |
| Thi gian chy ca trình phân tích cú pháp | Tiêu th mã thông báo và áp dng các quy tc ng pháp |
| AST xây dng | Xây dng các nút AST |
| Xác thc AST | Kim tra tính đúng đắn v cu trúc |
| Kim tra | Bo v cú pháp và chn đoán |

Khi đọc CPython, hãy bt đầu vi ng pháp. Sau đó làm theo cách quy tc ng pháp to nút AST.

## 19.22 Ví dụ: Phân tích hàm

Ngun:```python
def square(x):
    return x * x
```Chế độ xem cp mã thông báo:```text
NAME      "def"
NAME      "square"
LPAR      "("
NAME      "x"
RPAR      ")"
COLON     ":"
NEWLINE
INDENT
NAME      "return"
NAME      "x"
STAR      "*"
NAME      "x"
NEWLINE
DEDENT
ENDMARKER
```Chế độ xem cp AST:```text
Module
    FunctionDef
        name: "square"
        args:
            arguments
                arg: "x"
        body:
            Return
                BinOp
                    left: Name "x", Load
                    op: Mult
                    right: Name "x", Load
```Trình phân tích cú pháp to ra h thng phân cp này vì ng pháp cho biết:```text
a module contains statements
a function definition is a statement
a function body is a block
a return statement can contain an expression
a multiplication expression contains two operands
a name expression loads a value
```Mi cp độ mang li ý nghĩa cho lung mã thông báo phng.

## 19.23 Ví dụ: Phân tích một`if`Tuyên bố

Ngun:```python
if score >= 60:
    result = "pass"
else:
    result = "fail"
```Hình dng AST:```text
Module
    If
        test:
            Compare
                left: Name "score"
                op: GtE
                comparator: Constant 60
        body:
            Assign
                target: Name "result", Store
                value: Constant "pass"
        orelse:
            Assign
                target: Name "result", Store
                value: Constant "fail"
```Trình phân tích cú pháp phi đính kèm`else`đến đúng`if`.

Mã thông báo tht l giúp ích  đây. các`else`xut hin sau`DEDENT`kết thúc khi đầu tiên, nhưng  cùng mc tht l vi khi`if`.

Đây là nơi cú pháp nhy cm vi b cc ca Python tương tác trc tiếp vi cu trúc trình phân tích cú pháp.

## 19.24 Ví dụ: Phân tích cú pháp hiểu

Ngun:```python
squares = [x * x for x in values if x > 0]
```Hình dng AST:```text
Assign
    target: Name "squares", Store
    value:
        ListComp
            element:
                BinOp
                    Name "x"
                    Mult
                    Name "x"
            generators:
                comprehension
                    target: Name "x", Store
                    iter: Name "values", Load
                    ifs:
                        Compare
                            Name "x"
                            Gt
                            Constant 0
```Phn hiu là cú pháp biu thc, nhưng chúng cha các mc tiêu ging như phép gán và các mnh đề lng nhau.

Trình phân tích cú pháp phi phân bit:```python
[x * x for x in values]
```t mt danh sách theo nghĩa đen:```python
[x * x, y]
```C hai đều bt đầu bng`[`và mt biu hin. Chui mã thông báo sau biu thc đầu tiên xác định cu trúc mà trình phân tích cú pháp xây dng.

## 19.25 Ranh giới của trình phân tích cú pháp

Trình phân tích cú pháp không thc thi mã.

Nó không gi các chc năng:```python
f()
```Nó ch xây dng mt nút cuc gi.

Nó không nhp mô-đun:```python
import os
```Nó ch xây dng mt nút nhp.

Nó không gii quyết tên:```python
x + y
```Nó ch xây dng các nút tên và hot động nh phân.

Nó không đánh giá các hng s vượt quá nhng gì lp AST th hin.

Công vic ca trình phân tích cú pháp là có tính cu trúc. Các giai đon sau ch định phm vi, to mã byte và thc hin các hot động.

## 19.26 Mô hình tinh thần tối thiểu

S dng mô hình này:```text
The tokenizer emits a flat stream of tokens.
The parser matches that stream against Python grammar.
CPythons modern parser is PEG-based.
Grammar alternatives are ordered.
The parser builds an AST.
The AST records statements, expressions, contexts, and source locations.
Syntax errors are raised when the token stream cannot form valid grammar.
Some validity checks happen after parsing.
```Phân tích cú pháp là nơi văn bn ngun đầu tiên tr thành hình cây. Mi th sau giai đon này hot động theo cu trúc thay vì th t mã thông báo thô.