package parser_tests

import (
	"blk/lexer"
	"blk/parser"
	"testing"
)

func TestOperatorPrecedenceParsing(t *testing.T) {
	tests := []struct {
		input    string
		expected string
	}{
		{
			"-a * b",
			"((-a) * b)",
		},
		{
			"!-a",
			"(!(-a))",
		},
		{
			"a + b + c",
			"((a + b) + c)",
		},
		{
			"a + b - c",
			"((a + b) - c)",
		},
		{
			"a * b * c",
			"((a * b) * c)",
		},
		{
			"a * b / c",
			"((a * b) / c)",
		},
		{
			"a + b / c",
			"(a + (b / c))",
		},
		{
			"a + b * c + d / e - f",
			"(((a + (b * c)) + (d / e)) - f)",
		},
		{
			"3 + 4 - 5 * 5",
			"((3 + 4) - (5 * 5))",
		},
		{
			"5 > 4 == 3 < 4",
			"((5 > 4) == (3 < 4))",
		},
		{
			"5 < 4 != 3 > 4",
			"((5 < 4) != (3 > 4))",
		},
		{
			"3 + 4 * 5 == 3 * 1 + 4 * 5",
			"((3 + (4 * 5)) == ((3 * 1) + (4 * 5)))",
		},
		{
			"3 + 4 * 5 == 3 * 1 + 4 * 5",
			"((3 + (4 * 5)) == ((3 * 1) + (4 * 5)))",
		},
		{
			"1 + (2 + 3) + 4",
			"((1 + (2 + 3)) + 4)",
		},
		{
			"(5 + 5) * 2",
			"((5 + 5) * 2)",
		},
		{
			"2 / (5 + 5)",
			"(2 / (5 + 5))",
		},
		{
			"-(5 + 5)",
			"(-(5 + 5))",
		},
		{
			"!(true == true)",
			"(!(true == true))",
		},
		{
			"true && !false",
			"(true && (!false))",
		},
		{
			"a + add(b * c) + d",
			"((a + add((b * c))) + d)",
		},
		{
			"add(a, b, 1, 2 * 3, 4 + 5, add(6, 7 * 8))",
			"add(a, b, 1, (2 * 3), (4 + 5), add(6, (7 * 8)))",
		},
		{
			"add(a + b + c * d / f + g)",
			"add((((a + b) + ((c * d) / f)) + g))",
		},
		{
			"add(a, c) < 0 && a < 0",
			"((add(a, c) < 0) && (a < 0))",
		},
		{
			"11 << 5 & ~5",
			"((11 << 5) & (~5))",
		},
		{
			"7 | 3 ^ 2",
			"(7 | (3 ^ 2))",
		},
		{
			"15 & 7 << 2",
			"(15 & (7 << 2))",
		},
		{
			"~8 | 4 >> 1",
			"((~8) | (4 >> 1))",
		},
		{
			"5 ^ 3 & 6",
			"(5 ^ (3 & 6))",
		},
		{
			"12 >> 2 | 9",
			"((12 >> 2) | 9)",
		},
		{
			"~0 & 255 << 8",
			"((~0) & (255 << 8))",
		},
		{
			"6 & 3 | 8 >> 2",
			"((6 & 3) | (8 >> 2))",
		},
		{
			"1 << 4 ^ 5 & 7",
			"((1 << 4) ^ (5 & 7))",
		},
		{
			"~15 | 3 << 1 & 14",
			"((~15) | ((3 << 1) & 14))",
		},
	}
	for _, tt := range tests {
		l := lexer.NewLexer("", tt.input)
		p := parser.NewParser(l.Tokenize(), "")
		program := p.Parse()
		actual := program.String()
		if actual != tt.expected {
			t.Errorf("expected=%q, got=%q", tt.expected, actual)
		}
	}
}
