--- a
+++ b/c99.y
@@ -0,0 +1,591 @@
+%token IDENTIFIER CONSTANT STRING_LITERAL SIZEOF
+%token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
+%token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
+%token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
+%token XOR_ASSIGN OR_ASSIGN TYPE_NAME
+
+%token TYPEDEF EXTERN STATIC AUTO REGISTER INLINE RESTRICT
+%token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID
+%token BOOL COMPLEX IMAGINARY
+%token STRUCT UNION ENUM ELLIPSIS
+
+%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
+
+%union { char str[128]; }
+
+%start translation_unit
+
+%{
+/* fifo to store expression strings */
+#define NULL 0
+
+#define STMT_SIZE 128
+#define FIFO_SIZE 20
+
+static char *s_fifo[FIFO_SIZE][STMT_SIZE];
+static unsigned int s_fifor, s_fifow;
+
+void yyerror(char const *s);
+void push(const char *psz);
+char *pop(void);
+
+%}
+
+%%
+
+primary_expression
+	: IDENTIFIER
+	| CONSTANT
+	| STRING_LITERAL
+	| '(' expression ')'
+	{ sprintf($<str>$, "( %s )",$<str>2); }
+	;
+
+postfix_expression
+	: primary_expression
+	{ sprintf($<str>$, "%s",$<str>1); }
+	| postfix_expression '[' expression ']'
+	{ sprintf($<str>$, "[%s]",$<str>2); }
+	| postfix_expression '(' ')'
+	{ sprintf($<str>$, "%s()",$<str>1); }
+	| postfix_expression '(' argument_expression_list ')'
+	{ sprintf($<str>$, "%s(%s)",$<str>1, $<str>3); }
+	| postfix_expression '.' IDENTIFIER
+	{ sprintf($<str>$, "%s.%s",$<str>1,$<str>3); }
+	| postfix_expression PTR_OP IDENTIFIER
+	{ sprintf($<str>$, "%s %s %s",$<str>1, $<str>2, $<str>3);}
+	| postfix_expression INC_OP
+	{ sprintf($<str>$, "(%s:=%s+1)",$<str>1, $<str>1); }
+	| postfix_expression DEC_OP
+	{ sprintf($<str>$, "(%s:=%s-1)",$<str>1, $<str>1); }
+	| '(' type_name ')' '{' initializer_list '}'
+	| '(' type_name ')' '{' initializer_list ',' '}'
+	;
+
+argument_expression_list
+	: assignment_expression
+	| argument_expression_list ',' assignment_expression
+	{ sprintf($<str>$, "%s, %s",$<str>1, $<str>3); }
+	;
+
+unary_expression
+	: postfix_expression
+	| INC_OP unary_expression
+	{ sprintf($<str>$, "%s %s",$<str>1, $<str>2); }
+	| DEC_OP unary_expression
+	{ sprintf($<str>$, "%s %s",$<str>1, $<str>2); }
+	| unary_operator cast_expression
+	{ sprintf($<str>$, "%s^",$<str>2); }
+	| SIZEOF unary_expression
+	{ sprintf($<str>$, "%s %s",$<str>1, $<str>2); }
+	| SIZEOF '(' type_name ')'
+	{ sprintf($<str>$, "%s (%s)",$<str>1, $<str>3); }
+	;
+
+unary_operator
+	: '&'
+	| '*'
+	| '+'
+	| '-'
+	| '~'
+	| '!'
+	;
+
+cast_expression
+	: unary_expression
+	| '(' type_name ')' cast_expression
+	{ sprintf($<str>$, "ANY_TO_%s(%s)",$<str>2, $<str>4); }
+	;
+
+multiplicative_expression
+	: cast_expression
+	| multiplicative_expression '*' cast_expression
+	{ sprintf($<str>$, "%s * %s",$<str>1, $<str>3); }
+	| multiplicative_expression '/' cast_expression
+	{ sprintf($<str>$, "%s / %s",$<str>1, $<str>3); }
+	| multiplicative_expression '%' cast_expression
+	{ sprintf($<str>$, "%s % %s",$<str>1, $<str>3); }
+	;
+
+additive_expression
+	: multiplicative_expression
+	| additive_expression '+' multiplicative_expression
+	{ sprintf($<str>$, "%s + %s",$<str>1, $<str>3); }
+	| additive_expression '-' multiplicative_expression
+	{ sprintf($<str>$, "%s - %s",$<str>1, $<str>3); }
+	;
+
+shift_expression
+	: additive_expression
+	| shift_expression LEFT_OP additive_expression
+	{ sprintf($<str>$, "SHL(%s, %s)",$<str>1, $<str>3); }
+	| shift_expression RIGHT_OP additive_expression
+	{ sprintf($<str>$, "SHR(%s, %s)",$<str>1, $<str>3); }
+	;
+
+relational_expression	: shift_expression
+	| relational_expression '<' shift_expression
+	{ sprintf($<str>$, "%s < %s",$<str>1, $<str>3); }
+	| relational_expression '>' shift_expression
+	{ sprintf($<str>$, "%s > %s",$<str>1, $<str>3); }
+	| relational_expression LE_OP shift_expression
+	{ sprintf($<str>$, "%s <= %s",$<str>1, $<str>3); }
+	| relational_expression GE_OP shift_expression
+	{ sprintf($<str>$, "%s >= %s",$<str>1, $<str>3); }
+	;
+
+equality_expression
+	: relational_expression
+	| equality_expression EQ_OP relational_expression
+	{ sprintf($<str>$, "%s = %s",$<str>1, $<str>3); }
+	| equality_expression NE_OP relational_expression
+	{ sprintf($<str>$, "%s <> %s",$<str>1, $<str>3); }
+	;
+
+and_expression
+	: equality_expression
+	| and_expression '&' equality_expression
+	{ sprintf($<str>$, "%s AND %s",$<str>1, $<str>3); }
+	;
+
+exclusive_or_expression
+	: and_expression
+	| exclusive_or_expression '^' and_expression
+	{ sprintf($<str>$, "%s XOR %s",$<str>1, $<str>3); }
+	;
+
+inclusive_or_expression
+	: exclusive_or_expression
+	| inclusive_or_expression '|' exclusive_or_expression
+	{ sprintf($<str>$, "%s OR %s",$<str>1, $<str>3); }
+	;
+
+logical_and_expression
+	: inclusive_or_expression
+	| logical_and_expression AND_OP inclusive_or_expression
+	{ sprintf($<str>$, "%s AND %s",$<str>1, $<str>3); }
+	;
+
+logical_or_expression
+	: logical_and_expression
+	| logical_or_expression OR_OP logical_and_expression
+	{ sprintf($<str>$, "%s OR %s",$<str>1, $<str>3); }
+	;
+
+conditional_expression
+	: logical_or_expression
+	| logical_or_expression '?' expression ':' conditional_expression
+	;
+
+assignment_expression
+	: conditional_expression
+	| unary_expression assignment_operator assignment_expression
+	{ sprintf($<str>$, "%s %s %s",$<str>1, $<str>2, $<str>3); }
+	;
+
+assignment_operator
+	: '='
+	{ sprintf($<str>$, ":="); }
+	| MUL_ASSIGN
+	| DIV_ASSIGN
+	| MOD_ASSIGN
+	| ADD_ASSIGN
+	| SUB_ASSIGN
+	| LEFT_ASSIGN
+	| RIGHT_ASSIGN
+	| AND_ASSIGN
+	| XOR_ASSIGN
+	| OR_ASSIGN
+	;
+
+expression
+	: assignment_expression
+	| expression ',' assignment_expression
+	;
+
+constant_expression
+	: conditional_expression
+	;
+
+declaration
+	: declaration_specifiers ';'
+	{ sprintf($<str>$, "%s %s",$<str>1, $<str>2); }
+	| declaration_specifiers init_declarator_list ';'
+	{ char *p; while( (p=pop()) != NULL) { printf(p, $<str>1); strcpy($<str>$, ""); } }
+	;
+
+declaration_specifiers
+	: storage_class_specifier
+	| storage_class_specifier declaration_specifiers
+	{ sprintf($<str>$, "%s %s",$<str>1, $<str>2); }
+	| type_specifier
+	| type_specifier declaration_specifiers
+	{ sprintf($<str>$, "%s %s",$<str>1, $<str>2); }
+	| type_qualifier
+	| type_qualifier declaration_specifiers
+	{ sprintf($<str>$, "%s %s",$<str>1, $<str>2); }
+	| function_specifier
+	| function_specifier declaration_specifiers
+	{ sprintf($<str>$, "%s %s",$<str>1, $<str>2); }
+	;
+
+init_declarator_list
+	: init_declarator
+	| init_declarator_list ',' init_declarator
+	{ sprintf($<str>$, "%s, %s",$<str>1, $<str>3); }
+	;
+
+init_declarator
+	: declarator
+	| declarator '=' initializer
+	{ sprintf($<str>$, "%s = %s",$<str>1, $<str>3); }
+	;
+
+storage_class_specifier
+	: TYPEDEF
+	| EXTERN
+	| STATIC
+	| AUTO
+	| REGISTER
+	;
+
+type_specifier
+	: VOID
+	| CHAR
+	| SHORT
+	| INT
+	| LONG
+	| FLOAT
+	| DOUBLE
+	| SIGNED
+	| UNSIGNED
+	| BOOL
+	| COMPLEX
+	| IMAGINARY
+	| struct_or_union_specifier
+	| enum_specifier
+	| TYPE_NAME
+	;
+
+struct_or_union_specifier
+	: struct_or_union IDENTIFIER '{' struct_declaration_list '}'
+	| struct_or_union '{' struct_declaration_list '}'
+	| struct_or_union IDENTIFIER
+	;
+
+struct_or_union
+	: STRUCT
+	| UNION
+	;
+
+struct_declaration_list
+	: struct_declaration
+	| struct_declaration_list struct_declaration
+	{ sprintf($<str>$, "%s %s",$<str>1, $<str>2); }
+	;
+
+struct_declaration
+	: specifier_qualifier_list struct_declarator_list ';'
+	{ sprintf($<str>$, "%s %s",$<str>1, $<str>2); }
+	;
+
+specifier_qualifier_list
+	: type_specifier specifier_qualifier_list
+	{ sprintf($<str>$, "%s %s",$<str>1, $<str>2); }
+	| type_specifier
+	| type_qualifier specifier_qualifier_list
+	{ sprintf($<str>$, "%s %s",$<str>1, $<str>2); }
+	| type_qualifier
+	;
+
+struct_declarator_list
+	: struct_declarator
+	| struct_declarator_list ',' struct_declarator
+	{ sprintf($<str>$, "%s, %s",$<str>1, $<str>3); }
+	;
+
+struct_declarator
+	: declarator
+	| ':' constant_expression
+	| declarator ':' constant_expression
+	;
+
+enum_specifier
+	: ENUM '{' enumerator_list '}'
+	| ENUM IDENTIFIER '{' enumerator_list '}'
+	| ENUM '{' enumerator_list ',' '}'
+	| ENUM IDENTIFIER '{' enumerator_list ',' '}'
+	| ENUM IDENTIFIER
+	;
+
+enumerator_list
+	: enumerator
+	| enumerator_list ',' enumerator
+	;
+
+enumerator
+	: IDENTIFIER
+	| IDENTIFIER '=' constant_expression
+	;
+
+type_qualifier
+	: CONST
+	| RESTRICT
+	| VOLATILE
+	;
+
+function_specifier	: INLINE
+	;
+
+declarator
+	: pointer direct_declarator
+	{ 
+		sprintf($<str>$, "%s POINTER TO %%s;\n",$<str>2);
+		push($<str>$);
+	}
+	| direct_declarator
+	{
+		if (strlen($<str>1) > 0)
+		{
+			sprintf($<str>$, "%s %%s;\n",$<str>1);
+			push($<str>$);
+		}
+	}
+	;
+
+direct_declarator
+	: IDENTIFIER
+//	{ sprintf($<str>$, "%s: %%s;\n",$<str>1); push($<str>$);}
+	| '(' declarator ')'
+	| direct_declarator '[' type_qualifier_list assignment_expression ']'
+	| direct_declarator '[' type_qualifier_list ']'
+	| direct_declarator '[' assignment_expression ']'
+	{
+		sprintf($<str>$, "%s: ARRAY[ %s ] OF %%s;\n",$<str>1, $<str>3);
+		push($<str>$);
+		strcpy($<str>$, "");
+	}
+	| direct_declarator '[' STATIC type_qualifier_list assignment_expression ']'
+	| direct_declarator '[' type_qualifier_list STATIC assignment_expression ']'
+	| direct_declarator '[' type_qualifier_list '*' ']'
+	| direct_declarator '[' '*' ']'
+	| direct_declarator '[' ']'
+	| direct_declarator '(' parameter_type_list ')'
+	{ sprintf($<str>$, "FUNCTION %s:",$<str>1); }
+	| direct_declarator '(' identifier_list ')'
+	{ sprintf($<str>$, "FUNCTION %s:",$<str>1); }
+	| direct_declarator '(' ')'
+	{ sprintf($<str>$, "FUNCTION %s:",$<str>1); }
+	;
+
+pointer
+	: '*'
+	| '*' type_qualifier_list
+	| '*' pointer
+	| '*' type_qualifier_list pointer
+	;
+
+type_qualifier_list
+	: type_qualifier
+	| type_qualifier_list type_qualifier
+	;
+
+
+parameter_type_list
+	: parameter_list
+	| parameter_list ',' ELLIPSIS
+	;
+
+parameter_list
+	: parameter_declaration
+	| parameter_list ',' parameter_declaration
+	;
+
+parameter_declaration
+	: declaration_specifiers declarator
+	| declaration_specifiers abstract_declarator
+	| declaration_specifiers
+	;
+
+identifier_list
+	: IDENTIFIER
+	| identifier_list ',' IDENTIFIER
+	;
+
+type_name
+	: specifier_qualifier_list
+	| specifier_qualifier_list abstract_declarator
+	;
+
+abstract_declarator
+	: pointer
+	| direct_abstract_declarator
+	| pointer direct_abstract_declarator
+	;
+
+direct_abstract_declarator
+	: '(' abstract_declarator ')'
+	| '[' ']'
+	| '[' assignment_expression ']'
+	| direct_abstract_declarator '[' ']'
+	| direct_abstract_declarator '[' assignment_expression ']'
+	| '[' '*' ']'
+	| direct_abstract_declarator '[' '*' ']'
+	| '(' ')'
+	| '(' parameter_type_list ')'
+	| direct_abstract_declarator '(' ')'
+	| direct_abstract_declarator '(' parameter_type_list ')'
+	;
+
+initializer
+	: assignment_expression
+	| '{' initializer_list '}'
+	| '{' initializer_list ',' '}'
+	;
+
+initializer_list
+	: initializer
+	| designation initializer
+	| initializer_list ',' initializer
+	| initializer_list ',' designation initializer
+	;
+
+designation
+	: designator_list '='
+	;
+
+designator_list
+	: designator
+	| designator_list designator
+	;
+
+designator
+	: '[' constant_expression ']'
+	| '.' IDENTIFIER
+	;
+
+statement
+	: labeled_statement
+	| compound_statement
+	| expression_statement
+	| selection_statement
+	| iteration_statement
+	| jump_statement
+	;
+
+labeled_statement
+	: IDENTIFIER ':' statement
+	| CASE constant_expression ':' statement
+	| DEFAULT ':' statement
+	;
+
+compound_statement
+	: '{' '}'
+	| '{' block_item_list '}'
+	;
+
+block_item_list
+	: block_item
+	| block_item_list block_item
+	;
+
+block_item
+	: declaration
+	| statement
+	{ printf("%s\n",$<str>1); }
+	;
+
+expression_statement
+	: ';'
+	| expression ';'
+	{ sprintf($<str>$, "%s;",$<str>1); }
+	;
+
+selection_statement
+	: IF '(' expression ')' statement
+	| IF '(' expression ')' statement ELSE statement
+	| SWITCH '(' expression ')' statement
+	;
+
+iteration_statement
+	: WHILE '(' expression ')' statement
+	| DO statement WHILE '(' expression ')' ';'
+	| FOR '(' expression_statement expression_statement ')' statement
+	| FOR '(' expression_statement expression_statement expression ')' statement
+	| FOR '(' declaration expression_statement ')' statement
+	| FOR '(' declaration expression_statement expression ')' statement
+	;
+
+jump_statement
+	: GOTO IDENTIFIER ';'
+	| CONTINUE ';'
+	| BREAK ';'
+	| RETURN ';'
+	| RETURN expression ';'
+	;
+
+translation_unit
+	: external_declaration
+	| translation_unit external_declaration
+	;
+
+external_declaration
+	: function_definition
+	| declaration
+	;
+
+function_definition
+	: declaration_specifiers declarator declaration_list compound_statement
+	| declaration_specifiers declarator compound_statement
+	;
+
+declaration_list
+	: declaration
+	| declaration_list declaration
+	{ printf("| %s %s\n",$<str>1, $<str>2); }
+	;
+
+
+%%
+#include <stdio.h>
+
+extern char yytext[];
+extern int column;
+
+void yyerror(char const *s)
+{
+	fflush(stdout);
+	printf("\n%*s\n%*s\n", column, "^", column, s);
+}
+
+int main(void)
+{
+    yyparse();
+    return 0;
+}
+
+
+/* fifo implementation */
+void push(const char *psz)
+{
+	unsigned int fifow_next = (s_fifow + 1) % FIFO_SIZE; 
+	if (fifow_next != s_fifor)
+	{
+		//s_fifo[s_fifow] = psz;
+		strcpy(s_fifo[s_fifow], psz);
+		s_fifow = fifow_next;
+	}
+}
+
+char *pop(void)
+{
+	unsigned int fifor_prev;
+	if (s_fifor != s_fifow)
+	{
+		fifor_prev = s_fifor;
+		s_fifor = (s_fifor + 1) % FIFO_SIZE;
+		return s_fifo[fifor_prev];
+	}
+	return NULL;
+}
+