Skip to content

Commit dd573c9

Browse files
author
José Valim
committed
Initial work cleaning up op table
1 parent 58ee415 commit dd573c9

File tree

4 files changed

+96
-68
lines changed

4 files changed

+96
-68
lines changed

lib/elixir/lib/macro.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ defmodule Macro do
1717
:<, :>, :->,
1818
:+, :-, :*, :/, :=, :|, :.,
1919
:and, :or, :xor, :when, :in, :inlist, :inbits,
20-
:<<<, :>>>, :|||, :&&&, :^^^, :~~~
20+
:<<<, :>>>, :|||, :&&&, :^^^
2121
]
2222
end
2323

@@ -26,7 +26,7 @@ defmodule Macro do
2626
as a macro so it can be used in guard clauses.
2727
"""
2828
defmacro unary_ops do
29-
[:!, :@, :^, :not, :+, :-]
29+
[:!, :@, :^, :not, :+, :-, :~~~, :&]
3030
end
3131

3232
@doc """

lib/elixir/src/elixir_parser.yrl

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ Nonterminals
22
grammar expr_list
33
expr paren_expr block_expr fn_expr bracket_expr call_expr bracket_at_expr max_expr
44
base_expr matched_expr matched_op_expr unmatched_expr op_expr
5-
add_op mult_op unary_op two_op regex_op right_op bin_concat_op
5+
mult_op two_op regex_op right_op bin_concat_op
66
match_op send_op default_op when_op pipe_op in_op inc_op range_op
7-
andand_op oror_op and_op or_op comp_expr_op colon_colon_op three_op at_op
7+
andand_op oror_op and_op or_op colon_colon_op three_op
8+
comp_op_eol at_op_eol unary_op_eol dual_op_eol
89
open_paren close_paren empty_paren
910
open_bracket close_bracket
1011
open_curly close_curly
@@ -26,13 +27,14 @@ Terminals
2627
bracket_identifier paren_identifier do_identifier block_identifier
2728
fn 'end' aliases
2829
number signed_number atom bin_string list_string sigil
29-
dot_call_op comp_op op_identifier
30+
dot_call_op op_identifier
31+
comp_op at_op unary_op dual_op
3032
'not' 'and' 'or' 'xor' 'when' 'in' 'inlist' 'inbits' 'do'
3133
'true' 'false' 'nil'
32-
'=' '+' '-' '*' '/' '++' '--' '**' '//'
34+
'=' '*' '/' '++' '--' '**' '//'
3335
'(' ')' '[' ']' '{' '}' '<<' '>>' '::'
34-
eol ',' '&' '|' '.' '^' '@' '<-' '<>' '->' '|>' '=~'
35-
'&&' '||' '!' '...' '..'
36+
eol ',' '&' '|' '.' '<-' '<>' '->' '|>' '=~'
37+
'&&' '||' '...' '..'
3638
'<<<' '>>>' '&&&' '|||' '^^^' '~~~'
3739
.
3840

@@ -52,20 +54,20 @@ Left 120 oror_op.
5254
Left 130 andand_op.
5355
Left 140 or_op.
5456
Left 150 and_op.
55-
Left 160 comp_expr_op.
57+
Left 160 comp_op_eol.
5658
Left 170 in_op.
5759
Right 180 regex_op.
5860
Right 190 right_op.
5961
Left 200 range_op.
6062
Left 210 three_op.
61-
Left 220 add_op.
63+
Left 220 dual_op_eol. %% +, -
6264
Left 230 mult_op.
6365
Right 240 bin_concat_op.
6466
Right 250 two_op.
65-
Nonassoc 300 unary_op.
67+
Nonassoc 300 unary_op_eol. %% +, -, !, ^
6668
Left 310 dot_call_op.
6769
Left 310 dot_op.
68-
Nonassoc 320 at_op.
70+
Nonassoc 320 at_op_eol. %% @<op>
6971
Nonassoc 330 var.
7072

7173
%%% MAIN FLOW OF EXPRESSIONS
@@ -89,19 +91,19 @@ expr -> matched_expr : '$1'.
8991
expr -> unmatched_expr : '$1'.
9092

