@@ -14,32 +14,53 @@ defmodule ComponentsGuideWeb.UniversalModulesController do
1414 const verbose = false;
1515 const alwaysNull = null;
1616
17+ const debug = verbose;
18+
1719 export const dateFormat = "YYYY/MM/DD";
1820
21+ const exampleDotOrg = new URL("https://example.org");
22+
1923 const array = [1, 2, 3];
2024 const arrayMultiline = [
2125 4,
2226 5,
2327 6
2428 ];
2529 export const flavors = ["vanilla", "chocolate", "caramel", "raspberry"];
30+ export const flavorsSet = new Set(["vanilla", "chocolate", "caramel", "raspberry"]);
2631
2732 const object = { "key": "value" };
2833
2934 function hello() {}
30- function* gen() {}
35+ function* gen() {
36+ const a = 1;
37+ yield [1, 2, 3];
38+ }
3139 """
3240 # decoded = decode_module(source)
3341 decoded = Parser . decode ( source )
42+ identifiers = ComponentsGuideWeb.UniversalModulesInspector . list_identifiers ( elem ( decoded , 1 ) )
3443
3544 render ( conn , "index.html" ,
3645 page_title: "Universal Modules" ,
3746 source: source ,
38- decoded: inspect ( decoded )
47+ decoded: inspect ( decoded ) ,
48+ identifiers: inspect ( identifiers ) ,
3949 )
4050 end
4151end
4252
53+ defmodule ComponentsGuideWeb.UniversalModulesInspector do
54+ def is_identifier ( { :const , _ , _ } ) , do: true
55+ def is_identifier ( { :function , _ , _ , _ } ) , do: true
56+ def is_identifier ( { :generator_function , _ , _ , _ } ) , do: true
57+ def is_identifier ( _ ) , do: false
58+
59+ def list_identifiers ( module_body ) do
60+ for statement <- module_body , is_identifier ( statement ) , do: statement
61+ end
62+ end
63+
4364defmodule ComponentsGuideWeb.UniversalModulesParser do
4465 def compose ( submodule , input ) do
4566 mod = Module . concat ( __MODULE__ , submodule )
@@ -110,6 +131,8 @@ defmodule ComponentsGuideWeb.UniversalModulesParser do
110131 end
111132
112133 defmodule Function do
134+ defdelegate compose ( submodule , input ) , to: ComponentsGuideWeb.UniversalModulesParser
135+
113136 def decode ( << "function" , rest :: bitstring >> ) ,
114137 do: decode ( % { generator_mark: nil , name: nil , args: nil , body: nil } , rest )
115138
@@ -136,10 +159,33 @@ defmodule ComponentsGuideWeb.UniversalModulesParser do
136159 defp decode ( % { args: { :closed , args } , name: name , body: { :open , body_items } } = context , << "}" , rest :: bitstring >> ) do
137160 case context . generator_mark do
138161 true ->
139- { :ok , { :generator_function , name , args , body_items } , rest }
162+ { :ok , { :generator_function , name , args , Enum . reverse ( body_items ) } , rest }
140163
141164 nil ->
142- { :ok , { :function , name , args , body_items } , rest }
165+ { :ok , { :function , name , args , Enum . reverse ( body_items ) } , rest }
166+ end
167+ end
168+
169+ defp decode ( % { body: { :open , _ } } = context , << char :: utf8 , rest :: bitstring >> ) when char in [ ?\n , ?\t , ?; ] ,
170+ do: decode ( context , rest )
171+
172+ defp decode ( % { body: { :open , body_items } } = context , << "const " , _ :: bitstring >> = input ) do
173+ case compose ( Const , input ) do
174+ { :ok , term , rest } ->
175+ decode ( % { context | body: { :open , [ term | body_items ] } } , rest )
176+
177+ { :error , reason } ->
178+ { :error , { reason , body_items } }
179+ end
180+ end
181+
182+ defp decode ( % { body: { :open , body_items } } = context , << "yield " , _ :: bitstring >> = input ) do
183+ case compose ( Yield , input ) do
184+ { :ok , term , rest } ->
185+ decode ( % { context | body: { :open , [ term | body_items ] } } , rest )
186+
187+ { :error , reason } ->
188+ { :error , { reason , body_items } }
143189 end
144190 end
145191
@@ -168,6 +214,9 @@ defmodule ComponentsGuideWeb.UniversalModulesParser do
168214 def decode ( << "const " , rest :: bitstring >> ) ,
169215 do: decode ( { :expect_identifier , [ ] } , rest )
170216
217+ def decode ( << _ :: bitstring >> ) ,
218+ do: { :error , :expected_const }
219+
171220 defp decode ( { :expect_identifier , _ } = context , << " " , rest :: bitstring >> ) ,
172221 do: decode ( context , rest )
173222
@@ -199,16 +248,47 @@ defmodule ComponentsGuideWeb.UniversalModulesParser do
199248 end
200249
201250 defmodule Expression do
251+ import Unicode.Guards
252+
202253 def decode ( input ) , do: decode ( [ ] , input )
203254
255+ defp finalize ( [ { :found_identifier , reverse_identifier } | context_rest ] ) do
256+ identifier = reverse_identifier |> Enum . reverse ( ) |> :binary . list_to_bin ( )
257+ [ { :ref , identifier } | context_rest ]
258+ end
259+
260+ defp finalize ( expression ) , do: expression
261+
204262 defp decode ( expression , << ";" , rest :: bitstring >> ) ,
205- do: { :ok , expression , rest }
263+ do: { :ok , finalize ( expression ) , rest }
206264
207265 defp decode ( [ ] = context , << " " , rest :: bitstring >> ) , do: decode ( context , rest )
208266 defp decode ( [ ] , << "true" , rest :: bitstring >> ) , do: decode ( true , rest )
209267 defp decode ( [ ] , << "false" , rest :: bitstring >> ) , do: decode ( false , rest )
210268 defp decode ( [ ] , << "null" , rest :: bitstring >> ) , do: decode ( nil , rest )
211269
270+ defp decode ( [ ] , << "new URL(" , rest :: bitstring >> ) do
271+ [ encoded_json , rest ] = String . split ( rest , ");\n " , parts: 2 )
272+ case Jason . decode ( encoded_json ) do
273+ { :ok , value } ->
274+ { :ok , { :url , value } , rest }
275+
276+ { :error , error } ->
277+ { :error , error }
278+ end
279+ end
280+
281+ defp decode ( [ ] , << "new Set(" , rest :: bitstring >> ) do
282+ [ encoded_json , rest ] = String . split ( rest , ");\n " , parts: 2 )
283+ case Jason . decode ( encoded_json ) do
284+ { :ok , value } ->
285+ { :ok , { :set , value } , rest }
286+
287+ { :error , error } ->
288+ { :error , error }
289+ end
290+ end
291+
212292 # TODO: parse JSON by finding the end character followed by a semicolon + newline.
213293 # JSON strings cannoc contain literal newlines (it’s considered to be a control character),
214294 # so instead it must be encoded as "\n". So we can use this fast to know an actual newline is
@@ -245,6 +325,14 @@ defmodule ComponentsGuideWeb.UniversalModulesParser do
245325 decode ( f , rest )
246326 end
247327 end
328+
329+ defp decode ( [ ] , << char :: utf8 , rest :: bitstring >> ) when is_lower ( char ) or is_upper ( char ) ,
330+ do: decode ( [ { :found_identifier , [ char ] } ] , rest )
331+
332+ defp decode ( [ { :found_identifier , reverse_identifier } | context_rest ] , << char :: utf8 , rest :: bitstring >> )
333+ when is_lower ( char ) or is_upper ( char ) or is_digit ( char ) do
334+ decode ( [ { :found_identifier , [ char | reverse_identifier ] } | context_rest ] , rest )
335+ end
248336 end
249337
250338 defmodule KnownIdentifier do
0 commit comments