Skip to content

Commit

Permalink
interemediate commit
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexanderSLoburev committed Jan 8, 2024
1 parent 50d70c4 commit 7d6166d
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 65 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"cSpell.words": [
"paren"
"paren",
"Prec"
]
}
Binary file modified build/shunting_yard_algorithm.beam
Binary file not shown.
61 changes: 1 addition & 60 deletions common/tokenizer.erl
Original file line number Diff line number Diff line change
@@ -1,65 +1,6 @@
-module(tokenizer).
-export([tokenize/1]).

% Operators = [
% {"+", add, 5, left},
% {"-", subtr, 5, left},
% {"*", mult, 4, left},
% {"/", float_div, 4, left},
% {"//", int_div, 4, left},
% {"%", mod, 4, left},
% {"**", exp, 3, right},
% {"+", unary_plus, 2, right},
% {"-", unary_minus, 2, right},
% {"(", left_paren, 1, none},
% {")", right_paren, 1, none}
% ],


% '_read_number_string'([], Buffer, Length) -> {[], lists:reverse(Buffer), Length};

% '_read_number_string'(Expression, Buffer, Length) ->
% [FirstChar | RestChars] = Expression,
% case utils:is_digit(FirstChar) or (FirstChar =:= $.) of
% true -> '_read_number_string'(RestChars, [FirstChar | Buffer], Length + 1);
% false ->
% case utils:is_whitespace(FirstChar) of
% true -> {RestChars, lists:reverse(Buffer), Length + 1};
% false -> {Expression, lists:reverse(Buffer), Length}
% end
% end.

% read_number_string(Expression) -> '_read_number_string'(Expression, [], 0).


% '_read_operator_string'([], Buffer, Length) -> {[], lists:reverse(Buffer), Length};

% '_read_operator_string'(Expression, Buffer, Length) ->
% [FirstChar | RestChars] = Expression,
% case utils:is_digit(FirstChar) of
% true -> {Expression, lists:reverse(Buffer), Length};
% false ->
% case utils:is_whitespace(FirstChar) of
% true -> {RestChars, lists:reverse(Buffer), Length + 1};
% false -> '_read_operator_string'(RestChars, [FirstChar | Buffer], Length + 1)
% end
% end.

% read_operator_string(Expression) -> '_read_operator_string'(Expression, [], 0).


% '_tokenize'([], Tokens, _Position) -> Tokens;

% '_tokenize'(Expression, Tokens, Position) ->
% {RestCharsAfterReadingNumber, NumberBuffer, LengthOfNumber} = read_number_string(Expression),
% case LengthOfNumber =/= 0 of
% true -> '_tokenize'(RestCharsAfterReadingNumber, [{NumberBuffer, Position} | Tokens], Position + LengthOfNumber);
% false ->
% {RestCharsAfterReadingOperator, OperatorBuffer, LengthOfOperator} = read_operator_string(Expression),
% '_tokenize'(RestCharsAfterReadingOperator, [{OperatorBuffer, Position} | Tokens], Position + LengthOfOperator)
% end.

% tokenize(Expression) -> lists:reverse('_tokenize'(Expression, [], 1)).

% TOKEN_SPEC=[{TokenType, TokenRegexp}]
match(_Expression, []) -> throw({parse_error, _Expression});
Expand All @@ -75,7 +16,7 @@ match(Expression, TokenSpec) ->
'_tokenize'([], Tokens, _Position, _TokenSpec) -> lists:reverse(Tokens);

'_tokenize'(Expression, Tokens, Position, TokenSpec) ->
{TokenType, Token} = try
{TokenType, Token} = try
match(Expression, TokenSpec)
catch
throw:{parse_error, Message} ->
Expand Down
22 changes: 18 additions & 4 deletions common/utils.erl
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@
is_whitespace/1,
re_escape/1,
identity/1,
ifelse/3
ifelse/3,
unzip4/1
]).


try_parse_number(String) ->
case io_lib:fread("~d", String) of
{ok, [Value], _} -> Value;
{error, _} -> String
case string:to_float(String) of
{Float, Rest} ->
case Rest =:= "" of
true -> {value, Float};
false -> {error, no_float}
end;
{error, no_float} -> {error, no_float}
end.


Expand All @@ -35,3 +40,12 @@ ifelse(Condition, TrueResult, FalseResult) ->
true -> TrueResult;
false -> FalseResult
end.