9193
matched_expr -> matched_expr matched_op_expr : build_op(element(1, '$2'), '$1', element(2, '$2')).
92-
matched_expr -> unary_op matched_expr : build_unary_op('$1', '$2').
93-
matched_expr -> at_op matched_expr : build_unary_op('$1', '$2').
94+
matched_expr -> unary_op_eol matched_expr : build_unary_op('$1', '$2').
95+
matched_expr -> at_op_eol matched_expr : build_unary_op('$1', '$2').
9496
matched_expr -> bracket_at_expr : '$1'.
9597
matched_expr -> fn_expr : '$1'.
9698

9799
unmatched_expr -> matched_expr op_expr : build_op(element(1, '$2'), '$1', element(2, '$2')).
98100
unmatched_expr -> unmatched_expr op_expr : build_op(element(1, '$2'), '$1', element(2, '$2')).
99-
unmatched_expr -> unary_op expr : build_unary_op('$1', '$2').
100-
unmatched_expr -> at_op expr : build_unary_op('$1', '$2').
101+
unmatched_expr -> unary_op_eol expr : build_unary_op('$1', '$2').
102+
unmatched_expr -> at_op_eol expr : build_unary_op('$1', '$2').
101103
unmatched_expr -> block_expr : '$1'.
102104

103105
op_expr -> match_op expr : { '$1', '$2' }.
104-
op_expr -> add_op expr : { '$1', '$2' }.
106+
op_expr -> dual_op_eol expr : { '$1', '$2' }.
105107
op_expr -> mult_op expr : { '$1', '$2' }.
106108
op_expr -> two_op expr : { '$1', '$2' }.
107109
op_expr -> regex_op expr : { '$1', '$2' }.
@@ -120,10 +122,10 @@ op_expr -> send_op expr : { '$1', '$2' }.
120122
op_expr -> range_op expr : { '$1', '$2' }.
121123
op_expr -> default_op expr : { '$1', '$2' }.
122124
op_expr -> colon_colon_op expr : { '$1', '$2' }.
123-
op_expr -> comp_expr_op expr : { '$1', '$2' }.
125+
op_expr -> comp_op_eol expr : { '$1', '$2' }.
124126

125127
matched_op_expr -> match_op matched_expr : { '$1', '$2' }.
126-
matched_op_expr -> add_op matched_expr : { '$1', '$2' }.
128+
matched_op_expr -> dual_op_eol matched_expr : { '$1', '$2' }.
127129
matched_op_expr -> mult_op matched_expr : { '$1', '$2' }.
128130
matched_op_expr -> two_op matched_expr : { '$1', '$2' }.
129131
matched_op_expr -> regex_op matched_expr : { '$1', '$2' }.
@@ -142,7 +144,7 @@ matched_op_expr -> send_op matched_expr : { '$1', '$2' }.
142144
matched_op_expr -> range_op matched_expr : { '$1', '$2' }.
143145
matched_op_expr -> default_op matched_expr : { '$1', '$2' }.
144146
matched_op_expr -> colon_colon_op matched_expr : { '$1', '$2' }.
145-
matched_op_expr -> comp_expr_op matched_expr : { '$1', '$2' }.
147+
matched_op_expr -> comp_op_eol matched_expr : { '$1', '$2' }.
146148

147149
block_expr -> parens_call call_args_parens do_block : build_identifier('$1', '$2' ++ '$3').
148150
block_expr -> parens_call call_args_parens call_args_parens do_block : build_nested_parens('$1', '$2', '$3' ++ '$4').
@@ -171,9 +173,12 @@ max_expr -> open_paren stab close_paren : build_stab(lists:reverse('$2')).
171173
bracket_expr -> dot_bracket_identifier bracket_access : build_access(build_identifier('$1', nil), '$2').
172174
bracket_expr -> max_expr bracket_access : build_access('$1', '$2').
173175

