Huge progress

This commit is contained in:
Daniel Flanagan 2019-11-19 23:38:36 -06:00
parent ed602ab3f3
commit b78a2fa71a
5 changed files with 99 additions and 45 deletions

View file

@ -72,6 +72,8 @@ probably never even happen.
## Development Resources ## Development Resources
+ http://erlang.org/doc/man/yecc.html
+ http://erlang.org/doc/man/leex.html
+ https://hexdocs.pm/elixir/syntax-reference.html#the-elixir-ast + https://hexdocs.pm/elixir/syntax-reference.html#the-elixir-ast
+ https://medium.com/cirru-project/resources-on-elixir-ast-e045b613f284 + https://medium.com/cirru-project/resources-on-elixir-ast-e045b613f284
+ https://elixir-lang.org/getting-started/meta/quote-and-unquote.html + https://elixir-lang.org/getting-started/meta/quote-and-unquote.html

View file

@ -31,7 +31,7 @@ defmodule Lytlang do
end end
def parse(tokens, _opts \\ []) do def parse(tokens, _opts \\ []) do
{:ok, [tree]} = {:ok, tree} =
:lytlang_parser.parse(tokens) :lytlang_parser.parse(tokens)
|> IO.inspect(label: "Parsed") |> IO.inspect(label: "Parsed")
@ -40,10 +40,16 @@ defmodule Lytlang do
def eval_elixir(ast, opts \\ []) def eval_elixir(ast, opts \\ [])
def eval_elixir(ast, _opts) when is_list(ast) do
{:__block__, [], ast}
|> IO.inspect(label: "Wrapped in Block")
|> eval_elixir()
end
def eval_elixir(ast, _opts) do def eval_elixir(ast, _opts) do
{:__block__, [], [ast]} ast
|> Code.eval_quoted() |> Code.eval_quoted()
|> IO.inspect() |> IO.inspect(label: "Evaluated as Elixir")
end end
end end

View file

@ -13,7 +13,7 @@ Rules.
{D}+\.{D}+ : { token, { float, TokenLine, list_to_float(TokenChars) } }. {D}+\.{D}+ : { token, { float, TokenLine, list_to_float(TokenChars) } }.
{D}+ : { token, { integer, TokenLine, list_to_integer(TokenChars) } }. {D}+ : { token, { integer, TokenLine, list_to_integer(TokenChars) } }.
({L}|_)({U}{L}{D}|_)* : { token, var(TokenChars, TokenLine) }. [{L}|_][{U}{L}{D}|_]+ : { token, var(TokenChars, TokenLine) }.
\+ : { token, { '+', TokenLine } }. \+ : { token, { '+', TokenLine } }.
- : { token, { '-', TokenLine } }. - : { token, { '-', TokenLine } }.
@ -22,8 +22,18 @@ Rules.
// : { token, { '//', TokenLine } }. // : { token, { '//', TokenLine } }.
\( : { token, { '(', TokenLine } }. \( : { token, { '(', TokenLine } }.
\) : { token, { ')', TokenLine } }. \) : { token, { ')', TokenLine } }.
\[ : { token, { '[', TokenLine } }.
\] : { token, { ']', TokenLine } }.
\< : { token, { '<', TokenLine } }.
\> : { token, { '>', TokenLine } }.
\{ : { token, { '{', TokenLine } }.
\} : { token, { '}', TokenLine } }.
\" : { token, { '"', TokenLine } }.
\' : { token, { '\'', TokenLine } }.
, : { token, { ',', TokenLine } }.
= : { token, { '=', TokenLine } }. = : { token, { '=', TokenLine } }.
-> : { token, { '->', TokenLine } }. -> : { token, { '->', TokenLine } }.
: : { token, { ':', TokenLine } }.
; : { token, { eol, TokenLine } }. ; : { token, { eol, TokenLine } }.
{LF} : { token, { eol, TokenLine } }. {LF} : { token, { eol, TokenLine } }.

View file

