1115 lines
32 KiB
OCaml
1115 lines
32 KiB
OCaml
open Common
|
|
|
|
open Parse_info
|
|
open Ast_cpp
|
|
|
|
module Flag = Flag_parsing_cpp
|
|
|
|
let process_either _of_a _of_b =
|
|
function
|
|
| Left left -> "" ^ _of_a left
|
|
| Right right -> "" ^ _of_b right
|
|
|
|
let is_empty s =
|
|
(s = "")
|
|
|
|
let gen_indent num_spaces =
|
|
let rec aux acc num_spaces =
|
|
match num_spaces with
|
|
| 0 -> acc
|
|
| rest -> aux (acc^" ") (num_spaces-1)
|
|
in
|
|
aux "" num_spaces
|
|
|
|
let replace search sub str =
|
|
Str.global_replace (Str.regexp search) sub str
|
|
|
|
let indent ?(level=2) str =
|
|
let indent_str = gen_indent level
|
|
and search = Str.regexp "\n" in
|
|
indent_str ^ String.trim (Str.global_replace search ("\n" ^ indent_str) str)
|
|
|
|
|
|
let process_option ofa x =
|
|
match x with
|
|
| None -> ""
|
|
| Some stuff -> "" ^ ofa stuff
|
|
|
|
let process_tuple_option ofa x =
|
|
match x with
|
|
| None -> ("", "")
|
|
| Some stuff -> ofa stuff
|
|
|
|
let process_list ?(delimiter=", ") _of_a node =
|
|
let map = List.map _of_a node
|
|
in String.concat delimiter map
|
|
|
|
|
|
let rec process_info token =
|
|
process_token token
|
|
|
|
and process_token tok =
|
|
match tok.token with
|
|
| OriginTok loc -> loc.str
|
|
| FakeTokStr (v1, opt) -> ""
|
|
| Ab -> ""
|
|
| ExpandedTok (tok1, tok2, integer) -> tok1.str
|
|
|
|
and wrap _of_a (v1, v2) =
|
|
_of_a v1
|
|
|
|
and wrap2 _of_a (v1, v2) =
|
|
let v1 = _of_a v1 and v2 = process_info v2 in
|
|
v1 ^ v2
|
|
|
|
and process_paren _of_a (paren1, arglist, paren2) =
|
|
let paren1 = process_token paren1
|
|
and arglist = _of_a arglist
|
|
and paren2 = process_token paren2
|
|
in paren1 ^ arglist ^ paren2
|
|
|
|
and process_brace ?(include_braces=false) _of_a (br1, arglist, br2) =
|
|
if include_braces then
|
|
"{" ^ _of_a arglist ^ "}"
|
|
else
|
|
_of_a arglist
|
|
|
|
and process_bracket _of_a (br1, arglist, br2) =
|
|
let br1 = process_token br1
|
|
and arglist = _of_a arglist
|
|
and br2 = process_token br2 in
|
|
br1 ^ arglist ^ br2
|
|
|
|
and process_angle _of_a (ang1, args, ang2) =
|
|
let ang1 = process_token ang1
|
|
and args = _of_a args
|
|
and ang2 = process_token ang2
|
|
in ang1 ^ args ^ ang2
|
|
|
|
and process_comma_list ?(delimiter=", ") _of_a node =
|
|
process_list ~delimiter:delimiter (wrap _of_a) node
|
|
|
|
and process_comma_list2 _of_a =
|
|
process_list (process_either _of_a process_token)
|
|
|
|
let rec process_token tok =
|
|
match tok.token with
|
|
| OriginTok loc -> loc.str
|
|
| FakeTokStr (v1, opt) -> ""
|
|
| Ab -> ""
|
|
| ExpandedTok (tok1, tok2, integer) ->
|
|
tok1.str
|
|
|
|
and process_include_kind = function
|
|
| Local -> ""
|
|
| Standard -> ""
|
|
| Weird -> ""
|
|
|
|
and process_define_expr expr =
|
|
""
|
|
|
|
and process_constant =
|
|
function
|
|
| String (str, is_wchar) -> str
|
|
| MultiString -> ""
|
|
| Char (str, is_wchar) -> str
|
|
| Int str -> str
|
|
| Float (str, ftype) -> str
|
|
| Bool bval -> string_of_bool bval
|
|
|
|
and process_ident ident =
|
|
match ident with
|
|
| IdIdent (name, tok) ->
|
|
process_token tok
|
|
| IdTemplateId (ident, args) ->
|
|
""
|
|
| IdDestructor (tok, simple_ident) ->
|
|
let (_, idtok) = simple_ident in
|
|
"destructor" ^ process_token idtok
|
|
| IdOperator (tok, operator) ->
|
|
""
|
|
| IdConverter (tok, fullType) ->
|
|
""
|
|
|
|
and process_argument arg =
|
|
process_either process_expression process_weird_arg arg
|
|
|
|
and process_weird_arg =
|
|
function
|
|
| ArgType arg_type -> process_fullType arg_type
|
|
| ArgAction arg_action -> process_action_macro arg_action
|
|
|
|
and process_action_macro =
|
|
function
|
|
| ActMisc act_misc ->
|
|
process_list process_token act_misc
|
|
|
|
and process_typeC (tc, tok_list) =
|
|
process_typeCbis tc
|
|
|
|
and process_floatType =
|
|
function
|
|
| CFloat -> "cfloat"
|
|
| CDouble -> "cdouble"
|
|
| CLongDouble -> "clongdouble"
|
|
|
|
and process_intType =
|
|
function
|
|
| CChar -> "cchar"
|
|
| Si signed -> process_signed signed
|
|
| CBool -> "cbool"
|
|
| WChar_t -> "cwchar_t"
|
|
|
|
and process_signed (sign, base) =
|
|
let sign = process_sign sign and base = process_base base
|
|
in "c" ^ sign ^ base (* cuchar, cint, cuint, etc. *)
|
|
|
|
and process_base =
|
|
function
|
|
| CChar2 -> "char"
|
|
| CShort -> "short"
|
|
| CInt -> "int"
|
|
| CLong -> "long"
|
|
| CLongLong -> "longlong"
|
|
and process_sign =
|
|
function
|
|
| Signed -> ""
|
|
| UnSigned -> "u"
|
|
|
|
|
|
and process_baseType =
|
|
function
|
|
| Void -> "void"
|
|
| IntType intType -> process_intType intType
|
|
| FloatType floatType -> process_floatType floatType
|
|
|
|
and process_param_name =
|
|
function
|
|
| None -> ""
|
|
| Some (name, tok) -> process_token tok ^ ": "
|
|
|
|
and process_parameter {
|
|
p_name = p_name;
|
|
p_type = p_type;
|
|
p_register = p_register;
|
|
p_val = p_val
|
|
} =
|
|
let type_str = process_fullType p_type
|
|
and p_name = process_param_name p_name in
|
|
p_name ^ type_str
|
|
|
|
and process_functionType {
|
|
ft_ret = ft_ret;
|
|
ft_params = ft_params;
|
|
ft_dots = ft_dots;
|
|
ft_const = ft_const;
|
|
ft_throw = ft_throw
|
|
} =
|
|
let ret_type = process_fullType ft_ret
|
|
and paren_str =
|
|
process_paren (process_comma_list process_parameter) ft_params in
|
|
paren_str ^ ": " ^ ret_type
|
|
|
|
and process_simple_ident (name, tok) =
|
|
name
|
|
|
|
and process_e_val (tok, cexpr) =
|
|
let equals = process_token tok (* equals sign *)
|
|
and cexpr = process_constExpression cexpr (* const expr *)
|
|
in " " ^ equals ^ " " ^ cexpr
|
|
|
|
and process_enum_elem { e_name = e_name; e_val = e_val } =
|
|
let e_name = process_simple_ident e_name
|
|
and e_val = process_option process_e_val e_val in
|
|
e_name ^ e_val
|
|
|
|
and process_constExpression expr = process_expression expr
|
|
|
|
and process_template_arguments args =
|
|
process_angle (process_comma_list process_template_argument) args
|
|
|
|
and process_template_argument arg =
|
|
process_either process_fullType process_expression arg
|
|
|
|
and process_qualifier =
|
|
function
|
|
| QClassname ((name, info)) ->
|
|
name ^ process_info info
|
|
| QTemplateId ((name, args)) ->
|
|
let ident = process_simple_ident name
|
|
and args = process_template_arguments args in
|
|
ident ^ args
|
|
|
|
and process_name (v1, v2, v3) =
|
|
let v1 = process_option process_token v1
|
|
and v2 =
|
|
process_list
|
|
(fun (v1, v2) ->
|
|
let v1 = process_qualifier v1
|
|
and v2 = process_token v2 in
|
|
v1 ^ v2)
|
|
v2
|
|
and v3 = process_ident v3
|
|
in v1 ^ v2 ^ v3
|
|
|
|
and process_either_ft_or_expr ft_or_expr =
|
|
process_either process_fullType process_expression ft_or_expr
|
|
|
|
and process_structUnion =
|
|
function
|
|
| Struct -> "struct"
|
|
| Union -> "union"
|
|
| Class -> "class"
|
|
|
|
and process_typeCbis =
|
|
function
|
|
| BaseType btype ->
|
|
process_baseType btype
|
|
| Pointer point ->
|
|
"ptr " ^ process_fullType point
|
|
| Reference ref ->
|
|
"ref " ^ process_fullType ref
|
|
| Array ((arr, typ)) ->
|
|
let arr = process_bracket (process_option process_constExpression) arr
|
|
and typ = process_fullType typ
|
|
in arr ^ typ
|
|
| FunctionType ftype ->
|
|
process_functionType ftype
|
|
| EnumDef ((name, ident, elements)) ->
|
|
let ident = process_option process_simple_ident ident
|
|
and elements =
|
|
process_brace (process_comma_list process_enum_elem) elements
|
|
in ident ^ " = enum\n" ^ elements
|
|
| StructDef sdef ->
|
|
"" (*process_class_definition sdef*)
|
|
| EnumName ((enum, name)) ->
|
|
process_simple_ident name
|
|
| StructUnionName ((stype_tok, name)) ->
|
|
let (stype, _) = stype_tok in
|
|
let stype = process_structUnion stype
|
|
and name = process_simple_ident name in
|
|
stype ^ " " ^ name
|
|
| TypeName ((tname)) ->
|
|
process_name tname
|
|
| TypenameKwd ((tname (* 'typename' *), tdef_name)) ->
|
|
process_name tdef_name
|
|
| TypeOf ((typeof, tdef)) ->
|
|
process_paren process_either_ft_or_expr tdef
|
|
| ParenType paren ->
|
|
process_paren process_fullType paren
|
|
|
|
and process_info token =
|
|
process_token token
|
|
|
|
and process_expression (expr, toks) =
|
|
process_exprbis toks expr
|
|
|
|
and process_fixOp expr =
|
|
function
|
|
| Dec -> "- 1"
|
|
| Inc -> "+ 1"
|
|
|
|
and process_binaryOp =
|
|
function
|
|
| Arith arith ->
|
|
process_arithOp arith
|
|
| Logical log ->
|
|
process_logicalOp log
|
|
|
|
and process_arithOp =
|
|
function
|
|
| Plus -> "+"
|
|
| Minus -> "-"
|
|
| Mul -> "*"
|
|
| Div -> "/"
|
|
| Mod -> "mod"
|
|
| DecLeft -> "shl"
|
|
| DecRight -> "shr"
|
|
| And -> "and"
|
|
| Or -> "or"
|
|
| Xor -> "xor"
|
|
|
|
and process_logicalOp =
|
|
function
|
|
| Inf -> "<"
|
|
| Sup -> ">"
|
|
| InfEq -> "<="
|
|
| SupEq -> ">="
|
|
| Eq -> "=="
|
|
| NotEq -> "!="
|
|
| AndLog -> "and"
|
|
| OrLog -> "or"
|
|
|
|
and process_unaryOp expr =
|
|
let expr = process_expression expr in
|
|
function
|
|
| GetRef -> "addr " ^ expr
|
|
| DeRef -> expr ^ "[]"
|
|
| UnPlus -> "+" ^ expr
|
|
| UnMinus -> "-" ^ expr
|
|
| Tilde -> "not " ^ expr
|
|
| Not -> "not " ^ expr
|
|
| GetRefLabel -> failwith "Ref labels are not supported in flitter!"
|
|
|
|
and process_assignOp =
|
|
function
|
|
| SimpleAssign -> "="
|
|
| OpAssign arith ->
|
|
process_arithOp arith
|
|
|
|
and process_exprbis toks =
|
|
function
|
|
| Id ((name, info)) ->
|
|
let (_, _, ident) = name in
|
|
process_ident ident
|
|
| C const ->
|
|
let res = match toks with
|
|
| [] -> ""
|
|
| main_tok :: _ -> process_token main_tok in
|
|
res
|
|
| Call ((expr, args)) ->
|
|
let name = process_expression expr
|
|
and args = process_paren (process_comma_list process_argument) args in
|
|
name ^ args
|
|
| CondExpr ((binary, first_option, second_option)) ->
|
|
let bin = process_expression binary
|
|
and first_op = process_option process_expression first_option
|
|
and second_op = process_expression second_option in
|
|
"if " ^ bin ^ ": " ^ first_op ^ " else: " ^ second_op
|
|
| Sequence ((v1, v2)) ->
|
|
(*let v1 = process_expression v1
|
|
and v2 = process_expression v2
|
|
in Ocaml.VSum (("Sequence", [ v1; v2 ]))*)
|
|
""
|
|
| Assignment ((left, op, right)) ->
|
|
let left = process_expression left
|
|
and op = process_assignOp op
|
|
and right = process_expression right in
|
|
left ^ " " ^ op ^ " " ^ right
|
|
| Postfix ((expr, op)) ->
|
|
let expr = process_expression expr in
|
|
let op_expr =
|
|
match op with
|
|
| Dec -> "postDec(" ^ expr ^ ")"
|
|
| Inc -> "postInc(" ^ expr ^ ")" in
|
|
op_expr
|
|
| Infix ((expr, op)) ->
|
|
let expr = process_expression expr in
|
|
let op_expr =
|
|
match op with
|
|
| Dec -> "preDec(" ^ expr ^ ")"
|
|
| Inc -> "preInc(" ^ expr ^ ")" in
|
|
op_expr
|
|
| Unary ((expr, op)) ->
|
|
process_unaryOp expr op
|
|
| Binary ((left, op, right)) ->
|
|
let left = process_expression left
|
|
and op = process_binaryOp op
|
|
and right = process_expression right
|
|
in left ^ " " ^ op ^ " " ^ right
|
|
| ArrayAccess ((expr, bracket_expr)) ->
|
|
let expr = process_expression expr
|
|
and bracket_expr = process_bracket process_expression bracket_expr in
|
|
expr ^ bracket_expr
|
|
| RecordAccess ((expr, field)) ->
|
|
let expr = process_expression expr
|
|
and field = process_name field in
|
|
expr ^ "." ^ field
|
|
| RecordPtAccess ((expr, field)) ->
|
|
let expr = process_expression expr
|
|
and field = process_name field in
|
|
expr ^ "." ^ field
|
|
| RecordStarAccess ((left, right)) ->
|
|
(*
|
|
* Not sure what this is, exactly. The nim code
|
|
* will have it commented out for now.
|
|
*)
|
|
let left = process_expression left
|
|
and right = process_expression right in
|
|
"# " ^ left ^ process_list process_token toks ^ right
|
|
| RecordPtStarAccess ((left, right)) ->
|
|
(*
|
|
* Not sure what this is, exactly. The nim code
|
|
* will have it commented out for now.
|
|
*)
|
|
let left = process_expression left
|
|
and right = process_expression right in
|
|
"# " ^ left ^ process_list process_token toks ^ right
|
|
| SizeOfExpr ((sizeof, expr)) ->
|
|
let expr = process_expression expr in
|
|
"sizeof(" ^ expr ^ ")"
|
|
| SizeOfType ((sizeof, fullType)) ->
|
|
let ty = process_paren process_fullType fullType in
|
|
"sizeof" ^ ty
|
|
| Cast (((left, fullType, right), expr)) ->
|
|
let fullType = process_fullType fullType
|
|
and expr = process_expression expr in
|
|
"cast[" ^ fullType ^ "](" ^ expr ^ ")"
|
|
| StatementExpr v1 ->
|
|
process_paren process_compound v1
|
|
| GccConstructor ((v1, v2)) ->
|
|
(*
|
|
* Not sure what this is, exactly. The nim code
|
|
* will have it commented out for now.
|
|
*)
|
|
let v1 = process_paren process_fullType v1
|
|
and v2 = process_brace (process_comma_list process_initialiser) v2 in
|
|
"# " ^ v1 ^ process_list process_token toks ^ v2
|
|
| This v1 ->
|
|
(*let v1 = process_tok v1 in Ocaml.VSum (("This", [ v1 ]))*)
|
|
""
|
|
| ConstructedObject ((fullType, params)) ->
|
|
let fullType = process_fullType fullType
|
|
and params = process_paren (process_comma_list process_argument) params in
|
|
fullType ^ params
|
|
| TypeId ((v1, v2)) ->
|
|
(*let v1 = process_tok v1
|
|
and v2 = process_paren process_either_ft_or_expr v2
|
|
in Ocaml.VSum (("TypeId", [ v1; v2 ]))*)
|
|
""
|
|
| CplusplusCast ((cast_op, fullType, expr)) ->
|
|
(*let v1 = process_wrap2 process_cast_operator v1
|
|
and v2 = process_angle process_fullType v2
|
|
and v3 = process_paren process_expression v3
|
|
in Ocaml.VSum (("CplusplusCast", [ v1; v2; v3 ]))*)
|
|
""
|
|
| New ((v1, v2, v3, v4, v5)) ->
|
|
(*let v1 = Ocaml.process_option process_tok v1
|
|
and v2 = process_tok v2
|
|
and v3 = Ocaml.process_option (process_paren (process_comma_list process_argument)) v3
|
|
and v4 = process_fullType v4
|
|
and v5 = Ocaml.process_option (process_paren (process_comma_list process_argument)) v5
|
|
in Ocaml.VSum (("New", [ v1; v2; v3; v4; v5 ]))*)
|
|
""
|
|
| Delete ((v1, v2)) ->
|
|
(*let v1 = Ocaml.process_option process_tok v1
|
|
and v2 = process_expression v2
|
|
in Ocaml.VSum (("Delete", [ v1; v2 ]))*)
|
|
""
|
|
| DeleteArray ((tok, expr)) ->
|
|
let tok = process_option process_token tok
|
|
and expr = process_expression expr
|
|
in tok ^ expr
|
|
| Throw throw ->
|
|
process_option process_expression throw
|
|
| ParenExpr paren_expr ->
|
|
process_paren process_expression paren_expr
|
|
| ExprTodo -> "TODO"
|
|
|
|
and process_selection =
|
|
function
|
|
| If ((if_tok, paren_expr, stmt1, else_tok, stmt2)) ->
|
|
let paren_expr = process_paren process_expression paren_expr
|
|
and stmt1 = process_statement stmt1
|
|
and else_tok = process_option process_token else_tok
|
|
and stmt2 = process_statement stmt2 in
|
|
"if" ^ paren_expr ^
|
|
stmt1 ^ "\n" ^
|
|
replace "elseif" "elif" (else_tok ^ stmt2)
|
|
| Switch ((v1, v2, v3)) ->
|
|
let v1 = process_token v1
|
|
and v2 = process_paren process_expression v2
|
|
and v3 = process_statement v3
|
|
in v1 ^ v2 ^ v3
|
|
and process_iteration =
|
|
function
|
|
| While ((v1, v2, v3)) ->
|
|
let v1 = process_token v1
|
|
and v2 = process_paren process_expression v2
|
|
and v3 = process_statement v3
|
|
in v1 ^ v2 ^ v3
|
|
| DoWhile ((v1, v2, v3, v4, v5)) ->
|
|
let v1 = process_token v1
|
|
and v2 = process_statement v2
|
|
and v3 = process_token v3
|
|
and v4 = process_paren process_expression v4
|
|
and v5 = process_token v5
|
|
in v1 ^ v2 ^ v3 ^ v4 ^v5
|
|
| For ((v1, v2, v3)) ->
|
|
let v1 = process_token v1
|
|
and v2 =
|
|
process_paren
|
|
(fun (v1, v2, v3) ->
|
|
let v1 = wrap process_exprStatement v1
|
|
and v2 = wrap process_exprStatement v2
|
|
and v3 = wrap process_exprStatement v3
|
|
in v1 ^ v2 ^ v3)
|
|
v2
|
|
and v3 = process_statement v3
|
|
in v1 ^ v2 ^ v3
|
|
| MacroIteration ((v1, v2, v3)) ->
|
|
let v1 = process_simple_ident v1
|
|
and v2 = process_paren (process_comma_list process_argument) v2
|
|
and v3 = process_statement v3
|
|
in v1 ^ v2 ^ v3
|
|
|
|
and process_jump =
|
|
function
|
|
| Goto goto -> failwith "# XXX goto not supported: " ^ goto
|
|
| Continue -> "continue"
|
|
| Break -> "break"
|
|
| Return -> "return"
|
|
| ReturnExpr ret_expr ->
|
|
"return " ^ process_expression ret_expr
|
|
| GotoComputed goto_comp ->
|
|
failwith "#[ XXX goto not supported: " ^ process_expression goto_comp ^ "]#"
|
|
|
|
and process_handler (v1, v2, v3) =
|
|
let v1 = process_token v1
|
|
and v2 = process_paren process_exception_declaration v2
|
|
and v3 = process_compound v3
|
|
in v1 ^ v2 ^ v3
|
|
|
|
and process_exception_declaration =
|
|
function
|
|
| ExnDeclEllipsis exn_ellipsis ->
|
|
process_token exn_ellipsis
|
|
| ExnDecl exn_decl ->
|
|
process_parameter exn_decl
|
|
|
|
and get_tydef_prefix name storage =
|
|
match storage with
|
|
| NoSto -> ""
|
|
| StoTypedef st_tdef ->
|
|
"type " ^ name ^ " = "
|
|
| Sto (sto, tok) -> ""
|
|
|
|
and process_onedecl {
|
|
v_namei = v_namei;
|
|
v_type = v_type;
|
|
v_storage = v_storage
|
|
} =
|
|
let name =
|
|
process_tuple_option
|
|
(fun (name, init) ->
|
|
let name = process_name name
|
|
and init = process_option process_init init
|
|
in
|
|
pr (name ^ " " ^ init);
|
|
(name, init))
|
|
v_namei in
|
|
let res = process_onedeclFullType "" name v_storage v_type in
|
|
replace "ptr cchar" "cstring" res
|
|
|
|
|
|
and
|
|
process_class_definition ?(name_override=None) {
|
|
c_kind = c_kind;
|
|
c_name = c_name;
|
|
c_inherit = c_inherit;
|
|
c_members = (_, c_members, _)
|
|
} =
|
|
let members =
|
|
process_list ~delimiter:"\n" process_class_member_sequencable c_members in
|
|
let _ =
|
|
process_option
|
|
(fun (v1, v2) ->
|
|
let v1 = process_token v1
|
|
and v2 = process_comma_list process_base_clause v2
|
|
in v1 ^ v2)
|
|
c_inherit in
|
|
let name = match name_override with
|
|
| None -> process_option process_name c_name
|
|
| Some x -> x in
|
|
let _ = wrap2 process_structUnion c_kind in
|
|
"type\n" ^
|
|
indent (name ^ " = object\n" ^
|
|
indent (members))
|
|
|
|
and
|
|
process_base_clause {
|
|
i_name = v_i_name;
|
|
i_virtual = v_i_virtual;
|
|
i_access = v_i_access
|
|
} =
|
|
let access = process_option (wrap2 process_access_spec) v_i_access in
|
|
let virtual_tok = process_option process_token v_i_virtual in
|
|
let name = process_name v_i_name in
|
|
name ^ access ^ virtual_tok
|
|
|
|
and process_access_spec =
|
|
function
|
|
| Public -> "*"
|
|
| Private -> ""
|
|
| Protected -> ""
|
|
|
|
and process_exn_spec (v1, v2) =
|
|
let v1 = process_token v1
|
|
and v2 = process_paren (process_comma_list2 process_name) v2
|
|
in v1 ^ v2
|
|
|
|
and process_method_decl = function
|
|
| ConstructorDecl ((v1, v2, v3)) ->
|
|
let (v1, _) = v1
|
|
and v2 = process_paren (process_comma_list process_parameter) v2
|
|
and v3 = process_token v3
|
|
in v1 ^ v2 ^ v3
|
|
| DestructorDecl ((v1, v2, v3, v4, v5)) ->
|
|
let v1 = process_token v1
|
|
and (v2, _) = v2
|
|
and v3 = process_paren (process_option process_token) v3
|
|
and v4 = process_option process_exn_spec v4
|
|
and v5 = process_token v5
|
|
in v1 ^ v2 ^ v3 ^ v4 ^ v5
|
|
| MethodDecl ((v1, v2, v3)) ->
|
|
let v1 = process_onedecl v1
|
|
and v2 =
|
|
process_option
|
|
(fun (v1, v2) ->
|
|
let v1 = process_token v1
|
|
and v2 = process_token v2
|
|
in v1 ^ v2)
|
|
v2
|
|
and v3 = process_token v3
|
|
in v1 ^ v2 ^ v3
|
|
|
|
and process_template_parameters v =
|
|
process_angle (process_comma_list process_parameter) v
|
|
|
|
and process_class_member =
|
|
function
|
|
| Access ((v1, v2)) ->
|
|
let v1 = wrap2 process_access_spec v1
|
|
and v2 = process_token v2
|
|
in v1 ^ v2
|
|
| MemberField (fieldkinds, semi) ->
|
|
process_comma_list process_fieldkind fieldkinds
|
|
| MemberFunc v1 ->
|
|
process_func_or_else v1
|
|
| MemberDecl v1 ->
|
|
process_method_decl v1
|
|
| QualifiedIdInClass ((v1, v2)) ->
|
|
let v1 = process_name v1
|
|
and v2 = process_token v2
|
|
in v1 ^ v2
|
|
| TemplateDeclInClass v1 ->
|
|
let v1 =
|
|
(match v1 with
|
|
| (v1, v2, v3) ->
|
|
let v1 = process_token v1
|
|
and v2 = process_template_parameters v2
|
|
and v3 = process_declaration v3
|
|
in v1 ^ v2 ^ v3)
|
|
in v1
|
|
| UsingDeclInClass v1 ->
|
|
let v1 =
|
|
(match v1 with
|
|
| (v1, v2, v3) ->
|
|
let v1 = process_token v1
|
|
and v2 = process_name v2
|
|
and v3 = process_token v3
|
|
in v1 ^ v2 ^ v3)
|
|
in v1
|
|
| EmptyField v1 ->
|
|
process_token v1
|
|
|
|
and process_fieldkind =
|
|
function
|
|
| FieldDecl field_decl ->
|
|
process_onedecl field_decl
|
|
| BitField ((v1, v2, v3, v4)) ->
|
|
let v1 = process_option process_simple_ident v1
|
|
and v2 = process_token v2
|
|
and v3 = process_fullType v3
|
|
and v4 = process_constExpression v4
|
|
in v1 ^ v2 ^ v3 ^ v4
|
|
|
|
and process_class_member_sequencable =
|
|
function
|
|
| ClassElem elem ->
|
|
process_class_member elem
|
|
| CppDirectiveStruct dir_struct ->
|
|
process_cpp_directive dir_struct
|
|
| IfdefStruct ifdef_struct ->
|
|
process_ifdef_directive ifdef_struct
|
|
|
|
|
|
and process_onedeclFullType prefix (name, init) storage (qualifier, (typeCbis, tok_list)) =
|
|
match typeCbis with
|
|
| BaseType btype ->
|
|
if is_empty(init) then
|
|
name ^ ": " ^ prefix ^ process_baseType btype
|
|
else
|
|
"var " ^ name ^ ": " ^ prefix ^ process_baseType btype ^ " = " ^ init
|
|
| Pointer point ->
|
|
process_onedeclFullType "ptr " (name, init) storage point
|
|
| Reference ref ->
|
|
process_onedeclFullType "ref " (name, init) storage ref
|
|
| Array ((arr, typ)) ->
|
|
let arr = process_bracket (process_option process_constExpression) arr
|
|
and typ = process_fullType typ
|
|
in arr ^ typ
|
|
| FunctionType ftype ->
|
|
let ret = match storage with
|
|
| NoSto -> "proc " ^ name^init ^ process_functionType ftype
|
|
| StoTypedef st_tdef ->
|
|
"type " ^ name^init ^ " = " ^ "proc " ^ process_functionType ftype
|
|
| Sto sto -> "proc " ^ name^init ^ process_functionType ftype in
|
|
ret
|
|
| EnumDef ((_, ident, elements)) ->
|
|
let ident = process_option process_simple_ident ident
|
|
and elements =
|
|
process_brace (process_comma_list process_enum_elem) elements
|
|
in
|
|
let ty_str = "type " ^ ident ^ " = enum " ^ elements
|
|
and let_stmt = if is_empty(init) then
|
|
"\nvar " ^ name ^ ": " ^ ident
|
|
else
|
|
"\nvar " ^ name ^ ": " ^ ident ^ " = " ^ init in
|
|
if is_empty(name) then ty_str else ty_str ^ let_stmt
|
|
| StructDef sdef ->
|
|
if is_empty(name) then
|
|
process_class_definition sdef
|
|
else
|
|
process_class_definition ~name_override:(Some name) sdef
|
|
| EnumName ((enum, name)) ->
|
|
process_simple_ident name
|
|
| StructUnionName ((stype_tok, sname)) ->
|
|
let sname = process_simple_ident sname in
|
|
"var " ^ name ^ " = " ^ sname ^ " @ " ^ init
|
|
| TypeName ((tname)) ->
|
|
process_name tname
|
|
| TypenameKwd ((tname (* 'typename' *), tdef_name)) ->
|
|
process_name tdef_name
|
|
| TypeOf ((typeof, tdef)) ->
|
|
process_paren process_either_ft_or_expr tdef
|
|
| ParenType (left, type_inf, right) ->
|
|
process_onedeclFullType "" (name, init) storage type_inf
|
|
|
|
and process_storage st = process_storagebis st
|
|
and process_storagebis =
|
|
function
|
|
| NoSto -> ""
|
|
| StoTypedef st_tdef ->
|
|
process_token st_tdef
|
|
| Sto sto -> wrap2 process_storageClass sto
|
|
|
|
and process_storageClass =
|
|
function
|
|
| Auto -> "auto"
|
|
| Static -> "static"
|
|
| Register -> "register"
|
|
| Extern -> "extern"
|
|
|
|
and process_init =
|
|
function
|
|
| EqInit ((equals, init)) ->
|
|
let init = process_initialiser init
|
|
in init
|
|
| ObjInit v1 ->
|
|
process_paren (process_comma_list process_argument) v1
|
|
|
|
and process_block_declaration =
|
|
function
|
|
| DeclList ((decl, semi_col)) ->
|
|
process_comma_list process_onedecl decl
|
|
| MacroDecl ((v1, v2, v3, v4)) ->
|
|
let v1 = process_list process_token v1
|
|
and v2 = process_simple_ident v2
|
|
and v3 = process_paren (process_comma_list process_argument) v3
|
|
and v4 = process_token v4
|
|
in v1 ^ v2 ^ v3 ^ v4
|
|
| UsingDecl v1 ->
|
|
let v1 =
|
|
(match v1 with
|
|
| (v1, v2, v3) ->
|
|
let v1 = process_token v1
|
|
and v2 = process_name v2
|
|
and v3 = process_token v3
|
|
in v1 ^ v2 ^ v3)
|
|
in v1
|
|
| UsingDirective ((v1, v2, v3, v4)) ->
|
|
let v1 = process_token v1
|
|
and v2 = process_token v2
|
|
and v3 = process_name v3
|
|
and v4 = process_token v4
|
|
in v1 ^ v2 ^ v3 ^ v4
|
|
| NameSpaceAlias ((v1, v2, v3, v4, v5)) ->
|
|
let v1 = process_token v1
|
|
and v2 = process_simple_ident v2
|
|
and v3 = process_token v3
|
|
and v4 = process_name v4
|
|
and v5 = process_token v5
|
|
in v1 ^ v2 ^ v3 ^ v4 ^ v5
|
|
| Asm ((v1, v2, v3, v4)) ->
|
|
let v1 = process_token v1
|
|
and v2 = process_option process_token v2
|
|
and v3 = process_paren process_asmbody v3
|
|
and v4 = process_token v4
|
|
in v1 ^ v2 ^ v3 ^ v4
|
|
|
|
and process_asmbody (v1, v2) =
|
|
let v1 = process_list process_token v1
|
|
and v2 = process_list (wrap process_colon) v2
|
|
in v1 ^ v2
|
|
and process_colon =
|
|
function
|
|
| Colon v1 ->
|
|
let v1 = process_comma_list process_colon_option v1
|
|
in v1
|
|
and process_colon_option v = wrap process_colon_optionbis v
|
|
and process_colon_optionbis =
|
|
function
|
|
| ColonMisc -> "colonmisc"
|
|
| ColonExpr v1 ->
|
|
let v1 = process_paren process_expression v1
|
|
in v1
|
|
|
|
and process_statement stmt = wrap process_statementbis stmt
|
|
and process_statementbis =
|
|
function
|
|
| Compound comp ->
|
|
":\n" ^ indent (process_compound comp)
|
|
| ExprStatement expr ->
|
|
process_exprStatement expr
|
|
| Labeled labeled ->
|
|
process_labeled labeled
|
|
| Selection selection ->
|
|
process_selection selection
|
|
| Iteration iter ->
|
|
process_iteration iter
|
|
| Jump jump ->
|
|
process_jump jump
|
|
| DeclStmt decl ->
|
|
process_block_declaration decl
|
|
| Try ((tok, comp, handler_list)) ->
|
|
let comp = process_compound comp
|
|
and handler_list = process_list process_handler handler_list
|
|
in "try: " ^ comp ^ handler_list
|
|
| NestedFunc nest_func ->
|
|
process_func_definition nest_func
|
|
| MacroStmt -> ""
|
|
| StmtTodo -> "# TODO"
|
|
|
|
and process_compound comp =
|
|
process_brace (process_list ~delimiter:"\n" process_statement_sequencable) comp
|
|
|
|
and process_statement_sequencable =
|
|
function
|
|
| StmtElem stmt ->
|
|
process_statement stmt
|
|
| CppDirectiveStmt direc ->
|
|
process_cpp_directive direc
|
|
| IfdefStmt ifdef ->
|
|
process_ifdef_directive ifdef
|
|
|
|
and process_ifdef_directive if_def = wrap2 process_ifdefkind if_def
|
|
and process_ifdefkind =
|
|
function (* TODO fix this for Nim *)
|
|
| Ifdef -> "ifdef"
|
|
| IfdefElse -> "ifdefelse"
|
|
| IfdefElseif -> "ifdefelseif"
|
|
| IfdefEndif -> "ifdefendif"
|
|
|
|
and process_exprStatement expr_stmt =
|
|
process_option process_expression expr_stmt
|
|
|
|
and process_labeled =
|
|
function
|
|
| Label ((name, stmt)) ->
|
|
let stmt = process_statement stmt
|
|
in name ^ " " ^ stmt
|
|
| Case ((expr, stmt)) ->
|
|
let expr = process_expression expr
|
|
and stmt = process_statement stmt
|
|
in expr ^ " " ^stmt
|
|
| CaseRange ((expr1, expr2, stmt)) ->
|
|
let expr1 = process_expression expr1
|
|
and expr2 = process_expression expr2
|
|
and stmt = process_statement stmt
|
|
in expr1 ^ expr2 ^ stmt
|
|
| Default def ->
|
|
process_statement def
|
|
|
|
and process_initialiser =
|
|
function
|
|
| InitExpr expr ->
|
|
process_expression expr
|
|
| InitList init_list ->
|
|
process_brace
|
|
~include_braces:true (process_comma_list process_initialiser) init_list
|
|
| InitDesignators ((v1, v2, v3)) ->
|
|
let v1 = process_list process_designator v1
|
|
and v2 = process_token v2
|
|
and v3 = process_initialiser v3
|
|
in v1 ^ v2 ^ v3
|
|
| InitFieldOld ((v1, v2, v3)) ->
|
|
let v1 = process_simple_ident v1
|
|
and v2 = process_token v2
|
|
and v3 = process_initialiser v3
|
|
in v1 ^ v2 ^ v3
|
|
| InitIndexOld ((v1, v2)) ->
|
|
let v1 = process_bracket process_expression v1
|
|
and v2 = process_initialiser v2
|
|
in v1 ^ v2
|
|
and process_designator =
|
|
function
|
|
| DesignatorField ((v1, v2)) ->
|
|
let v1 = process_token v1
|
|
and v2 = process_simple_ident v2
|
|
in v1 ^ v2
|
|
| DesignatorIndex v1 ->
|
|
process_bracket process_expression v1
|
|
| DesignatorRange v1 ->
|
|
process_bracket
|
|
(fun (v1, v2, v3) ->
|
|
let v1 = process_expression v1
|
|
and v2 = process_token v2
|
|
and v3 = process_expression v3
|
|
in v1 ^ v2 ^ v3)
|
|
v1
|
|
|
|
and process_define_val =
|
|
function
|
|
| DefinePrintWrapper ((if_tok, expr_paren, name)) ->
|
|
let expr_paren = process_paren process_expression expr_paren
|
|
and name = process_name name in
|
|
expr_paren ^ name
|
|
| DefineExpr expr ->
|
|
process_expression expr
|
|
| DefineStmt stmt ->
|
|
process_statement stmt
|
|
| DefineType dtype ->
|
|
process_fullType dtype
|
|
| DefineDoWhileZero (stmt, tok_list) ->
|
|
process_statement stmt
|
|
| DefineFunction dfunc ->
|
|
process_func_definition dfunc
|
|
| DefineInit init ->
|
|
process_initialiser init
|
|
| DefineText (str, toks) ->
|
|
str
|
|
| DefineEmpty -> ""
|
|
| DefineTodo -> ""
|
|
|
|
and process_define _tok ident kind value =
|
|
match kind with
|
|
| DefineVar ->
|
|
let (idname, _ ) = ident in
|
|
"const " ^ idname ^ " = " ^ process_define_val value
|
|
| DefineFunc func ->
|
|
""
|
|
(*let (idname, _) = ident
|
|
in *)
|
|
|
|
and process_include ((tok, kind, path)) =
|
|
let include_file =
|
|
match kind with
|
|
| Local -> path
|
|
| Standard -> path
|
|
| Weird ->
|
|
let search = Str.regexp "_"
|
|
and lower = String.lowercase_ascii path
|
|
in Str.global_replace search "." lower
|
|
in "#" ^ include_file ^ " " ^ process_token tok
|
|
|
|
and process_cpp_directive = function
|
|
| Define ((tok, ident, kind, value)) ->
|
|
process_define tok ident kind value
|
|
| Include ((tok, inc_kind, path)) ->
|
|
process_include (tok, inc_kind, path)
|
|
| Undef ((name, tok)) ->
|
|
process_token tok
|
|
| PragmaAndCo tok ->
|
|
process_token tok
|
|
|
|
and process_func_definition {
|
|
f_name = f_name;
|
|
f_type = f_type;
|
|
f_storage = f_storage;
|
|
f_body = f_body
|
|
} =
|
|
let name = process_name f_name
|
|
and def_str = process_functionType f_type
|
|
and body = process_compound f_body in
|
|
|
|
"proc " ^ name ^ def_str ^ " =\n" ^ (indent body)
|
|
|
|
and process_func_or_else =
|
|
function
|
|
| FunctionOrMethod func_meth ->
|
|
process_func_definition func_meth
|
|
| Constructor ((func)) ->
|
|
process_func_definition func
|
|
| Destructor func ->
|
|
process_func_definition func
|
|
|
|
and process_declaration =
|
|
function
|
|
| BlockDecl block ->
|
|
process_block_declaration block
|
|
| Func func ->
|
|
process_func_or_else func
|
|
| TemplateDecl (v1, v2, v3) ->
|
|
(*let v1 = process_tok v1
|
|
and v2 = process_template_parameters v2
|
|
and v3 = process_declaration v3
|
|
in Ocaml.VSum (("TemplateDecl", [ v1; v2; v3 ]))*)
|
|
""
|
|
| TemplateSpecialization ((v1, v2, v3)) ->
|
|
(*let v1 = process_tok v1
|
|
and v2 = process_angle Ocaml.process_unit v2
|
|
and v3 = process_declaration v3
|
|
in Ocaml.VSum (("TemplateSpecialization", [ v1; v2; v3 ]))*)
|
|
""
|
|
| ExternC ((v1, v2, v3)) ->
|
|
(*let v1 = process_tok v1
|
|
and v2 = process_tok v2
|
|
and v3 = process_declaration v3
|
|
in Ocaml.VSum (("ExternC", [ v1; v2; v3 ]))*)
|
|
""
|
|
| ExternCList ((v1, v2, v3)) ->
|
|
(*let v1 = process_tok v1
|
|
and v2 = process_tok v2
|
|
and v3 = process_brace (Ocaml.process_list process_declaration_sequencable) v3
|
|
in Ocaml.VSum (("ExternCList", [ v1; v2; v3 ]))*)
|
|
""
|
|
| NameSpace ((v1, v2, v3)) ->
|
|
(*let v1 = process_tok v1
|
|
and v2 = process_wrap2 Ocaml.process_string v2
|
|
and v3 = process_brace (Ocaml.process_list process_declaration_sequencable) v3
|
|
in Ocaml.VSum (("NameSpace", [ v1; v2; v3 ]))*)
|
|
""
|
|
| NameSpaceExtend ((v1, v2)) ->
|
|
(*let v1 = Ocaml.process_string v1
|
|
and v2 = Ocaml.process_list process_declaration_sequencable v2
|
|
in Ocaml.VSum (("NameSpaceExtend", [ v1; v2 ]))*)
|
|
""
|
|
| NameSpaceAnon ((v1, v2)) ->
|
|
(*let v1 = process_tok v1
|
|
and v2 = process_brace (Ocaml.process_list process_declaration_sequencable) v2
|
|
in Ocaml.VSu:m (("NameSpaceAnon", [ v1; v2 ]))*)
|
|
""
|
|
| EmptyDef def -> ""
|
|
| DeclTodo -> "# TODO"
|
|
|
|
and process_fullType ((qualifier, typeC)) =
|
|
process_typeC typeC
|
|
|
|
and process_toplevel = function
|
|
| NotParsedCorrectly node -> "# Error parsing: " ^ process_list ~delimiter:"" process_token node
|
|
| DeclElem node -> process_declaration node
|
|
| CppDirectiveDecl node -> process_cpp_directive node
|
|
| IfdefDecl node -> ""
|
|
| MacroTop ((v1, v2, v3)) -> "# MacroTop"
|
|
| MacroVarTop ((v1, v2)) -> "# MacroVarTop"
|
|
|
|
let iter_ast ast =
|
|
List.map process_toplevel ast
|
|
|
|
let generate_nim cfile ?(macro_files = []) =
|
|
Parse_cpp.init_defs cfile;
|
|
List.iter Parse_cpp.add_defs macro_files;
|
|
let ast = Parse_cpp.parse_program cfile in
|
|
let res = iter_ast ast in
|
|
String.concat "\n" res
|
|
|
|
let test_gen_nim file =
|
|
let macro_list = [!Flag.macros_h] in
|
|
let nim_str = generate_nim file ~macro_files:macro_list in
|
|
pr nim_str
|
|
|
|
let actions () = [
|
|
"-generate-nim", " <file>",
|
|
Common.mk_action_1_arg test_gen_nim;
|
|
]
|