datatype exp =
Var of ident
| ConstExp of Word32.word
+ | StringExp of string
| OpExp of oper * exp list
| Marked of (* Kane *) exp Mark.marked
| FuncCall of ident * (exp list)
datatype exp =
Var of ident
| ConstExp of Word32.word
+ | StringExp of string
| OpExp of oper * exp list
| Marked of exp Mark.marked
| FuncCall of ident * (exp list)
fun pp_exp (Var(id)) = pp_ident id
| pp_exp (ConstExp(c)) = Word32Signed.toString c
+ | pp_exp (StringExp(s)) = "\"" ^ s ^ "\""
| pp_exp (OpExp(oper, [e])) =
pp_oper oper ^ "(" ^ pp_exp e ^ ")"
| pp_exp (OpExp(oper, [e1,e2])) =
| SEMI
| INTNUM of Word32.word
| IDENT of Symbol.symbol
+ | STRING of string
| RETURN
| PLUS | MINUS | STAR | SLASH | PERCENT | LSH | RSH | LOGOR | LOGAND | BITAND | BITXOR | BITOR | BITNOT | BANG
| ASSIGN | PLUSEQ | MINUSEQ | STAREQ | SLASHEQ | PERCENTEQ | LSHEQ | RSHEQ | BITANDEQ | BITXOREQ | BITOREQ
| LBRACE | RBRACE
| LPAREN | RPAREN
| UNARY | ASNOP (* dummy *)
- | EXTERN | VAR | INT | QUESTION | COLON | COMMA | STRUCT | NULL | LBRACKET | RBRACKET | ARROW | DOT | NEW
+ | EXTERN | VAR | INT | TSTRING | QUESTION | COLON | COMMA | STRUCT | NULL | LBRACKET | RBRACKET | ARROW | DOT | NEW
| PLUSPLUS | MINUSMINUS
%nonterm
| programx function (AUP.append_function programx function)
vtype : INT (T.Int)
+ | TSTRING (T.String)
| IDENT (T.Typedef IDENT)
| vtype STAR (T.Pointer vtype)
| vtype LBRACKET RBRACKET
exp : LPAREN exp RPAREN (exp)
| INTNUM (mark (A.ConstExp(INTNUM),(INTNUMleft,INTNUMright)))
+ | STRING (mark (A.StringExp(STRING),(STRINGleft,STRINGright)))
| IDENT (mark (A.Var(IDENT), (IDENTleft,IDENTright)))
| exp DOT IDENT (mark (A.Member(exp, IDENT), (expleft, IDENTright)))
| exp ARROW IDENT (mark (A.DerefMember(exp, IDENT), (expleft, IDENTright)))
local
val commentLevel = ref 0
val commentPos = ref 0
+ val inString = ref false
+ val stringPos = ref 0
+ val stringAcc : string list ref = ref [] (* :( *)
in
fun enterComment yypos =
( commentLevel := !commentLevel + 1 ;
( if (!commentLevel > 0)
then (ErrorMsg.error (ParseState.ext (!commentPos,!commentPos)) "unterminated comment")
else ();
+ if (!inString)
+ then (ErrorMsg.error (ParseState.ext (!stringPos,!stringPos)) "unterminated string")
+ else ();
Tokens.EOF (0,0) ) (* bogus position information; unused *)
+ fun newString yyp = ( inString := true; stringPos := yyp; stringAcc := [] )
+ fun endString yyp = ( Tokens.STRING (concat (rev (!stringAcc)), !stringPos, yyp+1) )
+ fun addString yyt = ( inString := false; stringAcc := yyt :: (!stringAcc) )
end
%%
%header (functor L5LexFn(structure Tokens : L5_TOKENS));
%full
-%s COMMENT COMMENT_LINE;
+%s COMMENT COMMENT_LINE STRING;
id = [A-Za-z_][A-Za-z0-9_]*;
decnum = [0-9][0-9]*;
<INITIAL> "else" => (Tokens.ELSE (yypos, yypos + size yytext));
<INITIAL> "var" => (Tokens.VAR (yypos, yypos + size yytext));
<INITIAL> "int" => (Tokens.INT (yypos, yypos + size yytext));
+<INITIAL> "string" => (Tokens.TSTRING (yypos, yypos + size yytext));
<INITIAL> "extern" => (Tokens.EXTERN (yypos, yypos + size yytext));
<INITIAL> "struct" => (Tokens.STRUCT (yypos, yypos + size yytext));
<INITIAL> "NULL" => (Tokens.NULL (yypos, yypos + size yytext));
<INITIAL> "//" => (YYBEGIN COMMENT_LINE; lex());
<INITIAL> "#" => (YYBEGIN COMMENT_LINE; lex());
+<INITIAL> "\"" => (YYBEGIN STRING; newString yypos ; lex () );
<INITIAL> . => (ErrorMsg.error (ParseState.ext (yypos,yypos))
("illegal character: \"" ^ yytext ^ "\"");
lex ());
+
<COMMENT> "/*" => (enterComment yypos; lex());
<COMMENT> "*/" => (if exitComment () then YYBEGIN INITIAL else (); lex());
<COMMENT> \n => (ParseState.newline yypos; lex ());
<COMMENT_LINE> \n => (ParseState.newline yypos; YYBEGIN INITIAL; lex());
<COMMENT_LINE> . => (lex());
+
+<STRING> [^\"\\]* => (addString yytext ; lex() );
+<STRING> "\"" => (YYBEGIN INITIAL; endString yypos );
| trans_exp env vartypes (A.ArrIndex(exp1, exp2)) =
let
val asubk = T.BINOP(T.ADD, trans_exp env vartypes exp1,
- T.BINOP(T.MUL, trans_exp env vartypes exp2,
- T.CONST(Word32.fromInt(sizeof (deref (typeof' vartypes exp1))))))
+ if sizeof (deref (typeof' vartypes exp1)) = 1
+ then trans_exp env vartypes exp2
+ else T.BINOP(T.MUL, trans_exp env vartypes exp2,
+ T.CONST(Word32.fromInt(sizeof (deref (typeof' vartypes exp1))))
+ )
+ )
val tipo = deref (typeof' vartypes exp1)
val d =
if not (Flag.isset Flags.safe)
end
| trans_exp env vartypes (A.NewArr(tipo, exp)) =
let
- val size = T.BINOP(T.MUL, trans_exp env vartypes exp, T.CONST(Word32.fromInt(sizeof tipo)))
+ val size = if (sizeof tipo) = 1
+ then trans_exp env vartypes exp
+ else T.BINOP(T.MUL, trans_exp env vartypes exp, T.CONST(Word32.fromInt(sizeof tipo)))
val t1 = T.TEMP (Temp.new "allocated address")
val ts = T.TEMP (Temp.new "size")
in
signature TYPE =
sig
type ident = Symbol.symbol
- datatype vtype = Int | Typedef of ident | Pointer of vtype | Array of vtype | TNull
+ datatype vtype = Int | String | Typedef of ident | Pointer of vtype | Array of vtype | TNull
type variable = ident * vtype
datatype typedef = MarkedTypedef of typedef Mark.marked | Struct of variable list
structure Type :> TYPE =
struct
type ident = Symbol.symbol
- datatype vtype = Int | Typedef of ident | Pointer of vtype | Array of vtype | TNull
+ datatype vtype = Int | String | Typedef of ident | Pointer of vtype | Array of vtype | TNull
type variable = ident * vtype
datatype typedef = MarkedTypedef of typedef Mark.marked | Struct of variable list
- fun size (Int) = 4
- | size (Pointer _) = 8
- | size (Array _) = 8
- | size (TNull) = 8
+ fun size (Int) = 1
+ | size (String) = 1
+ | size (Pointer _) = 1
+ | size (Array _) = 1
+ | size (TNull) = 1
| size _ = raise ErrorMsg.InternalError "Type.size on non-small type..."
(************************************************)
(* determine size of items *)
fun sizeof_reset () = ( size_memotable := Symbol.empty )
fun alignment_reset () = ( align_memotable := Symbol.empty )
- fun sizeof _ (Int) = 4
- | sizeof _ (Pointer _) = 8
- | sizeof _ (Array _) = 8
+ fun sizeof _ (Int) = 1
+ | sizeof _ (String) = 1
+ | sizeof _ (Pointer _) = 1
+ | sizeof _ (Array _) = 1
| sizeof _ (TNull) = raise ErrorMsg.InternalError "Type.sizeof on TNull?"
| sizeof d (Typedef id) =
(case (Symbol.look (!size_memotable) id)
| sizeof_s d (MarkedTypedef(a)) = sizeof_s d (Mark.data a)
(* determine alignment of items *)
- and alignment _ (Int) = 4
- | alignment _ (Pointer _) = 8
- | alignment _ (Array _) = 8
+ and alignment _ (Int) = 1
+ | alignment _ (String) = 1
+ | alignment _ (Pointer _) = 1
+ | alignment _ (Array _) = 1
| alignment d (Typedef id) =
(case Symbol.look (!align_memotable) id
of SOME(r) => r
fun issmall (Int) = true
+ | issmall (String) = true
| issmall (Pointer _) = true
| issmall (Array _) = true
| issmall (TNull) = true
| issmall _ = false
fun typeeq (Int, Int) = true
+ | typeeq (String, String) = true
| typeeq (Typedef a, Typedef b) = (Symbol.name a) = (Symbol.name b)
| typeeq (Pointer a, Pointer b) = typeeq (a, b)
| typeeq (Array a, Array b) = typeeq (a, b)
fun pp_ident i = Symbol.name i
fun pp_type (Int) = "int"
+ | pp_type (String) = "string"
| pp_type (Pointer t) = pp_type t ^ "*"
| pp_type (Array t) = pp_type t ^ "[]"
| pp_type (TNull) = "{NULL type}"
of NONE => (ErrorMsg.error mark ("variable `"^(Symbol.name a)^"' not declared here") ; raise ErrorMsg.Error)
| SOME t => t)
| A.ConstExp _ => T.Int
+ | A.StringExp _ => T.String
| A.OpExp (A.EQ, [a, b]) =>
(case (typeof (tds, funcs) vars mark a, typeof (tds, funcs) vars mark b)
of (T.Int, T.Int) => T.Int (* You shall pass! *)
raise ErrorMsg.Error )
| SOME ASSIGNED => ())
| varcheck_exp env (A.ConstExp _) mark = ()
+ | varcheck_exp env (A.StringExp _) mark = ()
| varcheck_exp env (A.OpExp (_, l)) mark = List.app (fn znt => varcheck_exp env znt mark) l
| varcheck_exp env (A.FuncCall (f, l)) mark = List.app (fn znt => varcheck_exp env znt mark) l
| varcheck_exp env (A.Marked m) mark = varcheck_exp env (Mark.kane m) (Mark.ext m)
(* XXX does not check big vs. small types *)
fun typecheck_type (tds, funcs) mark T.Int = ()
+ | typecheck_type (tds, funcs) mark T.String = ()
| typecheck_type (tds, funcs) mark T.TNull = ()
| typecheck_type (tds, funcs) mark (T.Pointer t) = typecheck_type (tds, funcs) mark t
| typecheck_type (tds, funcs) mark (T.Array t) = typecheck_type (tds, funcs) mark t