每个词都对,句子却错

let = rate 12 ; 的每一个 token 都是合法的词,lexer 一声不吭地放行了。它错在【0】。

开始练习 →

一排词为什么不够用

1 + 2 * 3 切出来是五个 token 排成一排。光看这一排,看不出的东西是【0】。

开始练习 →

结构从哪里来

parser 凭什么知道 let rate = 12 ; 是「let 语句」、1 + 2 * 3 里乘先于加?它依据的是【0】。

开始练习 →

语法分析的产物

上一站切好了一排词,然后呢 ? parser 读完 token 流、确认没有语法错误之后,交给下一站的是【0】。

开始练习 →

先数一数句子

(每道题开头都有同一段:T() 是上一站 lexer 的替身——源码里 token 之间用空格分开,它切成 (kind, text, line, col);show() 把树写成一行:二元运算全加括号,语句之间用 |。) 贯穿的源码(接 c

开始练习 →

产生式的两边

玩具语言的文法(八节共用):program := stmt*;stmt := "let" IDENT "=" expr ";" | IDENT "=" expr

开始练习 →

带引号和不带引号

玩具语言的文法(八节共用):program := stmt*;stmt := "let" IDENT "=" expr ";" | IDENT "=" expr

开始练习 →

星号和问号

玩具语言的文法(八节共用):program := stmt*;stmt := "let" IDENT "=" expr ";" | IDENT "=" expr

开始练习 →

规则里出现自己

玩具语言的文法(八节共用):program := stmt*;stmt := "let" IDENT "=" expr ";" | IDENT "=" expr

开始练习 →

对着规则核一句

(每道题开头都有同一段:T() 是上一站 lexer 的替身——源码里 token 之间用空格分开,它切成 (kind, text, line, col);show() 把树写成一行:二元运算全加括号,语句之间用 |。) 还没写完整 par

开始练习 →