commit cdbb4b5045c3a748b09cd6df33e40324ff05c69d parent 556320b2bed32f2e01328c1cfe7e030b1be75e98 Author: Michael Savage <mikejsavage@gmail.com> Date: Fri Mar 4 23:44:51 +0000 Add stub IDL parser Diffstat:
models/trees/spec.lua | | | 153 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
diff --git a/models/trees/spec.lua b/models/trees/spec.lua @@ -0,0 +1,153 @@ +#! /usr/bin/lua + +-- lexing + +local lpeg = require( "lpeg" ) +local json = require( "cjson" ) + +local f = io.open( "models.spec" ) +local contents = f:read( "*all" ) +f:close() + +local identifier = ( lpeg.R( "az" ) + lpeg.R( "AZ" ) + lpeg.R( "09" ) + lpeg.P( "_" ) ) ^ 1 +local whitespace = lpeg.S( " \r\n\t" ) ^ 0 +local array = lpeg.P( "[" ) * whitespace * lpeg.C( identifier ) * whitespace * lpeg.P( "]" ) + +local function printf( form, ... ) + print( form:format( ... ) ) +end + +local function wrap_member( type, count, name ) + if not name then + name = count + count = nil + end + + return { + type = type, + count = count, + name = name, + } +end + +local function wrap_array( ... ) + return { ... } +end + +local function wrap_type( name, members ) + return { + name = name, + members = members, + } +end + +local member = lpeg.C( identifier ) * ( array + "" ) * whitespace * lpeg.C( identifier ) * whitespace * lpeg.P( ";" ) / wrap_member +local members = whitespace * ( member * whitespace ) ^ 1 / wrap_array +local typedef = lpeg.C( identifier ) * whitespace * lpeg.P( "{" ) * members * lpeg.P( "}" ) / wrap_type + +local typedefs = whitespace * ( ( typedef * whitespace ) ^ 1 / wrap_array ) * -lpeg.P( 1 ) + +local ast = typedefs:match( contents ) + +-- parsing + +local types = { } + +local function add_simple_type( t ) + types[ t ] = { + simple = true, + cpp_read = "read_" .. t .. "();", + cpp_write = "write_" .. t .. "();", + } +end + +add_simple_type( "u8" ) +add_simple_type( "u16" ) +add_simple_type( "u32" ) +add_simple_type( "u64" ) +add_simple_type( "s8" ) +add_simple_type( "s16" ) +add_simple_type( "s32" ) +add_simple_type( "s64" ) +add_simple_type( "f32" ) +add_simple_type( "f64" ) + +for _, t in ipairs( ast ) do + types[ t.name ] = t +end + +local function implement( impl ) + if impl.cpp_read then + return + end + + assert( impl.members, impl.name .. " is messed up" ) + + local r = "Stream read_" .. impl.name .. "( Stream in, " .. impl.name .. " * v ) {" + local w = "Stream write_" .. impl.name .. "( Stream out, const " .. impl.name .. " * v ) {" + + local seen_members = { } + + for _, member in ipairs( impl.members ) do + implement( types[ member.type ] ) + + -- TODO: this isn't parsing/writing properly + if member.count then + local count = member.count + if not tonumber( member.count ) then + assert( seen_members[ member.count ] ) + count = "v->" .. count + + end + + r = r .. "\n\tfor( size_t i = 0; i < " .. count .. "; i++ ) {" + w = w .. "\n\tfor( size_t i = 0; i < " .. count .. "; i++ ) {" + + r = r .. "\n\t\tin = read_" .. member.type .. "( in, &v->" .. member.name .. " );" + w = w .. "\n\t\t" .. "out = write_" .. member.type .. "( out, &v->" .. member.name .. " );" + + r = r .. "\n\t}" + w = w .. "\n\t}" + else + r = r .. "\n\tin = read_" .. member.type .. "( in, &v->" .. member.name .. " );" + w = w .. "\n\t" .. "out = write_" .. member.type .. "( out, &v->" .. member.name .. " );" + end + + seen_members[ member.name ] = true + end + + impl.cpp_read = r .. "\n\treturn in;\n}" + impl.cpp_write = w .. "\n\treturn out;\n}" +end + +print( "#include \"stream.h\"" ) +print() + +-- TODO: convert this to a dependency and print the leaves first +for name, impl in pairs( types ) do + if not impl.simple then + local struct = "struct " .. impl.name .. " {" + for _, member in ipairs( impl.members ) do + struct = struct .. "\n\t" .. member.type .. " " .. member.name .. ";" + end + print( struct .. "\n};" ) + end +end +print() + +for name, impl in pairs( types ) do + if not impl.simple then + print( "Stream read_" .. impl.name .. "( Stream in, " .. impl.name .. " * v );" ) + print( "Stream write_" .. impl.name .. "( Stream out, const " .. impl.name .. " * v );" ) + end +end +print() + +for name, impl in pairs( types ) do + implement( impl ) + if impl.name then + print( "\n" .. impl.cpp_read ) + print( "\n" .. impl.cpp_write ) + end +end +