-
Notifications
You must be signed in to change notification settings - Fork 5
/
main.c
156 lines (141 loc) · 4.29 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/**
* Entry point for parer for C Programming Language
* (ISO/IEC 9899:2018).
*
* @authors: Denis Chernikov, Vladislav Kuleykin
*/
#include <stdio.h>
#include <stdlib.h>
#include "ast.h"
#include "string_tools.h"
#include "typedef_name.h"
#include "y.tab.h"
/// Input file for Flex.
extern FILE *yyin;
/// Conversion function for AST node content.
///
/// \param obj Object of AST content
/// \return String representation of the given node's content
char *content_to_str(AST_NODE *node)
{
if (node->type == Identifier || node->type == StringLiteral || node->type == IntegerConstant
|| node->type == FloatingConstant || node->type == CharacterConstant)
{
return alloc_const_str((char *) node->content.value); // TODO constant types support
}
switch (node->content.token)
{
case AUTO: return "AUTO";
case BREAK: return "BREAK";
case CASE: return "CASE";
case CHAR: return "CHAR";
case CONST: return "CONST";
case CONTINUE: return "CONTINUE";
case DEFAULT: return "DEFAULT";
case DO: return "DO";
case DOUBLE: return "DOUBLE";
case ELSE: return "ELSE";
case ENUM: return "ENUM";
case EXTERN: return "EXTERN";
case FLOAT: return "FLOAT";
case FOR: return "FOR";
case GOTO: return "GOTO";
case IF: return "IF";
case INLINE: return "INLINE";
case INT: return "INT";
case LONG: return "LONG";
case REGISTER: return "REGISTER";
case RESTRICT: return "RESTRICT";
case RETURN: return "RETURN";
case SHORT: return "SHORT";
case SIGNED: return "SIGNED";
case SIZEOF: return "SIZEOF";
case STATIC: return "STATIC";
case STRUCT: return "STRUCT";
case SWITCH: return "SWITCH";
case TYPEDEF: return "TYPEDEF";
case UNION: return "UNION";
case UNSIGNED: return "UNSIGNED";
case VOID: return "VOID";
case VOLATILE: return "VOLATILE";
case WHILE: return "WHILE";
case ALIGNAS: return "ALIGNAS";
case ALIGNOF: return "ALIGNOF";
case ATOMIC: return "ATOMIC";
case BOOL: return "BOOL";
case COMPLEX: return "COMPLEX";
case GENERIC: return "GENERIC";
case IMAGINARY: return "IMAGINARY";
case NORETURN: return "NORETURN";
case STATIC_ASSERT: return "STATIC_ASSERT";
case THREAD_LOCAL: return "THREAD_LOCAL";
default: return NULL;
}
}
/// Program entry point.
///
/// \param argc Size of `argv'
/// \param argv Arguments passed to the program
/// \return 0 - OK, 1 - processing error, 2 - args error, 3 - I/O error
int main(int argc, char *argv[])
{
if (argc < 2)
{
printf("Usage: %s <out_file> OR %s <in_file> <out_file>\n",
argv[0], argv[0]);
return 2;
}
int res; // For results of I/O functions
char *in_name = argc > 2 ? argv[1] : NULL;
char *out_name = argc > 2 ? argv[2] : argv[1];
yyin = in_name ? fopen(in_name, "r") : stdin;
if (!yyin)
{
fprintf(stderr, "Cannot open for reading: %s\n", in_name);
return 3;
}
AST_NODE *root = NULL;
if (!in_name) printf("Input your code here (Ctrl+Z for EOF):\n");
int yyres = yyparse((void **) &root);
free_typedef_name();
res = argc > 2 ? fclose(yyin) : 0;
if (yyres || !root)
{
fprintf(stderr, "Parsing failed! No output will be provided.\n");
return 1;
}
if (res == EOF)
{
fprintf(stderr, "Cannot close opened source file: %s\n", in_name);
ast_free(root);
return 3;
}
char *json = ast_to_json(root, 0, " ", &content_to_str);
ast_free(root);
if (!json)
{
fprintf(stderr, "JSON generation failure!\n");
return 1;
}
FILE *out = fopen(argv[in_name ? 2 : 1], "w");
if (!out)
{
fprintf(stderr, "Cannot open for writing: %s\n", out_name);
free(json);
return 3;
}
res = fputs(json, out);
free(json);
if (res == EOF)
{
fprintf(stderr, "Cannot write into opened target file: %s\n", out_name);
return 3;
}
res = fclose(out);
if (res == EOF)
{
fprintf(stderr, "Cannot close opened target file: %s\n", out_name);
return 3;
}
return 0;
}