{
open Asm
open Asmpars
let keywords_ri = List.map (fun (k,o) -> (k ^ "i",o)) keywords_r
let keywords = [
"pop",POP;
"push",PUSH;
"incri",INCRI;
"shi",SHI;
"j",JJ;
"jal",JAL;
"jr",JR;
"jalr",JALR;
"lw",LW;
"sw",SW;
"lb",LB;
"sb",SB;
"not",NOT;
"lil",LIL;
"lilz",LILZ;
"liu",LIU;
"liuz",LIUZ;
"lra",LRA;
"li",LI;
"move",MOVE;
"jz",JZ;
"jnz",JNZ;
"_clock",INT 0x4000;
"_input",INT 0x4100;
"_output",INT 0x4102;
"word",WORD;
"byte",BYTE;
"hlt",HLT;
"ascii",ASCII
]
let regs = [
"Z",0;
"RA",6;
"F",6;
"A",1;
"B",2;
"C",3;
"D",4;
"E",5;
"G",7;
"SP",7
]
let vald d = Char.code d - (Char.code '0')
let valh d =
let c = Char.code d in
if c >= Char.code '0' && c <= Char.code '9' then c - (Char.code '0')
else if c >= Char.code 'a' && c <= Char.code 'f' then c - (Char.code 'a') + 10
else c - (Char.code 'A') + 10
let read_16 n =
let res = ref 0 in
for i = 0 to String.length n - 1 do
res := 16 * !res;
let v = valh n.[i] in
res := !res + v
done;
!res
let read_2 n =
let res = ref 0 in
for i = 0 to String.length n - 1 do
res := 2 * !res;
let v = Char.code n.[i] - Char.code '0' in
res := !res + v
done;
!res
}
let digit = ['0'-'9']
let alpha = ['a'-'z' 'A'-'Z']
let hexdigit = ['a'-'f' 'A'-'F' '0'-'9']
rule token = parse
| eof { EOF }
| '#' { comment lexbuf }
| ['\t' '\r' ' '] { token lexbuf }
| ':' { COLON }
| '\n' { Lexing.new_line lexbuf; token lexbuf }
| ((['a'-'z'] | '_') (alpha | digit | '_')*) as id
{ try ROP (List.assoc id keywords_r)
with Not_found -> try RIOP (List.assoc id keywords_ri)
with Not_found -> try List.assoc id keywords
with Not_found -> ID id }
| "0x" (((hexdigit)+) as n)
{ INT (read_16 n) }
| (digit)+ as n { INT (int_of_string n) }
| "0b" (['0' '1']+ as n) { INT (read_2 n) }
| ['A'-'Z']+ as name { try REG (List.assoc name regs) with Not_found -> raise (Asm_error ("no reg " ^ name))}
| '$' (['0'-'7'] as n) { REG (Char.code n - (Char.code '0')) }
| ".text" { TEXT }
| ".data" { DATA }
| '-' { MINUS }
| '(' { LP }
| ')' { RP }
| '"' { str [] lexbuf }
and str acc = parse
| "\\\\" { str ('\\' :: acc) lexbuf }
| '"' { STR (List.rev ('\000' :: acc)) }
| "\\t" { str ('\t' :: acc) lexbuf }
| "\\n" { str ('\n' :: acc) lexbuf }
| "\\r" { str ('\r' :: acc) lexbuf }
| "\\\"" { str ('"' :: acc) lexbuf }
| "\\a" { str ((Char.chr 7) :: acc) lexbuf }
| '\\' (digit as d1) (digit as d2) (digit as d3)
{ let c = 100 * (vald d1) + 10 * (vald d2) + (vald d3) in
str ((Char.chr c) :: acc) lexbuf }
| "\\x" (hexdigit as h1) (hexdigit as h2)
{ let c = 16 * (valh h1) + (valh h2) in
str ((Char.chr c)::acc) lexbuf }
| eof { raise Lexer_error }
| '\n' { raise Lexer_error }
| [^ '\\' '"' '\n'] as c { str (c::acc) lexbuf }
and comment = parse
| eof { EOF }
| '\n' { Lexing.new_line lexbuf; token lexbuf }
| _ { comment lexbuf }