10 void yyerror(const char* s);
12 /* Data structures for CSV representation */
13 typedef struct field_node {
15 struct field_node* next;
18 typedef struct record_node {
20 struct record_node* next;
23 typedef struct csv_file {
24 record_node_t* header;
25 record_node_t* records;
28 /* Global variables */
29 csv_file_t* csv_data = NULL;
31 /* Helper functions */
32 field_node_t* create_field(char* content);
33 record_node_t* create_record(field_node_t* fields);
34 field_node_t* append_field(field_node_t* list, field_node_t* new_field);
35 record_node_t* append_record(record_node_t* list, record_node_t* new_record);
36 void print_csv(csv_file_t* csv);
37 void free_csv(csv_file_t* csv);
42 struct field_node* field_list;
43 struct record_node* record_node;
44 struct csv_file* csv_file;
47 %token <str> FIELD_TOK
51 %type <field_list> field_list
52 %type <field_list> field
53 %type <field_list> header
54 %type <record_node> record
55 %type <record_node> record_list
65 csv_data = malloc(sizeof(csv_file_t));
66 if (!csv_data) YYERROR;
67 csv_data->header = NULL;
68 csv_data->records = NULL;
73 csv_data = malloc(sizeof(csv_file_t));
74 if (!csv_data) YYERROR;
75 csv_data->header = create_record($1);
76 if (!csv_data->header) {
80 csv_data->records = NULL;
85 csv_data = malloc(sizeof(csv_file_t));
86 if (!csv_data) YYERROR;
87 csv_data->header = create_record($1);
88 if (!csv_data->header) {
92 csv_data->records = NULL;
97 csv_data = malloc(sizeof(csv_file_t));
98 if (!csv_data) YYERROR;
99 csv_data->header = NULL;
100 csv_data->records = $1;
103 | record_list CRLF_TOK
105 csv_data = malloc(sizeof(csv_file_t));
106 if (!csv_data) YYERROR;
107 csv_data->header = NULL;
108 csv_data->records = $1;
111 | header CRLF_TOK record_list
113 csv_data = malloc(sizeof(csv_file_t));
114 if (!csv_data) YYERROR;
115 csv_data->header = create_record($1);
116 if (!csv_data->header) {
120 csv_data->records = $3;
123 | header CRLF_TOK record_list CRLF_TOK
125 csv_data = malloc(sizeof(csv_file_t));
126 if (!csv_data) YYERROR;
127 csv_data->header = create_record($1);
128 if (!csv_data->header) {
132 csv_data->records = $3;
149 | record_list CRLF_TOK record
151 $$ = append_record($1, $3);
158 $$ = create_record($1);
168 | field_list COMMA_TOK field
170 $$ = append_field($1, $3);
177 $$ = create_field($1);
182 $$ = create_field("");
189 void yyerror(const char* s) {
190 fprintf(stderr, "Parse error at line %d: %s\n", yylineno, s);
192 fprintf(stderr, "Near token: %s\n", yytext);
196 field_node_t* create_field(char* content) {
197 field_node_t* field = malloc(sizeof(field_node_t));
198 if (!field) return NULL;
199 field->content = content ? strdup(content) : strdup("");
200 if (!field->content) {
208 record_node_t* create_record(field_node_t* fields) {
209 record_node_t* record = malloc(sizeof(record_node_t));
210 if (!record) return NULL;
211 record->fields = fields;
216 field_node_t* append_field(field_node_t* list, field_node_t* new_field) {
217 if (!list) return new_field;
219 field_node_t* current = list;
220 while (current->next) {
221 current = current->next;
223 current->next = new_field;
227 record_node_t* append_record(record_node_t* list, record_node_t* new_record) {
228 if (!list) return new_record;
230 record_node_t* current = list;
231 while (current->next) {
232 current = current->next;
234 current->next = new_record;
238 void print_csv(csv_file_t* csv) {
243 field_node_t* field = csv->header->fields;
245 printf("[%s]", field->content ? field->content : "");
246 if (field->next) printf(", ");
252 record_node_t* record = csv->records;
255 printf("Record %d: ", record_num++);
256 field_node_t* field = record->fields;
258 printf("[%s]", field->content ? field->content : "");
259 if (field->next) printf(", ");
263 record = record->next;
267 void free_field_list(field_node_t* fields) {
269 field_node_t* next = fields->next;
270 free(fields->content);
276 void free_record_list(record_node_t* records) {
278 record_node_t* next = records->next;
279 free_field_list(records->fields);
285 void free_csv(csv_file_t* csv) {
289 free_field_list(csv->header->fields);
293 free_record_list(csv->records);
298 printf("CSV Parser - Enter CSV data (Ctrl+D to end):\n");
300 int result = yyparse();
303 printf("\nParsing successful!\n\n");
306 printf("\nParsing failed!\n");