diff --git a/src/parser.c b/src/parser.c index 522feca..f7c7d4d 100644 --- a/src/parser.c +++ b/src/parser.c @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -56,6 +57,10 @@ static int _parameter_declaration(C99 * c99); static int _abstract_declarator(C99 * c99); static int _assignment_expr(C99 * c99); static int _unary_expr(C99 * c99); +static int _postfix_expr(C99 * c99); +static int _primary_expr(C99 * c99); +static int _type_name(C99 * c99); +static int _specifier_qualifier_list(C99 * c99); static int _assignment_operator(C99 * c99); static int _conditional_expr(C99 * c99); static int _logical_or_expr(C99 * c99); @@ -67,6 +72,8 @@ static int _equality_expr(C99 * c99); static int _relational_expr(C99 * c99); static int _shift_expr(C99 * c99); static int _additive_expr(C99 * c99); +static int _multiplicative_expr(C99 * c99); +static int _cast_expr(C99 * c99); static int _declaration_list(C99 * c99); static int _declaration(C99 * c99); static int _compound_statement(C99 * c99); @@ -83,6 +90,7 @@ static int _jump_statement(C99 * c99); static int _init_declarator_list(C99 * c99); static int _init_declarator(C99 * c99); static int _initializer(C99 * c99); +static int _initializer_list(C99 * c99); /* functions */ @@ -90,9 +98,9 @@ static int _parse_check(C99 * c99, TokenCode code) { int ret; - /* FIXME complete */ + /* FIXME use a string for the code */ if((ret = (token_get_code(c99->token) != code))) - _parse_error(c99, "Expected something else"); + _parse_error(c99, "%s%x", "Expected code 0x", code); c99_scan(c99); return ret; } @@ -101,11 +109,15 @@ static int _parse_check(C99 * c99, TokenCode code) static int _parse_error(C99 * c99, char const * format, ...) { Token * token = c99->token; + va_list ap; - /* FIXME complete */ - fprintf(stderr, "%s%s:%u, near \"%s\": %s\n", PACKAGE ": ", + fprintf(stderr, "%s%s:%u, near \"%s\": ", PACKAGE ": ", token_get_filename(token), token_get_line(token), - token_get_string(token), format); + token_get_string(token)); + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fputc('\n', stderr); return 1; } @@ -129,11 +141,14 @@ static int _translation_unit(C99 * c99) static int _external_declaration(C99 * c99) /* function-definition | declaration */ { - /* FIXME implement correctly */ #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); #endif - return _function_definition(c99); + if(token_in_set(c99->token, c99set_function_definition)) + return _function_definition(c99); + else if(token_in_set(c99->token, c99set_declaration)) + return _declaration(c99); + return _parse_error(c99, "Expected function definition or declaration"); } @@ -549,22 +564,168 @@ static int _assignment_expr(C99 * c99) /* unary-expr */ static int _unary_expr(C99 * c99) - /* postfix-expr + /* FIXME still recursive + * postfix-expr * ++ unary-expr * -- unary-expr * unary-operator cast-expr * sizeof unary-expr * sizeof "(" type-name ")" */ +{ + int ret; + int code; + + /* FIXME complete */ +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + if(token_in_set(c99->token, c99set_postfix_expr)) + return _postfix_expr(c99); + else if((code = token_get_code(c99->token)) == C99_CODE_OPERATOR_DPLUS + || code == C99_CODE_OPERATOR_DMINUS) + { + ret = c99_scan(c99); + ret |= _unary_expr(c99); + } + /* FIXME unary-operator */ + else if(code == C99_CODE_KEYWORD_SIZEOF) + { + ret = c99_scan(c99); + if(token_get_code(c99->token) == C99_CODE_OPERATOR_LPAREN) + { + ret |= c99_scan(c99); + ret |= _type_name(c99); + ret |= _parse_check(c99, C99_CODE_OPERATOR_RPAREN); + } + else + ret |= _unary_expr(c99); + } + return ret; +} + + +/* postfix-expr */ +static int _postfix_expr(C99 * c99) + /* primary-expr + * postfix-expr "[" expression "]" + * postfix-expr "(" argument-expression-list-opt ")" + * postfix-expr "." identifier + * postfix-expr "->" identifier + * postfix-expr "++" + * postfix-expr "--" + * "(" type-name ")" "{" initializer-list "}" + * "(" type-name ")" "{" initializer-list "," "}" */ +{ + int ret = 0; + int code; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + if(token_in_set(c99->token, c99set_primary_expr)) + ret |= _primary_expr(c99); + else if(token_get_code(c99->token) == C99_CODE_OPERATOR_LPAREN) + { + ret |= c99_scan(c99); + ret |= _type_name(c99); + ret |= _parse_check(c99, C99_CODE_OPERATOR_RPAREN); + ret |= _parse_check(c99, C99_CODE_OPERATOR_LBRACE); + ret |= _initializer_list(c99); + if(token_get_code(c99->token) == C99_CODE_COMMA) + ret |= c99_scan(c99); + ret |= _parse_check(c99, C99_CODE_OPERATOR_RBRACE); + } + for(;;) + { + code = token_get_code(c99->token); + if(code == C99_CODE_OPERATOR_LBRACKET) + { + ret |= c99_scan(c99); + ret |= _expression(c99); + ret |= _parse_check(c99, C99_CODE_OPERATOR_RBRACKET); + } + else if(code == C99_CODE_OPERATOR_LPAREN) + { + ret |= c99_scan(c99); +#if 0 /* FIXME optional and implement */ + ret |= _argument_expression_list(c99); +#endif + ret |= _parse_check(c99, C99_CODE_OPERATOR_RPAREN); + } + else if(code == C99_CODE_OPERATOR_DOT + || code == C99_CODE_OPERATOR_MGREATER) + { + ret |= c99_scan(c99); + ret |= _identifier(c99); + } + else if(code == C99_CODE_OPERATOR_DPLUS + || code == C99_CODE_OPERATOR_DMINUS) + ret |= c99_scan(c99); + else + break; + } + return ret; +} + + +/* primary-expr */ +static int _primary_expr(C99 * c99) + /* identifier + * constant + * string-literal + * "(" expression ")" */ { /* FIXME implement */ #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); #endif - c99_scan(c99); /* FIXME wrong */ return 0; } +/* type-name */ +static int _type_name(C99 * c99) + /* specifier-qualifier-list [ abstract-declarator ] */ +{ + int ret; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + ret = _specifier_qualifier_list(c99); + if(token_in_set(c99->token, c99set_abstract_declarator)) + ret |= _abstract_declarator(c99); + return ret; +} + + +/* specifier-qualifier-list */ +static int _specifier_qualifier_list(C99 * c99) + /* (type-specifier | type-qualifier) { (type-specifier | type-qualifier) } */ +{ + int ret = 0; + int looped = 0; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + for(;;) + { + if(token_in_set(c99->token, c99set_type_specifier)) + ret |= _type_specifier(c99); + else if(token_in_set(c99->token, c99set_type_qualifier)) + ret |= _type_qualifier(c99); + else if(looped == 0) + ret |= _parse_error(c99, "Expected type specifier" + " or type qualifier"); + else + break; + looped = 1; + } + return ret; +} + + /* assignment-operator */ static int _assignment_operator(C99 * c99) /* "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" @@ -762,11 +923,65 @@ static int _shift_expr(C99 * c99) /* additive-expr */ static int _additive_expr(C99 * c99) + /* multiplicative-expr { ("+" | "-") multiplicative-expr } */ { + int ret; + int code; + #ifdef DEBUG fprintf(stderr, "DEBUG: %s()\n", __func__); #endif - return 0; + ret = _multiplicative_expr(c99); + while((code = token_get_code(c99->token)) == C99_CODE_OPERATOR_PLUS + || code == C99_CODE_OPERATOR_MINUS) + { + ret |= c99_scan(c99); + ret |= _multiplicative_expr(c99); + } + return ret; +} + + +/* multiplicative-expr */ +static int _multiplicative_expr(C99 * c99) + /* cast-expr { ("*" | "/" | "%") cast-expr } */ +{ + int ret; + int code; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif + ret = _cast_expr(c99); + while((code = token_get_code(c99->token)) == C99_CODE_OPERATOR_TIMES + || code == C99_CODE_OPERATOR_DIVIDE + || code == C99_CODE_OPERATOR_MODULO) + { + ret |= c99_scan(c99); + ret |= _cast_expr(c99); + } + return ret; +} + + +/* cast-expr */ +static int _cast_expr(C99 * c99) + /* { "(" type-name ")" } unary-expr */ +{ + int ret = 0; + +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, + token_get_string(c99->token)); +#endif + while(token_get_code(c99->token) == C99_CODE_OPERATOR_LPAREN) + { + ret |= c99_scan(c99); + ret |= _type_name(c99); + ret |= _parse_check(c99, C99_CODE_OPERATOR_RPAREN); + } + ret |= _unary_expr(c99); + return ret; } @@ -774,7 +989,6 @@ static int _additive_expr(C99 * c99) static int _compound_statement(C99 * c99) /* "{" [ block-item-list ] "}" */ { - /* FIXME implement */ #ifdef DEBUG fprintf(stderr, "DEBUG: %s() \"{\" got \"%s\"\n", __func__, token_get_string(c99->token)); @@ -891,7 +1105,8 @@ static int _expression_statement(C99 * c99) int ret = 0; #ifdef DEBUG - fprintf(stderr, "DEBUG: %s()\n", __func__); + fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, + token_get_string(c99->token)); #endif if(token_in_set(c99->token, c99set_expression)) ret = _expression(c99); @@ -950,8 +1165,7 @@ static int _selection_statement(C99 * c99) static int _iteration_statement(C99 * c99) /* while "(" expression ")" statement * do statement while "(" expression ")" ; - * for ( expr-opt ; expr-opt ; expr-opt ) statement - * for ( declaration ; expr-opt ; expr-opt ) statement */ + * for ( [ (expr | declaration) ] ; [ expr ] ; [ expr ] ) statement */ { int ret; int code; @@ -1015,7 +1229,7 @@ static int _jump_statement(C99 * c99) } -/* init-declarator-list-opt */ +/* init-declarator-list */ static int _init_declarator_list(C99 * c99) /* init-declarator { init-declarator } */ { @@ -1059,7 +1273,7 @@ static int _initializer(C99 * c99) /* FIXME complete */ #ifdef DEBUG - fprintf(stderr, "DEBUG: %s()\n", __func__); + fprintf(stderr, "DEBUG: %s() NOT COMPLETE\n", __func__); #endif if(token_in_set(c99->token, c99set_assignment_expr)) ret = _assignment_expr(c99); @@ -1067,6 +1281,19 @@ static int _initializer(C99 * c99) } +/* initializer-list */ +static int _initializer_list(C99 * c99) + /* [ designation ] initializer + * initializer-list "," [ designation ] initializer */ +{ + /* FIXME implement */ +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s() NOT IMPLEMENTED\n", __func__); +#endif + return 0; +} + + /* public */ /* functions */ /* useful */ diff --git a/src/scanner.c b/src/scanner.c index 9809879..446081b 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -87,6 +87,9 @@ int c99_scan(C99 * c99) char const * string; size_t i; +#ifdef DEBUG + fprintf(stderr, "DEBUG: %s()\n", __func__); +#endif if(c99->token != NULL) token_delete(c99->token); /* skip white-space and meta tokens */ diff --git a/src/sets/cast_expr.set b/src/sets/cast_expr.set new file mode 100644 index 0000000..12a4184 --- /dev/null +++ b/src/sets/cast_expr.set @@ -0,0 +1,2 @@ +#include "unary_expr.set" + C99_CODE_OPERATOR_LPAREN, diff --git a/src/sets/conditional_expr.set b/src/sets/conditional_expr.set index e69de29..f6e8bb7 100644 --- a/src/sets/conditional_expr.set +++ b/src/sets/conditional_expr.set @@ -0,0 +1,2 @@ +/* FIXME not supposed to be directly this */ +#include "cast_expr.set" diff --git a/src/sets/function_definition.set b/src/sets/function_definition.set new file mode 100644 index 0000000..775692e --- /dev/null +++ b/src/sets/function_definition.set @@ -0,0 +1 @@ +#include "declaration_specifiers.set" diff --git a/src/sets/identifier.set b/src/sets/identifier.set index e69de29..8c1cb60 100644 --- a/src/sets/identifier.set +++ b/src/sets/identifier.set @@ -0,0 +1 @@ + C99_CODE_IDENTIFIER, diff --git a/src/sets/identifier_list.set b/src/sets/identifier_list.set index e69de29..aa52917 100644 --- a/src/sets/identifier_list.set +++ b/src/sets/identifier_list.set @@ -0,0 +1 @@ +#include "identifier.set" diff --git a/src/sets/init_declarator.set b/src/sets/init_declarator.set index e69de29..b561781 100644 --- a/src/sets/init_declarator.set +++ b/src/sets/init_declarator.set @@ -0,0 +1 @@ +#include "declarator.set" diff --git a/src/sets/parameter_declaration.set b/src/sets/parameter_declaration.set new file mode 100644 index 0000000..775692e --- /dev/null +++ b/src/sets/parameter_declaration.set @@ -0,0 +1 @@ +#include "declaration_specifiers.set" diff --git a/src/sets/parameter_list.set b/src/sets/parameter_list.set new file mode 100644 index 0000000..0f164e2 --- /dev/null +++ b/src/sets/parameter_list.set @@ -0,0 +1 @@ +#include "parameter_declaration.set" diff --git a/src/sets/parameter_type_list.set b/src/sets/parameter_type_list.set index e69de29..e487152 100644 --- a/src/sets/parameter_type_list.set +++ b/src/sets/parameter_type_list.set @@ -0,0 +1 @@ +#include "parameter_list.set" diff --git a/src/tokenset.c b/src/tokenset.c index b5b1904..2f3111f 100644 --- a/src/tokenset.c +++ b/src/tokenset.c @@ -142,6 +142,16 @@ static TokenCode _c99set_expression_statement[] = TokenSet c99set_expression_statement = _c99set_expression_statement; +/* function-definition */ +static TokenCode _c99set_function_definition[] = +{ +#include "sets/function_definition.set" + C99_CODE_NULL +}; + +TokenSet c99set_function_definition = _c99set_function_definition; + + /* function-specifier */ static TokenCode _c99set_function_specifier[] = { @@ -232,6 +242,26 @@ static TokenCode _c99set_pointer[] = TokenSet c99set_pointer = _c99set_pointer; +/* postfix-expr */ +static TokenCode _c99set_postfix_expr[] = +{ +#include "sets/postfix_expr.set" + C99_CODE_NULL +}; + +TokenSet c99set_postfix_expr = _c99set_postfix_expr; + + +/* primary-expr */ +static TokenCode _c99set_primary_expr[] = +{ +#include "sets/primary_expr.set" + C99_CODE_NULL +}; + +TokenSet c99set_primary_expr = _c99set_primary_expr; + + /* punctuator */ static TokenCode _c99set_punctuator[] = { diff --git a/src/tokenset.h b/src/tokenset.h index 4e1db80..8946a4f 100644 --- a/src/tokenset.h +++ b/src/tokenset.h @@ -35,6 +35,7 @@ extern TokenSet c99set_declarator; extern TokenSet c99set_enum_specifier; extern TokenSet c99set_expression; extern TokenSet c99set_expression_statement; +extern TokenSet c99set_function_definition; extern TokenSet c99set_function_specifier; extern TokenSet c99set_init_declarator; extern TokenSet c99set_iteration_statement; @@ -44,6 +45,8 @@ extern TokenSet c99set_identifier_list; extern TokenSet c99set_labeled_statement; extern TokenSet c99set_parameter_type_list; extern TokenSet c99set_pointer; +extern TokenSet c99set_postfix_expr; +extern TokenSet c99set_primary_expr; extern TokenSet c99set_punctuator; extern TokenSet c99set_selection_statement; extern TokenSet c99set_statement;