60 implicit none;
private
76 enumerator :: unknown = -1
77 enumerator :: number = 0
78 enumerator :: operation = 1
79 enumerator :: identifier = 2
80 enumerator :: parenthesis = 3
81 enumerator :: defined = 4
107 character(:),
allocatable ::
value
108 integer(tokens_enum) ::
type
144 module procedure :: strtol_default
145 module procedure :: strtol_with_base
162 character(*),
intent(in) :: expr
163 type(
token),
allocatable,
intent(out) :: tokens(:)
164 integer,
intent(out) :: ntokens
166 character(:),
allocatable :: temp
167 integer :: i, pos, len_expr
169 logical,
save :: in_comment
171 if (
allocated(tokens))
deallocate(tokens)
174 temp =
trim(adjustl(expr)) //
' '
179 do while (i <= len_expr)
180 if (temp(i:i) ==
' ')
then
186 if (.not. in_word)
then
187 ntokens = ntokens + 1
190 message=
'The maximum number of tokens has been reached', &
191 label=
label_type(
'Too many tokens in expression.', 1, 1)), &
198 if (temp(i:i) ==
'(' .or. temp(i:i) ==
')')
then
199 tokens(ntokens)%value = temp(i:i)
200 tokens(ntokens)%type = parenthesis
201 tokens(ntokens)%start = i
204 else if (temp(i:i + 1) ==
'&&' .or. temp(i:i + 1) ==
'||' .or. temp(i:i + 1) ==
'==' .or. &
205 temp(i:i + 1) ==
'!=' .or. temp(i:i + 1) ==
'<=' .or. temp(i:i + 1) ==
'>=')
then
206 tokens(ntokens)%value = temp(i:i + 1)
207 tokens(ntokens)%type = operation
208 tokens(ntokens)%start = i
211 else if (temp(i:i) ==
'!')
then
212 tokens(ntokens)%value = temp(i:i)
213 tokens(ntokens)%type = operation
214 tokens(ntokens)%start = i
217 else if (temp(i:i + 1) ==
'**')
then
218 tokens(ntokens)%value = temp(i:i + 1)
219 tokens(ntokens)%type = operation
220 tokens(ntokens)%start = i
223 else if (temp(i:i + 1) ==
'<<' .or. temp(i:i + 1) ==
'>>')
then
224 tokens(ntokens)%value = temp(i:i + 1)
225 tokens(ntokens)%type = operation
226 tokens(ntokens)%start = i
229 else if (temp(i:i) ==
'<' .or. temp(i:i) ==
'>' .or. temp(i:i) ==
'=' .or. &
230 temp(i:i) ==
'+' .or. temp(i:i) ==
'-' .or. temp(i:i) ==
'*' .or. &
231 temp(i:i) ==
'/' .or. temp(i:i) ==
'%' .or. &
232 temp(i:i) ==
'?' .or. temp(i:i) ==
':')
then
233 tokens(ntokens)%value = temp(i:i)
234 tokens(ntokens)%type = operation
235 tokens(ntokens)%start = i
238 else if (temp(i:i) ==
'&' .or. temp(i:i) ==
'|' .or. temp(i:i) ==
'^' .or. &
239 temp(i:i) ==
'~')
then
240 tokens(ntokens)%value = temp(i:i)
241 tokens(ntokens)%type = operation
242 tokens(ntokens)%start = i
247 do while (i <= len_expr .and. temp(i:i) ==
' ')
250 if (i <= len_expr .and. temp(i:i) ==
'(')
then
253 do while (pos <= len_expr .and. temp(pos:pos) /=
')')
256 tokens(ntokens)%value =
trim(adjustl(temp(i:pos - 1)))
257 tokens(ntokens)%type = defined
258 tokens(ntokens)%start = i
262 do while (pos <= len_expr .and. temp(pos:pos) /=
' ')
265 tokens(ntokens)%value =
trim(adjustl(temp(i:pos - 1)))
266 tokens(ntokens)%type = defined
267 tokens(ntokens)%start = i
271 else if (is_typeless(temp(i:), pos))
then
273 tokens(ntokens)%value =
trim(adjustl(temp(i:pos - 1)))
274 tokens(ntokens)%type = number
275 tokens(ntokens)%start = i
278 else if (is_digit(temp(i:i)))
then
280 do while (pos <= len_expr .and. is_digit(temp(pos:pos)))
283 tokens(ntokens)%value =
trim(adjustl(temp(i:pos - 1)))
284 tokens(ntokens)%type = number
285 tokens(ntokens)%start = i
290 do while (pos <= len_expr .and. temp(pos:pos) /=
' ' .and. &
291 temp(pos:pos) /=
'(' .and. temp(pos:pos) /=
')')
294 tokens(ntokens)%value =
trim(temp(i:pos - 1))
295 tokens(ntokens)%type = identifier
296 tokens(ntokens)%start = i
309 logical elemental function is_digit(ch) result(res)
310 character(*),
intent(in) :: ch
312 res = verify(ch,
'0123456789') == 0
323 logical function is_typeless(str, pos)
result(res)
324 character(*),
intent(in) :: str
325 integer,
intent(out) :: pos
327 integer :: i, base, n
329 pos = 0; base = 0; n = len(str)
331 if (verify(str(i:i),
'0123456789xXaAbBcCdDeEfF') /= 0)
then
336 if (pos > 0) i =
strtol(str(:pos - 1), base, success=res)
337 if (base == 10) res = .false.
341 integer function strtol_default(str, success)
result(val)
342 character(*),
intent(in) :: str
343 logical,
intent(out),
optional :: success
348 val = strtol_with_base(str, base, success)
352 integer function strtol_with_base(str, base, success)
result(val)
353 character(*),
intent(in) :: str
354 integer,
intent(inout) :: base
355 logical,
intent(out),
optional :: success
357 integer :: i, len, digit
359 logical :: is_valid, isdigit, is_lower_hex, is_upper_hex
360 character(len=len_trim(str)) :: work_str
362 val = 0; is_valid = .true.
363 work_str = adjustl(str)
364 len = len_trim(work_str)
369 if (work_str(1:2) ==
'0x' .or. work_str(1:2) ==
'0X')
then
371 work_str = work_str(3:len)
373 else if (work_str(1:2) ==
'0b' .or. work_str(1:2) ==
'0B')
then
375 work_str = work_str(3:len)
379 if (work_str(1:1) ==
'0')
then
394 if (base /= 2 .and. base /= 8 .and. base /= 10 .and. base /= 16)
then
396 if (
present(success)) success = .false.
406 isdigit = c >=
'0' .and. c <=
'9'
407 if (isdigit) digit = ichar(c) - ichar(
'0')
409 is_lower_hex = base == 16 .and. c >=
'a' .and. c <=
'f'
410 if (is_lower_hex) digit = ichar(c) - ichar(
'a') + 10
412 is_upper_hex = base == 16 .and. c >=
'A' .and. c <=
'F'
413 if (is_upper_hex) digit = ichar(c) - ichar(
'A') + 10
416 if (digit == -1)
then
420 if (digit >= base)
then
426 if (val > (huge(val) - digit) / base)
then
432 val = val * base + digit
436 if (
present(success)) success = is_valid
integer, parameter, public max_tokens
Maximum number of tokens per line, set to 100 for efficient tokenization.
logical function, public starts_with(str, arg1, idx)
Checks if a string starts with a given prefix Returns .true. if the string str (after trimming leadin...
integer, parameter, public tokens_enum
Kind parameter for token type enumeration. Values are (unknown, number, operation,...
subroutine, public tokenize(expr, tokens, ntokens)
Tokenizes a preprocessor expression into an array of token structures. Handles whitespace,...
Interface to render diagnostic messages and labels.
Return the trimmed length of a string.
Return the trimmed string.
Converts a string to integer.
Definition of diagnostic message.
Represents text as a sequence of ASCII code units. The derived type wraps an allocatable character ar...
Represents a single token in a parsed expression. Holds the string value of the token and its classif...