add string support
This commit is contained in:
parent
ed8b504ee9
commit
6a4c1744c4
10 changed files with 64 additions and 27 deletions
4
ast.ml
4
ast.ml
|
@ -3,6 +3,7 @@ type type_t =
|
||||||
| Void_t
|
| Void_t
|
||||||
| Int_t
|
| Int_t
|
||||||
| Bool_t
|
| Bool_t
|
||||||
|
| Str_t
|
||||||
| Func_t of type_t * type_t list
|
| Func_t of type_t * type_t list
|
||||||
|
|
||||||
module Syntax = struct
|
module Syntax = struct
|
||||||
|
@ -12,6 +13,7 @@ module Syntax = struct
|
||||||
| Void
|
| Void
|
||||||
| Int of int
|
| Int of int
|
||||||
| Bool of bool
|
| Bool of bool
|
||||||
|
| Str of string
|
||||||
|
|
||||||
type expr =
|
type expr =
|
||||||
| Val of
|
| Val of
|
||||||
|
@ -79,6 +81,7 @@ module V1 = struct
|
||||||
| Void
|
| Void
|
||||||
| Int of int
|
| Int of int
|
||||||
| Bool of bool
|
| Bool of bool
|
||||||
|
| Str of string
|
||||||
end
|
end
|
||||||
|
|
||||||
module V2 = struct
|
module V2 = struct
|
||||||
|
@ -86,6 +89,7 @@ module V2 = struct
|
||||||
| Void
|
| Void
|
||||||
| Int of int
|
| Int of int
|
||||||
| Bool of bool
|
| Bool of bool
|
||||||
|
| Data of string
|
||||||
end
|
end
|
||||||
|
|
||||||
module IR (P : Parameters) = struct
|
module IR (P : Parameters) = struct
|
||||||
|
|
|
@ -15,6 +15,7 @@ let compile_value = function
|
||||||
| Void -> [ Li (V0, 0) ]
|
| Void -> [ Li (V0, 0) ]
|
||||||
| Int n -> [ Li (V0, n) ]
|
| Int n -> [ Li (V0, n) ]
|
||||||
| Bool b -> [ Li (V0, if b then 1 else 0) ]
|
| Bool b -> [ Li (V0, if b then 1 else 0) ]
|
||||||
|
| Data l -> [ La (V0, Lbl l) ]
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let rec compile_expr env = function
|
let rec compile_expr env = function
|
||||||
|
|
|
@ -3,6 +3,7 @@ open Lexing
|
||||||
|
|
||||||
exception LexerError of char
|
exception LexerError of char
|
||||||
exception SemanticsError of string * Lexing.position
|
exception SemanticsError of string * Lexing.position
|
||||||
|
exception SyntaxError of string
|
||||||
|
|
||||||
let err msg pos =
|
let err msg pos =
|
||||||
Printf.eprintf
|
Printf.eprintf
|
||||||
|
@ -18,6 +19,7 @@ let rec string_of_type_t = function
|
||||||
| Void_t -> "void"
|
| Void_t -> "void"
|
||||||
| Int_t -> "int"
|
| Int_t -> "int"
|
||||||
| Bool_t -> "bool"
|
| Bool_t -> "bool"
|
||||||
|
| Str_t -> "str"
|
||||||
| Func_t (r, a) ->
|
| Func_t (r, a) ->
|
||||||
(if List.length a > 1 then "(" else "")
|
(if List.length a > 1 then "(" else "")
|
||||||
^ String.concat ", " (List.map string_of_type_t a)
|
^ String.concat ", " (List.map string_of_type_t a)
|
||||||
|
|
10
lexer.mll
10
lexer.mll
|
@ -19,6 +19,7 @@ rule token = parse
|
||||||
| "int" { Ltype (Int_t) }
|
| "int" { Ltype (Int_t) }
|
||||||
| "bool" { Ltype (Bool_t) }
|
| "bool" { Ltype (Bool_t) }
|
||||||
| "void" { Ltype (Void_t) }
|
| "void" { Ltype (Void_t) }
|
||||||
|
| "str" { Ltype (Str_t) }
|
||||||
| '{' { Lbracedeb }
|
| '{' { Lbracedeb }
|
||||||
| '}' { Lbracefin }
|
| '}' { Lbracefin }
|
||||||
| '(' { Lpardeb }
|
| '(' { Lpardeb }
|
||||||
|
@ -30,6 +31,7 @@ rule token = parse
|
||||||
| '-' { Lsub }
|
| '-' { Lsub }
|
||||||
| '*' { Lmul }
|
| '*' { Lmul }
|
||||||
| '/' { Ldiv }
|
| '/' { Ldiv }
|
||||||
|
| '"' { read_string (Buffer.create 16) lexbuf }
|
||||||
| ident as i { Lvar i }
|
| ident as i { Lvar i }
|
||||||
| '#' { comment lexbuf }
|
| '#' { comment lexbuf }
|
||||||
| _ as c { raise (LexerError c) }
|
| _ as c { raise (LexerError c) }
|
||||||
|
@ -38,3 +40,11 @@ and comment = parse
|
||||||
| eof { Lend }
|
| eof { Lend }
|
||||||
| '\n' { Lexing.new_line lexbuf; token lexbuf }
|
| '\n' { Lexing.new_line lexbuf; token lexbuf }
|
||||||
| _ { comment lexbuf }
|
| _ { comment lexbuf }
|
||||||
|
|
||||||
|
and read_string buffer = parse
|
||||||
|
| '"' { Lstr (Buffer.contents buffer) }
|
||||||
|
| [^ '"' '\\']+ { Buffer.add_string buffer (Lexing.lexeme lexbuf)
|
||||||
|
; read_string buffer lexbuf
|
||||||
|
}
|
||||||
|
| _ as c { raise (LexerError c) }
|
||||||
|
| eof { raise (SyntaxError "String is not terminated") }
|
||||||
|
|
1
main.ml
1
main.ml
|
@ -18,6 +18,7 @@ let () =
|
||||||
with
|
with
|
||||||
| LexerError c ->
|
| LexerError c ->
|
||||||
err (Printf.sprintf "Unrecognized char \"%c\"" c) (Lexing.lexeme_start_p buf)
|
err (Printf.sprintf "Unrecognized char \"%c\"" c) (Lexing.lexeme_start_p buf)
|
||||||
|
| SyntaxError s -> err (Printf.sprintf "%s" s) (Lexing.lexeme_start_p buf)
|
||||||
| Parser.Error -> err "Syntax error" (Lexing.lexeme_start_p buf)
|
| Parser.Error -> err "Syntax error" (Lexing.lexeme_start_p buf)
|
||||||
| SemanticsError (msg, pos) -> err msg pos
|
| SemanticsError (msg, pos) -> err msg pos
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
%token <int> Lint
|
%token <int> Lint
|
||||||
%token <bool> Lbool
|
%token <bool> Lbool
|
||||||
|
%token <string> Lstr
|
||||||
%token <Ast.type_t> Ltype
|
%token <Ast.type_t> Ltype
|
||||||
%token <string> Lvar
|
%token <string> Lvar
|
||||||
%token Lend Lassign Lsc Lreturn
|
%token Lend Lassign Lsc Lreturn
|
||||||
|
@ -15,7 +16,7 @@
|
||||||
%left Ladd Lsub Lmul Ldiv
|
%left Ladd Lsub Lmul Ldiv
|
||||||
|
|
||||||
%left Lbracedeb Lparfin Lbracefin Lreturn
|
%left Lbracedeb Lparfin Lbracefin Lreturn
|
||||||
%left Ltype Lbool Lint Lvar
|
%left Ltype Lbool Lint Lvar Lstr
|
||||||
|
|
||||||
%start prog
|
%start prog
|
||||||
|
|
||||||
|
@ -117,6 +118,11 @@ expr:
|
||||||
Val { value = Bool (b) ; pos = $startpos(b) }
|
Val { value = Bool (b) ; pos = $startpos(b) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* string */
|
||||||
|
| s = Lstr {
|
||||||
|
Val { value = Str (s) ; pos = $startpos(s) }
|
||||||
|
}
|
||||||
|
|
||||||
/* Variable */
|
/* Variable */
|
||||||
| v = Lvar {
|
| v = Lvar {
|
||||||
Var { name = v ; pos = $startpos(v) }
|
Var { name = v ; pos = $startpos(v) }
|
||||||
|
|
|
@ -8,6 +8,7 @@ let analyze_value = function
|
||||||
| Syntax.Void -> Void, Void_t
|
| Syntax.Void -> Void, Void_t
|
||||||
| Syntax.Int n -> Int n, Int_t
|
| Syntax.Int n -> Int n, Int_t
|
||||||
| Syntax.Bool b -> Bool b, Bool_t
|
| Syntax.Bool b -> Bool b, Bool_t
|
||||||
|
| Syntax.Str s -> Str s, Str_t
|
||||||
;;
|
;;
|
||||||
|
|
||||||
let rec analyze_expr env ua t = function
|
let rec analyze_expr env ua t = function
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
open Ast
|
open Ast
|
||||||
|
|
||||||
let collect_constant_strings code =
|
let collect_constant_strings code =
|
||||||
|
let counter = ref 0 in
|
||||||
let ccs_value = function
|
let ccs_value = function
|
||||||
| V1.Void -> V2.Void, []
|
| V1.Void -> V2.Void, []
|
||||||
| V1.Bool b -> V2.Bool b, []
|
| V1.Bool b -> V2.Bool b, []
|
||||||
| V1.Int n -> V2.Int n, []
|
| V1.Int n -> V2.Int n, []
|
||||||
|
| V1.Str s ->
|
||||||
|
incr counter;
|
||||||
|
let lbl = "str" ^ string_of_int !counter in
|
||||||
|
V2.Data lbl, [ lbl, Mips.Asciiz s ]
|
||||||
in
|
in
|
||||||
let rec ccs_expr = function
|
let rec ccs_expr = function
|
||||||
| IR1.Val v ->
|
| IR1.Val v ->
|
||||||
|
|
3
tests/20_str.test
Normal file
3
tests/20_str.test
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
void main () {
|
||||||
|
str a = "bonjour!";
|
||||||
|
}
|
4
tests/21_bad-str.test
Normal file
4
tests/21_bad-str.test
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
void main () {
|
||||||
|
# Error on line 3 col 28: String is not terminated.
|
||||||
|
str a = "au revoir !;
|
||||||
|
}
|
Reference in a new issue