88 lines
2.9 KiB
OCaml
88 lines
2.9 KiB
OCaml
(*sprejme .asm file in pretvori v neko interno predstavitev*)
|
|
|
|
type line = {
|
|
line_no : int;
|
|
label : string option;
|
|
opcode : string;
|
|
operand : string list; (*list of operands*)
|
|
comment : string option;
|
|
mutable loc : int option; (* assigned in pass1 *)
|
|
}
|
|
|
|
|
|
let parseLine (lineNo : int) (line : string) : line option=
|
|
let trimmedLine = String.trim (line) in (*Znebimo se zacetnih in koncnih presledkov*)
|
|
(*empty line or comment line*)
|
|
if trimmedLine = "" then None
|
|
else if trimmedLine.[0] = '.' then
|
|
Some {
|
|
line_no = lineNo;
|
|
label = None;
|
|
opcode = "COMMENT";
|
|
operand = [];
|
|
comment = Some trimmedLine ;
|
|
loc = None;
|
|
|
|
}
|
|
|
|
else
|
|
(*razdelimo na kodo in komentar za njo*)
|
|
let code, (comment : string option) =
|
|
match String.index_opt line '.' with
|
|
| None -> line, None
|
|
| Some i ->
|
|
(*izluščimo komentar in komentarju odstranimo predhodnje presledke*)
|
|
let c = String.sub line i (String.length line - i) |> String.trim in
|
|
(*izluščimo kodo, je pa ne trimamo, ker rabimo prvo presledek da razločimo opcode od label-a*)
|
|
let code = String.sub line 0 i in
|
|
code, Some c
|
|
in
|
|
|
|
let tokens =
|
|
code
|
|
|> String.map (fun c -> if c = ',' then ' ' else c) (*zamenja , z ' ' da lepo parsamo npr RMO A, B*)
|
|
|> String.split_on_char ' '
|
|
|> List.map String.trim (* removes surrounding spaces and \r *)
|
|
|> List.filter (fun s -> s <> "") in
|
|
match tokens with
|
|
| [] ->
|
|
Some{
|
|
line_no = lineNo;
|
|
label = None;
|
|
opcode = "";
|
|
operand = [];
|
|
comment;
|
|
loc = None;
|
|
}
|
|
| x :: xs ->
|
|
if code.[0] <> ' ' && code.[0] <> '\t' then (*pogledamo whitespace ali tab*)
|
|
(*se ne začne z presledkom ali tab -> imamo labelo*)
|
|
let label = Some x in
|
|
match xs with
|
|
(*samo labela*)
|
|
| [] -> Some{line_no = lineNo; label = label; opcode = ""; operand = []; comment = comment; loc = None}
|
|
(*labela + opcode + še nekaj*)
|
|
| opcode :: operand ->
|
|
Some{line_no = lineNo; label = label;opcode = opcode; operand = operand; comment = comment; loc = None}
|
|
else
|
|
(*nimamo labele*)
|
|
let opcode = x in
|
|
let operand = xs in
|
|
Some{line_no = lineNo; label = None; opcode = opcode; operand = operand; comment = comment; loc = None}
|
|
|
|
(*naredi listo line-ov iz filename*)
|
|
let parser (filename : string) : line list =
|
|
let ic = open_in filename in
|
|
let rec loop line_no acc =
|
|
match input_line ic with
|
|
| line ->
|
|
begin
|
|
match parseLine line_no line with
|
|
| Some parsed_line -> loop (line_no + 1) (parsed_line :: acc)
|
|
| None -> loop (line_no + 1) acc
|
|
end
|
|
| exception End_of_file ->
|
|
close_in ic;
|
|
List.rev acc
|
|
in
|
|
loop 1 []
|