Current section

Files

Jump to
efene src fn_parser.yrl
Raw

src/fn_parser.yrl

%% Copyright 2015 Mariano Guerra
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
Nonterminals
program tl_exprs tl_expr literal raw_literal e_fn_tl
l_atom l_var l_integer l_float l_boolean l_string l_bstring l_fn l_fn_ref
guard_seq seq_items l_tuple l_list l_cons
kv_items kv_item
kv_key kv_val l_map l_map_update
e_bool
e_case e_cases e_case_cond e_case_else e_else_only_case
e_switch e_receive e_try
e_when e_when_cond e_when_else e_when_final_else e_when_elses
e_begin
e_for for_items for_item
raw_expr expr body
attrs attr
e_call e_call_do e_call_thread e_call_thread_funs
e_assign e_send
e_bool_and e_comp e_concat e_add e_mul e_unary
path path_item
e_def_tl.
Terminals
fn atom var integer float boolean string bstring colon end nl case else match when
begin receive after try catch for in
hash open close sep semicolon open_list close_list
open_map close_map split_def_op at arrow arrowend dot larrow larrowend
assign send_op
bool_or bool_orr bool_xor bool_and bool_andd comp_op concat_op add_op mul_op
bin_or bin_and bin_shift bin_not bool_not
def.
Rootsymbol program.
program -> tl_exprs : '$1'.
program -> nl tl_exprs : '$2'.
tl_exprs -> tl_expr : ['$1'].
tl_exprs -> tl_expr nl tl_exprs : ['$1'|'$3'].
tl_expr -> e_fn_tl: '$1'.
tl_expr -> attr: '$1'.
tl_expr -> e_def_tl: '$1'.
tl_expr -> expr: '$1'.
e_fn_tl -> fn l_atom e_case end:
Name = '$2',
Cases = '$3',
{expr, line('$1'), fn, {Name, [], Cases}}.
e_fn_tl -> fn l_atom attrs e_case end:
Name = '$2',
Attrs = '$3',
Cases = '$4',
{expr, line('$1'), fn, {Name, Attrs, Cases}}.
e_def_tl -> def l_atom colon e_case end:
Name = '$2',
Args = [],
Attrs = [],
Cases = '$4',
{expr, line('$1'), def, {Name, Args, Attrs, Cases}}.
e_def_tl -> def l_atom colon attrs e_case end:
Name = '$2',
Args = [],
Attrs = '$4',
Cases = '$5',
{expr, line('$1'), def, {Name, Args, Attrs, Cases}}.
e_def_tl -> def l_atom seq_items colon e_case end:
Name = '$2',
Args = '$3',
Attrs = [],
Cases = '$5',
{expr, line('$1'), def, {Name, Args, Attrs, Cases}}.
e_def_tl -> def l_atom seq_items colon attrs e_case end:
Name = '$2',
Args = '$3',
Attrs = '$5',
Cases = '$6',
{expr, line('$1'), def, {Name, Args, Attrs, Cases}}.
e_else_only_case -> e_case_else : {expr, line('$1'), 'case', ['$1']}.
e_else_only_case -> e_case : '$1'.
e_case -> e_cases : {expr, line('$1'), 'case', '$1'}.
e_case_cond -> case colon body : {cmatch, line('$1'), {[], nowhen, '$3'}}.
e_case_cond -> case seq_items colon body : {cmatch, line('$1'), {'$2', nowhen, '$4'}}.
e_case_cond -> case seq_items when guard_seq colon body : {cmatch, line('$1'), {'$2', '$4', '$6'}}.
e_case_cond -> case seq_items nl when guard_seq colon body : {cmatch, line('$1'), {'$2', '$5', '$7'}}.
e_case_else -> else colon body : {celse, line('$1'), '$3'}.
e_cases -> e_case_cond : ['$1'].
e_cases -> e_case_cond e_case_else : ['$1', '$2'].
e_cases -> e_case_cond e_cases : ['$1'|'$2'].
e_switch -> match seq_items colon e_case end:
case '$2' of
[Item] ->
{expr, line('$1'), switch, {Item, '$4'}};
Items ->
{expr, line('$1'), switch, {seq_value(Items, line('$1'), tuple), '$4'}}
end.
e_receive -> receive e_case end:
{expr, line('$1'), 'receive', {'$2', noafter}}.
e_receive -> receive e_case after literal colon body end:
{expr, line('$1'), 'receive', {'$2', {'$4', '$6'}}}.
e_receive -> receive after literal colon body end:
{expr, line('$1'), 'receive', {[], {'$3', '$5'}}}.
e_try -> try body after body end:
{expr, line('$1'), 'try', {'$2', nocatch, '$4'}}.
e_try -> try body catch e_else_only_case end:
{expr, line('$1'), 'try', {'$2', '$4', noafter}}.
e_try -> try body catch e_else_only_case after body end:
{expr, line('$1'), 'try', {'$2', '$4', '$6'}}.
e_when -> e_when_cond end : {expr, line('$1'), 'when', ['$1']}.
e_when -> e_when_cond e_when_elses end : {expr, line('$1'), 'when', ['$1'|'$2']}.
e_when_cond -> when guard_seq colon body : {wcond, line('$1'), '$2', '$4'}.
e_when_else -> else guard_seq colon body : {wcond, line('$1'), '$2', '$4'}.
e_when_final_else -> else colon body : {welse, line('$1'), '$3'}.
e_when_elses -> e_when_else : ['$1'].
e_when_elses -> e_when_final_else : ['$1'].
e_when_elses -> e_when_else e_when_elses : ['$1'|'$2'].
e_begin -> begin body end: {expr, line('$1'), 'begin', '$2'}.
e_for -> for for_items colon body end : {expr, line('$1'), 'for', {'$2', '$4'}}.
for_item -> when e_bool : {filter, '$2'}.
for_item -> literal in literal : {generate, line('$2'), '$1', '$3'}.
for_item -> literal larrow literal : {b_generate, line('$2'), '$1', '$3'}.
for_items -> for_item : ['$1'].
for_items -> for_item semicolon for_items : ['$1'|'$3'].
e_bool -> e_bool_and bool_or e_bool: op('$2', '$1', '$3').
e_bool -> e_bool_and: '$1'.
e_bool_and -> e_comp bool_and e_bool_and: op('$2', '$1', '$3').
e_bool_and -> e_comp: '$1'.
e_comp -> e_concat comp_op e_comp : op('$2', '$1', '$3').
e_comp -> e_concat : '$1'.
e_concat -> e_add concat_op e_concat : op('$2', '$1', '$3').
e_concat -> e_add : '$1'.
e_add -> e_add add_op e_mul : op('$2', '$1', '$3').
e_add -> e_add bool_orr e_mul : op('$2', '$1', '$3').
e_add -> e_add bool_xor e_mul : op('$2', '$1', '$3').
e_add -> e_add bin_shift e_mul : op('$2', '$1', '$3').
e_add -> e_add bin_or e_mul : op('$2', '$1', '$3').
e_add -> e_mul : '$1'.
e_mul -> e_mul mul_op e_unary : op('$2', '$1', '$3').
e_mul -> e_mul bool_andd e_unary : op('$2', '$1', '$3').
e_mul -> e_mul bin_and e_unary : op('$2', '$1', '$3').
e_mul -> e_unary : '$1'.
e_unary -> bin_not literal: unary_op('$1', '$2').
e_unary -> bool_not literal: unary_op('$1', '$2').
e_unary -> add_op literal: unary_op('$1', '$2').
e_unary -> literal : '$1'.
expr -> bin_or path raw_expr: {tag, line('$1'), '$2', '$3'}.
expr -> raw_expr : '$1'.
raw_expr -> e_switch : '$1'.
raw_expr -> e_when: '$1'.
raw_expr -> e_for: '$1'.
raw_expr -> e_receive: '$1'.
raw_expr -> e_try: '$1'.
raw_expr -> e_send : '$1'.
raw_expr -> e_call_do : '$1'.
raw_expr -> e_call_thread : '$1'.
body -> expr: ['$1'].
body -> expr nl: ['$1'].
body -> expr nl body : ['$1'|'$3'].
literal -> hash path raw_literal : {ltag, line('$1'), '$2', '$3'}.
literal -> raw_literal : '$1'.
path -> path_item : ['$1'].
path -> path_item dot path : ['$1'|'$3'].
path_item -> l_atom : '$1'.
path_item -> l_var : '$1'.
raw_literal -> l_atom : '$1'.
raw_literal -> l_var : '$1'.
raw_literal -> l_integer : '$1'.
raw_literal -> l_float : '$1'.
raw_literal -> l_boolean : '$1'.
raw_literal -> l_string : '$1'.
raw_literal -> l_bstring : '$1'.
raw_literal -> l_tuple : '$1'.
raw_literal -> l_list : '$1'.
raw_literal -> l_cons : '$1'.
raw_literal -> l_map : '$1'.
raw_literal -> l_map_update : '$1'.
raw_literal -> l_fn : '$1'.
raw_literal -> l_fn_ref : '$1'.
raw_literal -> e_begin: '$1'.
raw_literal -> e_call : '$1'.
raw_literal -> open expr close : '$2'.
l_atom -> atom : value('$1', atom).
l_var -> var : value('$1', var).
l_integer -> integer : value('$1', integer).
l_float -> float : value('$1', float).
l_boolean -> boolean : value('$1', boolean).
l_string -> string : value('$1', string).
l_bstring -> bstring : value('$1', bstring).
l_fn -> fn e_case end: expr_raw('$2', fn).
l_fn -> fn l_var e_case end: {expr, line('$1'), fn, {'$2', '$3'}}.
l_fn_ref -> fn path colon l_integer : {val, line('$1'), fn_ref, {'$2', '$4'}}.
l_tuple -> open close : seq_value([], line('$1'), tuple).
l_tuple -> open e_assign sep close : seq_value(['$2'], line('$1'), tuple).
l_tuple -> open e_assign sep seq_items close: seq_value(['$2'|'$4'], line('$1'), tuple).
l_list -> open_list close_list : seq_value([], line('$1'), list).
l_list -> open_list seq_items close_list : seq_value('$2', line('$1'), list).
l_cons -> open_list seq_items split_def_op literal close_list : seq_value({'$2', '$4'}, line('$1'), cons).
guard_seq -> seq_items : ['$1'].
guard_seq -> seq_items semicolon guard_seq :
Tail = '$3',
[TailHead|_] = Tail,
if is_tuple(TailHead) -> ['$1',Tail];
true -> ['$1'|Tail]
end.
seq_items -> e_assign: ['$1'].
seq_items -> e_assign sep: ['$1'].
seq_items -> e_assign sep seq_items : ['$1'|'$3'].
l_map -> open_map close_map: seq_value([], line('$1'), map).
l_map -> open_map kv_items close_map: seq_value('$2', line('$1'), map).
l_map_update -> l_var hash l_map :
{seq, Line, map, Items} = '$3',
{seq, Line, map, {'$1', Items}}.
kv_key -> literal : '$1'.
kv_val -> e_bool : '$1'.
kv_item -> kv_key colon kv_val: {kv, line('$1'), '$1', '$3'}.
kv_item -> kv_key assign kv_val: {kvmatch, line('$1'), '$1', '$3'}.
kv_items -> kv_item: ['$1'].
kv_items -> kv_item sep: ['$1'].
kv_items -> kv_item sep kv_items: ['$1'|'$3'].
attrs -> attr : ['$1'].
attrs -> attr attrs : ['$1'|'$2'].
attrs -> attr nl attrs : ['$1'|'$3'].
attr -> at path : make_attr(line('$1'), '$2', noparams, noresult).
attr -> at path arrow e_bool : make_attr(line('$1'), '$2', noparams, '$4').
attr -> at path open seq_items close : make_attr(line('$1'), '$2', '$4', noresult).
attr -> at path open seq_items close arrow e_bool : make_attr(line('$1'), '$2', '$4', '$7').
e_call -> path open close : {expr, line('$2'), call, {'$1', []}}.
e_call -> path open seq_items close : {expr, line('$2'), call, {'$1', '$3'}}.
e_call_do -> e_call larrow e_case end:
{expr, line('$2'), call_do, {last, '$1', expr_raw('$3', fn)}}.
e_call_do -> e_call larrowend e_case end:
{expr, line('$2'), call_do, {first, '$1', expr_raw('$3', fn)}}.
e_call_thread -> literal e_call_thread_funs : {expr, line('$1'), call_thread, {'$1', '$2'}}.
e_call_thread_funs -> arrow e_call : [{first, '$2'}].
e_call_thread_funs -> arrowend e_call : [{last, '$2'}].
e_call_thread_funs -> arrow e_call e_call_thread_funs : [{first, '$2'}|'$3'].
e_call_thread_funs -> arrowend e_call e_call_thread_funs : [{last, '$2'}|'$3'].
e_send -> literal send_op expr : op('$2', '$1', '$3').
e_send -> e_assign : '$1'.
% can't chain assignments a = b = c, this is to simplify the parser and why
% woud you make that is that or you have to wrap the right side in parenthesis
% if it's an expression, which is much more common
e_assign -> e_bool assign expr : op('$2', '$1', '$3').
e_assign -> e_bool : '$1'.
Erlang code.
unwrap({_,V}) -> V;
unwrap({_,_,V}) -> V;
unwrap(V) -> ct:print("WAT ~p", [V]).
line(T) when is_tuple(T) -> element(2, T);
line([H|_T]) -> element(2, H);
line(T) -> ct:print("WAT ~p", [T]).
value(Val, Type) -> {val, line(Val), Type, unwrap(Val)}.
expr_raw(Val, Type) -> {expr, line(Val), Type, Val}.
seq_value(Val, Line, Type) -> {seq, Line, Type, Val}.
make_attr(Line, Path, Params, Result) ->
{attr, Line, Path, Params, Result}.
op(Op, Left, Right) ->
{op, line(Op), unwrap(Op), Left, Right}.
unary_op(Op, Val) ->
{unary_op, line(Op), unwrap(Op), Val}.