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