-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patheval_math_expression_unit.pas
More file actions
118 lines (104 loc) · 2.01 KB
/
eval_math_expression_unit.pas
File metadata and controls
118 lines (104 loc) · 2.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
{
2 kyu
Evaluate mathematical expression
https://www.codewars.com/kata/52a78825cdfc2cfc87000005
}
unit eval_math_expression_unit;
{$mode objfpc}{$H+}
interface
function Calc(expression: string): double;
implementation
uses
Math,
SysUtils;
var
str: string;
pos: integer;
len: integer;
procedure SkipSpaces(); forward;
function ParseFactor(): double; forward;
function ParseTerm(): double; forward;
function ParseExpression(): double; forward;
procedure SkipSpaces();
begin
while (pos <= len) and (str[pos] <= ' ') do
Inc(pos);
end;
function ParseFactor(): double;
var
start: integer;
begin
SkipSpaces();
if (pos <= len) and (str[pos] = '-') then
begin
Inc(pos);
Exit(-ParseFactor());
end;
if (pos <= len) and (str[pos] = '(') then
begin
Inc(pos);
Result := ParseExpression();
SkipSpaces();
Inc(pos); // remove ')'
Exit(Result);
end;
start := pos;
while (pos <= len) and (((str[pos] >= '0') and (str[pos] <= '9')) or
(str[pos] = '.')) do
Inc(pos);
Result := StrToFloat(Copy(str, start, pos - start));
end;
function ParseTerm(): double;
var
op: char;
rhs: double;
begin
Result := ParseFactor();
while True do
begin
SkipSpaces();
if (pos <= len) and ((str[pos] = '*') or (str[pos] = '/')) then
begin
op := str[pos];
Inc(pos);
rhs := ParseFactor();
case op of
'*': Result *= rhs;
'/': Result /= rhs;
end;
end
else
Break;
end;
end;
function ParseExpression(): double;
var
op: char;
rhs: double;
begin
Result := ParseTerm();
while True do
begin
SkipSpaces();
if (pos <= len) and ((str[pos] = '+') or (str[pos] = '-')) then
begin
op := str[pos];
Inc(pos);
rhs := ParseTerm();
case op of
'+': Result += rhs;
'-': Result -= rhs;
end;
end
else
Break;
end;
end;
function Calc(expression: string): double;
begin
pos := 1;
str := expression;
len := Length(str);
Result := ParseExpression();
end;
end.