131 lines
2.6 KiB
C
131 lines
2.6 KiB
C
#include "parsen.h"
|
|
#include "gm-parser.h"
|
|
#include "gm-debug.h"
|
|
|
|
typedef struct _ParserState {
|
|
GList *code;
|
|
gchar *line;
|
|
gint cur_line;
|
|
gint cur_char;
|
|
GList *errors;
|
|
GList *warnings;
|
|
} ParserState;
|
|
|
|
static void
|
|
gm_parser_error(void *data, const char *msg) {
|
|
ParserState *state = (ParserState *)data;
|
|
GmParserError *r = g_new0(GmParserError, 1);
|
|
|
|
r->line = state->cur_line;
|
|
r->ch = state->cur_char;
|
|
r->message = g_strdup(msg);
|
|
|
|
state->errors = g_list_append(state->errors, r);
|
|
}
|
|
|
|
static void
|
|
gm_parser_warning(void *data, const char *msg) {
|
|
ParserState *state = (ParserState *)data;
|
|
GmParserError *r = g_new0(GmParserError, 1);
|
|
|
|
r->line = state->cur_line;
|
|
r->ch = state->cur_char;
|
|
r->message = g_strdup(msg);
|
|
|
|
state->warnings = g_list_append(state->warnings, r);
|
|
}
|
|
|
|
static int
|
|
gm_parser_getc(void *data) {
|
|
ParserState *state = (ParserState *)data;
|
|
guchar c;
|
|
gchar *line;
|
|
|
|
if (state->line == NULL) {
|
|
return EOF;
|
|
} else if ((c = state->line[state->cur_char]) == '\n' || c == '\0') {
|
|
state->code = state->code->next;
|
|
|
|
if (state->code != NULL) {
|
|
state->line = (gchar *)(state->code->data);
|
|
} else {
|
|
state->line = NULL;
|
|
}
|
|
|
|
++state->cur_line;
|
|
state->cur_char = 0;
|
|
return '\n';
|
|
} else {
|
|
++state->cur_char;
|
|
return c;
|
|
}
|
|
}
|
|
|
|
void
|
|
gm_parser_init_state(ParserState *state) {
|
|
state->cur_line = 0;
|
|
state->cur_char = 0;
|
|
state->errors = NULL;
|
|
state->warnings = NULL;
|
|
}
|
|
|
|
void
|
|
gm_parser_init_result(GmParserResult *result) {
|
|
result->isOk = TRUE;
|
|
result->warnings = NULL;
|
|
result->errors = NULL;
|
|
}
|
|
|
|
static Parser_Client list_parser_client = {
|
|
gm_parser_error,
|
|
gm_parser_warning,
|
|
gm_parser_getc
|
|
};
|
|
|
|
GmParserResult *
|
|
gm_parser_parse(GList *code) {
|
|
ParserState state;
|
|
GmParserResult *result = g_new0(GmParserResult, 1);
|
|
|
|
gm_parser_init_result(result);
|
|
|
|
if (!code) {
|
|
return result;
|
|
}
|
|
|
|
gm_parser_init_state(&state);
|
|
state.code = code;
|
|
state.line = (gchar *)(code->data);
|
|
|
|
parse_program(current_version, list_parser_client, &state);
|
|
|
|
result->errors = state.errors;
|
|
result->warnings = state.warnings;
|
|
result->isOk = (result->errors == NULL && result->warnings == NULL);
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
gm_parser_error_free(GmParserError *error) {
|
|
g_free(error->message);
|
|
g_free(error);
|
|
}
|
|
|
|
void
|
|
gm_parser_result_free(GmParserResult *result) {
|
|
GList *item;
|
|
|
|
for (item = result->errors; item; item = item->next) {
|
|
gm_parser_error_free((GmParserError *)(item->data));
|
|
}
|
|
|
|
for (item = result->warnings; item; item = item->next) {
|
|
gm_parser_error_free((GmParserError *)(item->data));
|
|
}
|
|
|
|
g_list_free(result->errors);
|
|
g_list_free(result->warnings);
|
|
|
|
g_free(result);
|
|
}
|