#include <string.h>
#include <ctype.h>
-//#define DEBUG_CHARS
+#define DEBUG_CHARS
#define MAX_PUTBACK 3
static int c;
lexer_token.source_position.linenr++; \
code;
-static void maybe_concat_lines(void)
+static inline void eat(char c_type)
{
+ assert(c == c_type);
next_char();
+}
+
+static void maybe_concat_lines(void)
+{
+ eat('\\');
+
switch(c) {
MATCH_NEWLINE(return;)
static int parse_escape_sequence(void)
{
- while(1) {
- int ec = c;
- next_char();
+ eat('\\');
- switch(ec) {
- case '"': return '"';
- case '\'': return'\'';
- case '\\': return '\\';
- case '?': return '\?';
- case 'a': return '\a';
- case 'b': return '\b';
- case 'f': return '\f';
- case 'n': return '\n';
- case 'r': return '\r';
- case 't': return '\t';
- case 'v': return '\v';
- case 'x':
- return parse_hex_sequence();
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- return parse_octal_sequence();
- case EOF:
- parse_error("reached end of file while parsing escape sequence");
- return EOF;
- default:
- parse_error("unknown escape sequence");
- return EOF;
- }
+ int ec = c;
+ next_char();
+
+ switch(ec) {
+ case '"': return '"';
+ case '\'': return'\'';
+ case '\\': return '\\';
+ case '?': return '\?';
+ case 'a': return '\a';
+ case 'b': return '\b';
+ case 'f': return '\f';
+ case 'n': return '\n';
+ case 'r': return '\r';
+ case 't': return '\t';
+ case 'v': return '\v';
+ case 'x':
+ return parse_hex_sequence();
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ return parse_octal_sequence();
+ case EOF:
+ parse_error("reached end of file while parsing escape sequence");
+ return EOF;
+ default:
+ parse_error("unknown escape sequence");
+ return EOF;
}
}
assert(c == '"');
next_char();
+ int tc;
while(1) {
switch(c) {
case '\\':
- next_char();
- int ec = parse_escape_sequence();
- obstack_1grow(&symbol_obstack, ec);
+ tc = parse_escape_sequence();
+ obstack_1grow(&symbol_obstack, tc);
break;
case EOF:
static void parse_character_constant(void)
{
- assert(c == '\'');
- next_char();
+ eat('\'');
int found_char = 0;
while(1) {
switch(c) {
case '\\':
- next_char();
found_char = parse_escape_sequence();
break;
#include "adt/error.h"
#include "adt/array.h"
-//#define PRINT_TOKENS
+#define PRINT_TOKENS
//#define ABORT_ON_ERROR
#define MAX_LOOKAHEAD 2
+//#define STRICT_C99
struct environment_entry_t {
symbol_t *symbol;
next_token();
}
-void parser_print_error_prefix_pos(const source_position_t source_position)
+void error(void)
{
- fputs(source_position.input_name, stderr);
- fputc(':', stderr);
- fprintf(stderr, "%d", source_position.linenr);
- fputs(": error: ", stderr);
#ifdef ABORT_ON_ERROR
abort();
#endif
}
+void parser_print_prefix_pos(const source_position_t source_position)
+{
+ fputs(source_position.input_name, stderr);
+ fputc(':', stderr);
+ fprintf(stderr, "%d", source_position.linenr);
+ fputs(": ", stderr);
+}
+
+void parser_print_error_prefix_pos(const source_position_t source_position)
+{
+ parser_print_prefix_pos(source_position);
+ fputs("error: ", stderr);
+ error();
+}
+
void parser_print_error_prefix(void)
{
- parser_print_error_prefix_pos(token.source_position);
+ parser_print_prefix_pos(token.source_position);
+ error();
}
static void parse_error(const char *message)
fprintf(stderr, "parse error: %s\n", message);
}
+__attribute__((unused))
+static void parse_warning(const char *message)
+{
+ parser_print_prefix_pos(token.source_position);
+ fprintf(stderr, "warning: %s\n", message);
+}
+
static void parse_error_expected(const char *message, ...)
{
va_list args;
while(token.type != ')') {
if(token.type == T_EOF)
return;
+ if(token.type == ')' || token.type == ';' || token.type == '}') {
+ return;
+ }
+ if(token.type == '(') {
+ eat_brace();
+ continue;
+ }
if(token.type == '{') {
eat_block();
continue;
parser_print_error_prefix_pos(declaration->source_position);
fprintf(stderr, "definition of symbol '%s' with type ",
declaration->symbol->string);
+ error();
print_type(declaration->type);
fputc('\n', stderr);
parser_print_error_prefix_pos(
default:
/* invalid specifier combination, give an error message */
if(type_specifiers == 0) {
+#ifndef STRICT_C99
+ parse_warning("no type specifiers in declaration (using int)");
+ atomic_type = ATOMIC_TYPE_INT;
+ break;
+#else
parse_error("no type specifiers given in declaration");
+#endif
} else if((type_specifiers & SPECIFIER_SIGNED) &&
(type_specifiers & SPECIFIER_UNSIGNED)) {
parse_error("signed and unsigned specifiers gives");
return result;
}
-#if 0
-static type_t *make_pointers(type_t *type, parsed_pointer_t *pointer)
-{
- for( ; pointer != NULL; pointer = pointer->next) {
- pointer_type_t *pointer_type
- = allocate_type_zero(sizeof(pointer_type[0]));
- pointer_type->type.type = TYPE_POINTER;
- pointer_type->points_to = type;
- pointer_type->type.qualifiers = pointer->type_qualifiers;
-
- type_t *result = typehash_insert((type_t*) pointer_type);
- if(result != (type_t*) pointer_type) {
- obstack_free(type_obst, pointer_type);
- }
-
- type = result;
- }
-
- return type;
-}
-#endif
-
static type_t *construct_declarator_type(construct_type_t *construct_list,
type_t *type)
{
parser_print_error_prefix_pos(previous->source_position);
fprintf(stderr, "this is the location of the previous "
"definition.\n");
+ error();
}
static void parse_init_declarators(const declaration_specifiers_t *specifiers)
cnst->expression.type = EXPR_CONST;
cnst->expression.datatype = type_int;
- cnst->value = token.v.intvalue;
+ cnst->v.int_value = token.v.intvalue;
+
+ next_token();
+
+ return (expression_t*) cnst;
+}
+
+static expression_t *parse_float_const(void)
+{
+ const_t *cnst = allocate_ast_zero(sizeof(cnst[0]));
+
+ cnst->expression.type = EXPR_CONST;
+ cnst->expression.datatype = type_int;
+ cnst->v.float_value = token.v.floatvalue;
next_token();
ref->expression.type = EXPR_REFERENCE;
ref->symbol = token.v.symbol;
- if(ref->symbol->declaration == NULL) {
+ declaration_t *declaration = ref->symbol->declaration;
+ next_token();
+
+ if(declaration == NULL) {
+#ifndef STRICT_C99
+ /* is it an implicitely defined function */
+ if(token.type == '(') {
+ parser_print_prefix_pos(token.source_position);
+ fprintf(stderr, "warning: implicit declaration of function '%s'\n",
+ ref->symbol->string);
+ /* TODO: do this correctly */
+ return (expression_t*) ref;
+ }
+#endif
+
parser_print_error_prefix();
fprintf(stderr, "unknown symbol '%s' found.\n", ref->symbol->string);
+ } else {
+ ref->declaration = declaration;
+ ref->expression.datatype = declaration->type;
}
- ref->declaration = ref->symbol->declaration;
- ref->expression.datatype = ref->declaration->type;
- next_token();
return (expression_t*) ref;
}
switch(token.type) {
case T_INTEGER:
return parse_int_const();
+ case T_FLOATINGPOINT:
+ return parse_float_const();
case T_STRING_LITERAL:
return parse_string_const();
case T_IDENTIFIER:
print_token(stderr, &token);
fprintf(stderr, "\n");
eat_statement();
- return NULL;
+
+ expression_t *expression = allocate_ast_zero(sizeof(expression[0]));
+ expression->type = EXPR_INVALID;
+ expression->datatype = type_void;
+
+ return expression;
}
static expression_t *parse_array_expression(unsigned precedence,
if(token.type != ']') {
parse_error_expected("Problem while parsing array access", ']', 0);
- return NULL;
+ return (expression_t*) array_access;
}
next_token();
if(token.type != T_IDENTIFIER) {
parse_error_expected("Problem while parsing select", T_IDENTIFIER, 0);
- return NULL;
+ return (expression_t*) select;
}
select->symbol = token.v.symbol;
next_token();
fprintf(stderr, "%s, but found type ", msg);
print_type(type);
fputc('\n', stderr);
+ error();
}
static void type_error_incompatible(const char *msg,
fprintf(stderr, " - ");
print_type(type2);
fprintf(stderr, ")\n");
+ error();
}
static type_t *get_type_after_conversion(const type_t *type1,
left = parse_primary_expression();
}
assert(left != NULL);
- assert(left->type != EXPR_INVALID);
left->source_position = source_position;
while(true) {