174-
bracket_at_expr -> at_op dot_bracket_identifier bracket_access : build_access(build_unary_op('$1', build_identifier('$2', nil)), '$3').
175-
bracket_at_expr -> at_op max_expr bracket_access : build_access(build_unary_op('$1', '$2'), '$3').
176-
bracket_at_expr -> bracket_at_expr bracket_access : build_access('$1', '$2').
176+
bracket_at_expr -> at_op_eol dot_bracket_identifier bracket_access :
177+
build_access(build_unary_op('$1', build_identifier('$2', nil)), '$3').
178+
bracket_at_expr -> at_op_eol max_expr bracket_access :
179+
build_access(build_unary_op('$1', '$2'), '$3').
180+
bracket_at_expr -> bracket_at_expr bracket_access :
181+
build_access('$1', '$2').
177182

178183
base_expr -> number : ?exprs('$1').
179184
base_expr -> signed_number : { element(4, '$1'), [{line,?line('$1')}], ?exprs('$1') }.
@@ -262,10 +267,8 @@ close_curly -> eol '}' : '$2'.
262267

263268
% Operators
264269

265-
add_op -> '+' : '$1'.
266-
add_op -> '-' : '$1'.
267-
add_op -> '+' eol : '$1'.
268-
add_op -> '-' eol : '$1'.
270+
dual_op_eol -> dual_op : '$1'.
271+
dual_op_eol -> dual_op eol : '$1'.
269272

270273
mult_op -> '*' : '$1'.
271274
mult_op -> '/' : '$1'.
@@ -302,21 +305,14 @@ default_op -> '//' eol : '$1'.
302305
colon_colon_op -> '::' : '$1'.
303306
colon_colon_op -> '::' eol : '$1'.
304307

305-
unary_op -> '+' : '$1'.
306-
unary_op -> '+' eol : '$1'.
307-
unary_op -> '-' : '$1'.
308-
unary_op -> '-' eol : '$1'.
309-
unary_op -> '!' : '$1'.
310-
unary_op -> '!' eol : '$1'.
311-
unary_op -> '^' : '$1'.
312-
unary_op -> '^' eol : '$1'.
313-
unary_op -> 'not' : '$1'.
314-
unary_op -> 'not' eol : '$1'.
315-
unary_op -> '~~~' : '$1'.
316-
unary_op -> '~~~' eol : '$1'.
317-
318-
at_op -> '@' : '$1'.
319-
at_op -> '@' eol : '$1'.
308+
unary_op_eol -> unary_op : '$1'.
309+
unary_op_eol -> unary_op eol : '$1'.
310+
unary_op_eol -> dual_op : '$1'.
311+
unary_op_eol -> dual_op eol : '$1'.
312+
unary_op_eol -> 'not' : '$1'.
313+
unary_op_eol -> 'not' eol : '$1'.
314+
unary_op_eol -> '~~~' : '$1'.
315+
unary_op_eol -> '~~~' eol : '$1'.
320316

321317
match_op -> '=' : '$1'.
322318
match_op -> '=' eol : '$1'.
@@ -361,8 +357,11 @@ send_op -> '<-' eol : '$1'.
361357
range_op -> '..' : '$1'.
362358
range_op -> '..' eol : '$1'.
363359

364-
comp_expr_op -> comp_op : '$1'.
365-
comp_expr_op -> comp_op eol : '$1'.
360+
at_op_eol -> at_op : '$1'.
361+
at_op_eol -> at_op eol : '$1'.
362+
363+
comp_op_eol -> comp_op : '$1'.
364+
comp_op_eol -> comp_op eol : '$1'.
366365

367366
% Dot operator
368367

@@ -483,15 +482,18 @@ Erlang code.
483482

484483
%% Operators
485484

486-
build_op({ _, _, _ } = Op, Left, Right) ->
487-
{ ?exprs(Op), [{line,?line(Op)}], [Left, Right] };
485+
build_op({ _, Line, Op }, Left, Right) ->
486+
build_op({ Op, Line }, Left, Right);
488487

489488
build_op({ BOp, Line }, { UOp, _, [Left] }, Right) when ?rearrange_bop(BOp), ?rearrange_uop(UOp) ->
490489
{ UOp, [{line,Line}], [{ BOp, [{line,Line}], [Left, Right] }] };
491490

492491
build_op(Op, Left, Right) ->
493492
{ ?op(Op), [{line,?line(Op)}], [Left, Right] }.
494493

