diff --git a/py/parse.c b/py/parse.c
index 3cf909d75273c55c31fc1d04fe93a0148ebf9dcd..7a8fd3b1f57ca58a794ef5b86ef80ff68e09c0e3 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -135,6 +135,20 @@ mp_parse_node_struct_t *parse_node_new_struct(int src_line, int rule_id, int num
     return pn;
 }
 
+int parse_node_free_struct(mp_parse_node_t pn_in) {
+    int cnt = 0;
+    if (MP_PARSE_NODE_IS_STRUCT(pn_in)) {
+        mp_parse_node_struct_t *pn = (mp_parse_node_struct_t *)pn_in;
+        int n = pn->kind_num_nodes >> 8;
+        for (int i = 0; i < n; i++) {
+            cnt += parse_node_free_struct(pn->nodes[i]);
+        }
+        m_del_var(mp_parse_node_struct_t, mp_parse_node_t, n, pn);
+        cnt++;
+    }
+    return cnt;
+}
+
 #if MICROPY_DEBUG_PRINTERS
 void mp_parse_node_print(mp_parse_node_t pn, int indent) {
     if (MP_PARSE_NODE_IS_STRUCT(pn)) {
diff --git a/py/parse.h b/py/parse.h
index 2801f414eef3aed6f5034d2186c7ff4a8e8c0fd3..b7f1904d99c3d3f8928a2076894c949876d8406a 100644
--- a/py/parse.h
+++ b/py/parse.h
@@ -53,6 +53,7 @@ typedef struct _mp_parse_node_struct_t {
 #define MP_PARSE_NODE_STRUCT_NUM_NODES(pns) ((pns)->kind_num_nodes >> 8)
 
 mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg);
+int parse_node_free_struct(mp_parse_node_t pn_in);
 
 void mp_parse_node_print(mp_parse_node_t pn, int indent);
 
diff --git a/unix/main.c b/unix/main.c
index 681bf2aa20fc506907d1bea5fd21c8458b46c6ce..34d9618ca21b7a66fbc7aaccbed4250409750cb3 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -62,6 +62,7 @@ static void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind
     */
 
     mp_obj_t module_fun = mp_compile(pn, source_name, is_repl);
+    parse_node_free_struct(pn);
 
     if (module_fun == mp_const_none) {
         // compile error