package codegen import "core:fmt" import "core:encoding/xml" parse_protocol :: proc(p: ^Parser) -> (protocol: Protocol, err: Parser_Error) { parser_enter(p) defer parser_exit(p) parser_ensure_ident(p, "protocol") or_return protocol.name = parser_get_attr(p, "name", string) or_return for ident in parser_iterate(p) { switch parser_get_ident(p) { case "copyright": protocol.copyright = parse_copyright(p) or_return case "description": protocol.description = parse_description(p) or_return case "interface": append(&protocol.interfaces, parse_interface(p) or_return) case: err = parser_make_error(p, .Unknown_Elem_Type, "", ident) return } } return } parse_copyright :: proc(p: ^Parser) -> (copyright: Copyright, err: Parser_Error) { parser_enter(p) defer parser_exit(p) return parser_get_body(p, string) } parse_description :: proc(p: ^Parser) -> (desc: Description, err: Parser_Error) { parser_enter(p) defer parser_exit(p) desc.summary, _ = parser_maybe_get_attr(p, "summary", string) or_return desc.body = parser_get_body(p, string) or_return return } parse_interface :: proc(p: ^Parser) -> (i: Interface, err: Parser_Error) { parser_enter(p) defer parser_exit(p) i.name = parser_get_attr(p, "name", string) or_return i.version = parser_get_attr(p, "version", Version) or_return i.frozen, _ = parser_maybe_get_attr(p, "frozen", bool) or_return for ident in parser_iterate(p) { switch ident { case "description": i.description = parse_description(p) or_return case "request": append(&i.requests, parse_message(p) or_return) case "event": append(&i.events, parse_message(p) or_return) case "enum": append(&i.enums, parse_enum(p) or_return) case: err = parser_make_error(p, .Unknown_Elem_Type, "", ident) return } } return } parse_message :: proc(p: ^Parser) -> (msg: Message, err: Parser_Error) { parser_enter(p) defer parser_exit(p) msg.name = parser_get_attr(p, "name", string) or_return if val, ok := parser_maybe_get_attr(p, "type", string) or_return; ok { if val == "destructor" { msg.destructor = true } else { err = parser_make_error(p, .Invalid_Attribute_Format, "destructor", val) return } } msg.since = parser_maybe_get_attr(p, "since", Version) or_return or_else 1 msg.deprecated_since, _ = parser_maybe_get_attr(p, "deprecated-since", Version) or_return for ident in parser_iterate(p) { switch ident { case "description": msg.description = parse_description(p) or_return case "arg": append(&msg.args, parse_arg(p) or_return) case: err = parser_make_error(p, .Unknown_Elem_Type, "", ident) return } } return } parse_arg :: proc(p: ^Parser) -> (arg: Arg, err: Parser_Error) { parser_enter(p) defer parser_exit(p) arg.name = parser_get_attr(p, "name", string) or_return arg.type = parser_get_attr(p, "type", Arg_Type) or_return arg.interface, _ = parser_maybe_get_attr(p, "interface", string) or_return arg.summary, _ = parser_maybe_get_attr(p, "summary", string) or_return arg.allow_null, _ = parser_maybe_get_attr(p, "allow-null", bool) or_return arg.enum_, _ = parser_maybe_get_attr(p, "enum", Arg_Enum) or_return return } parse_enum :: proc(p: ^Parser) -> (enum_: Enum, err: Parser_Error) { parser_enter(p) defer parser_exit(p) enum_.name = parser_get_attr(p, "name", string) or_return enum_.since = parser_maybe_get_attr(p, "since", Version) or_return or_else 1 enum_.bitfield = parser_maybe_get_attr(p, "bitfield", bool) or_return or_else false for ident in parser_iterate(p) { switch ident { case "description": enum_.description = parse_description(p) or_return case "entry": append(&enum_.entries, parse_enum_entry(p) or_return) case: err = parser_make_error(p, .Unknown_Elem_Type, "", ident) return } } return } parse_enum_entry :: proc(p: ^Parser) -> (entry: Enum_Entry, err: Parser_Error) { parser_enter(p) defer parser_exit(p) entry.name = parser_get_attr(p, "name", string) or_return entry.value = parser_get_attr(p, "value", Enum_Value) or_return entry.summary, _ = parser_maybe_get_attr(p, "summary", string) or_return entry.since = parser_maybe_get_attr(p, "since", Version) or_return or_else 1 entry.deprecated_since, _ = parser_maybe_get_attr(p, "deprecated-since", Version) or_return for ident in parser_iterate(p) { switch ident { case "description": entry.description = parse_description(p) or_return case: err = parser_make_error(p, .Unknown_Elem_Type, "", ident) return } } return }