@ -1,22 +1,8 @@
Nonterminals Nonterminals
grammar grammar e_list e assignment add sub mult div idiv unary number list map_el map.
e_list
e
assignment
add
sub
mult
div
idiv
unary
number
unary
.
Terminals Terminals
var float integer eol var float integer eol '+' '-' '*' '/' '//' '(' ')' '=' '"' '\'' '{' '}' '[' ']' '<' '>' ',' ':'.
'+' '-' '*' '/' '//' '(' ')' '='
.
Rootsymbol grammar. Rootsymbol grammar.
Endsymbol '$end'. Endsymbol '$end'.
@ -37,15 +23,13 @@ e_list -> e eol : ['$1'].
e_list -> eol e_list : '$2'. e_list -> eol e_list : '$2'.
e_list -> e eol e_list : ['$1' | '$3']. e_list -> e eol e_list : ['$1' | '$3'].
%% Minimum expressions e -> '<' e ',' e '>' : {'$2', '$4'}.
e -> var : '$1'. e -> '<' list '>' : {'{}', [], '$2'}.
e -> '[' ']' : [].
e -> var : ?var('$1').
e -> number : '$1'. e -> number : '$1'.
e -> '(' e ')' : '$2'. e -> '(' e ')' : '$2'.
%% Numbers
number -> float : '$1'.
number -> integer : ?e(3, '$1').
e -> mult : '$1'. e -> mult : '$1'.
e -> div : '$1'. e -> div : '$1'.
e -> idiv : '$1'. e -> idiv : '$1'.
@ -53,26 +37,29 @@ e -> assignment : '$1'.
e -> add : '$1'. e -> add : '$1'.
e -> sub : '$1'. e -> sub : '$1'.
e -> unary : '$1'. e -> unary : '$1'.
e -> '"' '"' : list_to_binary([]).
e -> '"' var '"' : list_to_binary('$2').
e -> '[' list ']' : '$2'.
e -> '{' map '}' : '$2'.
assignment -> var '=' e : list -> '$empty' : [].
{ '=', ?meta('$2'), [?var('$1'), '$3'] }. list -> e : ['$1'].
list -> e ',' list : ['$1' | '$3'].
%% Arithmetic operations map_el -> var ':' e : {?e(3, '$1'), '$3'}.
add -> e '+' e :
{ '+', ?meta('$2'), ['$1', '$3'] }.
sub -> e '-' e : map -> '$empty' : {'%{}', [], []}.
{ '-', ?meta('$2'), ['$1', '$3'] }. map -> map_el : {'%{}', [], ['$1']}.
map -> map_el ',' map : {'%{}', [], ['$1' | '$3']}.
mult -> e '*' e :
{ '*', ?meta('$2'), ['$1', '$3'] }.
div -> e '/' e :
{ '/', ?meta('$2'), ['$1', '$3'] }.
idiv -> e '//' e :
{ 'div', ?meta('$2'), ['$1', '$3'] }.
number -> float : ?e(3, '$1').
number -> integer : ?e(3, '$1').
assignment -> var '=' e : { '=', ?meta('$2'), [?var('$1'), '$3'] }.
add -> e '+' e : { '+', ?meta('$2'), ['$1', '$3'] }.
sub -> e '-' e : { '-', ?meta('$2'), ['$1', '$3'] }.
mult -> e '*' e : { '*', ?meta('$2'), ['$1', '$3'] }.
div -> e '/' e : { '/', ?meta('$2'), ['$1', '$3'] }.
idiv -> e '//' e : { 'div', ?meta('$2'), ['$1', '$3'] }.
unary -> '+' e : { '+', ?meta('$1'), ?op('$1'), '$2' }. unary -> '+' e : { '+', ?meta('$1'), ?op('$1'), '$2' }.
unary -> '-' e : { '-', ?meta('$1'), ?op('$1'), '$2' }. unary -> '-' e : { '-', ?meta('$1'), ?op('$1'), '$2' }.

View file

@ -1,5 +1,5 @@
defmodule LytlangTest do defmodule LytlangTest do
use ExUnit.Case use ExUnit.Case, async: false
doctest Lytlang doctest Lytlang
test "arithmetic" do test "arithmetic" do
@ -16,10 +16,59 @@ defmodule LytlangTest do
{"8 / 4", 2.0}, {"8 / 4", 2.0},
{"8 // 4", 2}, {"8 // 4", 2},
{"a = 8\na + 9", 17}, {"a = 8\na + 9", 17},
{"a_number = 8\na_number + 9", 17},
{"2 + 3", 5} {"2 + 3", 5}
] ]
|> Enum.map(fn {string, val} -> |> Enum.map(fn {string, val} ->
assert Lytlang.eval(string) == val assert Lytlang.eval(string) == val
end) end)
end end
test "lists" do
[
{"[]", []},
{"[2]", [2]},
{"[2, 3]", [2, 3]},
{"[2, [3, 4], [5, [6, [7]]]]", [2, [3, 4], [5, [6, [7]]]]},
{"[2, 3, 4, 5, 6, 7]", [2, 3, 4, 5, 6, 7]}
]
|> Enum.map(fn {string, val} ->
assert Lytlang.eval(string) == val
end)
end
test "tuples" do
[
{"<>", {}},
{"<2>", {2}},
{"<2, 3>", {2, 3}},
{"<2, <3, 4>, <5, <6, <7>>>>", {2, {3, 4}, {5, {6, {7}}}}},
{"<2, 3, 4, 5, 6, 7>", {2, 3, 4, 5, 6, 7}}
]
|> Enum.map(fn {string, val} ->
assert Lytlang.eval(string) == val
end)
end
test "strings" do
[
{"\"\"", ""},
{"\"abcd\"", "abcd"}
]
|> Enum.map(fn {string, val} ->
assert Lytlang.eval(string) == val
end)
end
test "maps" do
[
{"{}", %{}},
{"{x : 9}", %{:x => 9}},
{"{x : 9}", %{x: 9}},
{"{x: 9}", %{x: 9}}
]
|> Enum.map(fn {string, val} ->
assert Lytlang.eval(string) == val
end)
end
end end