1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading.Tasks;
6
7using static libfcf.Tokenizer;
8
9namespace libfcf;
10
11public static class Parser
12{
13 internal static dynamic[] ParseDict(Token[] tokens)
14 {
15 Dictionary<string, dynamic> json_object = new Dictionary<string, dynamic>();
16 var t = tokens[0];
17 if (t.GetType() == typeof(TokenDictEnd))
18 {
19 return new dynamic[] { json_object, tokens.ToList().Skip(1).ToArray() };
20 }
21
22 while (true)
23 {
24 var json_key = tokens[0];
25 if (json_key.GetType() == typeof(TokenIdentifier))
26 {
27 tokens = tokens.ToList().Skip(1).ToArray();
28 }
29 else
30 {
31 throw new InvalidTokenTypeException("Expected identifier type for key got: " + GetTokenAsHuman(json_key), json_key);
32 }
33
34 if (tokens[0].GetType() != typeof(TokenAssign))
35 {
36 throw new InvalidTokenTypeException($"Expected '=' got {GetTokenAsHuman(tokens[0])}", tokens[0]);
37 }
38
39 var tmp = Parse(tokens.ToList().Skip(1).ToArray());
40 var json_value = tmp[0];
41 tokens = tmp[1];
42
43 if (!(json_value.GetType() == typeof(TokenString) || json_value.GetType() == typeof(TokenNumber) || json_value.GetType() == typeof(TokenBoolean) ||
44 json_value.GetType() == typeof(List<dynamic>) || json_value.GetType() == typeof(Dictionary<string, dynamic>)))
45 {
46 throw new InvalidTokenTypeException($"expected string, number or bool got {GetTokenAsHuman(json_value)}", json_value);
47 }
48
49 // json_object.Add((string)(((TokenIdentifier)json_key).value), json_value);
50
51 if (json_value.GetType() == typeof(TokenString) || json_value.GetType() == typeof(TokenNumber) || json_value.GetType() == typeof(TokenBoolean))
52 {
53 json_object.Add((string)(((TokenIdentifier)json_key).value), ((dynamic)json_value).value);
54 }
55 else
56 {
57 json_object.Add((string)(((TokenIdentifier)json_key).value), json_value);
58 }
59
60 t = tokens[0];
61 if (t.GetType() == typeof(TokenDictEnd))
62 {
63 return new dynamic[] { json_object, tokens.ToList().Skip(1).ToArray() };
64 }
65 else if (t.GetType() != typeof(TokenComma))
66 {
67 throw new InvalidTokenTypeException($"Expected '=' after pair in object got {GetTokenAsHuman(t)}", t);
68 }
69
70 tokens = tokens.ToList().Skip(1).ToArray();
71 }
72 }
73
74 internal static dynamic[] ParseArray(Token[] tokens)
75 {
76 List<dynamic> json_array = new List<dynamic>();
77
78 var t = tokens[0];
79 if (t.GetType() == typeof(TokenArrayEnd))
80 {
81 return new dynamic[] { json_array, tokens.ToList().Skip(1).ToArray() };
82 }
83
84 while (true)
85 {
86 var tmp = Parse(tokens);
87 var json = tmp[0];
88 tokens = tmp[1];
89
90 if (json.GetType() == typeof(TokenString) || json.GetType() == typeof(TokenNumber) || json.GetType() == typeof(TokenBoolean) || json.GetType() == typeof(TokenIdentifier))
91 {
92 json_array.Add(((dynamic)json).value);
93 }
94 else
95 {
96 json_array.Add(json);
97 }
98
99 t = tokens[0];
100 if (t.GetType() == typeof(TokenArrayEnd))
101 {
102 return new dynamic[] { json_array, tokens.ToList().Skip(1).ToArray() };
103 }
104 else if (t.GetType() != typeof(TokenComma))
105 {
106 throw new InvalidTokenTypeException($"Expected comma after object in array got {GetTokenAsHuman(t)}", t);
107 }
108 else
109 {
110 tokens = tokens.ToList().Skip(1).ToArray();
111 }
112 }
113 }
114
115 internal static dynamic[] Parse(Token[] tokens)
116 {
117 var t = tokens[0];
118
119 // Console.WriteLine("Parsing Array");
120 if (t.GetType() == typeof(TokenArrayStart))
121 {
122 // Console.WriteLine("Parsing Array: " + t);
123 return ParseArray(tokens.ToList().Skip(1).ToArray());
124 }
125 else if (t.GetType() == typeof(TokenDictStart))
126 {
127 // Console.WriteLine("Parsing Dict: " + t);
128 return ParseDict(tokens.ToList().Skip(1).ToArray());
129 }
130 else
131 {
132 return new dynamic[] { t, tokens.ToList().Skip(1).ToArray() };
133 }
134 }
135
136 public static Dictionary<string, object> DeserializeObject(Token[] tokens)
137 {
138 return (Dictionary<string, object>)Parse(tokens)[0];
139 }
140
141 public static Dictionary<string, object> DeserializeObjectFromFile(string filePath)
142 {
143 var stack = TokenizeFromFile(filePath);
144
145 return DeserializeObject(stack);
146 }
147
148 public static List<object> DeserializeArray(Token[] tokens)
149 {
150 return (List<object>)Parse(tokens)[0];
151 }
152
153 public static List<object> DeserializeArrayFromFile(string filePath)
154 {
155 var stack = TokenizeFromFile(filePath);
156
157 return DeserializeArray(stack);
158 }
159
160 public static List<object> DeserializeArrayFromMemory(string memory)
161 {
162 var stack = TokenizeFromMemory(memory.Split('\n'));
163 return DeserializeArray(stack);
164 }
165}