Huge progress
This commit is contained in:
parent
ed602ab3f3
commit
b78a2fa71a
5 changed files with 99 additions and 45 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 } }.
|
||||
|
||||
|
|
|
@ -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' }.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue