Search code examples
parsingprologdcg

Definite clause grammar in Prolog - Or statement


What would be the best way to define a phrase that can describe an adverb in either one of two ways?

Could you just say:

  1. adverb_phrase(N,adv(N,Adv)) --> Way 1.
  2. adverb_phrase(N,adv(N,Adv)) --> Way 2.

I've tried doing this but I get variables (like _G12345) in the output, which doesn't look right.


Solution

  • Yes, what you show is definitely a valid way to state alternatives in DCGs.

    There are other options too. Here are some:

    1. Your version

    This is your version, only extended to a somewhat more complete example:

    adverb_phrase(N, adv(N,Adv)) --> adv1(Adv).
    adverb_phrase(N, adv(N,Adv)) --> adv2(Adv).
    
    adv1(likely)  --> [].
    adv2(happily) --> [].
    

    Example query and answer:

    ?- phrase(adverb_phrase(N,A), Ls).
    A = adv(N, likely),
    Ls = [] ;
    A = adv(N, happily),
    Ls = [].
    

    Two solutions are found on backtracking. The variable N also occurs in the query. I do not know why you introduced it, and if you do not need it, you can simply omit it.

    2. More compact

    Using different rules to denote alternatives is straight-forward. Note that you can refactor the code to make it more compact:

    adverb_phrase(N, adv(N,Adv)) --> adv(Adv).
    
    adv(likely)  --> [].
    adv(happily) --> [].
    

    In this case, I have simply used the same nonterminal to denote the alternatives.

    3. Using ('|')//2

    Note that there are also other ways to denote alternatives. An elegant way is to use ('|')//2, in analogy to how alternatives are often indicated in other formalisms.

    For example, you can write your initial example as:

    adverb_phrase(N, adv(N,Adv)) --> adv1(Adv) | adv2(Adv).
    
    adv1(likely)  --> [].
    adv2(happily) --> [].
    

    Instead of ('|')//2, you can also use (;)//2 if you want to, in analogy to plain Prolog.

    The shown variants yield exactly the same answers. The version you choose depends on several factors, for example: Are you using the DCG more in the "grammar" or more in the "monad" sense.

    For your specific case, version 2 seems a good fit from a first impression.

    Note that neither of these options is an "or statement". We call these nonterminals!