161 character(*),
intent(in) :: expr
162 type(
token),
allocatable,
intent(out) :: tokens(:)
163 integer,
intent(out) :: ntokens
165 character(:),
allocatable :: temp
166 integer :: i, pos, len_expr
168 logical,
save :: in_comment
170 if (
allocated(tokens))
deallocate(tokens)
173 temp =
trim(adjustl(expr)) //
' '
178 do while (i <= len_expr)
179 if (temp(i:i) ==
' ')
then
185 if (.not. in_word)
then
186 ntokens = ntokens + 1
188 if (
verbose) print *,
"Error: Too many tokens in expression"
194 if (temp(i:i) ==
'(' .or. temp(i:i) ==
')')
then
195 tokens(ntokens)%value = temp(i:i)
196 tokens(ntokens)%type = parenthesis
199 else if (temp(i:i + 1) ==
'&&' .or. temp(i:i + 1) ==
'||' .or. temp(i:i + 1) ==
'==' .or. &
200 temp(i:i + 1) ==
'!=' .or. temp(i:i + 1) ==
'<=' .or. temp(i:i + 1) ==
'>=')
then
201 tokens(ntokens)%value = temp(i:i + 1)
202 tokens(ntokens)%type = operator
205 else if (temp(i:i) ==
'!')
then
206 tokens(ntokens)%value = temp(i:i)
207 tokens(ntokens)%type = operator
210 else if (temp(i:i + 1) ==
'**')
then
211 tokens(ntokens)%value = temp(i:i + 1)
212 tokens(ntokens)%type = operator
215 else if (temp(i:i + 1) ==
'<<' .or. temp(i:i + 1) ==
'>>')
then
216 tokens(ntokens)%value = temp(i:i + 1)
217 tokens(ntokens)%type = operator
220 else if (temp(i:i) ==
'<' .or. temp(i:i) ==
'>' .or. temp(i:i) ==
'=' .or. &
221 temp(i:i) ==
'+' .or. temp(i:i) ==
'-' .or. temp(i:i) ==
'*' .or. &
222 temp(i:i) ==
'/' .or. temp(i:i) ==
'%' .or. &
223 temp(i:i) ==
'?' .or. temp(i:i) ==
':')
then
224 tokens(ntokens)%value = temp(i:i)
225 tokens(ntokens)%type = operator
228 else if (temp(i:i) ==
'&' .or. temp(i:i) ==
'|' .or. temp(i:i) ==
'^' .or. &
229 temp(i:i) ==
'~')
then
230 tokens(ntokens)%value = temp(i:i)
231 tokens(ntokens)%type = operator
236 do while (i <= len_expr .and. temp(i:i) ==
' ')
239 if (i <= len_expr .and. temp(i:i) ==
'(')
then
242 do while (pos <= len_expr .and. temp(pos:pos) /=
')')
245 tokens(ntokens)%value =
trim(adjustl(temp(i:pos - 1)))
246 tokens(ntokens)%type = defined
250 do while (pos <= len_expr .and. temp(pos:pos) /=
' ')
253 tokens(ntokens)%value =
trim(adjustl(temp(i:pos - 1)))
254 tokens(ntokens)%type = defined
260 tokens(ntokens)%value =
trim(adjustl(temp(i:pos - 1)))
261 tokens(ntokens)%type = number
266 do while (pos <= len_expr .and.
is_digit(temp(pos:pos)))
269 tokens(ntokens)%value =
trim(adjustl(temp(i:pos - 1)))
270 tokens(ntokens)%type = number
275 do while (pos <= len_expr .and. temp(pos:pos) /=
' ' .and. &
276 temp(pos:pos) /=
'(' .and. temp(pos:pos) /=
')')
279 tokens(ntokens)%value =
trim(temp(i:pos - 1))
280 tokens(ntokens)%type = identifier
286 if (
verbose) print *,
"Tokens for '",
trim(expr),
"':"
288 if (
verbose) print *,
" Token ", i,
": ",
trim(tokens(i)%value),
" (type ", tokens(i)%type,
")"
341 integer function strtol_with_base(str, base, success)
result(val)
342 character(*),
intent(in) :: str
343 integer,
intent(inout) :: base
344 logical,
intent(out),
optional :: success
346 integer :: i, len, digit
348 logical :: is_valid, isdigit, is_lower_hex, is_upper_hex
349 character(len=len_trim(str)) :: work_str
351 val = 0; is_valid = .true.
352 work_str = adjustl(str)
353 len = len_trim(work_str)
358 if (work_str(1:2) ==
'0x' .or. work_str(1:2) ==
'0X')
then
360 work_str = work_str(3:len)
362 else if (work_str(1:2) ==
'0b' .or. work_str(1:2) ==
'0B')
then
364 work_str = work_str(3:len)
368 if (work_str(1:1) ==
'0')
then
383 if (base /= 2 .and. base /= 8 .and. base /= 10 .and. base /= 16)
then
385 if (
present(success)) success = .false.
395 isdigit = c >=
'0' .and. c <=
'9'
396 if (isdigit) digit = ichar(c) - ichar(
'0')
398 is_lower_hex = base == 16 .and. c >=
'a' .and. c <=
'f'
399 if (is_lower_hex) digit = ichar(c) - ichar(
'a') + 10
401 is_upper_hex = base == 16 .and. c >=
'A' .and. c <=
'F'
402 if (is_upper_hex) digit = ichar(c) - ichar(
'A') + 10
405 if (digit == -1)
then
409 if (digit >= base)
then
415 if (val > (huge(val) - digit) / base)
then
421 val = val * base + digit
425 if (
present(success)) success = is_valid
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, operator, identifier,...
subroutine, public tokenize(expr, tokens, ntokens)
Tokenizes a preprocessor expression into an array of token structures. Handles whitespace,...
logical function is_typeless(str, pos)
Detects whether a string starts a typeless constant (hex, octal, binary). Used to avoid treating them...