1 /** Init file parser library
2  *
3  * The basic structure of the parser is as follows: there is a table of hooks
4  * which are run when a directive matching their format is encountered. When the
5  * hook is called, all the arguments it declares in its format have been parsed
6  * out and can be accessed with parser_get*(). See the unit tests for examples.
7  */
8 #ifndef PARSER_H
9 #define PARSER_H
10 
11 #include "h-basic.h"
12 #include "z-bitflag.h"
13 #include "z-rand.h"
14 
15 struct parser;
16 
17 enum parser_error {
18 	PARSE_ERROR_NONE = 0,
19 	PARSE_ERROR_GENERIC,
20 	PARSE_ERROR_INVALID_FLAG,
21 	PARSE_ERROR_INVALID_ITEM_NUMBER,
22 	PARSE_ERROR_INVALID_SPELL_FREQ,
23 	PARSE_ERROR_INVALID_VALUE,
24 	PARSE_ERROR_INVALID_COLOR,
25 	PARSE_ERROR_INVALID_EFFECT,
26 	PARSE_ERROR_INVALID_OPTION,
27 	PARSE_ERROR_MISSING_FIELD,
28 	PARSE_ERROR_MISSING_RECORD_HEADER,
29 	PARSE_ERROR_FIELD_TOO_LONG,
30 	PARSE_ERROR_NON_SEQUENTIAL_RECORDS,
31 	PARSE_ERROR_NOT_NUMBER,
32 	PARSE_ERROR_NOT_RANDOM,
33 	PARSE_ERROR_OBSOLETE_FILE,
34 	PARSE_ERROR_OUT_OF_BOUNDS,
35 	PARSE_ERROR_OUT_OF_MEMORY,
36 	PARSE_ERROR_TOO_FEW_ENTRIES,
37 	PARSE_ERROR_TOO_MANY_ENTRIES,
38 	PARSE_ERROR_UNDEFINED_DIRECTIVE,
39 	PARSE_ERROR_UNRECOGNISED_BLOW,
40 	PARSE_ERROR_UNRECOGNISED_TVAL,
41 	PARSE_ERROR_UNRECOGNISED_SVAL,
42 	PARSE_ERROR_VAULT_TOO_BIG,
43 	PARSE_ERROR_INTERNAL,
44 
45 	PARSE_ERROR_MAX
46 };
47 
48 struct parser_state {
49 	enum parser_error error;
50 	unsigned int line;
51 	unsigned int col;
52 	char *msg;
53 };
54 
55 struct file_parser {
56 	const char *name;
57 	struct parser *(*init)(void);
58 	errr (*run)(struct parser *p);
59 	errr (*finish)(struct parser *p);
60 	void (*cleanup)(void);
61 };
62 
63 extern const char *parser_error_str[PARSE_ERROR_MAX];
64 
65 /** Allocates a new parser. */
66 extern struct parser *parser_new(void);
67 
68 /** Parses the provided line.
69  *
70  * This runs the first parser hook registered with `p` that matches `line`.
71  */
72 extern enum parser_error parser_parse(struct parser *p, const char *line);
73 
74 /** Destroys a parser. */
75 extern void parser_destroy(struct parser *p);
76 
77 /** Gets parser's private data. */
78 extern void *parser_priv(struct parser *p);
79 
80 /** Sets parser's private data.
81  *
82  * This is commonly used to store context for stateful parsing.
83  */
84 extern void parser_setpriv(struct parser *p, void *v);
85 
86 /** Registers a parser hook.
87  *
88  * Hooks have the following format:
89  *   <fmt>  ::= <name> [<type> <name>]* [?<type> <name>]*
90  *   <type> ::= int | str | sym | rand | char
91  * The first <name> is called the directive for this hook. Any other hooks with
92  * the same directive are superseded by this hook. It is an error for a
93  * mandatory field to follow an optional field. It is an error for any field to
94  * follow a field of type `str`, since `str` fields are not delimited and will
95  * consume the entire rest of the line.
96  */
97 extern errr parser_reg(struct parser *p, const char *fmt,
98                        enum parser_error (*func)(struct parser *p));
99 
100 /** A placeholder parse hook indicating a value is ignored */
101 extern enum parser_error ignored(struct parser *p);
102 
103 /** Returns whether the parser has a value named `name`.
104  *
105  * Used to test for presence of optional values.
106  */
107 extern bool parser_hasval(struct parser *p, const char *name);
108 
109 /** Returns the symbol named `name`. This symbol must exist. */
110 extern const char *parser_getsym(struct parser *p, const char *name);
111 
112 /** Returns the string named `name`. This symbol must exist. */
113 extern const char *parser_getstr(struct parser *p, const char *name);
114 
115 /** Returns the integer named `name`. This symbol must exist. */
116 extern int parser_getint(struct parser *p, const char *name);
117 
118 /** Returns the unsigned integer named `name`. This symbol must exist. */
119 extern unsigned int parser_getuint(struct parser *p, const char *name);
120 
121 /** Returns the random value named `name`. This symbol must exist. */
122 extern struct random parser_getrand(struct parser *p, const char *name);
123 
124 /** Returns the character named `name`. This symbol must exist. */
125 extern wchar_t parser_getchar(struct parser *p, const char *name);
126 
127 /** Fills the provided struct with the parser's state, if any. Returns true if
128  * the parser is in an error state, and false otherwise.
129  */
130 extern int parser_getstate(struct parser *p, struct parser_state *s);
131 
132 /** Sets the parser's detailed error description and field number. */
133 extern void parser_setstate(struct parser *p, unsigned int col, const char *msg);
134 
135 errr run_parser(struct file_parser *fp);
136 void cleanup_parser(struct file_parser *fp);
137 int lookup_flag(const char **flag_table, const char *flag_name);
138 errr grab_flag(bitflag *flags, const size_t size, const char **flag_table, const char *flag_name);
139 errr remove_flag(bitflag *flags, const size_t size, const char **flag_table, const char *flag_name);
140 
141 #endif /* !PARSER_H */
142