494+
build_unary_op({ _Kind, Line, Op }, Expr) ->
495+
{ Op, [{line,Line}], [Expr] };
496+
495497
build_unary_op(Op, Expr) ->
496498
{ ?op(Op), [{line,?line(Op)}], [Expr] }.
497499

lib/elixir/src/elixir_tokenizer.erl

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,24 @@
5959
).
6060

6161
-define(op1(T),
62-
T == $+;
63-
T == $-;
6462
T == $*;
6563
T == $/;
6664
T == $=;
67-
T == $|;
68-
T == $!;
69-
T == $^;
70-
T == $@
65+
T == $|
7166
).
7267

68+
%% New ops table
69+
70+
-define(at_op(T),
71+
T == $@).
72+
73+
-define(dual_op(T),
74+
T == $+ orelse T == $-).
75+
7376
-define(unary_op(T),
74-
T == '+';
75-
T == '-';
76-
T == '@';
77-
T == '!';
78-
T == '^'
77+
% T == $&;
78+
T == $!;
79+
T == $^
7980
).
8081

8182
tokenize(String, Line, Opts) ->
@@ -234,6 +235,9 @@ tokenize([$.,T1,T2|Rest], Line, Scope, Tokens) when ?comp2(T1, T2); ?op2(T1, T2)
234235
handle_call_identifier(Rest, Line, list_to_atom([T1, T2]), Scope, Tokens);
235236

236237
% ## Single Token Operators
238+
tokenize([$.,T|Rest], Line, Scope, Tokens) when ?at_op(T); ?unary_op(T); ?dual_op(T) ->
239+
handle_call_identifier(Rest, Line, list_to_atom([T]), Scope, Tokens);
240+
237241
tokenize([$.,T|Rest], Line, Scope, Tokens) when ?comp1(T); ?op1(T); T == $& ->
238242
handle_call_identifier(Rest, Line, list_to_atom([T]), Scope, Tokens);
239243

@@ -307,6 +311,10 @@ tokenize([$:,T1,T2|Rest], Line, Scope, Tokens) when ?comp2(T1, T2); ?op2(T1, T2)
307311
tokenize(Rest, Line, Scope, [{ atom, Line, list_to_atom([T1,T2]) }|Tokens]);
308312

309313
% ## Single Token Operators
314+
315+
tokenize([$:,T|Rest], Line, Scope, Tokens) when ?at_op(T); ?unary_op(T); ?dual_op(T) ->
316+
tokenize(Rest, Line, Scope, [{ atom, Line, list_to_atom([T]) }|Tokens]);
317+
310318
tokenize([$:,T|Rest], Line, Scope, Tokens) when ?comp1(T); ?op1(T); T == $&; T == $. ->
311319
tokenize(Rest, Line, Scope, [{ atom, Line, list_to_atom([T]) }|Tokens]);
312320

@@ -367,6 +375,15 @@ tokenize([T|Rest], Line, Scope, Tokens) when ?comp1(T) ->
367375
handle_comp_op(Rest, Line, list_to_atom([T]), Scope, Tokens);
368376

369377
% ## Single Token Operators
378+
tokenize([T|Rest], Line, Scope, Tokens) when ?at_op(T) ->
379+
handle_unary_op(Rest, Line, at_op, list_to_atom([T]), Scope, Tokens);
380+
381+
tokenize([T|Rest], Line, Scope, Tokens) when ?unary_op(T) ->
382+
handle_unary_op(Rest, Line, unary_op, list_to_atom([T]), Scope, Tokens);
383+
384+
tokenize([T|Rest], Line, Scope, Tokens) when ?dual_op(T) ->
385+
handle_unary_op(Rest, Line, dual_op, list_to_atom([T]), Scope, Tokens);
386+
370387
tokenize([T|Rest], Line, Scope, Tokens) when ?op1(T) ->
371388
handle_op(Rest, Line, list_to_atom([T]), Scope, Tokens);
372389

@@ -410,13 +427,13 @@ tokenize([H|_] = String, Line, Scope, Tokens) when ?is_downcase(H); H == $_ ->
410427
% Ambiguous unary/binary operators tokens
411428

