Parsing numbers with multiple digits in Prolog
Asked Answered
K

3

11

I have the following simple expression parser:

expr(+(T,E))-->term(T),"+",expr(E).
expr(T)-->term(T).

term(*(F,T))-->factor(F),"*",term(T).
term(F)-->factor(F).

factor(N)-->nat(N).
factor(E)-->"(",expr(E),")".

nat(0)-->"0".
nat(1)-->"1".
nat(2)-->"2".
nat(3)-->"3".
nat(4)-->"4".
nat(5)-->"5".
nat(6)-->"6".
nat(7)-->"7".
nat(8)-->"8".
nat(9)-->"9".

However this only supports 1-digit numbers. How can I parse numbers with multiple digits in this case?

Kalliekallista answered 19/7, 2010 at 9:27 Comment(3)
Which prolog are you using? Mine dones not have the "-->" think iirc. (SWI-Prolog)Scaramouch
Huh. Shouldent it be :- instead? scratchheadScaramouch
No, --> is the short notation for a definite clause grammar.Kalliekallista
P
10

Use accumulator variables, and pass those in recursive calls. In the following, A and A1 are the accumulator.

digit(0) --> "0".
digit(1) --> "1".
% ...
digit(9) --> "9".

nat(N)   --> digit(D), nat(D,N).
nat(N,N) --> [].
nat(A,N) --> digit(D), { A1 is A*10 + D }, nat(A1,N).

Note that the first nat clause initializes the accumulator by consuming a digit, because you don't want to match the empty string.

Paynter answered 19/7, 2010 at 11:54 Comment(2)
@ubuntodroid: I think this is a good solution if you have to implement the number parsing yourself. I don't know if there is a predicate to parse natural numbers by default in Prolog. The code can also be reduced if one can do character arithmetic that is "0" -> 0, "1" -> "0" + 1, ... in Prolog.Gaygaya
@thequark: I don't know of any such predicate. atom_char/2 can be used, but it wouldn't be pretty. You could also write a predicate digit_int/2 with the ASCII value of '0' hard-coded (yuck).Paynter
S
-1
nat(0). 
nat(N):-nat(N-1).

But you use a syntax that I don't know (see my comment above).

Scaramouch answered 19/7, 2010 at 11:52 Comment(0)
G
-3

Can you provide a sample input?

I think this might work:

nat(N)-->number(N).

If that fails try:

nat(N)-->number(N),!.

The ! is a cut it stops the unification. You can read about it in books/tutorials.

Gaygaya answered 19/7, 2010 at 10:39 Comment(2)
Some sample input could be expr(E,"2*14+3",""). The code you provided leads to an error message telling me, that number/3 is an undefined procedure and that only number/1 is known. I thought of a DGC-Clause to solve my problem, but I wasn't able to get one working.Kalliekallista
number/1 is an ordinary predicate, not a DCG predicate. Besides, it fails if its input is not ground (is a variable).Paynter

© 2022 - 2024 — McMap. All rights reserved.