parser.go.y 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. %{
  2. package parse
  3. import (
  4. "github.com/yuin/gopher-lua/ast"
  5. )
  6. %}
  7. %type<stmts> chunk
  8. %type<stmts> chunk1
  9. %type<stmts> block
  10. %type<stmt> stat
  11. %type<stmts> elseifs
  12. %type<stmt> laststat
  13. %type<funcname> funcname
  14. %type<funcname> funcname1
  15. %type<exprlist> varlist
  16. %type<expr> var
  17. %type<namelist> namelist
  18. %type<exprlist> exprlist
  19. %type<expr> expr
  20. %type<expr> string
  21. %type<expr> prefixexp
  22. %type<expr> functioncall
  23. %type<expr> afunctioncall
  24. %type<exprlist> args
  25. %type<expr> function
  26. %type<funcexpr> funcbody
  27. %type<parlist> parlist
  28. %type<expr> tableconstructor
  29. %type<fieldlist> fieldlist
  30. %type<field> field
  31. %type<fieldsep> fieldsep
  32. %union {
  33. token ast.Token
  34. stmts []ast.Stmt
  35. stmt ast.Stmt
  36. funcname *ast.FuncName
  37. funcexpr *ast.FunctionExpr
  38. exprlist []ast.Expr
  39. expr ast.Expr
  40. fieldlist []*ast.Field
  41. field *ast.Field
  42. fieldsep string
  43. namelist []string
  44. parlist *ast.ParList
  45. }
  46. /* Reserved words */
  47. %token<token> TAnd TBreak TDo TElse TElseIf TEnd TFalse TFor TFunction TIf TIn TLocal TNil TNot TOr TReturn TRepeat TThen TTrue TUntil TWhile TGoto
  48. /* Literals */
  49. %token<token> TEqeq TNeq TLte TGte T2Comma T3Comma T2Colon TIdent TNumber TString '{' '('
  50. /* Operators */
  51. %left TOr
  52. %left TAnd
  53. %left '>' '<' TGte TLte TEqeq TNeq
  54. %right T2Comma
  55. %left '+' '-'
  56. %left '*' '/' '%'
  57. %right UNARY /* not # -(unary) */
  58. %right '^'
  59. %%
  60. chunk:
  61. chunk1 {
  62. $$ = $1
  63. if l, ok := yylex.(*Lexer); ok {
  64. l.Stmts = $$
  65. }
  66. } |
  67. chunk1 laststat {
  68. $$ = append($1, $2)
  69. if l, ok := yylex.(*Lexer); ok {
  70. l.Stmts = $$
  71. }
  72. } |
  73. chunk1 laststat ';' {
  74. $$ = append($1, $2)
  75. if l, ok := yylex.(*Lexer); ok {
  76. l.Stmts = $$
  77. }
  78. }
  79. chunk1:
  80. {
  81. $$ = []ast.Stmt{}
  82. } |
  83. chunk1 stat {
  84. $$ = append($1, $2)
  85. } |
  86. chunk1 ';' {
  87. $$ = $1
  88. }
  89. block:
  90. chunk {
  91. $$ = $1
  92. }
  93. stat:
  94. varlist '=' exprlist {
  95. $$ = &ast.AssignStmt{Lhs: $1, Rhs: $3}
  96. $$.SetLine($1[0].Line())
  97. } |
  98. /* 'stat = functioncal' causes a reduce/reduce conflict */
  99. prefixexp {
  100. if _, ok := $1.(*ast.FuncCallExpr); !ok {
  101. yylex.(*Lexer).Error("parse error")
  102. } else {
  103. $$ = &ast.FuncCallStmt{Expr: $1}
  104. $$.SetLine($1.Line())
  105. }
  106. } |
  107. TDo block TEnd {
  108. $$ = &ast.DoBlockStmt{Stmts: $2}
  109. $$.SetLine($1.Pos.Line)
  110. $$.SetLastLine($3.Pos.Line)
  111. } |
  112. TWhile expr TDo block TEnd {
  113. $$ = &ast.WhileStmt{Condition: $2, Stmts: $4}
  114. $$.SetLine($1.Pos.Line)
  115. $$.SetLastLine($5.Pos.Line)
  116. } |
  117. TRepeat block TUntil expr {
  118. $$ = &ast.RepeatStmt{Condition: $4, Stmts: $2}
  119. $$.SetLine($1.Pos.Line)
  120. $$.SetLastLine($4.Line())
  121. } |
  122. TIf expr TThen block elseifs TEnd {
  123. $$ = &ast.IfStmt{Condition: $2, Then: $4}
  124. cur := $$
  125. for _, elseif := range $5 {
  126. cur.(*ast.IfStmt).Else = []ast.Stmt{elseif}
  127. cur = elseif
  128. }
  129. $$.SetLine($1.Pos.Line)
  130. $$.SetLastLine($6.Pos.Line)
  131. } |
  132. TIf expr TThen block elseifs TElse block TEnd {
  133. $$ = &ast.IfStmt{Condition: $2, Then: $4}
  134. cur := $$
  135. for _, elseif := range $5 {
  136. cur.(*ast.IfStmt).Else = []ast.Stmt{elseif}
  137. cur = elseif
  138. }
  139. cur.(*ast.IfStmt).Else = $7
  140. $$.SetLine($1.Pos.Line)
  141. $$.SetLastLine($8.Pos.Line)
  142. } |
  143. TFor TIdent '=' expr ',' expr TDo block TEnd {
  144. $$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Stmts: $8}
  145. $$.SetLine($1.Pos.Line)
  146. $$.SetLastLine($9.Pos.Line)
  147. } |
  148. TFor TIdent '=' expr ',' expr ',' expr TDo block TEnd {
  149. $$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Step:$8, Stmts: $10}
  150. $$.SetLine($1.Pos.Line)
  151. $$.SetLastLine($11.Pos.Line)
  152. } |
  153. TFor namelist TIn exprlist TDo block TEnd {
  154. $$ = &ast.GenericForStmt{Names:$2, Exprs:$4, Stmts: $6}
  155. $$.SetLine($1.Pos.Line)
  156. $$.SetLastLine($7.Pos.Line)
  157. } |
  158. TFunction funcname funcbody {
  159. $$ = &ast.FuncDefStmt{Name: $2, Func: $3}
  160. $$.SetLine($1.Pos.Line)
  161. $$.SetLastLine($3.LastLine())
  162. } |
  163. TLocal TFunction TIdent funcbody {
  164. $$ = &ast.LocalAssignStmt{Names:[]string{$3.Str}, Exprs: []ast.Expr{$4}}
  165. $$.SetLine($1.Pos.Line)
  166. $$.SetLastLine($4.LastLine())
  167. } |
  168. TLocal namelist '=' exprlist {
  169. $$ = &ast.LocalAssignStmt{Names: $2, Exprs:$4}
  170. $$.SetLine($1.Pos.Line)
  171. } |
  172. TLocal namelist {
  173. $$ = &ast.LocalAssignStmt{Names: $2, Exprs:[]ast.Expr{}}
  174. $$.SetLine($1.Pos.Line)
  175. } |
  176. T2Colon TIdent T2Colon {
  177. $$ = &ast.LabelStmt{Name: $2.Str}
  178. $$.SetLine($1.Pos.Line)
  179. } |
  180. TGoto TIdent {
  181. $$ = &ast.GotoStmt{Label: $2.Str}
  182. $$.SetLine($1.Pos.Line)
  183. }
  184. elseifs:
  185. {
  186. $$ = []ast.Stmt{}
  187. } |
  188. elseifs TElseIf expr TThen block {
  189. $$ = append($1, &ast.IfStmt{Condition: $3, Then: $5})
  190. $$[len($$)-1].SetLine($2.Pos.Line)
  191. }
  192. laststat:
  193. TReturn {
  194. $$ = &ast.ReturnStmt{Exprs:nil}
  195. $$.SetLine($1.Pos.Line)
  196. } |
  197. TReturn exprlist {
  198. $$ = &ast.ReturnStmt{Exprs:$2}
  199. $$.SetLine($1.Pos.Line)
  200. } |
  201. TBreak {
  202. $$ = &ast.BreakStmt{}
  203. $$.SetLine($1.Pos.Line)
  204. }
  205. funcname:
  206. funcname1 {
  207. $$ = $1
  208. } |
  209. funcname1 ':' TIdent {
  210. $$ = &ast.FuncName{Func:nil, Receiver:$1.Func, Method: $3.Str}
  211. }
  212. funcname1:
  213. TIdent {
  214. $$ = &ast.FuncName{Func: &ast.IdentExpr{Value:$1.Str}}
  215. $$.Func.SetLine($1.Pos.Line)
  216. } |
  217. funcname1 '.' TIdent {
  218. key:= &ast.StringExpr{Value:$3.Str}
  219. key.SetLine($3.Pos.Line)
  220. fn := &ast.AttrGetExpr{Object: $1.Func, Key: key}
  221. fn.SetLine($3.Pos.Line)
  222. $$ = &ast.FuncName{Func: fn}
  223. }
  224. varlist:
  225. var {
  226. $$ = []ast.Expr{$1}
  227. } |
  228. varlist ',' var {
  229. $$ = append($1, $3)
  230. }
  231. var:
  232. TIdent {
  233. $$ = &ast.IdentExpr{Value:$1.Str}
  234. $$.SetLine($1.Pos.Line)
  235. } |
  236. prefixexp '[' expr ']' {
  237. $$ = &ast.AttrGetExpr{Object: $1, Key: $3}
  238. $$.SetLine($1.Line())
  239. } |
  240. prefixexp '.' TIdent {
  241. key := &ast.StringExpr{Value:$3.Str}
  242. key.SetLine($3.Pos.Line)
  243. $$ = &ast.AttrGetExpr{Object: $1, Key: key}
  244. $$.SetLine($1.Line())
  245. }
  246. namelist:
  247. TIdent {
  248. $$ = []string{$1.Str}
  249. } |
  250. namelist ',' TIdent {
  251. $$ = append($1, $3.Str)
  252. }
  253. exprlist:
  254. expr {
  255. $$ = []ast.Expr{$1}
  256. } |
  257. exprlist ',' expr {
  258. $$ = append($1, $3)
  259. }
  260. expr:
  261. TNil {
  262. $$ = &ast.NilExpr{}
  263. $$.SetLine($1.Pos.Line)
  264. } |
  265. TFalse {
  266. $$ = &ast.FalseExpr{}
  267. $$.SetLine($1.Pos.Line)
  268. } |
  269. TTrue {
  270. $$ = &ast.TrueExpr{}
  271. $$.SetLine($1.Pos.Line)
  272. } |
  273. TNumber {
  274. $$ = &ast.NumberExpr{Value: $1.Str}
  275. $$.SetLine($1.Pos.Line)
  276. } |
  277. T3Comma {
  278. $$ = &ast.Comma3Expr{}
  279. $$.SetLine($1.Pos.Line)
  280. } |
  281. function {
  282. $$ = $1
  283. } |
  284. prefixexp {
  285. $$ = $1
  286. } |
  287. string {
  288. $$ = $1
  289. } |
  290. tableconstructor {
  291. $$ = $1
  292. } |
  293. expr TOr expr {
  294. $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "or", Rhs: $3}
  295. $$.SetLine($1.Line())
  296. } |
  297. expr TAnd expr {
  298. $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "and", Rhs: $3}
  299. $$.SetLine($1.Line())
  300. } |
  301. expr '>' expr {
  302. $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">", Rhs: $3}
  303. $$.SetLine($1.Line())
  304. } |
  305. expr '<' expr {
  306. $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<", Rhs: $3}
  307. $$.SetLine($1.Line())
  308. } |
  309. expr TGte expr {
  310. $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">=", Rhs: $3}
  311. $$.SetLine($1.Line())
  312. } |
  313. expr TLte expr {
  314. $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<=", Rhs: $3}
  315. $$.SetLine($1.Line())
  316. } |
  317. expr TEqeq expr {
  318. $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "==", Rhs: $3}
  319. $$.SetLine($1.Line())
  320. } |
  321. expr TNeq expr {
  322. $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "~=", Rhs: $3}
  323. $$.SetLine($1.Line())
  324. } |
  325. expr T2Comma expr {
  326. $$ = &ast.StringConcatOpExpr{Lhs: $1, Rhs: $3}
  327. $$.SetLine($1.Line())
  328. } |
  329. expr '+' expr {
  330. $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "+", Rhs: $3}
  331. $$.SetLine($1.Line())
  332. } |
  333. expr '-' expr {
  334. $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "-", Rhs: $3}
  335. $$.SetLine($1.Line())
  336. } |
  337. expr '*' expr {
  338. $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "*", Rhs: $3}
  339. $$.SetLine($1.Line())
  340. } |
  341. expr '/' expr {
  342. $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "/", Rhs: $3}
  343. $$.SetLine($1.Line())
  344. } |
  345. expr '%' expr {
  346. $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "%", Rhs: $3}
  347. $$.SetLine($1.Line())
  348. } |
  349. expr '^' expr {
  350. $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "^", Rhs: $3}
  351. $$.SetLine($1.Line())
  352. } |
  353. '-' expr %prec UNARY {
  354. $$ = &ast.UnaryMinusOpExpr{Expr: $2}
  355. $$.SetLine($2.Line())
  356. } |
  357. TNot expr %prec UNARY {
  358. $$ = &ast.UnaryNotOpExpr{Expr: $2}
  359. $$.SetLine($2.Line())
  360. } |
  361. '#' expr %prec UNARY {
  362. $$ = &ast.UnaryLenOpExpr{Expr: $2}
  363. $$.SetLine($2.Line())
  364. }
  365. string:
  366. TString {
  367. $$ = &ast.StringExpr{Value: $1.Str}
  368. $$.SetLine($1.Pos.Line)
  369. }
  370. prefixexp:
  371. var {
  372. $$ = $1
  373. } |
  374. afunctioncall {
  375. $$ = $1
  376. } |
  377. functioncall {
  378. $$ = $1
  379. } |
  380. '(' expr ')' {
  381. if ex, ok := $2.(*ast.Comma3Expr); ok {
  382. ex.AdjustRet = true
  383. }
  384. $$ = $2
  385. $$.SetLine($1.Pos.Line)
  386. }
  387. afunctioncall:
  388. '(' functioncall ')' {
  389. $2.(*ast.FuncCallExpr).AdjustRet = true
  390. $$ = $2
  391. }
  392. functioncall:
  393. prefixexp args {
  394. $$ = &ast.FuncCallExpr{Func: $1, Args: $2}
  395. $$.SetLine($1.Line())
  396. } |
  397. prefixexp ':' TIdent args {
  398. $$ = &ast.FuncCallExpr{Method: $3.Str, Receiver: $1, Args: $4}
  399. $$.SetLine($1.Line())
  400. }
  401. args:
  402. '(' ')' {
  403. if yylex.(*Lexer).PNewLine {
  404. yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)")
  405. }
  406. $$ = []ast.Expr{}
  407. } |
  408. '(' exprlist ')' {
  409. if yylex.(*Lexer).PNewLine {
  410. yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)")
  411. }
  412. $$ = $2
  413. } |
  414. tableconstructor {
  415. $$ = []ast.Expr{$1}
  416. } |
  417. string {
  418. $$ = []ast.Expr{$1}
  419. }
  420. function:
  421. TFunction funcbody {
  422. $$ = &ast.FunctionExpr{ParList:$2.ParList, Stmts: $2.Stmts}
  423. $$.SetLine($1.Pos.Line)
  424. $$.SetLastLine($2.LastLine())
  425. }
  426. funcbody:
  427. '(' parlist ')' block TEnd {
  428. $$ = &ast.FunctionExpr{ParList: $2, Stmts: $4}
  429. $$.SetLine($1.Pos.Line)
  430. $$.SetLastLine($5.Pos.Line)
  431. } |
  432. '(' ')' block TEnd {
  433. $$ = &ast.FunctionExpr{ParList: &ast.ParList{HasVargs: false, Names: []string{}}, Stmts: $3}
  434. $$.SetLine($1.Pos.Line)
  435. $$.SetLastLine($4.Pos.Line)
  436. }
  437. parlist:
  438. T3Comma {
  439. $$ = &ast.ParList{HasVargs: true, Names: []string{}}
  440. } |
  441. namelist {
  442. $$ = &ast.ParList{HasVargs: false, Names: []string{}}
  443. $$.Names = append($$.Names, $1...)
  444. } |
  445. namelist ',' T3Comma {
  446. $$ = &ast.ParList{HasVargs: true, Names: []string{}}
  447. $$.Names = append($$.Names, $1...)
  448. }
  449. tableconstructor:
  450. '{' '}' {
  451. $$ = &ast.TableExpr{Fields: []*ast.Field{}}
  452. $$.SetLine($1.Pos.Line)
  453. } |
  454. '{' fieldlist '}' {
  455. $$ = &ast.TableExpr{Fields: $2}
  456. $$.SetLine($1.Pos.Line)
  457. }
  458. fieldlist:
  459. field {
  460. $$ = []*ast.Field{$1}
  461. } |
  462. fieldlist fieldsep field {
  463. $$ = append($1, $3)
  464. } |
  465. fieldlist fieldsep {
  466. $$ = $1
  467. }
  468. field:
  469. TIdent '=' expr {
  470. $$ = &ast.Field{Key: &ast.StringExpr{Value:$1.Str}, Value: $3}
  471. $$.Key.SetLine($1.Pos.Line)
  472. } |
  473. '[' expr ']' '=' expr {
  474. $$ = &ast.Field{Key: $2, Value: $5}
  475. } |
  476. expr {
  477. $$ = &ast.Field{Value: $1}
  478. }
  479. fieldsep:
  480. ',' {
  481. $$ = ","
  482. } |
  483. ';' {
  484. $$ = ";"
  485. }
  486. %%
  487. func TokenName(c int) string {
  488. if c >= TAnd && c-TAnd < len(yyToknames) {
  489. if yyToknames[c-TAnd] != "" {
  490. return yyToknames[c-TAnd]
  491. }
  492. }
  493. return string([]byte{byte(c)})
  494. }