A1

Appendix I

Dưới đây là toàn bộ grammar của Lox. Các chương giới thiệu từng phần của ngôn ngữ đều có kèm các quy tắc grammar tương ứng, nhưng ở đây chúng được tập hợp lại thành một chỗ.

A1 . 1Syntax Grammar

Syntax grammar được dùng để phân tích chuỗi token tuyến tính thành cấu trúc cây cú pháp lồng nhau. Nó bắt đầu với quy tắc đầu tiên khớp với toàn bộ một chương trình Lox (hoặc một mục nhập đơn trong REPL).

programdeclaration* EOF ;

A1 . 1 . 1Declarations

Một chương trình là một chuỗi các declaration, tức là các statement gắn kết định danh mới hoặc bất kỳ loại statement nào khác.

declarationclassDecl
               | funDecl
               | varDecl
               | statement ;

classDecl"class" IDENTIFIER ( "<" IDENTIFIER )?
                 "{" function* "}" ;
funDecl"fun" function ;
varDecl"var" IDENTIFIER ( "=" expression )? ";" ;

A1 . 1 . 2Statements

Các quy tắc statement còn lại tạo ra side effect, nhưng không giới thiệu binding mới.

statementexprStmt
               | forStmt
               | ifStmt
               | printStmt
               | returnStmt
               | whileStmt
               | block ;

exprStmtexpression ";" ;
forStmt"for" "(" ( varDecl | exprStmt | ";" )
                           expression? ";"
                           expression? ")" statement ;
ifStmt"if" "(" expression ")" statement
                 ( "else" statement )? ;
printStmt"print" expression ";" ;
returnStmt"return" expression? ";" ;
whileStmt"while" "(" expression ")" statement ;
block"{" declaration* "}" ;

Lưu ý rằng block là một quy tắc statement, nhưng cũng được dùng như một nonterminal trong một vài quy tắc khác, chẳng hạn như thân hàm.

A1 . 1 . 3Expressions

Expression tạo ra giá trị. Lox có nhiều toán tử unary và binary với các mức độ ưu tiên khác nhau. Một số grammar của ngôn ngữ không mã hóa trực tiếp quan hệ ưu tiên mà quy định ở nơi khác. Ở đây, chúng ta dùng một quy tắc riêng cho mỗi mức ưu tiên để thể hiện rõ ràng.

expressionassignment ;

assignment     → ( call "." )? IDENTIFIER "=" assignment
               | logic_or ;

logic_orlogic_and ( "or" logic_and )* ;
logic_andequality ( "and" equality )* ;
equalitycomparison ( ( "!=" | "==" ) comparison )* ;
comparisonterm ( ( ">" | ">=" | "<" | "<=" ) term )* ;
termfactor ( ( "-" | "+" ) factor )* ;
factorunary ( ( "/" | "*" ) unary )* ;

unary          → ( "!" | "-" ) unary | call ;
callprimary ( "(" arguments? ")" | "." IDENTIFIER )* ;
primary"true" | "false" | "nil" | "this"
               | NUMBER | STRING | IDENTIFIER | "(" expression ")"
               | "super" "." IDENTIFIER ;

A1 . 1 . 4Utility rules

Để giữ cho các quy tắc trên gọn gàng hơn, một số phần của grammar được tách ra thành các quy tắc phụ tá có thể tái sử dụng.

functionIDENTIFIER "(" parameters? ")" block ;
parametersIDENTIFIER ( "," IDENTIFIER )* ;
argumentsexpression ( "," expression )* ;

A1 . 2Lexical Grammar

Lexical grammar được scanner dùng để nhóm các ký tự thành token. Nếu syntax là context free, thì lexical grammar là regular — lưu ý rằng không có quy tắc đệ quy.

NUMBERDIGIT+ ( "." DIGIT+ )? ;
STRING"\"" <any char except "\"">* "\"" ;
IDENTIFIERALPHA ( ALPHA | DIGIT )* ;
ALPHA"a" ... "z" | "A" ... "Z" | "_" ;
DIGIT"0" ... "9" ;