medfall

A super great game engine
Log | Files | Refs

spec.lua (3820B)


      1 #! /usr/bin/lua
      2 
      3 -- lexing
      4 
      5 local lpeg = require( "lpeg" )
      6 local json = require( "cjson" )
      7 
      8 local f = io.open( "models.spec" )
      9 local contents = f:read( "*all" )
     10 f:close()
     11 
     12 local identifier = ( lpeg.R( "az" ) + lpeg.R( "AZ" ) + lpeg.R( "09" ) + lpeg.P( "_" ) ) ^ 1
     13 local whitespace = lpeg.S( " \r\n\t" ) ^ 0
     14 local array = lpeg.P( "[" ) * whitespace * lpeg.C( identifier ) * whitespace * lpeg.P( "]" )
     15 
     16 local function printf( form, ... )
     17 	print( form:format( ... ) )
     18 end
     19 
     20 local function wrap_member( type, count, name )
     21 	if not name then
     22 		name = count
     23 		count = nil
     24 	end
     25 
     26 	return {
     27 		type = type,
     28 		count = count,
     29 		name = name,
     30 	}
     31 end
     32 
     33 local function wrap_array( ... )
     34 	return { ... }
     35 end
     36 
     37 local function wrap_type( name, members )
     38 	return {
     39 		name = name,
     40 		members = members,
     41 	}
     42 end
     43 
     44 local member = lpeg.C( identifier ) * ( array + "" ) * whitespace * lpeg.C( identifier ) * whitespace * lpeg.P( ";" ) / wrap_member
     45 local members = whitespace * ( member * whitespace ) ^ 1 / wrap_array
     46 local typedef = lpeg.C( identifier ) * whitespace * lpeg.P( "{" ) * members * lpeg.P( "}" ) / wrap_type
     47 
     48 local typedefs = whitespace * ( ( typedef * whitespace ) ^ 1 / wrap_array ) * -lpeg.P( 1 )
     49 
     50 local ast = typedefs:match( contents )
     51 
     52 -- parsing
     53 
     54 local types = { }
     55 
     56 local function add_simple_type( t )
     57 	types[ t ] = {
     58 		simple = true,
     59 		cpp_read = "read_" .. t .. "();",
     60 		cpp_write = "write_" .. t .. "();",
     61 	}
     62 end
     63 
     64 add_simple_type( "u8" )
     65 add_simple_type( "u16" )
     66 add_simple_type( "u32" )
     67 add_simple_type( "u64" )
     68 add_simple_type( "s8" )
     69 add_simple_type( "s16" )
     70 add_simple_type( "s32" )
     71 add_simple_type( "s64" )
     72 add_simple_type( "float" )
     73 add_simple_type( "double" )
     74 
     75 for _, t in ipairs( ast ) do
     76 	types[ t.name ] = t
     77 end
     78 
     79 local function implement( impl )
     80 	if impl.cpp_read then
     81 		return
     82 	end
     83 
     84 	assert( impl.members, impl.name .. " is messed up" )
     85 
     86 	local r = "Stream read_" .. impl.name .. "( Stream in, " .. impl.name .. " * v ) {"
     87 	local w = "Stream write_" .. impl.name .. "( Stream out, const " .. impl.name .. " * v ) {"
     88 
     89 	local seen_members = { }
     90 
     91 	for _, member in ipairs( impl.members ) do
     92 		implement( types[ member.type ] )
     93 
     94 		-- TODO: this isn't parsing/writing properly
     95 		if member.count then
     96 			local count = member.count
     97 			if not tonumber( member.count ) then
     98 				assert( seen_members[ member.count ] )
     99 				count = "v->" .. count
    100 
    101 			end
    102 
    103 			r = r .. "\n\tfor( size_t i = 0; i < " .. count .. "; i++ ) {"
    104 			w = w .. "\n\tfor( size_t i = 0; i < " .. count .. "; i++ ) {"
    105 
    106 			r = r .. "\n\t\tin = read_" .. member.type .. "( in, &v->" .. member.name .. " );"
    107 			w = w .. "\n\t\t" .. "out = write_" .. member.type .. "( out, &v->" .. member.name .. " );"
    108 
    109 			r = r .. "\n\t}"
    110 			w = w .. "\n\t}"
    111 		else
    112 			r = r .. "\n\tin = read_" .. member.type .. "( in, &v->" .. member.name .. " );"
    113 			w = w .. "\n\t" .. "out = write_" .. member.type .. "( out, &v->" .. member.name .. " );"
    114 		end
    115 
    116 		seen_members[ member.name ] = true
    117 	end
    118 
    119 	impl.cpp_read = r .. "\n\treturn in;\n}"
    120 	impl.cpp_write = w .. "\n\treturn out;\n}"
    121 end
    122 
    123 print( "#include \"stream.h\"" )
    124 print()
    125 
    126 -- TODO: convert this to a dependency and print the leaves first
    127 for name, impl in pairs( types ) do
    128 	if not impl.simple then
    129 		local struct = "struct " .. impl.name .. " {"
    130 		for _, member in ipairs( impl.members ) do
    131 			struct = struct .. "\n\t" .. member.type .. " " .. member.name .. ";"
    132 		end
    133 		print( struct .. "\n};" )
    134 	end
    135 end
    136 print()
    137 
    138 for name, impl in pairs( types ) do
    139 	if not impl.simple then
    140 		print( "Stream read_" .. impl.name .. "( Stream in, " .. impl.name .. " * v );" )
    141 		print( "Stream write_" .. impl.name .. "( Stream out, const " .. impl.name .. " * v );" )
    142 	end
    143 end
    144 print()
    145 
    146 for name, impl in pairs( types ) do
    147 	implement( impl )
    148 	if impl.name then
    149 		print( "\n" .. impl.cpp_read )
    150 		print( "\n" .. impl.cpp_write )
    151 	end
    152 end
    153