hacking erlang
TRANSCRIPT
![Page 1: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/1.jpg)
Hacking Erlangbuilding strange and magical creations
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
1
![Page 2: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/2.jpg)
Things Worth Trying:•code injection
•meta programming
•reverse engineering byte code
•anything that makes Ericsson cringe...
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
2
![Page 3: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/3.jpg)
Step 1understanding the abstract format
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
3
![Page 4: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/4.jpg)
-module(example1). -> {attribute,LINE,module,example1}
10 -> {integer,LINE,10}
foo -> {atom,LINE,foo}
“bar” -> {string,LINE,“bar”}
[a,b,c] -> {cons,LINE,a,{cons,LINE,b,{cons,LINE,c, {nil,LINE}}}}
Some Examples
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
4
![Page 5: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/5.jpg)
The Abstract Format• a tree-like structure representing parsed Erlang code• comprised of a list of forms
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
5
![Page 6: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/6.jpg)
What are forms?
The Abstract Format• a tree-like structure representing parsed Erlang code• comprised of a list of forms
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
6
![Page 7: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/7.jpg)
Forms are tuples that represent top-level
constructs like function declarations and
attributes
The Abstract Format• a tree-like structure representing parsed Erlang code• comprised of a list of forms
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
7
![Page 8: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/8.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
-module(example1).-export([foo/0]).
foo() -> "Hello Stockholm!".
[{attribute,1,module,example1}, {attribute,3,export,[{foo,0}]}, {function,5,foo,0,[{clause,5,[],[], [{string,5,"Hello Stockholm!"}]}]}]
8
![Page 9: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/9.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
[{attribute,1,module,example1}, {attribute,3,export,[{foo,0}]}, {function,5,foo,0,[{clause,5,[],[], [{string,5,"Hello Stockholm!"}]}]}]
form
-module(example1).-export([foo/0]).
foo() -> "Hello Stockholm!".
9
![Page 10: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/10.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
-module(example1).-export([foo/0]).
foo() -> "Hello Stockholm!".
[{attribute,1,module,example1}, {attribute,3,export,[{foo,0}]}, {function,5,foo,0,[{clause,5,[],[], [{string,5,"Hello Stockholm!"}]}]}]
form
10
![Page 11: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/11.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
-module(example1).-export([foo/0]).
foo() -> "Hello Stockholm!".
[{attribute,1,module,example1}, {attribute,3,export,[{foo,0}]}, {function,5,foo,0,[{clause,5,[],[], [{string,5,"Hello Stockholm!"}]}]}]
form
11
![Page 12: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/12.jpg)
Where do forms come from?Taking a step back:
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
12
![Page 13: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/13.jpg)
Forms are generated by grouping and interpreting tokens scanned from source code.
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
13
![Page 14: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/14.jpg)
How does scanning source code work?
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
14
![Page 15: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/15.jpg)
How does scanning source code work?
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
•use regular expressions to tokenize string input
•generate a list of tuples, each representing an atomic unit of source code, which can be grouped into forms
15
![Page 16: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/16.jpg)
erl_scan
This module contains functions for tokenizing characters into Erlang tokens.
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
16
![Page 17: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/17.jpg)
erl_scan
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
1> Code = "-module(example1).\n-export([foo/0]).\n\n foo() -> \"Hello Stockholm!\". "
2> erl_scan:string(Code).
-module(example1).-export([foo/0]).
foo() -> "Hello Stockholm!".
17
![Page 18: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/18.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
2> erl_scan:string(Code).{ok,[{'-',1}, {atom,1,module}, {'(',1}, {atom,1,example1}, {')',1}, {dot,1}, {'-',2}, {atom,2,export}, {'(',2}, {'[',2}, {atom,2,foo}, {'/',2}, {integer,2,0}, {']',2}, {')',2}, {dot,2}, {atom,4,foo}, {'(',4}, {')',4}, {'->',4}, {string,4,"Hello Stockholm!"}, {dot,4}], 4}
-module(example1).
-export([foo/0]).
foo() -> "Hello Stockholm!".
18
![Page 19: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/19.jpg)
erl_parse
This module is the basic Erlang parser which converts tokens into the abstract format.
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
19
![Page 20: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/20.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
-module(example1).
2> erl_scan:string(Code).{ok,[{'-',1}, {atom,1,module}, {'(',1}, {atom,1,example1}, {')',1}, {dot,1}, {'-',2}, {atom,2,export}, {'(',2}, {'[',2}, {atom,2,foo}, {'/',2}, {integer,2,0}, {']',2}, {')',2}, {dot,2}, {atom,4,foo}, {'(',4}, {')',4}, {'->',4}, {string,4,"Hello Stockholm!"}, {dot,4}], 4}
1> erl_parse:parse_form([{'-',1},{atom,1,module},{'(',1},{atom,1,example1},{')',1},{dot,1}]).
{ok,{attribute,1,module,example1}}
20
![Page 21: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/21.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
-export([foo/0]).
2> erl_scan:string(Code).{ok,[{'-',1}, {atom,1,module}, {'(',1}, {atom,1,example1}, {')',1}, {dot,1}, {'-',2}, {atom,2,export}, {'(',2}, {'[',2}, {atom,2,foo}, {'/',2}, {integer,2,0}, {']',2}, {')',2}, {dot,2}, {atom,4,foo}, {'(',4}, {')',4}, {'->',4}, {string,4,"Hello Stockholm!"}, {dot,4}], 4}
2> erl_parse:parse_form([{'-',2},{atom,2,export},{'(',2},{'[',2},{atom,2,foo},{'/',2},{integer,2,0},{']',2},{')',2},{dot,2}]).
{ok,{attribute,2,export,[{foo,0}]}}
21
![Page 22: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/22.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
3> erl_parse:parse_form([{atom,4,foo},{'(',4},{')',4},{'->',4},{string,4,"Hello Stockholm!"},{dot,4}]).
{ok,{function,4,foo,0, [{clause,4,[],[],[{string, 4,"Hello Stockholm!"}]}]}}
2> erl_scan:string(Code).{ok,[{'-',1}, {atom,1,module}, {'(',1}, {atom,1,example1}, {')',1}, {dot,1}, {'-',2}, {atom,2,export}, {'(',2}, {'[',2}, {atom,2,foo}, {'/',2}, {integer,2,0}, {']',2}, {')',2}, {dot,2}, {atom,4,foo}, {'(',4}, {')',4}, {'->',4}, {string,4,"Hello Stockholm!"}, {dot,4}], 4}
foo() -> "Hello Stockholm!".
22
![Page 23: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/23.jpg)
compile
This module provides an interface to the standard Erlang compiler. It can generate either a new file which contains the object code, or return a binary which can be loaded directly.
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
23
![Page 24: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/24.jpg)
compile
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
1> Forms = [{attribute,1,module,example1},{attribute,2,export,[{foo,0}]},{function,4,foo,0,[{clause,4,[],[],
[{string,4,"Hello Stockholm!"}]}]}].
24
![Page 25: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/25.jpg)
compile
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
1> Forms = [{attribute,1,module,example1},{attribute,2,export,[{foo,0}]},{function,4,foo,0,[{clause,4,[],[],
[{string,4,"Hello Stockholm!"}]}]}].
2> {ok, Mod, Bin} = compile:forms(Forms, []).{ok,example1,<<70,79,82,49,...>>}
25
![Page 26: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/26.jpg)
compile
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
1> Forms = [{attribute,1,module,example1},{attribute,2,export,[{foo,0}]},{function,4,foo,0,[{clause,4,[],[],
[{string,4,"Hello Stockholm!"}]}]}].
2> {ok, Mod, Bin} = compile:forms(Forms, []).{ok,example1,<<70,79,82,49,...>>}
3> code:load_binary(Mod, [], Bin).{module,example1}
26
![Page 27: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/27.jpg)
compile
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
1> Forms = [{attribute,1,module,example1},{attribute,2,export,[{foo,0}]},{function,4,foo,0,[{clause,4,[],[],
[{string,4,"Hello Stockholm!"}]}]}].
2> {ok, Mod, Bin} = compile:forms(Forms, []).{ok,example1,<<70,79,82,49,...>>}
3> code:load_binary(Mod, [], Bin).{module,example1}
4> example1:foo()."Hello Stockholm!"
27
![Page 28: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/28.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
28
![Page 29: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/29.jpg)
dynamic_compile
The dynamic_compile module performs the actions we’ve just seen, plus takes care of macro expansion and inclusion of external header files.
http://github.com/JacobVorreuter/dynamic_compile
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
29
![Page 30: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/30.jpg)
dynamic_compile
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
1> Code = "-module(example1)...".
2> dynamic_compile:load_from_string(Code).{module,example1}
3> example1:foo()."Hello Stockholm!"
30
![Page 31: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/31.jpg)
moving on...
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
31
![Page 32: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/32.jpg)
the parse_transform debate...
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
32
![Page 33: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/33.jpg)
Programmers are strongly advised NOT
to engage in parse transformations
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
33
![Page 34: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/34.jpg)
yeah, you can do everything with
macros anyway
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
34
![Page 35: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/35.jpg)
wait! parse_transforms are cool and have their place in the
language...in moderation.
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
35
![Page 36: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/36.jpg)
If the option {parse_transform, Module} is passed to the compiler, a user written function parse_transform/2 is called by the compiler before the code is checked for errors.
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
How do parse_transforms work?
36
![Page 37: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/37.jpg)
How do parse_transforms work?
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
-module(print_forms).-export([parse_transform/2]).
parse_transform(Forms, _Options) -> io:format("forms: ~p~n", [Forms]), Forms.
-module(example1).-compile({parse_transform, print_forms}).-export([foo/0]).
foo() -> "Hello Stockholm!".
37
![Page 38: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/38.jpg)
How do parse_transforms work?
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
jvorreuter$ erlc -o ebin src/print_forms.erl
jvorreuter$ erlc -o ebin -pa ebin src/example1.erl forms: [{attribute,1,file,{"src/example1.erl",1}}, {attribute,1,module,example1}, {attribute,3,export,[{foo,0}]}, {function,5,foo,0,[{clause,5,[],[],[{string,
5,"Hello Stockholm!"}]}]}, {eof,8}]
38
![Page 39: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/39.jpg)
#pizza{ size = "large", toppings = ["onions", "peppers", "olives"], price = "$14.99"}
[{size, "large"}, {toppings, ["onions", "peppers", "olives"]}, {price, "$14.99"}]
a pizza example
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
encode pizza
39
![Page 40: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/40.jpg)
#pizza{ size = "large", toppings = ["onions", "peppers", "olives"], price = "$14.99"}
[{size, "large"}, {toppings, ["onions", "peppers", "olives"]}, {price, "$14.99"}]
a pizza example
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
record_to_proplist(#pizza{})
40
![Page 41: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/41.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
-module(example2).-export([record_to_proplist/1]). -record(pizza, {size, toppings, price}). record_to_proplist(Rec) when is_tuple(Rec) -> case Rec of Pizza when is_record(Pizza, pizza) -> [{size, Pizza#pizza.size}, {toppings, Pizza#pizza.toppings}, {price, Pizza#pizza.price}]; _ -> exit(wtf_do_i_do_with_this) end.
manually assemble proplist with correct fields
41
![Page 42: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/42.jpg)
remember, at runtime all references to record instances have been replaced with indexed tuples.
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
42
![Page 43: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/43.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
-module(example2).-compile({parse_transform, expand_records}).-export([record_to_proplist/1]). -record(pizza, {size, toppings, price}). record_to_proplist(Rec) when is_tuple(Rec) -> [RecName|FieldValues] = tuple_to_list(Rec), FieldNames = expanded_record_fields(RecName), lists:zip(FieldNames, FieldValues).
this function is injected into the precompiled forms
during the parse_transform
43
![Page 44: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/44.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
1> Pizza = #pizza{size="large", toppings=["onions", "peppers", "olives"], price="$14.99"}.
2> example2:record_to_proplist(Pizza).[{size,"large"}, {toppings,["onions","peppers","olives"]}, {price,"$14.99"}]
44
![Page 45: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/45.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
a look at expand_records.erl
45
![Page 46: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/46.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
two accumulators:list of forms to return to the compiler and a list of record definitions that we will use to
build our injected function
46
![Page 47: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/47.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
accumulate record attributes
47
![Page 48: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/48.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
once all record attributes have been collected we use them to construct
our function
48
![Page 49: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/49.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
49
![Page 50: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/50.jpg)
intermission
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
50
![Page 51: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/51.jpg)
Act IIcompiling custom syntax
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
51
![Page 52: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/52.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
➸ dingbats ✂
➽ numbers ✓ ◤ 1 ➟ 16 ✈ ❤ ◥ ✂
52
![Page 53: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/53.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
➸ dingbats ✂
➽ numbers ✓ ◤ 1 ➟ 16 ✈ ❤ ◥ ✂
1> dingbats:numbers().[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
53
![Page 54: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/54.jpg)
leex - A regular expression based lexical analyzer generator for Erlang, similar to lex or flex.
yecc - An LALR-1 parser generator for Erlang, similar to yacc.
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
54
![Page 55: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/55.jpg)
leexThe leex module takes a definition file with the extension .xrl as input and generates the source code for a lexical analyzer as output.
< Definitions >< Rules ><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
55
![Page 56: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/56.jpg)
example_scanner.xrl< Definitions >< Rules ><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
56
![Page 57: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/57.jpg)
Definitions.A = [a-z][0-9a-zA-Z_]*I = [0-9]+WS = ([\000-\s]|%.*)
< Rules ><Erlang Code>
example_scanner.xrl
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
57
![Page 58: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/58.jpg)
Definitions.A = [a-z][0-9a-zA-Z_]*I = [0-9]+WS = ([\000-\s]|%.*)
Rules.\➸ : {token,{module,TokenLine}}.\➽ : {token,{function,TokenLine}}.\✓ : {token,{'->',TokenLine}}.\◤ : {token,{'[',TokenLine}}.\◥ : {token,{']',TokenLine}}.{A} : {token,{atom,TokenLine,list_to_atom(TokenChars)}}.{I} : {token,{integer,TokenLine,list_to_integer(TokenChars)}}.\➟ : {token,{'<-',TokenLine}}.\✈ : {token,{'||',TokenLine}}.\❤ : {token,{heart,TokenLine}}.\✂{WS} : {end_token,{dot,TokenLine}}.{WS}+ : skip_token.
<Erlang Code>
example_scanner.xrl
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
58
![Page 59: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/59.jpg)
Definitions.A = [a-z][0-9a-zA-Z_]*I = [0-9]+WS = ([\000-\s]|%.*)
Rules.\➸ : {token,{module,TokenLine}}.\➽ : {token,{function,TokenLine}}.\✓ : {token,{'->',TokenLine}}.\◤ : {token,{'[',TokenLine}}.\◥ : {token,{']',TokenLine}}.{A} : {token,{atom,TokenLine,list_to_atom(TokenChars)}}.{I} : {token,{integer,TokenLine,list_to_integer(TokenChars)}}.\➟ : {token,{'<-',TokenLine}}.\✈ : {token,{'||',TokenLine}}.\❤ : {token,{heart,TokenLine}}.\✂{WS} : {end_token,{dot,TokenLine}}.{WS}+ : skip_token.
Erlang code.
example_scanner.xrl
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
59
![Page 60: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/60.jpg)
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
1> leex:file("src/example_scanner.xrl").{ok,"src/example_scanner.erl"}
example_scanner.xrl
60
![Page 61: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/61.jpg)
yecc
* Backus–Naur Form (BNF) is a metasyntax used to express context-free grammars: that is, a formal way to describe formal languages
The yecc module takes a BNF* grammar definition as input, and produces the source code for a parser.
<Header><Non-terminals><Terminals><Root Symbol><End Symbol><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
61
![Page 62: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/62.jpg)
example_parse.yrl<Header><Non-terminals><Terminals><Root Symbol><End Symbol><Erlang Code>
The header provides a chance to add
documentation before the module declaration
in your parser
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
62
![Page 63: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/63.jpg)
example_parse.yrlHeader "%% Copyright (C)""%% @Author Jacob Vorreuter"
<Non-terminals><Terminals><Root Symbol><End Symbol><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
We could do something like
this, but whatever
63
![Page 64: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/64.jpg)
example_parse.yrl<Non-terminals><Terminals><Root Symbol><End Symbol><Erlang Code>
Terminal symbols are literal strings forming the input of a formal grammar and cannot be broken down into smaller
units without losing their literal meaning
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
64
![Page 65: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/65.jpg)
example_parse.yrl<Non-terminals>
Terminals atom integer heart module function '[' ']' '->' '<-' '||'.
<Root Symbol><End Symbol><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
65
![Page 66: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/66.jpg)
example_parse.yrl<Non-terminals>
Terminals atom integer heart module function '[' ']' '->' '<-' '||'.
<Root Symbol><End Symbol><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
These terminal symbols are the products of the regular
expressions in our lexical analyzer
66
![Page 67: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/67.jpg)
example_parse.yrl<Non-terminals>
Terminals atom integer heart module function '[' ']' '->' '<-' '||'.
<Root Symbol><End Symbol><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
\➸ : {token,{module,TokenLine}}.\➽ : {token,{function,TokenLine}}.\✓ : {token,{'->',TokenLine}}.\◤ : {token,{'[',TokenLine}}.
\◥ : {token,{']',TokenLine}}.
{A} : {token,{atom,TokenLine, list_to_atom(TokenChars)}}.{I} : {token,{integer,TokenLine, list_to_integer(TokenChars)}}.\➟ : {token,{'<-',TokenLine}}.\✈ : {token,{'||',TokenLine}}.\❤ : {token,{heart,TokenLine}}.\✂{WS} : {end_token,{dot,TokenLine}}.{WS}+ : skip_token.
67
![Page 68: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/68.jpg)
example_parse.yrl<Non-terminals>
Terminals atom integer heart module function '[' ']' '->' '<-' '||'.
<Root Symbol><End Symbol><Erlang Code> Nonterminal symbols are the
rules within the formal grammar consisting of a sequence of
terminal symbols or nonterminal symbols. Nonterminal symbols
may self reference to specify recursion.
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
68
![Page 69: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/69.jpg)
example_parse.yrlNonterminals element module_declaration function_declaration function_body comprehension.
Terminals atom integer heart module function '[' ']' '->' '<-' '||'.<Root Symbol><End Symbol><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
69
![Page 70: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/70.jpg)
example_parse.yrlNonterminals element module_declaration function_declaration function_body comprehension.
Terminals atom integer heart module function '[' ']' '->' '<-' '||'.<Root Symbol><End Symbol><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
Here we are declaring symbols that will be further defined as
descendants of the root symbol
70
![Page 71: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/71.jpg)
example_parse.yrlNonterminals element module_declaration function_declaration function_body comprehension.Terminals atom integer heart module function '[' ']' '->' '<-' '||'.<Root Symbol><End Symbol><Erlang Code> The root symbol is the most
general syntactic category which the parser ultimately will parse
every input string into.
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
71
![Page 72: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/72.jpg)
example_parse.yrlNonterminals element module_declaration function_declaration function_body comprehension.Terminals atom integer heart module function '[' ']' '->' '<-' '||'.
Rootsymbol element.
<End Symbol><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
72
![Page 73: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/73.jpg)
example_parse.yrlNonterminals element module_declaration function_declaration function_body comprehension.Terminals atom integer heart module function '[' ']' '->' '<-' '||'.
Rootsymbol element.element -> module_declaration : '$1'.element -> function_declaration : '$1'.
<End Symbol><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
the dollar sign notation references the value of the indexed item on the right
side of the symbol definition
73
![Page 74: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/74.jpg)
example_parse.yrlNonterminals element module_declaration function_declaration function_body comprehension.Terminals atom integer heart module function '[' ']' '->' '<-' '||'.
Rootsymbol element.element -> module_declaration : '$1'.element -> function_declaration : '$1'.module_declaration -> module atom :
{attribute,line_of('$2'),module,value_of('$2')}.function_declaration -> function atom '->' function_body :
{function,line_of('$2'),value_of('$2'),0,[{clause,line_of('$2'),[],[],'$4'}]}.
<End Symbol><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
since our example module is named dingbats, the value of ‘$2’ in this case will be
{atom,LINE,dingbats}
74
![Page 75: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/75.jpg)
example_parse.yrlNonterminals element module_declaration function_declaration function_body comprehension.Terminals atom integer heart module function '[' ']' '->' '<-' '||'.
Rootsymbol element.element -> module_declaration : '$1'.element -> function_declaration : '$1'.module_declaration -> module atom :
{attribute,line_of('$2'),module,value_of('$2')}.function_declaration -> function atom '->' function_body :
{function,line_of('$2'),value_of('$2'),0,[{clause,line_of('$2'),[],[],'$4'}]}.function_body -> comprehension : ['$1'].
<End Symbol><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
75
![Page 76: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/76.jpg)
example_parse.yrlNonterminals element module_declaration function_declaration function_body comprehension.Terminals atom integer heart module function '[' ']' '->' '<-' '||'.
Rootsymbol element.element -> module_declaration : '$1'.element -> function_declaration : '$1'.module_declaration -> module atom :
{attribute,line_of('$2'),module,value_of('$2')}.function_declaration -> function atom '->' function_body :
{function,line_of('$2'),value_of('$2'),0,[{clause,line_of('$2'),[],[],'$4'}]}.function_body -> comprehension : ['$1'].comprehension -> '[' ']' : nil.comprehension -> '[' integer '<-' integer '||' heart ']' :
{lc,line_of('$2'),{var,line_of('$2'),'A'},[{generate,line_of('$2'),{var,line_of('$2'),'A'},{call,line_of('$2'),{remote,line_of('$2'),{atom,line_of('$2'),lists},{atom,line_of('$2'),seq}},['$2','$4']}}]}.
<End Symbol><Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
76
![Page 77: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/77.jpg)
example_parse.yrlNonterminals element module_declaration function_declaration function_body comprehension.Terminals atom integer heart module function '[' ']' '->' '<-' '||'.Rootsymbol element.element -> module_declaration : '$1'.element -> function_declaration : '$1'.module_declaration -> module atom :
{attribute,line_of('$2'),module,value_of('$2')}.function_declaration -> function atom '->' function_body :
{function,line_of('$2'),value_of('$2'),0,[{clause,line_of('$2'),[],[],'$4'}]}.function_body -> comprehension : ['$1'].comprehension -> '[' ']' : nil.comprehension -> '[' integer '<-' integer '||' heart ']' :
{lc,line_of('$2'),{var,line_of('$2'),'A'},[{generate,line_of('$2'),{var,line_of('$2'),'A'},{call,line_of('$2'),{remote,line_of('$2'),{atom,line_of('$2'),lists},{atom,line_of('$2'),seq}},['$2','$4']}}]}.
<End Symbol><Erlang Code>
the end symbol is a declaration of the end_of_input symbol that your scanner is expected to use.
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
77
![Page 78: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/78.jpg)
example_parse.yrlNonterminals element module_declaration function_declaration function_body comprehension.Terminals atom integer heart module function '[' ']' '->' '<-' '||'.Rootsymbol element.element -> module_declaration : '$1'.element -> function_declaration : '$1'.module_declaration -> module atom :
{attribute,line_of('$2'),module,value_of('$2')}.function_declaration -> function atom '->' function_body :
{function,line_of('$2'),value_of('$2'),0,[{clause,line_of('$2'),[],[],'$4'}]}.function_body -> comprehension : ['$1'].comprehension -> '[' ']' : nil.comprehension -> '[' integer '<-' integer '||' heart ']' :
{lc,line_of('$2'),{var,line_of('$2'),'A'},[{generate,line_of('$2'),{var,line_of('$2'),'A'},{call,line_of('$2'),{remote,line_of('$2'),{atom,line_of('$2'),lists},{atom,line_of('$2'),seq}},['$2','$4']}}]}.
Endsymbol dot.
<Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
78
![Page 79: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/79.jpg)
example_parse.yrlNonterminals element module_declaration function_declaration function_body comprehension.Terminals atom integer heart module function '[' ']' '->' '<-' '||'.Rootsymbol element.element -> module_declaration : '$1'.element -> function_declaration : '$1'.module_declaration -> module atom :
{attribute,line_of('$2'),module,value_of('$2')}.function_declaration -> function atom '->' function_body :
{function,line_of('$2'),value_of('$2'),0,[{clause,line_of('$2'),[],[],'$4'}]}.function_body -> comprehension : ['$1'].comprehension -> '[' ']' : nil.comprehension -> '[' integer '<-' integer '||' heart ']' :
{lc,line_of('$2'),{var,line_of('$2'),'A'},[{generate,line_of('$2'),{var,line_of('$2'),'A'},{call,line_of('$2'),{remote,line_of('$2'),{atom,line_of('$2'),lists},{atom,line_of('$2'),seq}},['$2','$4']}}]}.
Endsymbol dot.
<Erlang Code>
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
The Erlang code section can contain any functions that we need to call
from our symbol definitions
79
![Page 80: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/80.jpg)
example_parse.yrlNonterminals element module_declaration function_declaration function_body comprehension.Terminals atom integer heart module function '[' ']' '->' '<-' '||'.Rootsymbol element.element -> module_declaration : '$1'.element -> function_declaration : '$1'.module_declaration -> module atom :
{attribute,line_of('$2'),module,value_of('$2')}.function_declaration -> function atom '->' function_body :
{function,line_of('$2'),value_of('$2'),0,[{clause,line_of('$2'),[],[],'$4'}]}.function_body -> comprehension : ['$1'].comprehension -> '[' ']' : nil.comprehension -> '[' integer '<-' integer '||' heart ']' :
{lc,line_of('$2'),{var,line_of('$2'),'A'},[{generate,line_of('$2'),{var,line_of('$2'),'A'},{call,line_of('$2'),{remote,line_of('$2'),{atom,line_of('$2'),lists},{atom,line_of('$2'),seq}},['$2','$4']}}]}.
Endsymbol dot.
Erlang code.value_of(Token) -> element(3, Token).line_of(Token) -> element(2, Token).
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
80
![Page 81: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/81.jpg)
example_parse.yrl
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
2> yecc:file("src/example_parser.yrl", []).{ok,"src/example_parser.erl"}
jvorreuter$ erlc -o ebin src/*.erl
81
![Page 82: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/82.jpg)
example_parse.yrl
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
1> example4:compile_and_load("src/dingbats").{module,dingbats}
2> dingbats:numbers().[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
82
![Page 83: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/83.jpg)
example4.erl
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
-module(example4).-export([compile_and_load/1]).
compile_and_load(Path) -> {ok, Bin} = file:read_file(Path), [Form|Forms] = scan_parse([], binary_to_list(Bin), 0, []), Forms1 = [Form,{attribute,1,compile,export_all}|Forms], {ok, Mod, Bin1} = compile:forms(Forms1, []), code:load_binary(Mod, [], Bin1).scan_parse(Cont, Str, StartLoc, Acc) -> case example_scanner:tokens(Cont, Str, StartLoc) of {done, {ok, Tokens, EndLoc}, LeftOverChars} -> {ok, Form} = example_parser:parse(Tokens), scan_parse([], LeftOverChars, EndLoc, [Form|Acc]); _ -> lists:reverse(Acc) end.
read the contents of the source file
83
![Page 84: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/84.jpg)
-module(example4).-export([compile_and_load/1]).
compile_and_load(Path) -> {ok, Bin} = file:read_file(Path), [Form|Forms] = scan_parse([], binary_to_list(Bin), 0, []), Forms1 = [Form,{attribute,1,compile,export_all}|Forms], {ok, Mod, Bin1} = compile:forms(Forms1, []), code:load_binary(Mod, [], Bin1).scan_parse(Cont, Str, StartLoc, Acc) -> case example_scanner:tokens(Cont, Str, StartLoc) of {done, {ok, Tokens, EndLoc}, LeftOverChars} -> {ok, Form} = example_parser:parse(Tokens), scan_parse([], LeftOverChars, EndLoc, [Form|Acc]); _ -> lists:reverse(Acc) end.
example4.erl
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
tokenize the source code using our custom scanner
84
![Page 85: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/85.jpg)
-module(example4).-export([compile_and_load/1]).
compile_and_load(Path) -> {ok, Bin} = file:read_file(Path), [Form|Forms] = scan_parse([], binary_to_list(Bin), 0, []), Forms1 = [Form,{attribute,1,compile,export_all}|Forms], {ok, Mod, Bin1} = compile:forms(Forms1, []), code:load_binary(Mod, [], Bin1).scan_parse(Cont, Str, StartLoc, Acc) -> case example_scanner:tokens(Cont, Str, StartLoc) of {done, {ok, Tokens, EndLoc}, LeftOverChars} -> {ok, Form} = example_parser:parse(Tokens), scan_parse([], LeftOverChars, EndLoc, [Form|Acc]); _ -> lists:reverse(Acc) end.
example4.erl
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
parse the tokens into forms using our custom parser
85
![Page 86: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/86.jpg)
-module(example4).-export([compile_and_load/1]).
compile_and_load(Path) -> {ok, Bin} = file:read_file(Path), [Form|Forms] = scan_parse([], binary_to_list(Bin), 0, []), Forms1 = [Form,{attribute,1,compile,export_all}|Forms], {ok, Mod, Bin1} = compile:forms(Forms1, []), code:load_binary(Mod, [], Bin1).scan_parse(Cont, Str, StartLoc, Acc) -> case example_scanner:tokens(Cont, Str, StartLoc) of {done, {ok, Tokens, EndLoc}, LeftOverChars} -> {ok, Form} = example_parser:parse(Tokens), scan_parse([], LeftOverChars, EndLoc, [Form|Acc]); _ -> lists:reverse(Acc) end.
example4.erl
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
compile and load the binary
86
![Page 87: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/87.jpg)
custom syntax in the wild...
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
• Lisp Flavored Erlang
• Prolog Interpreter for Erlang
• Erlang implementation of the Django Template Language
• Reia - a Ruby/Python-like scripting language for the Erlang VM
87
![Page 88: Hacking Erlang](https://reader033.vdocuments.net/reader033/viewer/2022050720/54692234b4af9fda3f8b5df6/html5/thumbnails/88.jpg)
END
http://github.com/JacobVorreuterhttp://jacobvorreuter.com/hacking-erlang
88