1 /*********************************************************************
3 Gazelle: a system for building fast, reusable grammars
7 These are Lua wrappers for Gazelle.
9 Copyright (c) 2007 Joshua Haberman. See LICENSE for details.
11 *********************************************************************/
13 #include "bc_read_stream_lua.h"
14 #include "interpreter.h"
22 struct gazelle_grammar_lua
27 struct gazelle_rtn_lua
32 struct gazelle_rtn_state_lua
34 struct rtn_state
*rtn_state
;
37 struct gazelle_rtn_transition_lua
39 struct rtn_transition
*rtn_transition
;
42 static void *newobj(lua_State
*L
, char *type
, int size
)
44 void *ptr
= lua_newuserdata(L
, size
);
45 luaL_getmetatable(L
, type
);
46 lua_setmetatable(L
, -2);
50 static bool get_from_cache(lua_State
*L
, void *ptr
)
52 static const luaL_reg no_methods
[] = {{NULL
, NULL
}};
53 luaL_register(L
, "gazelle", no_methods
); /* push the table for this module */
54 lua_getfield(L
, -1, "ObjectCache"); /* push our object cache */
56 /* attempt to get our stored value */
57 lua_pushlightuserdata(L
, ptr
);
62 /* object doesn't exist in the cache yet.
63 * leave the mod table and object cache on the stack -- we'll
64 * pop them when the caller makes the (required) call to
71 /* we found the object. pop everything else off the stack and leave it at the top. */
79 * When this is called the stack looks like:
81 * - object cache table
82 * - val to put in cache
84 static void put_in_cache(lua_State
*L
, void *ptr
)
86 lua_pushlightuserdata(L
, ptr
);
88 lua_rawset(L
, -4); /* store this in the object cache */
92 lua_pop(L
, 1); /* pop the mod table */
95 static void get_rtn(lua_State
*L
, struct rtn
*rtn
)
97 if(!get_from_cache(L
, rtn
))
99 struct gazelle_rtn_lua
*rtn_obj
= newobj(L
, "gazelle.rtn", sizeof(*rtn_obj
));
101 put_in_cache(L
, rtn
);
105 static void get_rtn_state(lua_State
*L
, struct rtn_state
*rtn_state
)
107 if(!get_from_cache(L
, rtn_state
))
109 struct gazelle_rtn_state_lua
*rtn_state_obj
= newobj(L
, "gazelle.rtn_state", sizeof(*rtn_state_obj
));
110 rtn_state_obj
->rtn_state
= rtn_state
;
111 put_in_cache(L
, rtn_state
);
120 static int gazelle_load_grammar(lua_State
*L
)
122 struct bc_read_stream_lua
*s
= luaL_checkudata(L
, 1, "bc_read_stream");
123 struct gazelle_grammar_lua
*g
= newobj(L
, "gazelle.grammar", sizeof(*g
));
124 g
->g
= load_grammar(s
->s
);
126 return luaL_error(L
, "Couldn't load grammar!");
131 static const luaL_reg global_functions
[] =
133 {"load_grammar", gazelle_load_grammar
},
138 * methods for "grammar" object
141 static int gazelle_grammar_strings(lua_State
*L
)
143 struct gazelle_grammar_lua
*g
= luaL_checkudata(L
, 1, "gazelle.grammar");
145 for(int i
= 0; g
->g
->strings
[i
] != NULL
; i
++)
147 lua_pushstring(L
, g
->g
->strings
[i
]);
148 lua_rawseti(L
, -2, i
+1);
153 static int gazelle_grammar_rtns(lua_State
*L
)
155 struct gazelle_grammar_lua
*g
= luaL_checkudata(L
, 1, "gazelle.grammar");
157 for(int i
= 0; i
< g
->g
->num_rtns
; i
++)
159 get_rtn(L
, &g
->g
->rtns
[i
]);
160 lua_rawseti(L
, -2, i
+1);
165 static int gazelle_grammar_rtn(lua_State
*L
)
167 struct gazelle_grammar_lua
*g
= luaL_checkudata(L
, 1, "gazelle.grammar");
168 const char *rtn_name
= luaL_checkstring(L
, 2);
169 for(int i
= 0; i
< g
->g
->num_rtns
; i
++)
171 if(strcmp(g
->g
->rtns
[i
].name
, rtn_name
) == 0)
173 get_rtn(L
, &g
->g
->rtns
[i
]);
180 static const luaL_reg grammar_methods
[] =
182 {"rtns", gazelle_grammar_rtns
},
183 {"rtn", gazelle_grammar_rtn
},
184 {"strings", gazelle_grammar_strings
},
189 * methods for "rtn" object
192 static int gazelle_rtn_name(lua_State
*L
)
194 struct gazelle_rtn_lua
*rtn
= luaL_checkudata(L
, 1, "gazelle.rtn");
195 lua_pushstring(L
, rtn
->rtn
->name
);
199 static int gazelle_rtn_num_slots(lua_State
*L
)
201 struct gazelle_rtn_lua
*rtn
= luaL_checkudata(L
, 1, "gazelle.rtn");
202 lua_pushnumber(L
, rtn
->rtn
->num_slots
);
206 static int gazelle_rtn_ignore_terminals(lua_State
*L
)
208 struct gazelle_rtn_lua
*rtn
= luaL_checkudata(L
, 1, "gazelle.rtn");
210 for(int i
= 0; i
< rtn
->rtn
->num_ignore
; i
++)
212 lua_pushstring(L
, rtn
->rtn
->ignore_terminals
[i
]);
213 lua_rawseti(L
, -2, i
+1);
218 static int gazelle_rtn_states(lua_State
*L
)
220 struct gazelle_rtn_lua
*rtn
= luaL_checkudata(L
, 1, "gazelle.rtn");
222 for(int i
= 0; i
< rtn
->rtn
->num_states
; i
++)
224 get_rtn_state(L
, &rtn
->rtn
->states
[i
]);
225 lua_rawseti(L
, -2, i
+1);
230 static const luaL_reg rtn_methods
[] =
232 {"name", gazelle_rtn_name
},
233 {"num_slots", gazelle_rtn_num_slots
},
234 {"ignore_terminals", gazelle_rtn_ignore_terminals
},
235 {"states", gazelle_rtn_states
},
240 * methods for "rtn_state" objects
243 static int gazelle_rtn_state_is_final(lua_State
*L
)
245 struct gazelle_rtn_state_lua
*rtn_state
= luaL_checkudata(L
, 1, "gazelle.rtn_state");
246 lua_pushboolean(L
, rtn_state
->rtn_state
->is_final
);
250 static int gazelle_rtn_state_transitions(lua_State
*L
)
252 struct gazelle_rtn_state_lua
*rtn_state
= luaL_checkudata(L
, 1, "gazelle.rtn_state");
254 for(int i
= 0; i
< rtn_state
->rtn_state
->num_transitions
; i
++)
256 struct rtn_transition
*t
= &rtn_state
->rtn_state
->transitions
[i
];
258 if(t
->transition_type
== TERMINAL_TRANSITION
|| t
->transition_type
== NONTERM_TRANSITION
)
260 if(t
->transition_type
== TERMINAL_TRANSITION
)
262 lua_pushstring(L
, "terminal");
263 lua_rawseti(L
, -2, 1);
264 lua_pushstring(L
, t
->edge
.terminal_name
);
265 lua_rawseti(L
, -2, 2);
267 else if(t
->transition_type
== NONTERM_TRANSITION
)
269 lua_pushstring(L
, "nonterm");
270 lua_rawseti(L
, -2, 1);
271 get_rtn(L
, t
->edge
.nonterminal
);
272 lua_rawseti(L
, -2, 2);
275 get_rtn_state(L
, t
->dest_state
);
276 lua_rawseti(L
, -2, 3);
277 lua_pushstring(L
, t
->slotname
);
278 lua_rawseti(L
, -2, 4);
279 lua_pushnumber(L
, t
->slotnum
);
280 lua_rawseti(L
, -2, 5);
282 else if(t
->transition_type
== DECISION
)
284 lua_pushstring(L
, "decision");
285 lua_rawseti(L
, -2, 1);
286 lua_pushstring(L
, t
->edge
.decision
->terminal_name
);
287 lua_rawseti(L
, -2, 2);
290 for(int j
= 0; j
< t
->edge
.decision
->num_actions
; j
++)
292 lua_pushnumber(L
, t
->edge
.decision
->actions
[j
]);
293 lua_rawseti(L
, -2, j
+1);
295 lua_rawseti(L
, -2, 3);
299 printf("%d\n", t
->transition_type
);
300 return luaL_error(L
, "corrupt grammar: invalid transition type!");
303 lua_rawseti(L
, -2, i
+1);
308 static const luaL_reg rtn_state_methods
[] =
310 {"is_final", gazelle_rtn_state_is_final
},
311 {"transitions", gazelle_rtn_state_transitions
},
316 * methods for "rtn_transition" objects
319 static const luaL_reg rtn_transition_methods
[] =
321 {"is_final", gazelle_rtn_state_is_final
},
322 {"transitions", gazelle_rtn_state_transitions
},
326 void register_object(lua_State
*L
, char *obj_name
, const luaL_reg
*methods
)
328 luaL_newmetatable(L
, obj_name
);
330 /* metatable.__index = metatable */
331 lua_pushvalue(L
, -1); /* duplicates the metatable */
332 lua_setfield(L
, -2, "__index");
334 luaL_register(L
, NULL
, methods
);
337 int luaopen_gazelle(lua_State
*L
)
339 register_object(L
, "gazelle.grammar", grammar_methods
);
340 register_object(L
, "gazelle.rtn", rtn_methods
);
341 register_object(L
, "gazelle.rtn_state", rtn_state_methods
);
343 luaL_register(L
, "gazelle", global_functions
);
345 lua_setfield(L
, -2, "ObjectCache");
352 * c-file-style: "bsd"
354 * indent-tabs-mode: nil