22
22
! * Copyright (c) 2017, Jacob Williams. All rights reserved.
23
23
! * This software is distributable under the BSD license. See the terms of the
24
24
! BSD license in the documentation provided with this software.
25
- !
26
- ! ### Function string syntax
27
- !
28
- ! Although they have to be passed as array elements of the same declared
29
- ! length (Fortran restriction), the variable names can be of arbitrary
30
- ! actual length for the parser. Parsing for variables can be case sensitive
31
- ! or insensitive, depanding on input flag to the parser function.
32
- !
33
- ! The syntax of the function string is similar to the Fortran convention.
34
- ! Mathematical Operators recognized are `+`, `-,` `*,` `/,` `**` or alternatively `^`,
35
- ! whereas symbols for brackets must be `()`.
36
- !
37
- ! The function parser recognizes the (single argument) Fortran 90 intrinsic
38
- ! functions `abs`, `exp`, `log10`, `log`, `sqrt`, `sinh`, `cosh`, `tanh`,
39
- ! `sin`, `cos`, `tan`, `asin`, `acos`, `atan`.
40
- ! Parsing for intrinsic functions is always case INsensitive.
41
- !
42
- ! Operations are evaluated in the correct order:
43
- !
44
- ! * `() ` expressions in brackets first
45
- ! * `-A ` unary minus (or plus)
46
- ! * `A**B A^B` exponentiation (`A` raised to the power `B`)
47
- ! * `A*B A/B` multiplication and division
48
- ! * `A+B A-B` addition and subtraction
49
- !
50
- ! The function string can contain integer or real constants. To be recognized
51
- ! as explicit constants these must conform to the format:
52
- !
53
- ! `[+|-][nnn][.nnn][e|E|d|D[+|-]nnn]`
54
- !
55
- ! where `nnn` means any number of digits. The mantissa must contain at least
56
- ! one digit before or following an optional decimal point. Valid exponent
57
- ! identifiers are 'e', 'E', 'd' or 'D'. If they appear they must be followed
58
- ! by a valid exponent.
59
25
60
26
module function_parser
61
27
@@ -125,12 +91,13 @@ module function_parser
125
91
integer ,parameter :: error_asin_arg_illegal = 4
126
92
integer ,parameter :: error_acos_arg_illegal = 5
127
93
integer ,parameter :: error_invalid_operation = 6
128
- character (len= 25 ),dimension (6 ),parameter :: error_messages = [ ' Division by zero ' , & ! 1
129
- ' Argument of SQRT negative' , & ! 2
130
- ' Argument of LOG negative ' , & ! 3
131
- ' Argument of ASIN illegal ' , & ! 4
132
- ' Argument of ACOS illegal ' , & ! 5
133
- ' Invalid operation ' ]
94
+ character (len= 25 ),dimension (6 ),parameter :: error_messages = &
95
+ [ ' Division by zero ' , & ! 1
96
+ ' Argument of SQRT negative' , & ! 2
97
+ ' Argument of LOG negative ' , & ! 3
98
+ ' Argument of ASIN illegal ' , & ! 4
99
+ ' Argument of ACOS illegal ' , & ! 5
100
+ ' Invalid operation ' ]
134
101
135
102
type stack_func_container
136
103
! ! to create an array of the function pointers in the fparser
@@ -253,7 +220,7 @@ subroutine parse_function (me, funcstr, var, case_sensitive, error_msg)
253
220
character (len=* ),intent (in ) :: funcstr ! ! function string
254
221
character (len=* ), dimension (:), intent (in ) :: var ! ! array with variable names
255
222
logical ,intent (in ) :: case_sensitive ! ! are the variables case sensitive?
256
- type (list_of_errors),intent (out ) :: error_msg ! ! list of error messages
223
+ type (list_of_errors),intent (out ) :: error_msg ! ! list of error messages
257
224
258
225
character (len= len (funcstr)) :: func ! ! function string, local use
259
226
character (len= len (var)),dimension (size (var)) :: tmp_var ! ! variable list, local use
@@ -292,7 +259,7 @@ subroutine evaluate_function (me, val, res, error_msg)
292
259
293
260
class(fparser),intent (inout ) :: me
294
261
real (wp), dimension (:), intent (in ) :: val ! ! variable values
295
- type (list_of_errors),intent (out ) :: error_msg ! ! error message list
262
+ type (list_of_errors),intent (out ) :: error_msg ! ! error message list
296
263
real (wp),intent (out ) :: res ! ! result
297
264
298
265
integer :: ip ! ! instruction pointer
@@ -332,7 +299,7 @@ subroutine parse_function_array (me, funcstr, var, case_sensitive, error_msg)
332
299
character (len=* ),dimension (:),intent (in ) :: funcstr ! ! function string array
333
300
character (len=* ),dimension (:),intent (in ) :: var ! ! array with variable names
334
301
logical ,intent (in ) :: case_sensitive ! ! are the variables case sensitive?
335
- type (list_of_errors),intent (out ) :: error_msg ! ! list of error messages
302
+ type (list_of_errors),intent (out ) :: error_msg ! ! list of error messages
336
303
337
304
integer :: i ! ! counter
338
305
integer :: n_funcs ! ! number of functions in the class
@@ -361,7 +328,7 @@ subroutine evaluate_function_array (me, val, res, error_msg)
361
328
362
329
class(fparser_array),intent (inout ) :: me
363
330
real (wp), dimension (:), intent (in ) :: val ! ! variable values
364
- type (list_of_errors),intent (out ) :: error_msg ! ! error message list
331
+ type (list_of_errors),intent (out ) :: error_msg ! ! error message list
365
332
real (wp),dimension (:),intent (out ) :: res ! ! result. Should be `size(me%f)`
366
333
367
334
integer :: i ! ! counter
@@ -889,7 +856,7 @@ subroutine check_syntax (func,funcstr,var,ipos,error_msg)
889
856
character (len=* ),intent (in ) :: funcstr ! ! original function string
890
857
character (len=* ), dimension (:),intent (in ) :: var ! ! array with variable names
891
858
integer ,dimension (:),intent (in ) :: ipos
892
- type (list_of_errors),intent (inout ) :: error_msg ! ! list of error messages
859
+ type (list_of_errors),intent (inout ) :: error_msg ! ! list of error messages
893
860
894
861
integer :: n
895
862
character (len= 1 ) :: c
@@ -1031,7 +998,7 @@ subroutine add_error_message_to_list (j, ipos, funcstr, error_msg, msg)
1031
998
integer ,intent (in ) :: j
1032
999
integer ,dimension (:),intent (in ) :: ipos
1033
1000
character (len=* ),intent (in ) :: funcstr ! ! original function string
1034
- type (list_of_errors),intent (inout ) :: error_msg ! ! list of error messages
1001
+ type (list_of_errors),intent (inout ) :: error_msg ! ! list of error messages
1035
1002
character (len=* ),optional ,intent (in ) :: msg
1036
1003
1037
1004
character (len= :),allocatable :: tmp ! ! to indicate where on
@@ -1196,7 +1163,7 @@ end subroutine replace_string
1196
1163
1197
1164
! *******************************************************************************
1198
1165
! >
1199
- ! Compile function string F into bytecode
1166
+ ! Compile function string `f` into bytecode
1200
1167
!
1201
1168
! @note This is not very efficient since it is parsing it twice
1202
1169
! just to get the size of all the arrays.
@@ -1208,18 +1175,17 @@ subroutine compile (me, f, var, error_msg)
1208
1175
class(fparser),intent (inout ) :: me
1209
1176
character (len=* ),intent (in ) :: f ! ! function string
1210
1177
character (len=* ),dimension (:),intent (in ) :: var ! ! array with variable names
1211
- type (list_of_errors),intent (inout ) :: error_msg ! ! list of error messages
1212
-
1213
- integer :: istat
1178
+ type (list_of_errors),intent (inout ) :: error_msg ! ! list of error messages
1214
1179
1215
- if ( allocated (me % bytecode)) deallocate ( me % bytecode,me % immed,me % stack,me % bytecode_ops )
1180
+ integer :: istat ! ! allocation status flag
1216
1181
1217
1182
me% bytecodesize = 0
1218
1183
me% immedsize = 0
1219
1184
me% stacksize = 0
1220
1185
me% stackptr = 0
1221
1186
1222
- call compile_substr (me,f,1 ,len_trim (f),var) ! compile string to determine size
1187
+ ! compile string to determine size:
1188
+ call compile_substr (me,f,1 ,len_trim (f),var)
1223
1189
1224
1190
allocate ( me% bytecode(me% bytecodesize), &
1225
1191
me% bytecode_ops(me% bytecodesize), &
@@ -1445,10 +1411,10 @@ end subroutine compile_substr
1445
1411
1446
1412
! *******************************************************************************
1447
1413
! >
1448
- ! Check if operator `F (j:j)` in string `F ` is binary operator.
1414
+ ! Check if operator `f (j:j)` in string `f ` is binary operator.
1449
1415
!
1450
1416
! Special cases already covered elsewhere: (that is corrected in v1.1)
1451
- ! * operator character `F (j:j)` is first character of string (`j=1`)
1417
+ ! * operator character `f (j:j)` is first character of string (`j=1`)
1452
1418
1453
1419
function is_binary_operator (j , f ) result (res)
1454
1420
@@ -1465,7 +1431,7 @@ function is_binary_operator (j, f) result (res)
1465
1431
if (f(j:j) == ' +' .or. f(j:j) == ' -' ) then ! plus or minus sign:
1466
1432
if (j == 1 ) then ! - leading unary operator ?
1467
1433
res = .false.
1468
- elseif (scan (f(j-1 :j-1 ),' +-*/^(' ) > 0 ) then ! - other unary operator ?
1434
+ elseif (scan (f(j-1 :j-1 ),' +-*/^(' ) > 0 ) then ! - other unary operator ?
1469
1435
res = .false.
1470
1436
elseif (scan (f(j+1 :j+1 ),' 0123456789' ) > 0 .and. & ! - in exponent of real number ?
1471
1437
scan (f(j-1 :j-1 ),' eEdD' ) > 0 ) then
0 commit comments