SPO_JakaFurlan/ass3/zbirnik/_build/default/lib/parser.ml
Jaka Furlan c707e3253c first
2025-12-07 20:13:19 +01:00

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 []