-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpcc.ml
84 lines (78 loc) · 2.95 KB
/
pcc.ml
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
open Lexing
open Lexer
open Parser
open TypeChecker
open Format
open Codegen
open AsmPrinter
let print_position (pos : Lexing.position) : unit =
printf "File \"%s\", line %d, characters %d-%d:\n"
(pos.pos_fname) (pos.pos_lnum)
(pos.pos_cnum) (pos.pos_cnum + 1)
let print_loc (loc : Lexing.position * Lexing.position) : unit =
printf "File \"%s\", line %d, characters %d-%d:\n"
((fst loc).pos_fname) ((fst loc).pos_lnum)
((fst loc).pos_cnum) ((snd loc).pos_cnum)
(* transform "path/to/name.c" into "name.s" *)
let asm_filename (c_filename : string) : string =
let len = String.length c_filename in
String.sub c_filename 0 (len - 2) ^ ".s"
(* let asm_filename (c_filename : string) : string =
let len = String.length c_filename in
if String.contains c_filename '/' then
let start = String.rindex_from c_filename (len - 1) '/' in
String.sub c_filename (start + 1) (len - start - 3) ^ ".s"
else
String.sub c_filename 0 (len - 2) ^ ".s" *)
let () =
let parse_only = Array.mem "--parse-only" Sys.argv in
let type_only = Array.mem "--type-only" Sys.argv in
match List.filter
(fun a -> not (List.mem a ["--parse-only"; "--type-only"]))
(List.tl (Array.to_list Sys.argv)) with
| [] | _::_::_ ->
print_endline "Usage: petitc [--parse-only] [--type-only] <filename.c>";
exit 3
| [filename] ->
if parse_only && type_only then begin
print_endline "Cannot have both --parse-only and --type-only at the same time.";
exit 3
end (**);
let file = open_in filename in
let buf = Lexing.from_channel ~with_positions:true file in
Lexing.set_position buf {Lexing.pos_fname = filename; pos_lnum = 1; pos_bol = 0; pos_cnum = 0};
Lexing.set_filename buf filename;
(* let buf = Lexing.from_channel file in *)
try
let file_ast = Parser.file Lexer.token buf in
close_in file;
if not parse_only then begin
try
let (funcs, id_of_main) = typecheck_file file_ast in
if type_only then
exit 0
else
let prog = compile_file_assoc_list funcs in
match prog with
| None -> failwith "unreachable (compile_file returned none)"
| Some prog -> let out = open_out (asm_filename filename) in
print_prog out prog id_of_main
with
| Typing_error (loc, msg) ->
print_loc loc;
printf "Typing error: %s\n" msg;
exit 1
| Linking_error msg ->
printf "Linking error: %s\n" msg;
exit 1
end
with
(* | Lexer_error pos ->
print_pos s;
printf "Syntax error." *)
| Custom_lexing_error (loc, msg) ->
print_loc loc;
printf "Syntax error: %s\n" msg;
exit 1
| Parser.Error -> printf "Parsing error\n"; (* to do: how do i get the position? *)
exit 1