GithubHelp home page GithubHelp logo

ezprolog's Introduction

EzProlog: A Simple Prolog Interpreter

This is an example for building Prolog term matching with some design patterns in C++. The patterns include Builder, Composite, Factory Method, Flyweight, Interpreter, Iterator, Proxy, Singleton, and Template Method. We only implement three operators, matching( = ), conjunction( , ), and disjunction( ; ), in this simple interpreter and try to make our output like swi-prolog. Here are some output examples:

Constant matching

-? tom = tom.
true.

-? tom = jerry.
false.

Variable matching

-? X = 1.
X = 1.

Structure(Compound) matching

-? point(X, 1) = point(0, 1).
X = 0.

List matching(syntax sugar of structure)

-? [tom, jerry] = [H|T].
H = tom,
T = [jerry].

Shared variables

-? A = s(B), A = C, B = D, A = D.
A = B,
B = C,
C = D,
D = s(D).

Conjunction and Disjunction

-? X = 1, X = 2.
false.

-? X = 1; X = 2.
X = 1;
X = 2.

Getting Started

Prerequest for Windows 10

Install GoogleTest for running unit test

Open your terminal or command line and do

make test

under your project folder and then you should see the following result

unit test result

The Basics - Goal

A query to the Prolog interpreter consists of one or more goals. For example, in

-? X = 1.
X = 1.

there is a relational goal "X = 1" which means "is X matchable to 1?". A goal is something that Prolog tries to satisfy. In here, "X = 1" succeeded because the variable X matches any legitimate term before instantiating.

-? X = 1, X = 2.
false.

there is another example, which contains two relational goals "X = 1" and "X = 2". It means "is X matchable to 1 and 2?". Unfortunately, the Prolog says no by printing "false" because the variable X can't be 1 and 2 at the same time.

-? X = 1; X = 2.
X = 1;
X = 2.

the final example also contains two relational goals. But it means "is X matchable to 1 or 2?". So the goal can be satisfied by instantiating 1 or 2 to X.

Data Objects in Prolog

In this example, we reference iso prolog to define the following data objects of prolog:

Atom

A series of letters, digits, and/or underscores, beginning with a lowercase letter

ex: atom, a_t_o_m, atom123

A series of 1 or more characters from the set #$&*+-./:<->?@^~\ provided it does not begin with /* (such atoms are called graphic tokens)

ex: :->, @-@?, ^+$*

A series of arbitrary characters in single quotes

ex: 'This is an atom, LoL'

The special atoms [] and {}

ex: [], {}

Number

A series of demical digits.

ex: 1, 0.2, -0.3

Variable

A variable name begin with a captical letter or the underscore mark(_) and consists of letters, digits, and/or underscores.

ex: Var, _var, Var123, V_A_R

Structure

The ordinary way to write a structure is to write the functor, an opening parenthesis, a series of terms separeted by commas, and a closing parenthesis. p.s. the functor should be an atom.

ex: date(feb, 19, 2018), age(tom, X)

List

List is defined as rightward-nested structures using the operator '.'.

ex: [a] = .(a, [])
    [a, b] = .(a, .(b, []))
    [a | b] = .(a, b)

Term Matching Rule

Let S and T be two terms.

  • If S and T are constants then they match only if both are the same object.
-? tom = tom.
true. (match success)

-? tom = jerry.
false. (match fail)
  • If one of them is variable then they match only if
    • the variable has not been instantiated, or
    • the instance of variable is equal to the other one
-? X = 1.
X = 1. (match success, X has been instantiated to 1)

-? X = 1, X = 2.
false. (match fail, the instance of X is 1 not 2)
  • If S and T are structures then they match only if
    • both have the same functor,
    • equal arity of arguments, and
    • all corresponding arguments match.
-? year(2018) = yEar(2018).
false. (match fail, different functor)

-? date(feb, 19, 2018) = date(feb, 19).
false. (match fail, different arity)

-? date(jan, 19, 2018) = date(feb, 19, 2018).
false. (match fail, 'jan' is not equal to 'feb')

-? date(feb, 19, 2018) = date(feb, 19, 2018).
true. (match success)

Lexical Analysis and Parsing

Lexical Analyzer

lexeme token-name attribute-value
Atom definition Atom Symbol of atom
Number definition Number Value of number
Variable definition Var Symbol of variable

Grammar

<query> ::= <disjunction expression> < disjunction expression'> '.'
<disjunction expression> ::= <conjunction expression> <disjunction expression'>
<disjunction expression'> ::= ';' <conjunction expression> <disjunction expression'> *
<conjunction expression> ::= <matching expression> <conjunction expression'>
<conjunction expression'> ::= ',' <matching expression> <conjunction expression'> *
<matching expression> ::= <term> '=' <term>
<structure> ::= <atom> '(' <terms> ')'
<terms> ::= <term> *
<term> ::= <atom> | <number> | <variable> | <structure>
<atom> ::= <lowercase letter> <string> | <specialchar>+ | '<string>'
<number> ::= <negative>?<digit>+
<variable> ::= <uppercase letter> <string>
<string> ::= <character> *
<character> ::= <digit> | <lowercase letter> | <uppercase letter>
<negative> ::= -
<digit> ::= [0 - 9]
<lowercase letter> ::= [a - z]
<uppercase letter> ::= [A - Z] | _
<specialchar> ::= # | $ | & | * | + | - | . | / | : | < | - | > | ? | @ | ^ | ~ | \

Bottom-Up Parser

Bottom-up parsing starts from the leaf nodes of a tree and works in upward direction till it reaches the root node. Here, we use a simple query, A = 1, B = 2, C = 3; D = 4., to explain how the parser works in the following figures.

parse tree build steps
SET OWB

In order to build a right recursive tree like the left one shows. We need some stacks to remember which terms, operators, or expressions has been parsed and pop them up to create other expressions if the priority of new operator is greater than the top of the operator stack. Then the parse steps will just be like the right figure.

Cycle Detection and Shared Variables

There are two situations may cause cycle when variable matching.

  • Instantiate to itself
-? X = X.
  • Instantiate to a structure(compound) which arugments contain itself
-? X = s(X).

In the first situation, it only occurs when a variable match itself or the last shared variable instantiates to the first one. So we check if there is a shared variable and it is equal to the reference one to avoid cycle.

Variable* other // which prepares to be an instance
for (; other != nullptr; other = other->instance())
    if (other == this)
        return true; // has cycle
return false;

The other one, we use a flag to check if this variable has been visited or not.

// hasBeenVisited is a bool property of variable
if (hasBeenVisited) {
    // do something when cycle detection
}

hasBeenVisited = true;
// do something on instance
hasBeenVisited = false;

In the swi-prolog, all variables are sorted by its address. Here, we use a int property called age to complete the same effect and sort the shared variables when instantiating a new variable to another variable by matching.

Class Diagram

Click the following image if you want to see the full version

class-diagram

ezprolog's People

Contributors

xenosxavier avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.