raiguard/odin-wayland
git clone https://git.raiguard.me/raiguard/odin-wayland
8d4791a
trunk
1package codegen 2 3import "core:fmt" 4import "core:encoding/xml" 5 6parse_protocol :: proc ( p : ^ Parser ) -> ( protocol : Protocol , err : Parser_Error ) { 7parser_enter ( p ) 8defer parser_exit ( p ) 9 10parser_ensure_ident ( p , "protocol" ) or_return 11 12protocol . name = parser_get_attr ( p , "name" , string ) or_return 13 14for ident in parser_iterate ( p ) { 15switch parser_get_ident ( p ) { 16case "copyright" : 17protocol . copyright = parse_copyright ( p ) or_return 18case "description" : 19protocol . description = parse_description ( p ) or_return 20case "interface" : 21append ( & protocol . interfaces , parse_interface ( p ) or_return ) 22case : 23err = parser_make_error ( p , . Unknown_Elem_Type , "" , ident ) 24return 25} 26} 27 28return 29} 30 31parse_copyright :: proc ( p : ^ Parser ) -> ( copyright : Copyright , err : Parser_Error ) { 32parser_enter ( p ) 33defer parser_exit ( p ) 34 35return parser_get_body ( p , string ) 36} 37 38parse_description :: proc ( p : ^ Parser ) -> ( desc : Description , err : Parser_Error ) { 39parser_enter ( p ) 40defer parser_exit ( p ) 41 42desc . summary , _ = parser_maybe_get_attr ( p , "summary" , string ) or_return 43desc . body = parser_get_body ( p , string ) or_return 44 45return 46} 47 48parse_interface :: proc ( p : ^ Parser ) -> ( i : Interface , err : Parser_Error ) { 49parser_enter ( p ) 50defer parser_exit ( p ) 51 52i . name = parser_get_attr ( p , "name" , string ) or_return 53i . version = parser_get_attr ( p , "version" , Version ) or_return 54i . frozen , _ = parser_maybe_get_attr ( p , "frozen" , bool ) or_return 55 56for ident in parser_iterate ( p ) { 57switch ident { 58case "description" : 59i . description = parse_description ( p ) or_return 60case "request" : 61append ( & i . requests , parse_message ( p ) or_return ) 62case "event" : 63append ( & i . events , parse_message ( p ) or_return ) 64case "enum" : 65append ( & i . enums , parse_enum ( p ) or_return ) 66case : 67err = parser_make_error ( p , . Unknown_Elem_Type , "" , ident ) 68return 69} 70} 71 72return 73} 74 75parse_message :: proc ( p : ^ Parser ) -> ( msg : Message , err : Parser_Error ) { 76parser_enter ( p ) 77defer parser_exit ( p ) 78 79msg . name = parser_get_attr ( p , "name" , string ) or_return 80if val , ok := parser_maybe_get_attr ( p , "type" , string ) or_return ; ok { 81if val == "destructor" { 82msg . destructor = true 83} else { 84err = parser_make_error ( p , . Invalid_Attribute_Format , "destructor" , val ) 85return 86} 87} 88msg . since = parser_maybe_get_attr ( p , "since" , Version ) or_return or_else 1 89msg . deprecated_since , _ = parser_maybe_get_attr ( p , "deprecated-since" , Version ) or_return 90 91for ident in parser_iterate ( p ) { 92switch ident { 93case "description" : 94msg . description = parse_description ( p ) or_return 95case "arg" : 96append ( & msg . args , parse_arg ( p ) or_return ) 97case : 98err = parser_make_error ( p , . Unknown_Elem_Type , "" , ident ) 99return 100} 101} 102 103return 104} 105 106parse_arg :: proc ( p : ^ Parser ) -> ( arg : Arg , err : Parser_Error ) { 107parser_enter ( p ) 108defer parser_exit ( p ) 109 110arg . name = parser_get_attr ( p , "name" , string ) or_return 111arg . type = parser_get_attr ( p , "type" , Arg_Type ) or_return 112 113arg . interface , _ = parser_maybe_get_attr ( p , "interface" , string ) or_return 114arg . summary , _ = parser_maybe_get_attr ( p , "summary" , string ) or_return 115arg . allow_null , _ = parser_maybe_get_attr ( p , "allow-null" , bool ) or_return 116arg . enum_ , _ = parser_maybe_get_attr ( p , "enum" , Arg_Enum ) or_return 117 118return 119} 120 121parse_enum :: proc ( p : ^ Parser ) -> ( enum_ : Enum , err : Parser_Error ) { 122parser_enter ( p ) 123defer parser_exit ( p ) 124 125enum_ . name = parser_get_attr ( p , "name" , string ) or_return 126enum_ . since = parser_maybe_get_attr ( p , "since" , Version ) or_return or_else 1 127enum_ . bitfield = parser_maybe_get_attr ( p , "bitfield" , bool ) or_return or_else false 128 129for ident in parser_iterate ( p ) { 130switch ident { 131case "description" : 132enum_ . description = parse_description ( p ) or_return 133case "entry" : 134append ( & enum_ . entries , parse_enum_entry ( p ) or_return ) 135case : 136err = parser_make_error ( p , . Unknown_Elem_Type , "" , ident ) 137return 138} 139} 140 141return 142} 143 144parse_enum_entry :: proc ( p : ^ Parser ) -> ( entry : Enum_Entry , err : Parser_Error ) { 145parser_enter ( p ) 146defer parser_exit ( p ) 147 148entry . name = parser_get_attr ( p , "name" , string ) or_return 149entry . value = parser_get_attr ( p , "value" , Enum_Value ) or_return 150entry . summary , _ = parser_maybe_get_attr ( p , "summary" , string ) or_return 151entry . since = parser_maybe_get_attr ( p , "since" , Version ) or_return or_else 1 152entry . deprecated_since , _ = parser_maybe_get_attr ( p , "deprecated-since" , Version ) or_return 153 154for ident in parser_iterate ( p ) { 155switch ident { 156case "description" : 157entry . description = parse_description ( p ) or_return 158case : 159err = parser_make_error ( p , . Unknown_Elem_Type , "" , ident ) 160return 161} 162} 163 164return 165}