raiguard/odin-wayland

git clone https://git.raiguard.me/raiguard/odin-wayland

Caleb HeuerCodegen: Parse XML files into an AST8d4791a

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