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