Files
mercury/extras/moose/samples/expr.moo
Julien Fischer b863e8bf52 Fix a bug in moose.
extras/moose/moose.m:
    Fix an invalid conversion specifier in a call to string.format
    in the generated code.

extras/moose/samples/alpha.moo:
extras/moose/samples/cgram.moo:
extras/moose/samples/expr.moo:
extras/moose/samples/small.moo:
    Fix compilation problems.

    Clean-up and update syntax.
2022-03-20 17:05:31 +11:00

71 lines
1.8 KiB
Plaintext

:- module expr.
:- interface.
:- import_module char.
:- import_module int.
:- import_module list.
:- type token
---> ('+')
; ('-')
; ('*')
; ('/')
; num(int)
; ('(')
; (')')
; eof.
:- parse(exprn/1, token, eof, xx, in, out).
:- pred scan(list(char)::in, list(token)::out) is det.
:- implementation.
:- import_module require.
:- import_module string.
:- rule exprn(int).
exprn(Num) ---> exprn(A), [+], term(B), { Num = A + B }.
exprn(Num) ---> exprn(A), [-], term(B), { Num = A - B }.
exprn(Num) ---> term(Num).
:- rule term(int).
term(Num) ---> term(A), [*], factor(B), { Num = A * B }.
term(Num) ---> term(A), [/], factor(B), { Num = A // B }.
term(Num) ---> factor(Num).
:- rule factor(int).
factor(Num) ---> ['('], exprn(Num), [')'].
factor(Num) ---> [num(Num)].
scan(Chars, Toks) :-
scan(Chars, [], Toks0),
list.reverse(Toks0, Toks).
:- pred scan(list(char)::in, list(token)::in, list(token)::out) is det.
scan([], Toks, [eof | Toks]).
scan([C | Cs], Toks0, Toks) :-
( if char.is_whitespace(C) then
scan(Cs, Toks0, Toks)
else if char.is_digit(C) then
take_while(char.is_digit, [C | Cs], Digits, Rest),
string.from_char_list(Digits, NumStr),
Num = string.det_to_int(NumStr),
scan(Rest, [num(Num) | Toks0], Toks)
else if C = ('+') then
scan(Cs, ['+' | Toks0], Toks)
else if C = ('-') then
scan(Cs, ['-' | Toks0], Toks)
else if C = ('*') then
scan(Cs, ['*' | Toks0], Toks)
else if C = ('/') then
scan(Cs, ['/' | Toks0], Toks)
else if C = ('(') then
scan(Cs, ['(' | Toks0], Toks)
else if C = (')') then
scan(Cs, [')' | Toks0], Toks)
else
error("expr: syntax error in input")
).