Ir para o conteúdo

Apêndice A — Gramática da linguagem Jack

Referência completa, para consulta rápida durante os capítulos 4 e 5. A notação segue a convenção do Nand2Tetris: 'x' símbolo terminal literal; x (sem aspas) não-terminal; () agrupamento; x|y alternativa; x? zero ou uma ocorrência; x* zero ou mais ocorrências.

Elementos léxicos

Terminal Regra
keyword class | constructor | function | method | field | static | var | int | char | boolean | void | true | false | null | this | let | do | if | else | while | return
symbol { } ( ) [ ] . , ; + - * / & | < > = ~
integerConstant Um número decimal
stringConstant Sequência de caracteres Unicode, sem aspas duplas nem quebra de linha
identifier Sequência de letras, dígitos e _, não iniciando com dígito

Estrutura de classe

Não-terminal Regra
class 'class' className '{' classVarDec subroutineDec '}'
classVarDec ('static'|'field') type varName (',' varName)* ';'
type 'int' | 'char' | 'boolean' | className
subroutineDec ('constructor'|'function'|'method') ('void'|type) subroutineName '(' parameterList ')' subroutineBody
parameterList ((type varName) (',' type varName)*)?
subroutineBody '{' varDec* statements '}'
varDec 'var' type varName (',' varName)* ';'
className identifier
subroutineName identifier
varName identifier

Comandos (statements)

Não-terminal Regra
statements statement*
statement letStatement | ifStatement | whileStatement | doStatement | returnStatement
letStatement 'let' varName ('[' expression ']')? '=' expression ';'
ifStatement 'if' '(' expression ')' '{' statements '}' ('else' '{' statements '}')?
whileStatement 'while' '(' expression ')' '{' statements '}'
doStatement 'do' subroutineCall ';'
returnStatement 'return' expression? ';'

Expressões

Não-terminal Regra
expression term (op term)*
term integerConstant | stringConstant | keywordConstant | varName | varName '[' expression ']' | subroutineCall | '(' expression ')' | unaryOp term
subroutineCall subroutineName '(' expressionList ')' | (className|varName) '.' subroutineName '(' expressionList ')'
expressionList (expression (',' expression)*)?
op + | - | * | / | & | | | < | > | =
unaryOp - | ~
keywordConstant true | false | null | this

Notas de implementação

  • term é o único não-terminal que exige mais de um token de lookahead para decidir a produção: ao ver um identifier, o parser precisa olhar o token seguinte ([, (, ., ou nenhum dos três) para diferenciar variável simples, acesso a array, e chamada de subroutine (qualificada ou não). Ver capítulo 5.
  • A ausência de precedência de operadores em Jack (capítulo 3) é o que permite expression ser term (op term)* — um único nível, sem a cadeia expression → term → factor que uma gramática com precedência exigiria.
  • Esta gramática já é LL(1): não há recursão à esquerda nem produções alternativas com o mesmo símbolo inicial dentro do mesmo não-terminal, exceto o lookahead extra de term descrito acima.