'_unzip4'([], {Acc1, Acc2, Acc3, Acc4}) ->
{lists:reverse(Acc1), lists:reverse(Acc2), lists:reverse(Acc3), lists:reverse(Acc4)};

'_unzip4'([{Value1, Value2, Value3, Value4} | Rest], {Acc1, Acc2, Acc3, Acc4}) ->
'_unzip4'(Rest, {[Value1 | Acc1], [Value2 | Acc2], [Value3 | Acc3], [Value4 | Acc4]}).

unzip4(ListOfTuples) -> '_unzip4'(ListOfTuples, {[], [], [], []}).
85 changes: 85 additions & 0 deletions shunting_yard_algorithm/src/shunting_yard_algorithm.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,90 @@
-export([start/0]).


process_binary_operator(Op, Operand1, Operand2) ->
case Op of
"+" -> Operand1 + Operand2;
"-" -> Operand1 - Operand2;
"*" -> Operand1 * Operand2;
"/" -> Operand1 / Operand2;
"//" ->
case is_integer(Operand1) and is_integer(Operand2) of
true -> Operand1 div Operand2;
false -> throw({syntax_error, Op, Operand1, Operand2})
end;
"%" ->
case is_integer(Operand1) and is_integer(Operand2) of
true -> Operand1 rem Operand2;
false -> throw({syntax_error, Op, Operand1, Operand2})
end;
"**" -> math:pow(Operand1, Operand2);
_WrongOp -> throw({syntax_error, Op, Operand1, Operand2})
end.


choose_operator(Op1Value, Op1Prec, Op1Assoc, Op2Value, Op2Prec) ->
utils:ifelse(
(Op1Value =/= "(") and ((Op2Prec > Op1Prec) or ((Op2Prec =:= Op1Prec) and (Op1Assoc =:= left)))
, Op1Value, Op2Value).


% {
% Op: {operator, Name, Value, Prec, Assoc, Arity}
% }
process_operators(Op1Spec, OpSpecs, OpStack, NumStack) ->
{operator, _Op1Name, Op1Value, Op1Prec, Op1Assoc, _Op1Arity} = Op1Spec,
Op2Spec = dict:find(stack:peek(OpStack), OpStack),
{operator, _Op2Name, Op2Value, Op2Prec, _Op2Assoc, _Op2Arity} = Op2Spec,
case choose_operator(Op1Value, Op1Prec, Op1Assoc, Op2Value, Op2Prec) =:= Op2Value of
true ->
process_operator(Op2Spec),
process_operators(Op1Spec, OpSpecs, OpStack, NumStack);
false -> none
end.


is_fun(Token, OpSpecs) ->
case dict:take(Token, OpSpecs) of
error -> false;
{operator, _Name, Value, _Prec, _Assoc, _Arity} -> is_function(Value).


run_process_operators(Op1, OpSpecs, OpStack, NumStack) ->
Op1Spec = dict:find(Op1, OpStack),
case not is_fun(Op1, OpSpecs) of
true ->
Op2Spec = dict:find(stack:peek(OpStack), OpStack),
process_operators();
false -> none
end,
stack:push(Op1, OpStack).


'_handle_token'(Token, OpSpecs, OpStack, NumStack) ->
% Check if the token is a number
case utils:try_parse_number(Token) of
{value, Value} -> stack:push(Value, NumStack);
{error, no_float} ->
case Token of
"(" -> stack:push("(", OpStack);
")" -> process_closing_paren();
Op -> run_process_operators(Op, OpSpecs, OpStack, NumStack)
end
end.


% '_handle_token'(Token, FunctionSpecs, OpSpecs, OpStack, NumStack) ->
% case utils:try_parse_number(Token) of
% ProcessingToken when is_number(ProcessingToken) -> stack:push(ProcessingToken, OpStack);
% ProcessingToken ->
% case lists:member(ProcessingToken, FunctionNames) of
% true -> stack:push(list_to_atom(ProcessingToken), OpStack);
% false ->
% OpSpec = dict:find(ProcessingToken, OpSpecs),
% case OpSpec of
% {Prec, Assoc, Arity} ->
% apply_operators(Op, OpSpec, OpStack, NumStack, OpSpecs)


start() ->
io:fwrite("Hello world!~n").

0 comments on commit 7d6166d

Please sign in to comment.