#include #include "apfl.h" #define POSFMT "%d:%d" #define POSARGS error.position.line, error.position.col #define POS2ARGS error.position2.line, error.position2.col const char * apfl_error_type_name(enum apfl_error_type type) { switch (type) { case APFL_ERR_MALLOC_FAILED: return "APFL_ERR_MALLOC_FAILED"; case APFL_ERR_INPUT_ERROR: return "APFL_ERR_INPUT_ERROR"; case APFL_ERR_UNEXPECTED_EOF: return "APFL_ERR_UNEXPECTED_EOF"; case APFL_ERR_EXPECTED_EQ_AFTER_COLON: return "APFL_ERR_EXPECTED_EQ_AFTER_COLON"; case APFL_ERR_UNEXPECTED_BYTE: return "APFL_ERR_UNEXPECTED_BYTE"; case APFL_ERR_UNEXPECTED_BYTE_IN_NUMBER: return "APFL_ERR_UNEXPECTED_BYTE_IN_NUMBER"; case APFL_ERR_EXPECTED_DIGIT: return "APFL_ERR_EXPECTED_DIGIT"; case APFL_ERR_EXPECTED_HEX_IN_HEX_ESCAPE: return "APFL_ERR_EXPECTED_HEX_IN_HEX_ESCAPE"; case APFL_ERR_INVALID_ESCAPE_SEQUENCE: return "APFL_ERR_INVALID_ESCAPE_SEQUENCE"; case APFL_ERR_NO_LINEBREAK_AFTER_CONTINUE_LINE: return "APFL_ERR_NO_LINEBREAK_AFTER_CONTINUE_LINE"; case APFL_ERR_UNEXPECTED_TOKEN: return "APFL_ERR_UNEXPECTED_TOKEN"; case APFL_ERR_MISMATCHING_CLOSING_BRACKET: return "APFL_ERR_MISMATCHING_CLOSING_BRACKET"; case APFL_ERR_UNEXPECTED_EOF_AFTER_TOKEN: return "APFL_ERR_UNEXPECTED_EOF_AFTER_TOKEN"; case APFL_ERR_STATEMENTS_BEFORE_PARAMETERS: return "APFL_ERR_STATEMENTS_BEFORE_PARAMETERS"; case APFL_ERR_EMPTY_ASSIGNMENT_BEFORE_PARAMETERS: return "APFL_ERR_EMPTY_ASSIGNMENT_BEFORE_PARAMETERS"; case APFL_ERR_UNEXPECTED_EXPRESSION: return "APFL_ERR_UNEXPECTED_EXPRESSION"; case APFL_ERR_INVALID_ASSIGNMENT_LHS: return "APFL_ERR_INVALID_ASSIGNMENT_LHS"; case APFL_ERR_EMPTY_ASSIGNMENT: return "APFL_ERR_EMPTY_ASSIGNMENT"; case APFL_ERR_ONLY_ONE_EXPAND_ALLOWED: return "APFL_ERR_ONLY_ONE_EXPAND_ALLOWED"; case APFL_ERR_UNEXPECTED_CONSTANT_IN_MEMBER_ACCESS: return "APFL_ERR_UNEXPECTED_CONSTANT_IN_MEMBER_ACCESS"; case APFL_ERR_UNEXPECTED_EXPR_IN_MEMBER_ACCESS: return "APFL_ERR_UNEXPECTED_EXPR_IN_MEMBER_ACCESS"; } return ""; } void apfl_error_print(struct apfl_error error, FILE *file) { switch (error.type) { case APFL_ERR_MALLOC_FAILED: fprintf(file, "Could not allocate memory\n"); return; case APFL_ERR_INPUT_ERROR: fprintf(file, "Input error while parsing\n"); return; case APFL_ERR_UNEXPECTED_EOF: fprintf(file, "Unexpected end of file\n"); return; case APFL_ERR_EXPECTED_EQ_AFTER_COLON: fprintf(file, "Expected '=' after ':' at " POSFMT "\n", POSARGS); return; case APFL_ERR_UNEXPECTED_BYTE: fprintf(file, "Unexpected byte '%c' (0x%X) at " POSFMT "\n", error.byte, (unsigned)error.byte, POSARGS); return; case APFL_ERR_UNEXPECTED_BYTE_IN_NUMBER: fprintf(file, "Unexpected byte '%c' while parsing number at " POSFMT "\n", error.byte, POSARGS); return; case APFL_ERR_EXPECTED_DIGIT: fprintf(file, "Expected a digit at " POSFMT "\n", POSARGS); return; case APFL_ERR_EXPECTED_HEX_IN_HEX_ESCAPE: fprintf(file, "Expected a hex-digit in hex escape at " POSFMT "\n", POSARGS); return; case APFL_ERR_INVALID_ESCAPE_SEQUENCE: fprintf(file, "Invalid escape sequence \\%c at " POSFMT "\n", error.byte, POSARGS); return; case APFL_ERR_NO_LINEBREAK_AFTER_CONTINUE_LINE: fprintf(file, "No line break (after optional comments) after \\ at " POSFMT "\n", POSARGS); return; case APFL_ERR_UNEXPECTED_TOKEN: fprintf(file, "Unexpected `%s` token at " POSFMT "\n", apfl_token_type_name(error.token_type), POSARGS); return; case APFL_ERR_MISMATCHING_CLOSING_BRACKET: fprintf( file, "Closing `%s` token at " POSFMT " does not match opening `%s` at " POSFMT "\n", apfl_token_type_name(error.token_type), POSARGS, apfl_token_type_name(error.token_type2), POS2ARGS ); return; case APFL_ERR_UNEXPECTED_EOF_AFTER_TOKEN: fprintf( file, "Unexpected end of file after `%s` token at " POSFMT "\n", apfl_token_type_name(error.token_type), POSARGS ); return; case APFL_ERR_STATEMENTS_BEFORE_PARAMETERS: fprintf( file, "Unexpected statements before parameters near " POSFMT "\n", POSARGS ); return; case APFL_ERR_EMPTY_ASSIGNMENT_BEFORE_PARAMETERS: fprintf( file, "Unexpected empty assignment before parameters near " POSFMT "\n", POSARGS ); return; case APFL_ERR_UNEXPECTED_EXPRESSION: fprintf( file, "Unexpected expression near " POSFMT "\n", POSARGS ); return; case APFL_ERR_INVALID_ASSIGNMENT_LHS: fprintf( file, "Invalid left hand side of assignment near " POSFMT "\n", POSARGS ); return; case APFL_ERR_EMPTY_ASSIGNMENT: fprintf( file, "Empty assignment at " POSFMT "\n", POSARGS ); return; case APFL_ERR_ONLY_ONE_EXPAND_ALLOWED: fprintf( file, "Only one expansion (~) is allowed per level, near " POSFMT "\n", POSARGS ); break; case APFL_ERR_UNEXPECTED_CONSTANT_IN_MEMBER_ACCESS: fprintf( file, "Unexpected constant in member access near " POSFMT "\n", POSARGS ); break; case APFL_ERR_UNEXPECTED_EXPR_IN_MEMBER_ACCESS: fprintf( file, "Unexpected expression in member access near " POSFMT "\n", POSARGS ); break; } fprintf(file, "Unknown error %d\n", (int)error.type); } struct apfl_error apfl_error_simple(enum apfl_error_type type) { return (struct apfl_error) { .type = type }; } bool apfl_error_is_fatal_type(enum apfl_error_type type) { switch (type) { case APFL_ERR_MALLOC_FAILED: case APFL_ERR_INPUT_ERROR: return true; default: return false; } }