This repository was archived by the owner on Oct 11, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathMakefile
More file actions
146 lines (127 loc) · 4.97 KB
/
Makefile
File metadata and controls
146 lines (127 loc) · 4.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
CC ?= $(shell command -v gcc)
CXX ?= $(shell command -v g++)
JSINTERP ?= $(shell command -v node)
CXX_FLAGS := -x c++ -Wno-write-strings
SHELL := $(shell echo $$SHELL)
.DEFAULT_GOAL := all
TESTS_PATH := test
LEXER_ASSERTS_PATH := lexer-assert
PARSER_ASSERTS_PATH := parser-assert
TESTS_ROOT := tests
TESTS := $(wildcard $(TESTS_ROOT)/**/$(TESTS_PATH)/*.js)
ERROR_LOG := error.log
TEMP_ERROR_LOG := temperror.log
PARSER_ERROR_LOG := error_parser.log
.checkdep:
ifndef CC
$(error gcc not installed)
endif
ifndef CXX
$(error g++ not installed)
endif
ifndef JSINTERP
$(warning babel not installed, test_all will not run)
endif
.checkbabeldep:
ifndef JSINTERP
$(error babel not installed, test_all will not run)
endif
all: .checkdep clean .build_prod
clean: .clean_prod
test_all: .checkdep .checkbabeldep clean .setup_tests .run_js_tests .run_lexer_tests .run_parser_tests .teardown_tests
test_lexer: .checkdep clean .setup_tests .run_lexer_tests .teardown_tests
test_parser: .checkdep clean .setup_tests .run_parser_tests .teardown_tests
simple: .checkdep clean .run_simple
test: .checkdep clean .setup_tests .run_lexer_tests .run_parser_tests .teardown_tests
generate: .bison .flex
.bison:
@bison -d grammar.y
$(info Parser Generated)
.flex:
@flex --header-file=lex.yy.h grammar.l
$(info Scanner Generated)
.clean_prod:
@rm -f grammar.tab.* && rm -f lex.yy.* && rm -f compiler
.build_prod: .bison .flex
@$(CXX) $(CXX_FLAGS) lex.yy.c grammar.tab.c utils.c main.cpp -o compiler -ll -ly
$(info Build Success)
.build_lexer_test: .bison .flex
@$(CXX) $(CXX_FLAGS) lex.yy.c grammar.tab.c utils.c test_lex.c -o tests/test_lex -ll -ly
$(info Build Lexer Success)
.build_parser_test: .bison .flex
@$(CXX) $(CXX_FLAGS) lex.yy.c grammar.tab.c utils.c test_parser.cpp -o tests/test_parser -ll -ly
$(info Build Parser Success)
# remove any previous ERROR_LOG and TEMP_ERROR_LOG, create new ERROR_LOG
.setup_tests:
@rm -f $(ERROR_LOG);
@rm -f $(TEMP_ERROR_LOG);
@touch $(ERROR_LOG);
# if ERROR_LOG is not empty, throw make error,
# otherwise if PARSER_ERROR_LOG is not empty, show info message
# otherwise indicate all tests are passed
.teardown_tests:
$(if $(shell if [ -s "./$(ERROR_LOG)" ]; then echo not empty; fi), \
$(error $(shell cat $(ERROR_LOG))), \
$(if $(shell if [ -s "./$(PARSER_ERROR_LOG)" ]; then echo not empty; fi), \
$(info Ignored some parser errors, see $(PARSER_ERROR_LOG) for details),\
$(info All Tests Passed)\
)\
)
# run babel transpiler on js files, if js file is invalid, it writes all stderr to ERROR_LOG
.run_js_tests:
$(foreach t, $(TESTS), \
$(shell $(JSINTERP) $(t) >> /dev/null 2>>$(ERROR_LOG);))
$(if $(shell if [ -s "./$(ERROR_LOG)" ]; then echo not empty; fi),\
$(error $(shell cat $(ERROR_LOG))),\
$(info All JS files are valid))
# run lexer tests, use diff to compare lexer dump to expected output
.run_lexer_tests: .build_lexer_test
$(info Running Lexer Tests)
$(foreach t, $(TESTS), \
$(eval ASSERT_FILE=$(subst /$(TESTS_PATH)/,/$(LEXER_ASSERTS_PATH)/, $(patsubst %.js, %.txt, $(t)))) \
$(shell diff $(ASSERT_FILE) <(./tests/test_lex < $(t))>> $(TEMP_ERROR_LOG) 2>&1;\
if [ -s "./$(TEMP_ERROR_LOG)" ]; then echo $(t) >> $(ERROR_LOG); \
cat $(TEMP_ERROR_LOG) >> $(ERROR_LOG); fi; \
rm -f $(TEMP_ERROR_LOG);\
)\
)
# test parseable tests, and create ast dump, log any error to ERROR_LOG
# if ast dump test is empty, show warning to indicate tests are not present
# test unparseable tests, if tests are parseable, show warning to indicate tests are parseable
.run_parser_tests: .build_parser_test
$(info Running Parser Tests)
$(foreach t, $(wildcard ./$(TESTS_ROOT)/parseable/$(TESTS_PATH)/*.js), \
$(eval ASSERT_FILE=$(subst /$(TESTS_PATH)/,/$(PARSER_ASSERTS_PATH)/, $(patsubst %.js, %.txt, $(t)))) \
$(if \
$(shell \
if [ -s "./$(ASSERT_FILE)" ]; then echo not empty; fi;\
),\
$(shell \
diff $(ASSERT_FILE) <(./tests/test_parser -d $(t))>> $(TEMP_ERROR_LOG) 2>&1;\
if [ -s "./$(TEMP_ERROR_LOG)" ]; then echo $(t) >> $(ERROR_LOG); \
cat $(TEMP_ERROR_LOG) >> $(ERROR_LOG); fi; \
rm -f $(TEMP_ERROR_LOG);\
),\
$(warning $(ASSERT_FILE) is missing, write a test!)\
)\
)
$(foreach t, $(wildcard ./$(TESTS_ROOT)/unparseable/$(TESTS_PATH)/*.js), \
$(if \
$(shell \
touch $(TEMP_ERROR_LOG);\
./tests/test_parser $(t) >> $(TEMP_ERROR_LOG) 2>&1;\
if [ -s "./$(TEMP_ERROR_LOG)" ]; then echo not empty; fi;\
echo $(t) >> $(PARSER_ERROR_LOG); \
cat $(TEMP_ERROR_LOG) >> $(PARSER_ERROR_LOG);\
rm -f $(TEMP_ERROR_LOG);\
),,\
$(warning $(t) is parseable, consider moving it to /parseable/, and write a test!)\
)\
)
.run_simple: .build_prod
$(info Running Simple Test)
@./compiler ./$(TESTS_ROOT)/parseable/$(TESTS_PATH)/string.js
@./compiler ./$(TESTS_ROOT)/parseable/$(TESTS_PATH)/simple.js
@./compiler ./$(TESTS_ROOT)/parseable/$(TESTS_PATH)/basic_if.js
@./compiler ./$(TESTS_ROOT)/parseable/$(TESTS_PATH)/while_basic_statement.js
@./compiler ./$(TESTS_ROOT)/unparseable/$(TESTS_PATH)/function_simple.js