412429
tokenize([Space, Sign, NotMarker|T], Line, Scope, [{ Identifier, _, _ } = H|Tokens]) when
413-
Sign == $+ orelse Sign == $-,
414-
?is_horizontal_space(Space),
415-
not(?is_space(NotMarker)),
416-
NotMarker /= $(, NotMarker /= $+, NotMarker /= $-, NotMarker /= $>,
417-
Identifier == identifier orelse Identifier == punctuated_identifier ->
430+
?dual_op(Sign),
431+
?is_horizontal_space(Space),
432+
not(?is_space(NotMarker)),
433+
NotMarker /= $(, NotMarker /= $+, NotMarker /= $-, NotMarker /= $>,
434+
Identifier == identifier orelse Identifier == punctuated_identifier ->
418435
Rest = [NotMarker|T],
419-
tokenize(Rest, Line, Scope, [{ list_to_atom([Sign]), Line }, setelement(1, H, op_identifier)|Tokens]);
436+
tokenize(Rest, Line, Scope, [{ dual_op, Line, list_to_atom([Sign]) }, setelement(1, H, op_identifier)|Tokens]);
420437

421438
% Spaces
422439

@@ -471,12 +488,21 @@ handle_comp_op(Rest, Line, Op, Scope, Tokens) ->
471488
handle_op([$:|Rest], Line, Op, Scope, Tokens) when ?is_space(hd(Rest)) ->
472489
tokenize(Rest, Line, Scope, [{ kw_identifier, Line, Op }|Tokens]);
473490

474-
handle_op(Rest, Line, Op, Scope, Tokens) when ?unary_op(Op) ->
475-
tokenize(Rest, Line, Scope, [{ Op, Line }|Tokens]);
476-
477491
handle_op(Rest, Line, Op, Scope, Tokens) ->
478492
tokenize(Rest, Line, Scope, add_token_with_nl({ Op, Line }, Tokens)).
479493

494+
handle_unary_op([$:|Rest], Line, _Kind, Op, Scope, Tokens) when ?is_space(hd(Rest)) ->
495+
tokenize(Rest, Line, Scope, [{ kw_identifier, Line, Op }|Tokens]);
496+
497+
handle_unary_op(Rest, Line, Kind, Op, Scope, Tokens) ->
498+
tokenize(Rest, Line, Scope, [{ Kind, Line, Op }|Tokens]).
499+
500+
handle_op([$:|Rest], Line, _Kind, Op, Scope, Tokens) when ?is_space(hd(Rest)) ->
501+
tokenize(Rest, Line, Scope, [{ kw_identifier, Line, Op }|Tokens]);
502+
503+
handle_op(Rest, Line, Kind, Op, Scope, Tokens) ->
504+
tokenize(Rest, Line, Scope, add_token_with_nl({ Kind, Op, Line }, Tokens)).
505+
480506
handle_call_identifier(Rest, Line, Op, Scope, Tokens) ->
481507
Token = check_call_identifier(identifier, Line, Op, Rest),
482508
tokenize(Rest, Line, Scope, [Token|add_token_with_nl({ '.', Line }, Tokens)]).

lib/elixir/test/erlang/tokenizer_test.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ colon_colon_test() ->
1616
{')',1}] = tokenize("foo.::(3)").
1717

1818
arithmetic_test() ->
19-
[{number,1,1},{'+',1},{number,1,2},{'+',1},{number,1,3}] = tokenize("1 + 2 + 3").
19+
[{number,1,1},{dual_op,1,'+'},{number,1,2},{dual_op,1,'+'},{number,1,3}] = tokenize("1 + 2 + 3").
2020

2121
op_kw_test() ->
22-
[{atom,1,foo},{'+',1},{atom,1,bar}] = tokenize(":foo+:bar").
22+
[{atom,1,foo},{dual_op,1,'+'},{atom,1,bar}] = tokenize(":foo+:bar").
2323

2424
scientific_test() ->
2525
[{number, 1, 0.1}] = tokenize("1.0e-1").

0 commit comments

Comments
 (0)