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
+ 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://medium.com/cirru-project/resources-on-elixir-ast-e045b613f284
+ https://elixir-lang.org/getting-started/meta/quote-and-unquote.html

View File

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

View File

@ -13,7 +13,7 @@ Rules.
{D}+\.{D}+ : { token, { float, TokenLine, list_to_float(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 } }.
@ -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, { eol, TokenLine } }.
{LF} : { token, { eol, TokenLine } }.

View File

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

View File

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