#ifndef WONKY_PARSE_EXPR_C
#define WONKY_PARSE_EXPR_C WONKY_PARSE_EXPR_C
#include "parse_expression.h"
struct AST* parse_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
return (struct AST*)parse_comma_expression(translation_data,scope);
}
struct AST_Expression* parse_const_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
return parse_comma_expression(translation_data,scope);
}
/*
primary-expression:
number
string
id
(e)
generic-selection
*/
struct AST_Expression* parse_primary_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct token *hold_token;
struct AST_Expression *hold;
if(translation_eof(translation_data))
{
push_translation_error("expected something here",translation_data);
return (struct AST_Expression*)get_error_tree(NULL);
}
hold_token=get_next_token(translation_data);
switch(hold_token->type)
{
case KW_STRING:
case KW_WIDE_STRING:
return (struct AST_Expression*)get_string_literal_tree(get_expression_value_constant(((struct token_string*)hold_token)->constant));
case KW_CONSTANT:
return (struct AST_Expression*)get_constant_tree(get_expression_value_constant(((struct token_constant*)hold_token)->constant));
case KW_ID:
return (struct AST_Expression*)get_designator_tree((struct token_identifier*)hold_token,scope,translation_data);
case KW_OPEN_NORMAL:
hold=(struct AST_Expression*)parse_expression(translation_data,scope);
if(get_and_check(translation_data,KW_CLOSE_NORMAL))
{
return (struct AST_Expression*)hold;
}else
{
/*TODO error*/
push_translation_error("expected ')' here",translation_data);
return (struct AST_Expression*)get_error_tree((struct AST*)hold);
}
default:
/*TODO error*/
push_translation_error("error in expression",translation_data);
return (struct AST_Expression*)get_error_tree(NULL);
}
/*just in case*/
wonky_assert(SHOULD_NOT_REACH_HERE);
return (struct AST_Expression*)get_error_tree(NULL);
}
/*
arglist:
(e)*\)
*/
struct AST_Function_Expression* parse_arglist(struct Translation_Data *translation_data,struct Scope *scope,struct AST_Expression* id)
{
struct AST_Function_Expression *ret;
struct AST_Expression *hold_expression;
struct Queue arg_list;
Queue_Init(&arg_list);
if(get_and_check(translation_data,KW_CLOSE_NORMAL))
{
return get_function_expression_tree(id,&arg_list,translation_data);
}
do
{
hold_expression=parse_assignment_expression(translation_data,scope);
Queue_Push(&arg_list,hold_expression);
}while(get_and_check(translation_data,KW_COMMA));
ret=get_function_expression_tree(id,&arg_list,translation_data);
wonky_assert(arg_list.size==0);
if(get_and_check(translation_data,KW_CLOSE_NORMAL))
{
wonky_assert(is_valid_ast((struct AST*)ret));
return ret;
}else
{
push_translation_error("expected ')' here",translation_data);
return (struct AST_Function_Expression*)get_error_tree((struct AST*)ret);
}
}
/*
postfix_expression:
postfix_expression ++
postfix_expression --
postfix_expression [ expression ]
postfix_expression.id
postfix_expression->id
postfix_expression ( arglist )
primary_expression
postfix_expression:
primary_expression ( ++ | -- | \[ expression \] | .id | ->id | \( arglist \) )*
*/
struct AST_Expression* parse_postfix_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_postfix_expression;
struct AST_Expression *hold_second_expr;
hold_postfix_expression=parse_primary_expression(translation_data,scope);
while(!translation_eof(translation_data))
{
wonky_assert(is_valid_ast_expression(hold_postfix_expression));
switch(kw_get(translation_data))
{
case KW_PLUSPLUS:
chomp(translation_data);
hold_postfix_expression=(struct AST_Expression*)get_postfix_inc_dec_tree(hold_postfix_expression,OP_POSTFIX_INC,translation_data);
break;
case KW_MINUSMINUS:
chomp(translation_data);
hold_postfix_expression=(struct AST_Expression*)get_postfix_inc_dec_tree(hold_postfix_expression,OP_POSTFIX_DEC,translation_data);
break;
case KW_DOT:
chomp(translation_data);
if(check(translation_data,KW_ID))
{
struct identifier *id;
id=((struct token_identifier*)get_next_token(translation_data))->id;
hold_postfix_expression=(struct AST_Expression*)get_struct_union_member_tree(hold_postfix_expression,id,translation_data);
}
break;
case KW_ARROW:
chomp(translation_data);
if(check(translation_data,KW_ID))
{
struct identifier *id;
id=((struct token_identifier*)get_next_token(translation_data))->id;
hold_postfix_expression=(struct AST_Expression*)get_struct_union_member_trough_ptr_tree(hold_postfix_expression,id,translation_data);
}
break;
case KW_OPEN_SQUARE:
chomp(translation_data);
if(get_and_check(translation_data,KW_CLOSE_SQUARE))
{
hold_postfix_expression=(struct AST_Expression*)get_array_subscript_tree(hold_postfix_expression,NULL,translation_data);
}else
{
hold_second_expr=(struct AST_Expression*)parse_expression(translation_data,scope);
hold_postfix_expression=(struct AST_Expression*)get_array_subscript_tree(hold_postfix_expression,hold_second_expr,translation_data);
if(!get_and_check(translation_data,KW_CLOSE_SQUARE))
{
push_translation_error("expected ']' here",translation_data);
return (struct AST_Expression*)get_error_tree((struct AST*)hold_postfix_expression);
}
}
break;
case KW_OPEN_NORMAL:
chomp(translation_data);
return (struct AST_Expression*)parse_arglist(translation_data,scope,hold_postfix_expression);
break;
default:
return hold_postfix_expression;
}
}
return hold_postfix_expression;
}
/*
cast-expression:
unary-expression
(type)cast-expression
*/
struct AST_Expression* parse_cast_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Unary_Expression *ret;
if(check(translation_data,KW_OPEN_NORMAL) && is_type_name(translation_data,scope))
{
struct Type *cast_type;
struct AST_Expression *operand;
chomp(translation_data);
cast_type=parse_type_name(translation_data,scope);
if(get_and_check(translation_data,KW_CLOSE_NORMAL))
{
operand=parse_cast_expression(translation_data,scope);
return (struct AST_Expression*)get_cast_expression_tree(operand,cast_type,translation_data);
}else
{
push_translation_error("expected ')' here",translation_data);
return (struct AST_Expression*)get_error_tree((struct AST*)operand);
}
}else
{
return parse_unary_expression(translation_data,scope);
}
}
/*
unary-expression:
++unary-expression
--unary-expression
+unary-expression
-unary-expression
!cast-expression
~cast-expression
*cast-expression
&cast-expression
sizeof ( typename )
sizeof unary-expression
postfix-expression
*/
struct AST_Expression* parse_unary_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_expression;
enum AST_Type operation_type;
if(translation_eof(translation_data))
{
/*TODO error*/
push_translation_error("expected something here",translation_data);
return (struct AST_Expression*)get_error_tree(NULL);
}
/*TODO make it iterative*/
switch(kw_get(translation_data))
{
case KW_PLUSPLUS:
chomp(translation_data); hold_expression=parse_unary_expression(translation_data,scope);
return (struct AST_Expression*)get_prefix_inc_dec_tree(hold_expression,OP_PREFIX_INC,translation_data);
case KW_MINUSMINUS:
chomp(translation_data); hold_expression=parse_unary_expression(translation_data,scope);
return (struct AST_Expression*)get_prefix_inc_dec_tree(hold_expression,OP_PREFIX_DEC,translation_data);
case KW_PLUS:
chomp(translation_data); hold_expression=parse_cast_expression(translation_data,scope);
return (struct AST_Expression*)get_unary_plus_minus_expression(hold_expression,OP_UNARY_PLUS,translation_data);
case KW_MINUS:
chomp(translation_data); hold_expression=parse_cast_expression(translation_data,scope);
return (struct AST_Expression*)get_unary_plus_minus_expression(hold_expression,OP_UNARY_MINUS,translation_data);
case KW_EXCLAMATION:
chomp(translation_data); hold_expression=parse_cast_expression(translation_data,scope);
return (struct AST_Expression*) get_unary_logical_not_expression(hold_expression,translation_data);
case KW_TILDE:
chomp(translation_data); hold_expression=parse_cast_expression(translation_data,scope);
return (struct AST_Expression*) get_unary_bitwise_not_expression(hold_expression,translation_data);
case KW_STAR:
chomp(translation_data); hold_expression=parse_cast_expression(translation_data,scope);
return (struct AST_Expression*) get_indirection_expression_tree(hold_expression,translation_data);
case KW_AND:
chomp(translation_data); hold_expression=parse_cast_expression(translation_data,scope);
return (struct AST_Expression*) get_address_expression_tree(hold_expression,translation_data);
case KW_SIZEOF:
chomp(translation_data);
if(get_and_check(translation_data,KW_OPEN_NORMAL))
{
return (struct AST_Expression*)get_sizeof_by_type_tree(parse_type_name(translation_data,scope));
}else
{
hold_expression=parse_unary_expression(translation_data,scope);
return (struct AST_Expression*)get_unary_sizeof_tree(hold_expression,translation_data);
}
default:
return parse_postfix_expression(translation_data,scope);
}
wonky_assert(SHOULD_NOT_REACH_HERE);
/*shouldn't reach here - the default of the switch returns*/
}
/*
multiplicative-expression:
cast-expression ( ( * | / | % ) cast-expression )*
*/
struct AST_Expression* parse_multiplicative_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_left_expression;
struct AST_Expression *hold_right_expression;
enum AST_Type operation_type;
hold_left_expression=parse_cast_expression(translation_data,scope);
while(!translation_eof(translation_data))
{
wonky_assert(is_valid_ast_expression(hold_left_expression));
switch(kw_get(translation_data))
{
case KW_STAR:
operation_type=OP_MUL;
break;
case KW_FORWARD_SLASH:
operation_type=OP_DIV;
break;
case KW_PERCENT:
operation_type=OP_DIV;
break;
default:
return hold_left_expression; /*BEWARE*/
}
chomp(translation_data);
hold_right_expression=parse_cast_expression(translation_data,scope);
hold_left_expression=(struct AST_Expression*)get_multiplicative_expression_tree(hold_left_expression,hold_right_expression,operation_type,translation_data);
}
return hold_left_expression; /*this could return null if there was a constraint check violation or the first cast operation is invalid*/
}
/*
additive-expression:
multiplicative-expression ( ( + | - ) multiplicative )*
*/
struct AST_Expression* parse_additive_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_left_expression;
struct AST_Expression *hold_right_expression;
enum AST_Type operation_type;
hold_left_expression=parse_multiplicative_expression(translation_data,scope);
while(!translation_eof(translation_data))
{
wonky_assert(is_valid_ast_expression(hold_left_expression));
switch(kw_get(translation_data))
{
case KW_PLUS:
operation_type=OP_ADDITION;
break;
case KW_MINUS:
operation_type=OP_SUBTRACTION;
break;
default:
return hold_left_expression; /*BEWARE*/
}
chomp(translation_data);
hold_right_expression=parse_multiplicative_expression(translation_data,scope);
hold_left_expression=(struct AST_Expression*)get_additive_expression_tree(hold_left_expression,hold_right_expression,operation_type,translation_data);
}
return hold_left_expression; /*this could return null if there was a constraint check violation or the first cast operation is invalid*/
}
/*
bitwise-shift:
additive-expression ( ( << | >> ) additive-expression)*
*/
struct AST_Expression* parse_shift_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_left_expression;
struct AST_Expression *hold_right_expression;
enum AST_Type operation_type;
hold_left_expression=parse_additive_expression(translation_data,scope);
while(!translation_eof(translation_data))
{
wonky_assert(is_valid_ast_expression(hold_left_expression));
switch(kw_get(translation_data))
{
case KW_SHIFT_LEFT:
operation_type=OP_SHIFT_LEFT;
break;
case KW_SHIFT_RIGHT:
operation_type=OP_SHIFT_RIGHT;
break;
default:
return hold_left_expression; /*BEWARE*/
}
chomp(translation_data);
hold_right_expression=parse_additive_expression(translation_data,scope);
hold_left_expression=(struct AST_Expression*)get_shift_expression_tree(hold_left_expression,hold_right_expression,operation_type,translation_data);
}
return hold_left_expression; /*this could return null if there was a constraint check violation or the first cast operation is invalid*/
}
/*
relational-expression:
shift-expression ( ( < | > | <= | >= ) shift-expression )*
*/
struct AST_Expression* parse_relational_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_left_expression;
struct AST_Expression *hold_right_expression;
enum AST_Type operation_type;
hold_left_expression=parse_shift_expression(translation_data,scope);
while(!translation_eof(translation_data))
{
wonky_assert(is_valid_ast_expression(hold_left_expression));
switch(kw_get(translation_data))
{
case KW_LESS:
operation_type=OP_LESS;
break;
case KW_LESS_EQ:
operation_type=OP_LESS_EQ;
break;
case KW_MORE:
operation_type=OP_GREATER;
break;
case KW_MORE_EQ:
operation_type=OP_GREATER_EQ;
break;
default:
return hold_left_expression; /*BEWARE*/
}
chomp(translation_data);
hold_right_expression=parse_shift_expression(translation_data,scope);
hold_left_expression=(struct AST_Expression*)get_relation_expression_tree(hold_left_expression,hold_right_expression,operation_type,translation_data);
}
return hold_left_expression; /*this could return null if there was a constraint check violation or the first cast operation is invalid*/
}
/*
equality-expression:
realtional-expression ( ( == | != ) relational-expression )*
*/
struct AST_Expression* parse_equality_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_left_expression;
struct AST_Expression *hold_right_expression;
enum AST_Type operation_type;
hold_left_expression=parse_relational_expression(translation_data,scope);
while(!translation_eof(translation_data))
{
wonky_assert(is_valid_ast_expression(hold_left_expression));
switch(kw_get(translation_data))
{
case KW_EQEQ:
operation_type=OP_EQUAL;
break;
case KW_NOT_EQ:
operation_type=OP_NOT_EQUAL;
break;
default:
return hold_left_expression; /*BEWARE*/
}
chomp(translation_data);
hold_right_expression=parse_relational_expression(translation_data,scope);
hold_left_expression=(struct AST_Expression*)get_equality_expression_tree(hold_left_expression,hold_right_expression,operation_type,translation_data);
}
return hold_left_expression; /*this could return null if there was a constraint check violation or the first cast operation is invalid*/
}
/*
and-expression:
equality-expression ( & equality-expression ) *
*/
struct AST_Expression* parse_and_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_left_expression;
struct AST_Expression *hold_right_expression;
hold_left_expression=parse_equality_expression(translation_data,scope);
while(get_and_check(translation_data,KW_AND))
{
wonky_assert(is_valid_ast_expression(hold_left_expression));
hold_right_expression=parse_equality_expression(translation_data,scope);
hold_left_expression=(struct AST_Expression*)get_bitwise_expression_tree(hold_left_expression,hold_right_expression,OP_BITWISE_AND,translation_data);
}
return hold_left_expression;
}
/*
exclusive-or-expression:
and-expression (^ and-expression)*
*/
struct AST_Expression* parse_exclusive_or_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_left_expression;
struct AST_Expression *hold_right_expression;
hold_left_expression=parse_and_expression(translation_data,scope);
while(get_and_check(translation_data,KW_HAT))
{
wonky_assert(is_valid_ast_expression(hold_left_expression));
hold_right_expression=parse_and_expression(translation_data,scope);
hold_left_expression=(struct AST_Expression*)get_bitwise_expression_tree(hold_left_expression,hold_right_expression,OP_BITWISE_XOR,translation_data);
}
return hold_left_expression;
}
/*
inclusive-or-expression:
exclusive-or-expression (|exclusive-or-expression)*
*/
struct AST_Expression* parse_inclusive_or_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_left_expression;
struct AST_Expression *hold_right_expression;
hold_left_expression=parse_exclusive_or_expression(translation_data,scope);
while(get_and_check(translation_data,KW_PIPE))
{
wonky_assert(is_valid_ast_expression(hold_left_expression));
hold_right_expression=parse_exclusive_or_expression(translation_data,scope);
hold_left_expression=(struct AST_Expression*)get_bitwise_expression_tree(hold_left_expression,hold_right_expression,OP_BITWISE_OR,translation_data);
}
return hold_left_expression;
}
/*
logical-and-expression:
inclusive-or-expression(&&inclusive-or-expression)*
*/
struct AST_Expression* parse_logical_and_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_left_expression;
struct AST_Expression *hold_right_expression;
hold_left_expression=parse_inclusive_or_expression(translation_data,scope);
while(get_and_check(translation_data,KW_AND_AND))
{
wonky_assert(is_valid_ast_expression(hold_left_expression));
hold_right_expression=parse_inclusive_or_expression(translation_data,scope);
hold_left_expression=(struct AST_Expression*)get_logical_expression_tree(hold_left_expression,hold_right_expression,OP_LOGICAL_AND,translation_data);
}
return hold_left_expression;
}
/*
logical-or-expression:
logical-and-expression ( || logical-and-expression )*
*/
struct AST_Expression* parse_logical_or_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_left_expression;
struct AST_Expression *hold_right_expression;
hold_left_expression=parse_logical_and_expression(translation_data,scope);
while(get_and_check(translation_data,KW_PIPE_PIPE))
{
wonky_assert(is_valid_ast_expression(hold_left_expression));
hold_right_expression=parse_logical_and_expression(translation_data,scope);
hold_left_expression=(struct AST_Expression*)get_logical_expression_tree(hold_left_expression,hold_right_expression,OP_LOGICAL_OR,translation_data);
}
return hold_left_expression;
}
/*
conditional-expression:
logical-or-expression
logical-or-expression?expression:conditional-expression
*/
struct AST_Expression* parse_conditional_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_left_expression;
struct AST_Expression *hold_center_expression;
struct AST_Expression *hold_right_expression;
hold_left_expression=parse_logical_or_expression(translation_data,scope);
wonky_assert(is_valid_ast_expression(hold_left_expression));
if(get_and_check(translation_data,KW_QUESTION))
{
hold_center_expression=(struct AST_Expression*)parse_expression(translation_data,scope);
if(get_and_check(translation_data,KW_COLUMN))
{
hold_right_expression=parse_conditional_expression(translation_data,scope);
}else
{
push_translation_error("expected ':' here",translation_data);
hold_right_expression=(struct AST_Expression*)get_error_tree(NULL);
}
return (struct AST_Expression*)get_conditional_expression_tree(hold_left_expression,hold_center_expression,hold_right_expression,translation_data);
}else
{
return hold_left_expression;
}
}
/*
assignment-expression:
conditional-expression
unary-expression ( ( = | += | -= | %= | /= | *= | >>= | <<= | &= | |= | ^= ) assignment-expression
*/
struct AST_Expression* parse_assignment_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_left_expression;
struct AST_Expression *hold_right_expression;
enum AST_Type operation_type;
if(translation_eof(translation_data))
{
push_translation_error("expected something here",translation_data);
return (struct AST_Expression*)get_error_tree(NULL);
}
hold_left_expression=parse_conditional_expression(translation_data,scope);
wonky_assert(is_valid_ast_expression(hold_left_expression));
if(translation_eof(translation_data))
return hold_left_expression;
/*TODO make it iterative*/
switch(kw_get(translation_data))
{
case KW_EQ:
operation_type=OP_ASSIGN;
break;
case KW_PLUS_EQ:
operation_type=OP_ADD_ASSIGN;
break;
case KW_MINUS_EQ:
operation_type=OP_SUBTRACT_ASSIGN;
break;
case KW_PERCENT_EQ:
operation_type=OP_REMAINDER_ASSIGN;
break;
case KW_DIV_EQ:
operation_type=OP_DIV_ASSIGN;
break;
case KW_STAR_EQ:
operation_type=OP_MULTIPLY_ASSIGN;
break;
case KW_SHIFT_RIGHT_EQ:
operation_type=OP_SHIFT_RIGHT_ASSIGN;
break;
case KW_SHIFT_LEFT_EQ:
operation_type=OP_SHIFT_LEFT_ASSIGN;
break;
case KW_AND_EQ:
operation_type=OP_AND_ASSIGN;
break;
case KW_PIPE_EQ:
operation_type=OP_PIPE_ASSIGN;
break;
case KW_HAT_EQ:
operation_type=OP_XOR_ASSIGN;
break;
default:
return hold_left_expression; /*BEWARE*/
}
chomp(translation_data);
hold_right_expression=parse_assignment_expression(translation_data,scope);
wonky_assert(is_valid_ast_expression(hold_right_expression));
if(operation_type==OP_ASSIGN)
return (struct AST_Expression*)get_simple_assignment_expression_tree(hold_left_expression,hold_right_expression,translation_data);
else
return (struct AST_Expression*)get_compound_assignment_expression_tree(hold_left_expression,hold_right_expression,operation_type,translation_data);
}
/*
comma-expression:
assignment-expression(,assignment-expression)*
*/
struct AST_Expression* parse_comma_expression(struct Translation_Data *translation_data,struct Scope *scope)
{
struct AST_Expression *hold_left_expression;
struct AST_Expression *hold_right_expression;
hold_left_expression=parse_assignment_expression(translation_data,scope);
while(get_and_check(translation_data,KW_COMMA))
{
wonky_assert(is_valid_ast_expression(hold_left_expression));
hold_right_expression=parse_assignment_expression(translation_data,scope);
hold_left_expression=(struct AST_Expression*)get_comma_expression_tree(hold_left_expression,hold_right_expression,translation_data);
}
return hold_left_expression;
}
#endif