Re: Suggestions for dcg_basics (was: Detecting the presence of a pattern in an atom)

Carlo Capelli <[email protected]>
Newsgroups gmane.comp.ai.prolog.swi
Message-ID <CABty9wzAzroU9McSR+4pPc+H7u5C=5JU5ZxYU7i+FSNHeheMhg@mail.gmail.com>
2013/10/16 Boris Vassilev <[email protected]>

> There is one small detail about string//1 that bothers me, probably
> because I don't understand how to use it properly:
>
> in its current implementation, it takes as few tokens as possible, and
> takes more on backtracking. So, for a n-token string, it will fail and
> backtrack n-1 times. string_without//2 on the other hand is deterministic.
>
>
I don't know either, I use to put a ! after the (near mandatory) separator.
Related to this, I happened to get exponential parsing time on practical
parsing (some MB of sql dump), and I found to be fairly difficult to debug,
specially when called from phrase_from_file.


> On Wed, Oct 16, 2013 at 2:15 AM, Carlo Capelli <[email protected]>wrote:
>
>> 2013/10/16 Richard A. O'Keefe <[email protected]>
>>
>> > > From: "Richard A. O'Keefe" <[email protected]>
>> > > Subject: Re: [SWIPL] Detecting the presence of a pattern in an atom
>> > > Date: 16 October 2013 11:49:11 AM NZDT
>> > > To: Steve Prior <[email protected]>
>> >
>> > I should also have commented that if you want to take something apart,
>> > it's probably _not_ a good idea to make it an atom in the first place.
>> > >
>> > >
>> > > On 15/10/2013, at 6:18 PM, Steve Prior wrote:
>> > >> Some name and some business name (ABC)
>> > >>
>> > >> I'm trying to get the "ABC".
>> > >>
>> > >> The titles don't have any formal grammar to them, but for starters I
>> > need to see if there is a substring which starts with '(' contains all
>> > upper case letters and ends with ')'.  I suppose it's possible that the
>> > title might contain multiple open/close parens, but I'd expect only one
>> set
>> > to fit the all upper case criterion.
>> > >>
>> > >> It seems a bit much to do a DCG grammar for this
>> > >
>> > >
>> > > Why?
>> > >
>> > > The Quintus library includes more_lists:lit//1.
>> > >
>> > >       lit([])     --> [].
>> > >       lit([X|Xs]) --> [X], lit(Xs).
>> > >
>> > > Adapt that pattern:
>> > >
>> > >       uplit([])     --> [].
>> > >       uplit([X|Xs]) --> [X], {is_upper(X)}, uplit(Xs).
>> > >
>> > > Now put them together:
>> > >
>> > >       extract(Wanted) --> lit(_), "(", uplit(Wanted), ")", !.
>> > >
>> > > There are other ways to do it.
>> > >
>> > > I personally find this _easier_ to write than /\(([A-Z]+)\)/
>> > > where the placement of the backslashes is too easy to get wrong.
>> >
>> > I don't see anything resembling lit//1 in SWI's library(dcg_basics).
>> >
>>
>> There is string//1 in library(dcg/basics), exactly the same.
>>
>> Of course OP's question can be solved by
>>
>>  ?- phrase((string(_), "(", string(S), ")", {forall(member(C,S),
>> code_type(C, upper))} ), "hello (again) (WORLD)", _).
>>
>> S = [87, 79, 82, 76, 68]
>>
>>
>> but I think Michael regex is so handy...
>>
>>
>>
>> > :- module(more_lists, [
>> >         adjust/5,       % Direction x Width x Pad x List -> List
>> >         adjust/6,       % Direction x Width x Pad x List -> List\List
>> >         bnd/2,          % Length x List
>> >         bnd/3,          % Length x List\List
>> >         bnd/4,          % Length x List\List x List
>> >         len/2,          % Length <-> List
>> >         len/3,          % Length <-> List\List
>> >         len/4,          % Length <-> List <-> List\List
>> >         lit/3,          % List <-> List\List
>> >         oneof/3,        % Set x List\List
>> >         oneof/4,        % Set x (Element <-> List\List)
>> >         replist/2,      % Datum x List
>> >         replist/3,      % Datum x Length <-> List
>> >         replist/4,      % Datum x Length <-> List\List
>> >         spaces/2,       % Length <-> List
>> >         spaces/3        % Length <-> List\List
>> >    ]).
>> >
>> > adjust/[5,6] are for generation.
>> > The other things were ultimately inspired by SNOBOL 4.
>> >
>> > %   bnd(+Length, ?List)
>> > %   is true when Length is a non-negative integer and List is a list
>> > %   having at most Length elements.  This can be used to test the
>> > %   length of a list, or it can be used to generate lists up to a
>> > %   given limit.  When used for generation, it will try shorter lists
>> > %   before longer ones.
>> >
>> > %   bnd(+Length, ?S0, ?S)
>> > %   is true when Length is a non-negative integer and the list segment
>> > %   S0\S contains at most Length elements.  This is mostly used to
>> > %   generate segments increasing in length from 0 to Length; in a
>> > %   grammar rule len(3) will match exactly 3 elements, while bnd(3)
>> > %   will match 0, 1, 2, or 3 elements.
>> >
>> > %   bnd(+Length, ?List, ?S0, ?S)
>> > %   is true when bnd(Length, List) & append(List, S, S0), that is,
>> > %   when Length is a non-negative integer, List is the list represented
>> > %   by the segment S0\S, and List (S0\S) has at most Length elements.
>> > %   It is meant for use in grammar rules, where bnd(3,X) will match
>> > %   0..3 elements and return a list of them as X.
>> >
>> > %   len(?Length, ?List)
>> > %   is true when List is a list and Length is a non-negative integer
>> > %   and List has exactly Length elements.  The normal use of this is
>> > %   to find the Length of a given List, but it can be used any way
>> > %   around provided that
>> > %       Length is instantiated, or
>> > %       List   is a proper list.
>> > %   This is identical to length/2 except for the argument order.
>> > %   This predicate is the basis of most things in this module.
>> >
>> > %   len(?Length, ?List0, ?List)
>> > %   is true when append(Part, List, List0) & len(Length, Part)
>> > %   for some list Part.  The idea is to have something we can use
>> > %   in grammar rules.  For example, if we want to recognise
>> > %   phone numbers in the form "(###) ###-####" and don't want the
>> > %   bother of checking that the # characters are digits, we can
>> > %   write
>> > %       phone --> "(", len(3), ") ", len(3), "-", len(4).
>> > %   The code was derived from len/2.
>> >
>> > %   len(?Length, ?Part, ?List0, ?List)
>> > %   is true when append(Part, List, List0) & len(Length, Part).
>> > %   This too is for use in grammar rules.  The difference between
>> > %   len(N) and len(N,X) as non-terminals is that len(N,X) gives
>> > %   us the elements which matched.  This predicate can also be
>> > %   used as a version of append/3 which returns (or is guided by)
>> > %   the length of the Part argument.
>> >
>> > %   lit(?Part, ?List0, ?List)
>> > %   is true when append(Part, List, List0).  It is just append/3 with
>> > %   the last two argument switched so that it can be used in DCGs.
>> >
>> > %   oneof(+Set, ?List0, ?List)
>> > %   is true when List0\List = [X] and X is an element of Set.
>> > %   It should only be used when Set is ground.
>> >
>> > %   oneof(+Set, ?Element, ?List0, ?List)
>> > %   is true when List0\List = [Element] and Element is an element of
>> Set.
>> > %   It should only be used when Set is ground.
>> >
>> > %   replist(?Datum, +List)
>> > %   is true when List is a list all of whose elements equal Datum.
>> > %   It will terminate if either List is a proper list or it is a
>> > %   partial list one of whose known elements does not unify with
>> > %   Datum.  If called with List a variable, it will enumerate
>> > %   successively longer Lists.
>> >
>> > %   replist(?Datum, ?Length, ?List)
>> > %   is true when replist(List, Datum) & length(List, Length).
>> > %   Note that the parameters are the wrong way around for this to
>> > %   be part of the library(length) family.
>> >
>> > %   replist(?Datum, ?Length, ?List0, ?List)
>> > %   is true when append(Part, List, List0) & replist(Datum, Length,
>> Part)
>> > %   for some list Part.  The idea is to have a version of replist/3 that
>> > %   we can use in grammar rules, e.g.
>> > %       ... -> ..., replist(0'*, 20), ...
>> > %   Note that there is no replist(Datum, Length, Part, List0, List) to
>> > %   give us back the elements which matched.  We can rebuild the Part
>> > %   by calling replist/3.
>> >
>> > Actually, that could have been programmed:
>> >
>> > replist(Datum, Length, Part, List0, List) :-
>> >     replist(Datum, Length, List0, List),
>> >     replist(Datum, Length, Part).
>> >
>> > %   spaces(?Length, ?Chars)
>> > %   is true when Chars is a list of Length blanks.
>> > %   This is a special case of replist/3.
>> >
>> > %   spaces(?Length, ?Chars0, ?Chars)
>> > %   is true when append(Spaces, Chars, Chars0) & spaces(Length, Spaces)
>> > %   for some list Spaces.  This is for use in grammar rules.
>> > %   It is a special case of replist/4.
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> > _______________________________________________
>> > SWI-Prolog mailing list
>> > [email protected]
>> > https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog
>> >
>> -------------- next part --------------
>> HTML attachment scrubbed and removed
>>
>> _______________________________________________
>> SWI-Prolog mailing list
>> [email protected]
>> https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog
>>
>
>
-------------- next part --------------
HTML attachment scrubbed and removed
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.