# Reading terms from strings

**Author(s):**Francisco Bueno, Daniel Cabeza, Manuel Hermenegildo, Jose F. Morales.

This module implements predicates for reading (parsing) terms from strings or atom codes.

## Usage and interface

**Library usage:**`:- use_module(library(read_from_string)).`**Exports:****Imports:***System library modules:*`dict`,`read`,`operators`.*Packages:*`prelude`,`nonpure`,`assertions`,`basicmodes`.

## Documentation on exports

**Usage:**`read_from_string(String,Term)`

Read a term Term from String.

*The following properties should hold at call time:*

(term_typing:nonvar/1)String is currently a term which is not a free variable.

(term_typing:var/1)Term is a free variable.

**Usage:**`read_from_string(String,Term,Rest)`

Read a term Term from String up to Rest (which is the non-parsed rest of the list).

*The following properties should hold at call time:*

(term_typing:nonvar/1)String is currently a term which is not a free variable.

(term_typing:var/1)Term is a free variable.

**Usage:**`read_from_string_opts(String,Term,Rest,Opts)`

String is parsed into Term up to Rest (which is the non-parsed rest of the list). The options in Opts can be:

`variable_names(Ns)`- Read variable names in Ns.

*The following properties should hold at call time:*

(term_typing:nonvar/1)String is currently a term which is not a free variable.

(term_typing:var/1)Term is a free variable.

(term_typing:nonvar/1)Opts is currently a term which is not a free variable.

**Usage:**`read_from_string_atmvars(String,Term)`

Read a term Term from String. It ignores the unparsed rest of the string (see `read_from_string_atmvars/3`).

*The following properties should hold at call time:*

(term_typing:nonvar/1)String is currently a term which is not a free variable.

(term_typing:var/1)Term is a free variable.

**General properties:**

**Test:**`read_from_string_atmvars(A,T)`

*If the following properties should hold at call time:*

(term_basic:= /2)term_basic:A=[97]*then the following properties should hold upon exit:*

(term_basic:= /2)term_basic:T=a

**Test:**`read_from_string_atmvars(A,T)`

*If the following properties should hold at call time:*

(term_basic:= /2)term_basic:A=[49]*then the following properties should hold upon exit:*

(term_basic:= /2)term_basic:T=1

**Test:**`read_from_string_atmvars(A,T)`

*If the following properties should hold at call time:*

(term_basic:= /2)term_basic:A=[65]*then the following properties should hold upon exit:*

(term_basic:= /2)term_basic:T=A

**Test:**`read_from_string_atmvars(A,T)`

*If the following properties should hold at call time:*

(term_basic:= /2)term_basic:A=[102,40,97,41]*then the following properties should hold upon exit:*

(term_basic:= /2)term_basic:T=f(a)

**Test:**`read_from_string_atmvars(A,T)`

*If the following properties should hold at call time:*

(term_basic:= /2)term_basic:A=[102,47,50]*then the following properties should hold upon exit:*

(term_basic:= /2)term_basic:T=f/2

**Usage:**`read_from_string_atmvars(String,Term,Rest)`

Read a term Term from String up to Rest (which is the non-parsed rest of the list). Unquoted uppercase identifiers are read as atoms instead of variables (thus, the read term is always ground).

*The following properties should hold at call time:*

(term_typing:nonvar/1)String is currently a term which is not a free variable.

(term_typing:var/1)Term is a free variable.

**General properties:**

**Test:**`read_from_string_atmvars(A,T,R)`

*If the following properties should hold at call time:*

(term_basic:= /2)term_basic:A=[102,40,97,41]*then the following properties should hold upon exit:*

(term_basic:= /2)term_basic:T=f(a)

(term_basic:= /2)term_basic:R=[]

**Test:**`read_from_string_atmvars(A,T,R)`

*If the following properties should hold at call time:*

(term_basic:= /2)term_basic:A=[102,40,97,41,32,102,111,111,32]*then the following properties should hold upon exit:*

(term_basic:= /2)term_basic:T=f(a)

(term_basic:= /2)term_basic:R=[32,102,111,111,32]

**Usage:**`read_from_atom_atmvars(Atom,Term)`

Like `read_from_string_atmvars/2`, but reads the term Term from the atom codes in Atom.

*The following properties should hold at call time:*

(term_typing:nonvar/1)Atom is currently a term which is not a free variable.

(term_typing:var/1)Term is a free variable.

**General properties:**

**Test:**`read_from_atom_atmvars(A,T)`

*If the following properties should hold at call time:*

(term_basic:= /2)term_basic:A=a*then the following properties should hold upon exit:*

(term_basic:= /2)term_basic:T=a

**Test:**`read_from_atom_atmvars(A,T)`

*If the following properties should hold at call time:*

(term_basic:= /2)term_basic:A=1*then the following properties should hold upon exit:*

(term_basic:= /2)term_basic:T=1

**Test:**`read_from_atom_atmvars(A,T)`

*If the following properties should hold at call time:*

(term_basic:= /2)term_basic:A=A*then the following properties should hold upon exit:*

(term_basic:= /2)term_basic:T=A

**Test:**`read_from_atom_atmvars(A,T)`

*If the following properties should hold at call time:*

(term_basic:= /2)term_basic:A=f(a)*then the following properties should hold upon exit:*

(term_basic:= /2)term_basic:T=f(a)

**Test:**`read_from_atom_atmvars(A,T)`

*If the following properties should hold at call time:*

(term_basic:= /2)term_basic:A=f/2*then the following properties should hold upon exit:*

(term_basic:= /2)term_basic:T=f/2

**Usage:**`read_from_atom(Atom,Term)`

Read the term Term from the atom codes in Atom.

*The following properties should hold at call time:*

(term_typing:nonvar/1)Atom is currently a term which is not a free variable.

(term_typing:var/1)Term is a free variable.

## Known bugs and planned improvements

- All predicates except
`read_from_atom/2`were implemented as a quick hack initially written mainly for parsing daVinci's messages. The good implementation should: a) create a read stream from a string, and b) call the standard reader. `read_from_atom/2`is implemented using`pipe/2`, which is not safe.