add project startup
This commit is contained in:
parent
a37aba9177
commit
1acd0af734
11 changed files with 145 additions and 0 deletions
10
ast.ml
Normal file
10
ast.ml
Normal file
|
@ -0,0 +1,10 @@
|
|||
module Syntax = struct
|
||||
type expr =
|
||||
| Int of { value: int
|
||||
; pos: Lexing.position }
|
||||
end
|
||||
|
||||
module IR = struct
|
||||
type expr =
|
||||
| Int of int
|
||||
end
|
7
baselib.ml
Normal file
7
baselib.ml
Normal file
|
@ -0,0 +1,7 @@
|
|||
open Ast
|
||||
|
||||
module Env = Map.Make(String)
|
||||
|
||||
let _types_ = Env.empty
|
||||
|
||||
let builtins = []
|
12
compiler.ml
Normal file
12
compiler.ml
Normal file
|
@ -0,0 +1,12 @@
|
|||
open Ast.IR
|
||||
open Mips
|
||||
|
||||
module Env = Map.Make(String)
|
||||
|
||||
let rec compile_expr e =
|
||||
match e with
|
||||
| Int n -> [ Li (V0, n) ]
|
||||
|
||||
let compile ir =
|
||||
{ text = Baselib.builtins @ compile_expr ir
|
||||
; data = [] }
|
15
lexer.mll
Normal file
15
lexer.mll
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
open Lexing
|
||||
open Parser
|
||||
|
||||
exception Error of char
|
||||
}
|
||||
|
||||
let num = ['0'-'9']
|
||||
|
||||
rule token = parse
|
||||
| eof { Lend }
|
||||
| [ ' ' '\t' ] { token lexbuf }
|
||||
| '\n' { Lexing.new_line lexbuf; token lexbuf }
|
||||
| num+ as n { Lint (int_of_string n) }
|
||||
| _ as c { raise (Error c) }
|
30
main.ml
Normal file
30
main.ml
Normal file
|
@ -0,0 +1,30 @@
|
|||
(* ocamlbuild -use-menhir test.byte *)
|
||||
|
||||
open Lexing
|
||||
open Ast
|
||||
|
||||
let err msg pos =
|
||||
Printf.eprintf "Error on line %d col %d: %s.\n"
|
||||
pos.pos_lnum (pos.pos_cnum - pos.pos_bol) msg ;
|
||||
exit 1
|
||||
|
||||
let () =
|
||||
if (Array.length Sys.argv) != 2 then begin
|
||||
Printf.eprintf "Usage: %s <file>\n" Sys.argv.(0) ;
|
||||
exit 1
|
||||
end;
|
||||
let f = open_in Sys.argv.(1) in
|
||||
let buf = Lexing.from_channel f in
|
||||
try
|
||||
let parsed = Parser.prog Lexer.token buf in
|
||||
close_in f ;
|
||||
let ast = Semantics.analyze parsed in
|
||||
let asm = Compiler.compile ast in
|
||||
Mips.emit Stdlib.stdout asm
|
||||
with
|
||||
| Lexer.Error c ->
|
||||
err (Printf.sprintf "unrecognized char '%c'" c) (Lexing.lexeme_start_p buf)
|
||||
| Parser.Error ->
|
||||
err "syntax error" (Lexing.lexeme_start_p buf)
|
||||
| Semantics.Error (msg, pos) ->
|
||||
err msg pos
|
32
mips.ml
Normal file
32
mips.ml
Normal file
|
@ -0,0 +1,32 @@
|
|||
type reg =
|
||||
| V0
|
||||
|
||||
type label = string
|
||||
|
||||
type instr =
|
||||
| Li of reg * int
|
||||
|
||||
type directive =
|
||||
| Asciiz of string
|
||||
|
||||
type decl = label * directive
|
||||
|
||||
type asm = { text: instr list ; data: decl list }
|
||||
|
||||
let ps = Printf.sprintf (* alias raccourci *)
|
||||
|
||||
let fmt_reg = function
|
||||
| V0 -> "$v0"
|
||||
|
||||
let fmt_instr = function
|
||||
| Li (r, i) -> ps " li %s, %d" (fmt_reg r) i
|
||||
|
||||
let fmt_dir = function
|
||||
| Asciiz (s) -> ps ".asciiz \"%s\"" s
|
||||
|
||||
let emit oc asm =
|
||||
Printf.fprintf oc ".text\n.globl main\nmain:\n" ;
|
||||
List.iter (fun i -> Printf.fprintf oc "%s\n" (fmt_instr i)) asm.text ;
|
||||
Printf.fprintf oc " move $a0, $v0\n li $v0, 1\n syscall\n jr $ra\n" ;
|
||||
Printf.fprintf oc "\n.data\n" ;
|
||||
List.iter (fun (l, d) -> Printf.fprintf oc "%s: %s\n" l (fmt_dir d)) asm.data
|
23
parser.mly
Normal file
23
parser.mly
Normal file
|
@ -0,0 +1,23 @@
|
|||
%{
|
||||
open Ast
|
||||
open Ast.Syntax
|
||||
%}
|
||||
|
||||
%token <int> Lint
|
||||
%token Lend
|
||||
|
||||
%start prog
|
||||
|
||||
%type <Ast.Syntax.expr> prog
|
||||
|
||||
%%
|
||||
|
||||
prog:
|
||||
| e = expr; Lend { e }
|
||||
;
|
||||
|
||||
expr:
|
||||
| n = Lint {
|
||||
Int { value = n ; pos = $startpos(n) }
|
||||
}
|
||||
;
|
12
semantics.ml
Normal file
12
semantics.ml
Normal file
|
@ -0,0 +1,12 @@
|
|||
open Ast
|
||||
open Ast.IR
|
||||
open Baselib
|
||||
|
||||
exception Error of string * Lexing.position
|
||||
|
||||
let rec analyze_expr expr env =
|
||||
match expr with
|
||||
| Syntax.Int n -> Int n.value
|
||||
|
||||
let analyze parsed =
|
||||
analyze_expr parsed Baselib._types_
|
1
tests/err-lex.test
Normal file
1
tests/err-lex.test
Normal file
|
@ -0,0 +1 @@
|
|||
abc
|
1
tests/err-syntax.test
Normal file
1
tests/err-syntax.test
Normal file
|
@ -0,0 +1 @@
|
|||
1312 42
|
2
tests/int.test
Normal file
2
tests/int.test
Normal file
|
@ -0,0 +1,2 @@
|
|||
1312
|
||||
|
Reference in a new issue