Questions tagged [dcg]

DCGs (Definite Clause Grammars) are a compact way to describe lists in Prolog.

DCGs (Definite Clause Grammars) are a compact way to describe lists in Prolog.

DCGs are usually associated with , but similar languages such as also include DCGs. They are called definite clause grammars because they represent a grammar as a set of definite clauses in first-order logic.

Some interesting contributions are available as SWI-Prolog packs, like

I like to think of DCGs as Attribute Grammars made practical.


References:

DCGs provide a threading state abstraction: don't break it


SWI-Prolog and double quotes

Many examples of DCGs on SO, in blogs and papers use the traditional and ISO standard conforming definition for double quotes. If you take such code and use it directly with SWI-Prolog it will sometimes fail because SWI uses by default double quoted syntax for its string type.

?- phrase("abc","abc").         % succeeds in other Prologs
ERROR: Type error: `list' expected, found `"abc"' (a string)

To make the examples work in SWI-Prolog set Prolog flags in .swiplrc or issue them directly on the top level.

:- set_prolog_flag(double_quotes, chars).   % or codes
:- set_prolog_flag(back_quotes, string).    % ISO conforming extension

Otherwise, to ensure the SWI-specific setting, proceed as in the following example.

:- module(course,
      [ courses//1,
        parse_courses/2
      ]).

:- [library(dcg/basics)].

:- set_prolog_flag(double_quotes, string).   % SWI's default setting
:- set_prolog_flag(back_quotes, codes).      % SWI's default setting

courses([Course|Courses]) -->
    course(Course),
    courses(Courses), !.
courses([]) --> [].

course(course(Course,Students)) -->
    string_without("\n", Course_codes),
    { string_codes(Course,Course_codes ) },
    "\n",
    students(Students),
    (
        empty_line
    ;
        []
    ).

students([Student|Students]) -->
    student(Student),
    students(Students).
students([]) --> [].

student(Student) -->
    spaces_or_tabs_plus,
    (
        (
            string_without("\n",Student_codes),
            { string_codes(Student,Student_codes) },
            "\n"
        )
    ;
        remainder(Student_codes),
        { string_codes(Student,Student_codes) }
    ).

spaces_or_tabs_plus -->
    space_or_tab,
    spaces_or_tabs_star.

spaces_or_tabs_star -->
    space_or_tab,
    spaces_or_tabs_star.
spaces_or_tabs_star --> [].

space_or_tab -->
    (
        "\s"
    |
        "\t"
    ).

empty_line --> "\n".

parse_courses(Codes,Courses) :-
    DCG = courses(Courses),
    phrase(DCG,Codes,Rest),
    assertion( Rest == [] ).

:- begin_tests(course).

:- set_prolog_flag(double_quotes, string).
:- set_prolog_flag(back_quotes, codes).

test(001) :-
    Input = "\c
        MATH2221\n\c
            \t201000001\n\c
            \t201000002\n\c
            \n\c
        MATH2251\n\c
            \t201000002\n\c
            \t201000003\n\c
            \n\c
        COMP2231\n\c
            \t201000003\n\c
            \t201000001\c
        ",
    string_codes(Input,Codes),
    parse_courses(Codes,Courses),

    assertion( Courses ==
        [
            course("MATH2221",["201000001","201000002"]),
            course("MATH2251",["201000002","201000003"]),
            course("COMP2231",["201000003","201000001"])
        ]
    ).

:- end_tests(course).

482 questions
6
votes
3 answers

Prolog DCG: find last element

I am trying to understand the use of DCGs better. In order to do this, I tried to translate some exercises in the LearnPrologNow book to DCG notation. However, I am failing miserably. What I tried to write a program that simply names the last…
Boreq
  • 95
  • 6
6
votes
2 answers

implement a simple C like language in Prolog?

I'm new to prolog, so this's quite a challenge to me. I'm supposed to implement a simple C like language in Prolog. the ultimate goal is to be able to execute something like this: ?-…
Hashbug
  • 127
  • 8
6
votes
1 answer

Prolog - Parsing

