-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathscanner.m
76 lines (59 loc) · 1.77 KB
/
scanner.m
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
%-----------------------------------------------------------------------------%
:- module scanner.
:- interface.
:- import_module char.
:- import_module list.
:- import_module tdop.
:- pred scan(list(char)::in, list(token)::out) is semidet.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module string.
scan(Cs, Tokens) :-
scan(Cs, [], RevTokens),
reverse(RevTokens, Tokens).
:- pred scan(list(char)::in, list(token)::in, list(token)::out) is semidet.
scan([], !Acc).
scan([C | Cs0], !Acc) :-
( is_whitespace(C) ->
scan(Cs0, !Acc)
; op(C, Token) ->
cons(Token, !Acc),
scan(Cs0, !Acc)
; name(C, Cs0, Token, Cs) ->
cons(Token, !Acc),
scan(Cs, !Acc)
; integer(C, Cs0, Token, Cs) ->
cons(Token, !Acc),
scan(Cs, !Acc)
;
fail
).
:- pred op(char::in, token::out) is semidet.
op('(', lparen).
op(')', rparen).
op(',', comma).
op('=', equals).
op('+', plus).
op('-', minus).
op('*', star).
op('/', slash).
op('^', caret).
op('!', bang).
op('?', question).
op(':', colon).
op('<', lt).
op('>', gt).
:- pred name(char::in, list(char)::in, token::out, list(char)::out) is semidet.
name(C, Cs0, name(Name), Cs) :-
is_alpha(C),
takewhile(is_alnum, Cs0, NameCs, Cs),
from_char_list([C | NameCs], Name).
:- pred integer(char::in, list(char)::in, token::out, list(char)::out)
is semidet.
integer(C, Cs0, integer(Integer), Cs) :-
is_decimal_digit(C),
takewhile(is_decimal_digit, Cs0, IntCs, Cs),
from_char_list([C | IntCs], Integer).
%-----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sts=4 sw=4 et