parser_test.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. package parser
  2. import (
  3. "testing"
  4. "fmt"
  5. "code.osinet.fr/fgm/waiig15/ast"
  6. "code.osinet.fr/fgm/waiig15/lexer"
  7. )
  8. func TestLetStatements(t *testing.T) {
  9. // Try removing the ident, the =, or both, to get human-readable errors.
  10. input := `
  11. let x = 5;
  12. let y = 10;
  13. let foobar = 838383;
  14. `
  15. l := lexer.New(input)
  16. p := New(l)
  17. program := p.ParseProgram()
  18. checkParserErrors(t, p)
  19. if program == nil {
  20. t.Fatalf("ParseProgram() returned nil.")
  21. }
  22. if len(program.Statements) != 3 {
  23. t.Fatalf("program.Statements does not contain 3 statements, got=%d",
  24. len(program.Statements))
  25. }
  26. tests := []struct {
  27. expectedIdentifier string
  28. }{
  29. {"x"},
  30. {"y"},
  31. {"foobar"},
  32. }
  33. for i, tt := range tests {
  34. stmt := program.Statements[i]
  35. if !testLetStatement(t, stmt, tt.expectedIdentifier) {
  36. return
  37. }
  38. }
  39. }
  40. func TestReturnStatements(t *testing.T) {
  41. // Try removing the ident, the =, or both, to get human-readable errors.
  42. input := `
  43. return 5;
  44. return 10;
  45. return 993322;
  46. `
  47. l := lexer.New(input)
  48. p := New(l)
  49. program := p.ParseProgram()
  50. checkParserErrors(t, p)
  51. if program == nil {
  52. t.Fatalf("ParseProgram() returned nil.")
  53. }
  54. if len(program.Statements) != 3 {
  55. t.Fatalf("program.Statements does not contain 3 statements, got=%d",
  56. len(program.Statements))
  57. }
  58. for _, stmt := range program.Statements {
  59. // Statement is an interface, we need a concrete type for the value, and
  60. // our test input only contains Let statements.
  61. returnStmt, ok := stmt.(*ast.ReturnStatement)
  62. if !ok {
  63. t.Errorf("s not *ast.ReturnStatement{}, got=%T", stmt)
  64. continue
  65. }
  66. if returnStmt.TokenLiteral() != "return" {
  67. t.Errorf("s.TokenLiteral not 'return', got=%q",
  68. stmt.TokenLiteral())
  69. }
  70. }
  71. }
  72. func TestIdentifierExpression(t *testing.T) {
  73. const input = "foobar"
  74. l := lexer.New(input)
  75. p := New(l)
  76. program := p.ParseProgram()
  77. checkParserErrors(t, p)
  78. if len(program.Statements) != 1 {
  79. t.Fatalf("program has not enough statements. got=%d",
  80. len(program.Statements))
  81. }
  82. stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
  83. if !ok {
  84. t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. Got=%T",
  85. program.Statements)
  86. }
  87. ident, ok := stmt.Expression.(*ast.Identifier)
  88. if !ok {
  89. t.Fatalf("exp not *ast.Identifier. got=%T", stmt.Expression)
  90. }
  91. // Why not use input instead of inline strings ?
  92. if ident.Value != input {
  93. t.Errorf("ident.Value not %s. got=%s", input,
  94. ident.Value)
  95. }
  96. if ident.TokenLiteral() != input {
  97. t.Errorf("ident.TokenLiteral not %s. got=%s", input,
  98. ident.TokenLiteral())
  99. }
  100. }
  101. func TestIntegerLiteralExpression(t *testing.T) {
  102. input := "5;"
  103. l := lexer.New(input)
  104. p := New(l)
  105. program := p.ParseProgram()
  106. checkParserErrors(t, p)
  107. if len(program.Statements) != 1 {
  108. t.Fatalf("program does not have 1 statement. got=%d",
  109. len(program.Statements))
  110. }
  111. stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
  112. if !ok {
  113. t.Fatalf("program.Statements[0] is not *ast.ExpressionStatement. got=%T",
  114. program.Statements[0])
  115. }
  116. literal, ok := stmt.Expression.(*ast.IntegerLiteral)
  117. if !ok {
  118. t.Fatalf("exp not *ast.IntegerLiteral. got=%T", stmt.Expression)
  119. }
  120. if literal.Value != 5 {
  121. t.Errorf("literal.Value not %d. got=%d", 5, literal.Value)
  122. }
  123. if literal.TokenLiteral() != "5" {
  124. t.Errorf("literal.TokenLiteral not %s. got=%s", "5",
  125. literal.TokenLiteral())
  126. }
  127. }
  128. func TestParsingPrefixExpressions(t *testing.T) {
  129. prefixTests := []struct {
  130. input string
  131. operator string
  132. integerValue int64
  133. }{
  134. {"!5", "!", 5},
  135. {"-15", "-", 15},
  136. }
  137. for _, tt := range prefixTests {
  138. l := lexer.New(tt.input)
  139. p := New(l)
  140. program := p.ParseProgram()
  141. checkParserErrors(t, p)
  142. if len(program.Statements) != 1 {
  143. t.Fatalf("program.Statements does not contain %d statements, got=%d\n",
  144. 1, len(program.Statements))
  145. }
  146. stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
  147. if !ok {
  148. t.Fatalf("program.STatements[0] is not ast.ExpressionStatement. got=%T",
  149. program.Statements[0])
  150. }
  151. exp, ok := stmt.Expression.(*ast.PrefixExpression)
  152. if !ok {
  153. t.Fatalf("stms is not ast.PrefixExpression. got=%T",
  154. stmt.Expression)
  155. }
  156. if exp.Operator != tt.operator {
  157. t.Fatalf("exp.Operator is not '%s'. got=%s",
  158. tt.operator, exp.Operator)
  159. }
  160. if !testIntegerLiteral(t, exp.Right, tt.integerValue) {
  161. return
  162. }
  163. }
  164. }
  165. func TestParsingInfixExpressions(t *testing.T) {
  166. infixTests := []struct {
  167. input string
  168. leftValue int64
  169. operator string
  170. rightValue int64
  171. }{
  172. {"5 + 5;", 5, "+", 5},
  173. {"5 - 5;", 5, "-", 5},
  174. {"5 * 5;", 5, "*", 5},
  175. {"5 / 5;", 5, "/", 5},
  176. {"5 > 5;", 5, ">", 5},
  177. {"5 < 5;", 5, "<", 5},
  178. {"5 == 5;", 5, "==", 5},
  179. {"5 != 5;", 5, "!=", 5},
  180. }
  181. for _, tt := range infixTests {
  182. l := lexer.New(tt.input)
  183. p := New(l)
  184. program := p.ParseProgram()
  185. checkParserErrors(t, p)
  186. if len(program.Statements) != 1 {
  187. t.Fatalf("program.Statements does not contain %d statements. got=%d",
  188. 1, len(program.Statements))
  189. }
  190. stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
  191. if !ok {
  192. t.Fatalf("program.Statements[0] is not expressionStatement. got=%T",
  193. program.Statements[0])
  194. }
  195. exp, ok := stmt.Expression.(*ast.InfixExpression)
  196. if !ok {
  197. t.Fatalf("exp is not infixExpression. got=%T", stmt.Expression)
  198. }
  199. // Why no error ?
  200. if !testIntegerLiteral(t, exp.Left, tt.leftValue) {
  201. return
  202. }
  203. if exp.Operator != tt.operator {
  204. t.Fatalf("exp.Operator is not '%s'. got=%s", tt.operator,
  205. exp.Operator)
  206. }
  207. // Why no error ?
  208. if !testIntegerLiteral(t, exp.Right, tt.rightValue) {
  209. return
  210. }
  211. }
  212. }
  213. func TestOperatorPrecedenceParsing(t *testing.T) {
  214. tests := []struct {
  215. input string
  216. expected string
  217. }{
  218. {
  219. "-a * b",
  220. "((-a) * b)",
  221. },
  222. {
  223. "!-a",
  224. "(!(-a))",
  225. },
  226. {
  227. "a + b + c",
  228. "((a + b) + c)",
  229. },
  230. {
  231. "a + b - c",
  232. "((a + b) - c)",
  233. },
  234. {
  235. "a * b * c",
  236. "((a * b) * c)",
  237. },
  238. {
  239. "a * b / c",
  240. "((a * b) / c)",
  241. },
  242. {
  243. "a + b / c",
  244. "(a + (b / c))",
  245. },
  246. {
  247. "a + b * c + d / e - f",
  248. "(((a + (b * c)) + (d / e)) - f)",
  249. },
  250. {
  251. "3 + 4; -5 * 5",
  252. "(3 + 4)((-5) * 5)",
  253. },
  254. {
  255. "5 > 4 == 3 < 4",
  256. "((5 > 4) == (3 < 4))",
  257. },
  258. {
  259. "5 < 4 != 3 > 4",
  260. "((5 < 4) != (3 > 4))",
  261. },
  262. {
  263. "3 + 4 * 5 == 3 * 1 + 4 * 5",
  264. "((3 + (4 * 5)) == ((3 * 1) + (4 * 5)))",
  265. },
  266. }
  267. for _, tt := range tests {
  268. l := lexer.New(tt.input)
  269. p := New(l)
  270. program := p.ParseProgram()
  271. checkParserErrors(t, p)
  272. actual := program.String()
  273. if actual != tt.expected {
  274. t.Errorf("expected=%q, got=%q", tt.expected, actual)
  275. }
  276. }
  277. }
  278. func testLetStatement(t *testing.T, s ast.Statement, name string) bool {
  279. if s.TokenLiteral() != "let" {
  280. t.Errorf("s.TokenLiteral not 'let'. got=%q", s.TokenLiteral())
  281. return false
  282. }
  283. // Statement is an interface, we need a concrete type for the value, and we
  284. // just determined this looked like a LetStatement.
  285. letStmt, ok := s.(*ast.LetStatement)
  286. if !ok {
  287. t.Errorf("s not *ast.LetStatement. got=%T", s)
  288. return false
  289. }
  290. if letStmt.Name.Value != name {
  291. t.Errorf("letStmt.Name.Value not '%s'. got=%s", name, letStmt.Name.Value)
  292. return false
  293. }
  294. if letStmt.Name.TokenLiteral() != name {
  295. t.Errorf("letStmt.Name.TokenLiteral() not '%s'. got=%s",
  296. name, letStmt.Name.TokenLiteral())
  297. return false
  298. }
  299. return true
  300. }
  301. func testInfixExpression(
  302. t *testing.T,
  303. exp ast.Expression,
  304. left interface{},
  305. operator string,
  306. right interface{},
  307. ) bool {
  308. opExp, ok := exp.(*ast.InfixExpression)
  309. if !ok {
  310. t.Errorf("exp is not ast.InfixExpression. got=%T(%s)", exp, exp)
  311. return false
  312. }
  313. if !testLiteralExpression(t, opExp.Left, left) {
  314. return false
  315. }
  316. if opExp.Operator != operator {
  317. t.Errorf("exp.Operator is not '%s'. got=%q", operator, opExp.Operator)
  318. return false
  319. }
  320. if !testLiteralExpression(t, opExp.Right, right) {
  321. return false
  322. }
  323. return true
  324. }
  325. func testLiteralExpression(
  326. t *testing.T,
  327. exp ast.Expression,
  328. expected interface{},
  329. ) bool {
  330. switch v := expected.(type) {
  331. case int:
  332. return testIntegerLiteral(t, exp, int64(v))
  333. case int64:
  334. return testIntegerLiteral(t, exp, v)
  335. case string:
  336. return testIdentifier(t, exp, v)
  337. }
  338. t.Errorf("type of exp not handled. got=%T", exp)
  339. return false
  340. }
  341. func testIntegerLiteral(t *testing.T, il ast.Expression, value int64) bool {
  342. integ, ok := il.(*ast.IntegerLiteral)
  343. if !ok {
  344. t.Errorf("il not *ast.IntegerLiteral. got=%T", il)
  345. return false
  346. }
  347. if integ.Value != value {
  348. t.Errorf("integ.Value not %d. got=%d", value, integ.Value)
  349. return false
  350. }
  351. if integ.TokenLiteral() != fmt.Sprintf("%d", value) {
  352. t.Errorf("integ.TokenLiteral not %d. got=%s", value,
  353. integ.TokenLiteral())
  354. return false
  355. }
  356. return true
  357. }
  358. func testIdentifier(t *testing.T, exp ast.Expression, value string) bool {
  359. ident, ok := exp.(*ast.Identifier)
  360. if !ok {
  361. t.Errorf("exp not *ast.Identifier. got=%T", exp)
  362. return false
  363. }
  364. if ident.Value != value {
  365. t.Errorf("ident.Value not %s. got=%s", value, ident.Value)
  366. return false
  367. }
  368. if ident.TokenLiteral() != value {
  369. t.Errorf("ident.TokenLiteral not %s. got=%s", value,
  370. ident.TokenLiteral())
  371. return false
  372. }
  373. return true
  374. }
  375. func checkParserErrors(t *testing.T, p *Parser) {
  376. errors := p.Errors()
  377. if len(errors) == 0 {
  378. return
  379. }
  380. t.Errorf("parser has %d errors", len(errors))
  381. for _, msg := range errors {
  382. t.Errorf("parser error: %q", msg)
  383. }
  384. t.FailNow()
  385. }