I'm new to the language prolog and have been given an assignment regarding parsing in prolog. I need some help in solving the problem. In the assingment we have the grammar: Expr ::= + Expr Expr | * Expr Expr | Num | Xer Xer ::= x | ^ x Num …
Taza
  • 63
  • 1
  • 5
6
votes
2 answers

How to avoid using assert and retractall in Prolog to implement global (or state) variables

I often end up writing code in Prolog which involves some arithmetic calculation (or state information important throughout the program), by means of first obtaining the value stored in a predicate, then recalculating the value and finally storing…
6
votes
1 answer

How to find out if Prolog performs Tail Call Optimization

Using the development version of SWI Prolog (Win x64), I wrote a DCG predicate for a deterministic lexer (hosted on github) (thus all external predicates leave no choice points): read_token(parser(Grammar, Tables), lexer(dfa-DFAIndex,…
Sebastian
  • 6,293
  • 6
  • 34
  • 47
6
votes
2 answers

prolog dcg restriction

I would like to use DCGs as a generator. As of now, the syntax is s-->a,b. a-->[]. a-->a,c. c-->[t1]. c-->[t2]. b-->[t3]. b-->[t4]. I would like to generate all s where the length of a is < someNumber. Using ?- phrase(a,X),length(X,Y),Y<4. i can…
Ruben Real
  • 63
  • 3
6
votes
1 answer

DCG Expansion: Is Steadfastness ignored?

Assume I have the following DCG rule: factor(X) --> "(", expr(X), ")". Normally this would be translated to: factor(X, A, B) :- [40|C] = A, expr(X, C, D), [41|B] = D. Would a Prolog system be allowed to translate it as follows, i.e. to merge…
user502187
6
votes
2 answers

Legitimate uses of (\+)//1

In grammar rules (dcg), there are several predefined constructs: (',')//2 meaning concatenation, ('|')//2 meaning alternation etc. One construct which is supported by several but not all Prolog systems is (\+)//1. Personally, I have used it only for…
false
  • 10,264
  • 13
  • 101
  • 209
6
votes
2 answers

Regular Expression Matching Prolog

I am trying to do Regular Expression matching. I have all the functions written out, but they are not working as they should. From what I can tell, it has a problem when I try to compare a list. For instance, "re_contains(a,a)." gives true…
Ryan C. Stacy
  • 87
  • 1
  • 7
6
votes
3 answers

Extension to CFG, what is it?

Consider the following extension to context-free grammars that permits rules to have in the left-hand side, one (or more) terminal on the right side of the non-terminal. That is, rules of the form: A b -> ... The right-hand side may be anything,…
false
  • 10,264
  • 13
  • 101
  • 209
6
votes
4 answers

Removing left recursion in DCG - Prolog

I've got a small problem with left recursion in this grammar. I'm trying to write it in Prolog, but I don't know how to remove left recursion. -> ->
Finley Osbert
  • 103
  • 2
  • 8
5
votes
5 answers

Prolog - Palindrome Functor

I am trying to write a predicate palindrome/1 in Prolog that is true if and only if its list input consists of a palindromic list. for example: ?- palindrome([1,2,3,4,5,4,3,2,1]). is true. Any ideas or solutions?
Amjad
  • 1,627
  • 5
  • 21
  • 41
5
votes
2 answers

How do you do a search and replace of a list with another sublist in Prolog?

I'm trying to modify a list by search and replace, was wondering how do I search through a list with the search term as a list as well? Lets say I have a list [1,2,3,4] I want to single out the 2 and 3 and replace it with 5,6 so ideally I could have…
chutsu
  • 13,612
  • 19
  • 65
  • 86
5
votes
2 answers

Building an Expression Tree in Prolog

I'm looking for a way to build an Expression Tree in Prolog. I already did some experiments and came up with the following working code (that will only handle constants and the plus expression): const(_). plus(_, _). eval(const(R),…
devoured elysium
  • 101,373
  • 131
  • 340
  • 557
5
votes
2 answers

Using phrase_from_file to read a file's lines

I've been trying to parse a file containing lines of integers using phrase_from_file with the grammar rules line --> I,line,{integer(I)}. line --> ['\n']. thusly: phrase_from_file(line,'input.txt'). It fails, and I got lost very quickly trying to…
moshewe
  • 127
  • 1
  • 9