CC = cc
BISON ?= $(firstword $(wildcard /opt/homebrew/opt/bison/bin/bison /usr/local/opt/bison/bin/bison) bison)
FLEX ?= flex
CFLAGS ?= -std=c11 -O2 -g -Wall -Wextra -Wpedantic
CPPFLAGS += -I. -Ibuild -D_POSIX_C_SOURCE=200809L
PYTHON ?= python3

OBJECTS = build/lang.o build/parser.o build/lexer.o build/parser_driver.o build/print.o build/main.o

.PHONY: all test clean sanitize
all: cparser

build:
	mkdir -p build

build/parser.c: parser.y lang.h parser_driver.h | build
	$(BISON) -Wall -Werror=conflicts-sr -Werror=conflicts-rr -d -v --defines=build/parser.h -o $@ $<

build/parser.h: build/parser.c
	@test -f $@ || $(BISON) -d --defines=$@ -o build/parser.c parser.y

build/lexer.c: lexer.l build/parser.h Makefile | build
	$(FLEX) --header-file=build/lexer.h -o $@ $<

build/lexer.h: build/lexer.c
	@test -f $@ || $(FLEX) --header-file=$@ -o build/lexer.c lexer.l

build/lexer.o: build/lexer.c build/parser.h build/lexer.h
	$(CC) $(CPPFLAGS) $(CFLAGS) -Wno-sign-compare -c $< -o $@

build/parser.o: build/parser.c build/parser.h build/lexer.h
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

build/parser_driver.o: build/lexer.h

build/%.o: %.c lang.h parser_driver.h print.h build/parser.h | build
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

cparser: $(OBJECTS)
	$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@

build/test_ast: tests/test_ast.c $(filter-out build/main.o,$(OBJECTS))
	$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $^ -o $@

test: cparser build/test_ast
	./build/test_ast
	$(PYTHON) tests/check.py ./cparser

sanitize:
	$(MAKE) clean
	$(MAKE) CFLAGS='-std=c11 -O1 -g -Wall -Wextra -Wpedantic -fsanitize=address,undefined -fno-omit-frame-pointer' test

clean:
	rm -rf build cparser
