1
0

parser.go.y 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  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
  48. /* Literals */
  49. %token<token> TEqeq TNeq TLte TGte T2Comma T3Comma 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. elseifs:
  177. {
  178. $$ = []ast.Stmt{}
  179. } |
  180. elseifs TElseIf expr TThen block {
  181. $$ = append($1, &ast.IfStmt{Condition: $3, Then: $5})
  182. $$[len($$)-1].SetLine($2.Pos.Line)
  183. }
  184. laststat:
  185. TReturn {
  186. $$ = &ast.ReturnStmt{Exprs:nil}
  187. $$.SetLine($1.Pos.Line)
  188. } |
  189. TReturn exprlist {
  190. $$ = &ast.ReturnStmt{Exprs:$2}
  191. $$.SetLine($1.Pos.Line)
  192. } |
  193. TBreak {
  194. $$ = &ast.BreakStmt{}
  195. $$.SetLine($1.Pos.Line)
  196. }
  197. funcname:
  198. funcname1 {
  199. $$ = $1
  200. } |
  201. funcname1 ':' TIdent {
  202. $$ = &ast.FuncName{Func:nil, Receiver:$1.Func, Method: $3.Str}
  203. }
  204. funcname1:
  205. TIdent {
  206. $$ = &ast.FuncName{Func: &ast.IdentExpr{Value:$1.Str}}
  207. $$.Func.SetLine($1.Pos.Line)
  208. } |
  209. funcname1 '.' TIdent {
  210. key:= &ast.StringExpr{Value:$3.Str}
  211. key.SetLine($3.Pos.Line)
  212. fn := &ast.AttrGetExpr{Object: $1.Func, Key: key}
  213. fn.SetLine($3.Pos.Line)
  214. $$ = &ast.FuncName{Func: fn}
  215. }
  216. varlist:
  217. var {
  218. $$ = []ast.Expr{$1}
  219. } |
  220. varlist ',' var {
  221. $$ = append($1, $3)
  222. }
  223. var:
  224. TIdent {
  225. $$ = &ast.IdentExpr{Value:$1.Str}
  226. $$.SetLine($1.Pos.Line)
  227. } |
  228. prefixexp '[' expr ']' {
  229. $$ = &ast.AttrGetExpr{Object: $1, Key: $3}
  230. $$.SetLine($1.Line())
  231. } |
  232. prefixexp '.' TIdent {
  233. key := &ast.StringExpr{Value:$3.Str}
  234. key.SetLine($3.Pos.Line)
  235. $$ = &ast.AttrGetExpr{Object: $1, Key: key}
  236. $$.SetLine($1.Line())
  237. }
  238. namelist:
  239. TIdent {
  240. $$ = []string{$1.Str}
  241. } |
  242. namelist ',' TIdent {
  243. $$ = append($1, $3.Str)
  244. }
  245. exprlist:
  246. expr {
  247. $$ = []ast.Expr{$1}
  248. } |
  249. exprlist ',' expr {
  250. $$ = append($1, $3)
  251. }
  252. expr:
  253. TNil {
  254. $$ = &ast.NilExpr{}
  255. $$.SetLine($1.Pos.Line)
  256. } |
  257. TFalse {
  258. $$ = &ast.FalseExpr{}
  259. $$.SetLine($1.Pos.Line)
  260. } |
  261. TTrue {
  262. $$ = &ast.TrueExpr{}
  263. $$.SetLine($1.Pos.Line)
  264. } |
  265. TNumber {
  266. $$ = &ast.NumberExpr{Value: $1.Str}
  267. $$.SetLine($1.Pos.Line)
  268. } |
  269. T3Comma {
  270. $$ = &ast.Comma3Expr{}
  271. $$.SetLine($1.Pos.Line)
  272. } |
  273. function {
  274. $$ = $1
  275. } |
  276. prefixexp {
  277. $$ = $1
  278. } |
  279. string {
  280. $$ = $1
  281. } |
  282. tableconstructor {
  283. $$ = $1
  284. } |
  285. expr TOr expr {
  286. $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "or", Rhs: $3}
  287. $$.SetLine($1.Line())
  288. } |
  289. expr TAnd expr {
  290. $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "and", Rhs: $3}
  291. $$.SetLine($1.Line())
  292. } |
  293. expr '>' expr {
  294. $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">", Rhs: $3}
  295. $$.SetLine($1.Line())
  296. } |
  297. expr '<' expr {
  298. $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<", Rhs: $3}
  299. $$.SetLine($1.Line())
  300. } |
  301. expr TGte expr {
  302. $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">=", Rhs: $3}
  303. $$.SetLine($1.Line())
  304. } |
  305. expr TLte expr {
  306. $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<=", Rhs: $3}
  307. $$.SetLine($1.Line())
  308. } |
  309. expr TEqeq expr {
  310. $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "==", Rhs: $3}
  311. $$.SetLine($1.Line())
  312. } |
  313. expr TNeq expr {
  314. $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "~=", Rhs: $3}
  315. $$.SetLine($1.Line())
  316. } |
  317. expr T2Comma expr {
  318. $$ = &ast.StringConcatOpExpr{Lhs: $1, Rhs: $3}
  319. $$.SetLine($1.Line())
  320. } |
  321. expr '+' expr {
  322. $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "+", Rhs: $3}
  323. $$.SetLine($1.Line())
  324. } |
  325. expr '-' expr {
  326. $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "-", 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 %prec UNARY {
  346. $$ = &ast.UnaryMinusOpExpr{Expr: $2}
  347. $$.SetLine($2.Line())
  348. } |
  349. TNot expr %prec UNARY {
  350. $$ = &ast.UnaryNotOpExpr{Expr: $2}
  351. $$.SetLine($2.Line())
  352. } |
  353. '#' expr %prec UNARY {
  354. $$ = &ast.UnaryLenOpExpr{Expr: $2}
  355. $$.SetLine($2.Line())
  356. }
  357. string:
  358. TString {
  359. $$ = &ast.StringExpr{Value: $1.Str}
  360. $$.SetLine($1.Pos.Line)
  361. }
  362. prefixexp:
  363. var {
  364. $$ = $1
  365. } |
  366. afunctioncall {
  367. $$ = $1
  368. } |
  369. functioncall {
  370. $$ = $1
  371. } |
  372. '(' expr ')' {
  373. $$ = $2
  374. $$.SetLine($1.Pos.Line)
  375. }
  376. afunctioncall:
  377. '(' functioncall ')' {
  378. $2.(*ast.FuncCallExpr).AdjustRet = true
  379. $$ = $2
  380. }
  381. functioncall:
  382. prefixexp args {
  383. $$ = &ast.FuncCallExpr{Func: $1, Args: $2}
  384. $$.SetLine($1.Line())
  385. } |
  386. prefixexp ':' TIdent args {
  387. $$ = &ast.FuncCallExpr{Method: $3.Str, Receiver: $1, Args: $4}
  388. $$.SetLine($1.Line())
  389. }
  390. args:
  391. '(' ')' {
  392. if yylex.(*Lexer).PNewLine {
  393. yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)")
  394. }
  395. $$ = []ast.Expr{}
  396. } |
  397. '(' exprlist ')' {
  398. if yylex.(*Lexer).PNewLine {
  399. yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)")
  400. }
  401. $$ = $2
  402. } |
  403. tableconstructor {
  404. $$ = []ast.Expr{$1}
  405. } |
  406. string {
  407. $$ = []ast.Expr{$1}
  408. }
  409. function:
  410. TFunction funcbody {
  411. $$ = &ast.FunctionExpr{ParList:$2.ParList, Stmts: $2.Stmts}
  412. $$.SetLine($1.Pos.Line)
  413. $$.SetLastLine($2.LastLine())
  414. }
  415. funcbody:
  416. '(' parlist ')' block TEnd {
  417. $$ = &ast.FunctionExpr{ParList: $2, Stmts: $4}
  418. $$.SetLine($1.Pos.Line)
  419. $$.SetLastLine($5.Pos.Line)
  420. } |
  421. '(' ')' block TEnd {
  422. $$ = &ast.FunctionExpr{ParList: &ast.ParList{HasVargs: false, Names: []string{}}, Stmts: $3}
  423. $$.SetLine($1.Pos.Line)
  424. $$.SetLastLine($4.Pos.Line)
  425. }
  426. parlist:
  427. T3Comma {
  428. $$ = &ast.ParList{HasVargs: true, Names: []string{}}
  429. } |
  430. namelist {
  431. $$ = &ast.ParList{HasVargs: false, Names: []string{}}
  432. $$.Names = append($$.Names, $1...)
  433. } |
  434. namelist ',' T3Comma {
  435. $$ = &ast.ParList{HasVargs: true, Names: []string{}}
  436. $$.Names = append($$.Names, $1...)
  437. }
  438. tableconstructor:
  439. '{' '}' {
  440. $$ = &ast.TableExpr{Fields: []*ast.Field{}}
  441. $$.SetLine($1.Pos.Line)
  442. } |
  443. '{' fieldlist '}' {
  444. $$ = &ast.TableExpr{Fields: $2}
  445. $$.SetLine($1.Pos.Line)
  446. }
  447. fieldlist:
  448. field {
  449. $$ = []*ast.Field{$1}
  450. } |
  451. fieldlist fieldsep field {
  452. $$ = append($1, $3)
  453. } |
  454. fieldlist fieldsep {
  455. $$ = $1
  456. }
  457. field:
  458. TIdent '=' expr {
  459. $$ = &ast.Field{Key: &ast.StringExpr{Value:$1.Str}, Value: $3}
  460. $$.Key.SetLine($1.Pos.Line)
  461. } |
  462. '[' expr ']' '=' expr {
  463. $$ = &ast.Field{Key: $2, Value: $5}
  464. } |
  465. expr {
  466. $$ = &ast.Field{Value: $1}
  467. }
  468. fieldsep:
  469. ',' {
  470. $$ = ","
  471. } |
  472. ';' {
  473. $$ = ";"
  474. }
  475. %%
  476. func TokenName(c int) string {
  477. if c >= TAnd && c-TAnd < len(yyToknames) {
  478. if yyToknames[c-TAnd] != "" {
  479. return yyToknames[c-TAnd]
  480. }
  481. }
  482. return string([]byte{byte(c)})
  483. }