diff --git a/open-nars/LICENSE.txt b/open-nars/LICENSE.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d511905c1647a1e311e8b20d5930a37a9c2531cd
--- /dev/null
+++ b/open-nars/LICENSE.txt
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/open-nars/com/googlecode/opennars/entity/Base.java b/open-nars/com/googlecode/opennars/entity/Base.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ccd3184214b6e76be8fcd1c0250fa5bdc9ad065
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/Base.java
@@ -0,0 +1,142 @@
+/*
+ * Base.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.entity;
+
+import com.googlecode.opennars.main.Parameters;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * Each Sentence has a list of serial numbers of a constant length.
+ * The input sentence gets a unique number.
+ * The derived sentences inherits from its parents.
+ */
+public class Base implements Cloneable {            // make it part of TruthValue?
+    private static final int MAXLENGTH = Parameters.MAXMUM_LABEL_RECORD_LENGTH;
+    private static final String opener = Symbols.Base_opener;
+    private static final String closer = Symbols.Base_closer;
+    private static final String separator = Symbols.Base_separator;
+    private static final String separator0 = Symbols.Base_separator0;
+    
+    // for each base
+    private int length;
+    private long list[] = new long[MAXLENGTH];
+    
+    // sequential number, for the whole system
+    private static long current = 0;
+    
+    // generate a new number --- serial number or generation time?
+    // called in StringParser
+    public Base() {
+        current++;
+        length = 1;
+        list[0] = current;
+    }
+    
+    // the first one is no shorter than the second
+    private Base(Base first, Base second) {
+        int i1, i2, j;
+        i1 = i2 = j = 0;
+        while (i2 < second.length() && j < MAXLENGTH) {
+            list[j] = first.list(i1);
+            i1++;
+            j++;
+            list[j] = second.list(i2);
+            i2++;
+            j++;
+        }
+        while (i1 < first.length() && j < MAXLENGTH) {
+            list[j] = first.list(i1);
+            i1++;
+            j++;
+        }
+        length = j;
+    }
+    
+    // try to merge two Bases, return null if have overlap
+    public static Base make(Base first, Base second) {
+        for (int i = 0; i < first.length(); i++)
+            for (int j = 0; j < second.length(); j++)
+                if (first.list(i) == second.list(j))
+                    return null;
+        if (first.length() > second.length())
+            return new Base(first, second);
+        else
+            return new Base(second, first);
+    }
+    
+    // Initialize the machenism
+    // called in Center
+    public static void init() {
+        current = 0;
+    }
+    
+    public int length() {
+        return length;
+    }
+    
+    public long list(int i) {
+        return list[i];
+    }
+
+    // to check for subset
+    public boolean include(Base s) {
+        boolean result = false;
+        if (length >= s.length())
+            for (int i = 0; i < s.length(); i++) {
+                result = false;
+                for (int j = 0; j < length; j++)
+                    if (list[j] == s.list(i)) {
+                        result = true;
+                        break;
+                    }
+                if (result == false)
+                    break;
+            }
+        return result;
+    }
+    
+    public boolean equals(Object that) {
+        return ((that instanceof Base) && this.include((Base) that) && ((Base) that).include(this));
+    }
+    
+    // called for update
+    public long latest() {
+        long v = list[0];
+        for (int i = 1; i < length(); i++) 
+            if (list[i] > v)
+                v = list[i];
+        return v;
+    }
+    
+    // for display
+    public String toString() {
+        String buf = new String(opener + length + separator0);
+        for (int i = 0; i < length; i++) {
+            buf = buf.concat(Long.toString(list[i]));
+            if (i < (length - 1))
+                buf = buf.concat(separator);
+            else
+                buf = buf.concat(closer);
+        }
+        return buf;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/entity/BudgetValue.java b/open-nars/com/googlecode/opennars/entity/BudgetValue.java
new file mode 100644
index 0000000000000000000000000000000000000000..a2c5bc589b0132540752d2affa2af43e94d549fd
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/BudgetValue.java
@@ -0,0 +1,163 @@
+/*
+ * BudgetValue.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.entity;
+
+import com.googlecode.opennars.inference.*;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.*;
+
+/**
+ * A triple of priority (current), durability (decay), and quality (long-term average).
+ */
+public class BudgetValue implements Cloneable {
+    public static final char mark = Symbols.BUDGET_VALUE_MARK;       // default
+    public static final char separator = Symbols.VALUE_SEPARATOR;    // default
+    protected ShortFloat priority;      // short-term, first-order
+    protected ShortFloat durability;    // short-term, second-order
+    protected ShortFloat quality;       // long-term
+	private Memory memory;
+	protected BudgetFunctions budgetfunctions;
+    
+    /* ----- constructors ----- */
+    
+    public BudgetValue(Memory memory) {
+        priority = new ShortFloat(0.01f);
+        durability = new ShortFloat(0.01f);
+        quality = new ShortFloat(0.01f);
+        this.memory = memory;
+        this.budgetfunctions = new BudgetFunctions(memory);
+    }
+
+    public BudgetValue(float p, float d, float q, Memory memory) {
+        priority = new ShortFloat(p);
+        durability = new ShortFloat(d);
+        quality = new ShortFloat(q);
+        this.memory = memory;
+        this.budgetfunctions = new BudgetFunctions(memory);
+    }
+
+    public BudgetValue(BudgetValue v, Memory memory) { // clone, not copy
+        priority = new ShortFloat(v.getPriority());
+        durability = new ShortFloat(v.getDurability());
+        quality = new ShortFloat(v.getQuality());
+        this.memory = memory;
+        this.budgetfunctions = new BudgetFunctions(memory);
+    }
+
+    public Object clone() {
+        return new BudgetValue(this.getPriority(), this.getDurability(), this.getQuality(), this.memory);
+    }
+
+    /* ----- priority ----- */
+
+    public float getPriority() {
+        return priority.getValue();
+    }
+
+    public void setPriority(float v) {
+        priority.setValue(v);
+    }
+    
+    public void incPriority(float v) {
+        priority.setValue(UtilityFunctions.or(priority.getValue(), v));
+    }
+
+    public void decPriority(float v) {
+        priority.setValue(UtilityFunctions.and(priority.getValue(), v));
+    }
+
+    /* ----- durability ----- */
+
+    public float getDurability() {
+        return durability.getValue();
+    }
+    
+    public void setDurability(float v) {
+        durability.setValue(v);
+    }
+    
+    public void incDurability(float v) {
+        durability.setValue(UtilityFunctions.or(durability.getValue(), v));
+    }
+
+    public void decDurability(float v) {
+        durability.setValue(UtilityFunctions.and(durability.getValue(), v));
+    }
+
+    /* ----- quality ----- */
+
+    public float getQuality() {
+        return quality.getValue();
+    }
+    
+    public void setQuality(float v) {
+        quality.setValue(v);
+    }
+        
+    public void incQuality(float v) {
+        quality.setValue(UtilityFunctions.or(quality.getValue(), v));
+    }
+
+    public void decQuality(float v) {
+        quality.setValue(UtilityFunctions.and(quality.getValue(), v));
+    }
+
+    /* ----- utility ----- */
+
+    public void merge(BudgetValue that) {
+        this.budgetfunctions.merge(this, that);
+    }
+
+    // called from Memory only
+    public float singleValue() {
+//        return (priority.getValue() + quality.getValue()) * durability.getValue() / 2.0f;
+        return UtilityFunctions.aveAri(priority.getValue(), durability.getValue(), quality.getValue());
+    }
+    
+    public boolean aboveThreshold() {
+        return (singleValue() > 0.001); // to be revised to depend on how busy the system is
+    }
+    
+    // full output
+    public String toString() {
+        return mark + priority.toString() + separator + durability.toString() + separator + quality.toString() + mark;
+    }
+
+    // short output
+    public String toString2() {
+        return mark + priority.toString2() + separator + durability.toString2() + separator + quality.toString2() + mark;
+    }
+
+	/**
+	 * @param memory the memory to set
+	 */
+	public void setMemory(Memory memory) {
+		this.memory = memory;
+	}
+
+	/**
+	 * @return the memory
+	 */
+	public Memory getMemory() {
+		return memory;
+	}
+}
diff --git a/open-nars/com/googlecode/opennars/entity/Concept.java b/open-nars/com/googlecode/opennars/entity/Concept.java
new file mode 100644
index 0000000000000000000000000000000000000000..b32ce46573fc429b98537e042d522046511e3b7e
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/Concept.java
@@ -0,0 +1,315 @@
+/*
+ * Concept.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.entity;
+
+import java.util.*;
+import java.io.*;
+
+import com.googlecode.opennars.inference.*;
+import com.googlecode.opennars.language.*;
+import com.googlecode.opennars.main.*;
+import com.googlecode.opennars.operation.*;
+import com.googlecode.opennars.parser.*;
+import com.googlecode.opennars.storage.*;
+
+
+/**
+ * A concept contains information directly related to a term, including directly and indirectly related tasks and beliefs.
+ * <p>
+ * To make sure the space will be released, no other will refer to a concept, except in a concept bag.
+ */
+public final class Concept extends Item {
+    /* Constant term as the unique ID of the concept */
+    private Term term;
+    /* Direct Task lists (they may never be used for a Term that is not used as a Statement) */
+    private ArrayList<Judgement> directBeliefs;      // Judgments with the same content
+    private ArrayList<Goal> directGoals;            // Goals that can be directly achieved
+    private Question directQuestion;                // Question that can be directly answered
+    private boolean revisible = true;               // truth value of judgments can be revised
+    /* Link bags for indirect processing (always used) */
+    private ArrayList<TermLink> linkTemplates;  // templates of TermLink, only in Concepts for CompoundTerms
+    private TaskLinkBag taskLinks;
+    private TermLinkBag termLinks;
+    
+    /* ---------- constructor ---------- */
+    
+    /**
+     * Constructor
+     * @param tm A constant term corresponding to the concept
+     */
+    public Concept(Term tm, Memory memory) {
+        super(memory);
+        term = tm;
+        key = tm.toString();
+        directBeliefs = new ArrayList<Judgement>();
+        directGoals = new ArrayList<Goal>();
+        directQuestion = null;
+        taskLinks = new TaskLinkBag();
+        termLinks = new TermLinkBag();
+        if (tm instanceof CompoundTerm) {
+            linkTemplates = ((CompoundTerm) tm).prepareComponentLinks(getMemory());
+            checkRevisibility();
+        }
+    }
+    
+    private void checkRevisibility() {
+        revisible = !(term instanceof Tense);                                   // no tense
+        if (revisible)
+            revisible = ((key.indexOf("()") < 0) && (key.indexOf("(#")) < 0);   // no dependent variable
+    }
+    
+    /* ---------- add direct information as Tasks ---------- */
+    
+    /**
+     * New task to be directly processed in a constant time, called from Memory only
+     * @param task The task to be processed
+     */
+    public void directProcess(Task task) {
+        getMemory().currentTask = task;
+        Sentence sentence = task.getSentence();
+        if (sentence instanceof Question)
+            processQuestion(task);
+        else if (sentence instanceof Goal)
+            processGoal(task);
+        else
+            processJudgment(task);
+        getMemory().activateConcept(this, task.getBudget());
+    }
+    
+    /**
+     * New question to be directly answered by existing beliefs
+     * @param task The task to be processed
+     */
+    private void processQuestion(Task task) {
+        if (directQuestion == null)
+            directQuestion = (Question) task.getSentence();         // remember it
+        for (int i = 0; i < directBeliefs.size(); i++) {
+            Judgement judg = directBeliefs.get(i);
+            getMemory().getRuletables().getMatchingRules().trySolution(directQuestion, judg, task);    // look for better answer
+        }
+    }
+    
+    /**
+     * New judgment
+     * @param task The task to be processed
+     */
+    private void processJudgment(Task task) {
+        Judgement judg = (Judgement) task.getSentence();
+        if (revisible)
+            reviseTable(task, directBeliefs);
+        else
+            updateTable(task);
+        if (task.getPriority() > 0) {               // if still valuable --- necessary???
+            if (directQuestion != null)
+                getMemory().getRuletables().getMatchingRules().trySolution(directQuestion, judg, task);
+            for (int i = 0; i < directGoals.size(); i++) {
+                Goal goal = directGoals.get(i);
+                getMemory().getRuletables().getMatchingRules().trySolution(goal, judg, task);
+            }
+            addToTable(judg, directBeliefs, getMemory().getParameters().MAXMUM_BELIEF_LENGTH);
+        }
+    }
+    
+    /**
+     * New goal
+     * @param task The task to be processed
+     */
+    private void processGoal(Task task) {
+        Goal goal = (Goal) task.getSentence();
+        if (revisible)
+            reviseTable(task, directGoals);
+        else
+            updateTable(task);
+        for (int i = 0; i < directBeliefs.size(); i++) {
+            Judgement judg = directBeliefs.get(i);
+            getMemory().getRuletables().getMatchingRules().trySolution(goal, judg, task);
+        }
+        if (task.getPriority() > 0) {              // if still valuable
+            addToTable(goal, directGoals, getMemory().getParameters().MAXMUM_GOALS_LENGTH);         // with the feedbacks
+        }
+        decisionMaking(task);
+    }
+    
+    private void decisionMaking(Task task) {    // add plausibility
+        Goal goal = (Goal) task.getSentence();
+        float desire = 2 * goal.getTruth().getExpectation() - 1;
+        float quality = (desire < 0) ? 0 : desire;
+        task.setQuality(quality);
+    }
+    
+    // revise previous beliefs or goals
+    private void reviseTable(Task task, ArrayList table) {
+        Judgement belief;
+        for (int i = 0; i < table.size(); i++) {    // call select()
+            belief = (Judgement) table.get(i);
+            if (belief.noOverlapping((Judgement) task.getSentence()))
+                getMemory().getRuletables().getMatchingRules().revision(task, belief, false);
+        }
+    }
+    
+    // to be rewritten
+    private void updateTable(Task task) {
+//        Judgement belief;
+//        for (int i = 0; i < directBeliefs.size(); i++) {    // call select()
+//            belief = directBeliefs.get(i);
+//            if (((Judgement) task.getSentence()).getBase().latest() > belief.getBase().latest())
+//                getMemory().getRuletables().getMatchingRules().update(task, belief);
+//        }
+    }
+    
+    // add the Task as a new direct Belief or Goal, remove redundant ones
+    // table sorted by rank
+    private void addToTable(Judgement newJudgement, ArrayList table, int capacity) {
+        float rank1 = this.budgetfunctions.rankBelief(newJudgement);    // for the new belief
+        Base base1 = newJudgement.getBase();
+        Judgement judgement2;
+        float rank2;
+        int i;
+        for (i = 0; i < table.size(); i++) {        // go through everyone
+            judgement2 = (Judgement) table.get(i);
+            rank2 = this.budgetfunctions.rankBelief(judgement2); // previous belief
+            if (rank1 >= rank2) {
+                if (newJudgement.equivalentTo(judgement2))
+                    return;
+                table.add(i, newJudgement);
+                break;
+            }
+        }
+        if (table.size() == capacity)
+            table.remove(capacity - 1);
+        else if (i == table.size())
+            table.add(newJudgement);
+    }
+
+    // return a piece of Belief to be used with the task
+    // get the first qualified one
+    public Judgement getBelief(Task task) {
+        Sentence sentence = task.getSentence();
+        Judgement belief;
+        for (int i = 0; i < directBeliefs.size(); i++) {
+            belief = directBeliefs.get(i);
+            if ((sentence instanceof Question) || belief.noOverlapping((Judgement) sentence)) {
+                return belief;
+            }
+        }
+        return null;
+    }
+    
+    /* ---------- insert relational information as Links ---------- */
+    
+    public ArrayList<TermLink> getTermLinks() {
+        return linkTemplates;
+    }
+    
+    // insert TaskLink into the task base, called from Memory only
+    public void insertTaskLink(TaskLink taskLink) {
+        BudgetValue budget = taskLink.getBudget();
+        taskLinks.putIn(taskLink);
+        getMemory().activateConcept(this, budget);       // activate the concept
+        if (term instanceof CompoundTerm)
+            buildTermLinks(budget);
+    }
+    
+    private void buildTermLinks(BudgetValue budget) {
+        Term t;
+        Concept c;
+        TermLink cLink1, cLink2;
+        BudgetValue subBudget = this.budgetfunctions.distributeAmongLinks(budget, linkTemplates.size());
+        if (!subBudget.aboveThreshold())
+            return;
+        for(TermLink link : linkTemplates) {
+            t = link.getTarget();
+            c = getMemory().getConcept(t);
+            cLink1 = new TermLink(t, link, subBudget, getMemory());
+            insertTermLink(cLink1);   // this link to that
+            cLink2 = new TermLink(term, link, subBudget, getMemory());
+            c.insertTermLink(cLink2);   // that link to this
+            if (t instanceof CompoundTerm)
+                c.buildTermLinks(subBudget);
+        }
+    }
+    
+    // insert TermLink into the Belief base, called from Memory only
+    public void insertTermLink(TermLink cLink) {
+        termLinks.putIn(cLink);
+        getMemory().activateConcept(this, cLink.getBudget());
+    }
+    
+    /* ---------- main loop ---------- */
+    
+    // a single step of syllogism within a concept
+    public void fire() {
+        TaskLink tLink = (TaskLink) taskLinks.takeOut();
+        if (tLink == null)
+            return;
+        getMemory().currentTaskLink = tLink;
+        getMemory().currentBeliefLink = null;
+        Task task = tLink.getTargetTask();
+        getMemory().currentTask = task;
+        if ((tLink.getType() == TermLink.TRANSFORM) && !task.isStructual()) {
+            getMemory().getRuletables().transformTask(task, tLink);      // inference from a TaskLink and the Task --- for Product and Image
+            return; // cannot be used otherwise
+        }
+        TermLink bLink = (TermLink) termLinks.takeOut(tLink);  // to avoid repeated syllogism
+        if (bLink != null) {
+            getMemory().currentBeliefLink = bLink;
+            getMemory().getRuletables().reason(tLink, bLink);
+            termLinks.putBack(bLink);
+        }
+        taskLinks.putBack(tLink);
+    }
+    
+    /* ---------- utility ---------- */
+    
+    public Term getTerm() {     // called from Memory only
+        return term;
+    }
+    
+    public String toString() {  // called from concept bag
+    	return (super.toString2() + " " + key);
+    }
+    
+    public float getQuality() {         // re-calculate-and-set? consider syntactic complexity?
+        return UtilityFunctions.and(taskLinks.averagePriority(), termLinks.averagePriority());
+    }
+    
+    /* ---------- reporting ---------- */
+    
+    // display direct belief, questions, and goals
+    public String displayContent() {
+        StringBuffer buffer = new StringBuffer();
+        if (directBeliefs.size() > 0) {
+            buffer.append("  Beliefs:\n");
+            for (int i = 0; i < directBeliefs.size(); i++)
+                buffer.append(directBeliefs.get(i) + "\n");
+        }
+        if (directGoals.size() > 0) {
+            buffer.append("\n  Goals:\n");
+            for (int i = 0; i < directGoals.size(); i++)
+                buffer.append(directGoals.get(i) + "\n");
+        }
+        if (directQuestion != null)
+            buffer.append("\n  Question:\n" + directQuestion + "\n");
+        return buffer.toString();
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/entity/Goal.java b/open-nars/com/googlecode/opennars/entity/Goal.java
new file mode 100644
index 0000000000000000000000000000000000000000..8cf4c4272455f2ed18edadf01feef3e80525e71b
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/Goal.java
@@ -0,0 +1,35 @@
+/*
+ * Goal.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.entity;
+
+import com.googlecode.opennars.language.Term;
+import com.googlecode.opennars.main.Memory;
+
+/**
+ * A Goal is an event to be realized, and may conain query variables
+ */
+public class Goal extends Judgement {
+    public Goal(Term term, char punc, TruthValue t, Base b, Memory memory) {
+        super(term, punc, t, b, memory);
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/entity/Item.java b/open-nars/com/googlecode/opennars/entity/Item.java
new file mode 100644
index 0000000000000000000000000000000000000000..636d801d00dd6b56c6f98cd7ee01a6a6ce590a18
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/Item.java
@@ -0,0 +1,78 @@
+/*
+ * Item.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.entity;
+
+import com.googlecode.opennars.main.Memory;
+
+/**
+ * An item is an object that can be put into a Bag,
+ * and it participates in the resource competation of the system.
+ */
+public abstract class Item extends BudgetValue implements Cloneable {
+
+	/**
+     * The key of the Item, unique in a Bag
+     */
+    protected String key;   // uniquely define an Item in a bag
+    
+    protected Item(Memory memory) {
+    	super(memory);
+    }
+    
+    protected Item(BudgetValue v, Memory memory) {
+        super(v, memory);
+    }
+            
+    /**
+     * Get the current key
+     * @return Current key value
+     */
+    public String getKey() {
+        return key;
+    }
+    
+    /**
+     * Set a new key value
+     * @param k New key value
+     */
+    public void setKey(String k) {
+        key = k;
+    }
+
+    /**
+     * Get current BudgetValue
+     * @return Current BudgetValue
+     */
+    public BudgetValue getBudget() {
+        return this;
+    }
+
+    /**
+     * Set new BudgetValue
+     * @param v new BudgetValue
+     */
+    public void setBudget(BudgetValue v) {      // is this necessary?
+        setPriority(v.getPriority());
+        setDurability(v.getDurability());
+        setQuality(v.getQuality());
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/entity/Judgement.java b/open-nars/com/googlecode/opennars/entity/Judgement.java
new file mode 100644
index 0000000000000000000000000000000000000000..0d632d9b699fd54282677dfc3abca486ccde9db9
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/Judgement.java
@@ -0,0 +1,82 @@
+/*
+ * Judgement.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.entity;
+
+import com.googlecode.opennars.language.Term;
+import com.googlecode.opennars.main.*;
+
+/**
+ * A Judgement is an piece of new knowledge to be absorbed.
+ */
+public class Judgement extends Sentence {
+    
+    public Judgement(Term term, char punc, TruthValue t, Base b, Memory memory) {
+        content = term;
+        punctuation = punc;
+        truth = t;
+        base = b;
+        this.memory = memory;
+    }
+  
+    public TruthValue getTruth() {
+        return truth;
+    }
+
+    public float getFrequency() {
+        return truth.getFrequency();
+    }
+
+    public float getConfidence() {
+        return truth.getConfidence();
+    }
+
+    public Base getBase() {
+        return base;
+    }
+
+    boolean equivalentTo(Judgement judgement2) {
+        return (truth.equals(judgement2.getTruth()) && base.equals(judgement2.getBase())); // may have different key
+    }
+
+    public float getExpectationDifference(Judgement that) {
+        return getTruth().getExpDifAbs(that.getTruth());
+    }
+    
+    public float solutionQuality(Sentence sentence) {
+        Term problem = sentence.getContent(); 
+        if (sentence instanceof Goal) 
+            return truth.getExpectation();
+        else if (problem.isConstant())          // "yes/no" question
+            return truth.getConfidence();                                 // by confidence
+        else                                                            // "what" question or goal
+            return truth.getExpectation() / content.getComplexity();      // by likelihood/simplicity, to be refined
+    }
+    
+    public boolean noOverlapping(Judgement judgement) {
+        Base b = Base.make(base, judgement.getBase());
+        if (b == null)
+            return false;
+        memory.currentBase = b;
+        return true;
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/entity/Question.java b/open-nars/com/googlecode/opennars/entity/Question.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa677eb8ea739edea8258edb76676f421d208d50
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/Question.java
@@ -0,0 +1,38 @@
+/*
+ * Question.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.entity;
+
+import com.googlecode.opennars.language.Term;
+import com.googlecode.opennars.main.Memory;
+
+/**
+ * A Question is a sentence without a truth value needs evaluation, and may conain query variables
+ */
+public class Question extends Sentence {
+
+    public Question(Term term, char punc, Memory memory) {
+        content = term;
+        punctuation = punc;
+        this.memory = memory;
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/entity/Sentence.java b/open-nars/com/googlecode/opennars/entity/Sentence.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d1d60ed3145c26f2d659f3a290d245c012cef65
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/Sentence.java
@@ -0,0 +1,156 @@
+/*
+ * Sentence.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.entity;
+
+import com.googlecode.opennars.language.*;
+import com.googlecode.opennars.main.*;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A Sentence contains a Statement, a TruthValue, and a Base list.
+ *<p>
+ * It is used as the premises and conclusions of all inference rules.
+ */
+public abstract class Sentence {    
+    protected Term content;
+    protected char punctuation;
+    protected TruthValue truth = null;
+    protected Base base = null;
+    protected boolean input = false;            // whether it is an input sentence
+    protected Judgement bestSolution = null;       // for Question and Goal
+    protected Memory memory;					// to change things
+//    protected Object token;						// to track information through inferences
+    
+    /**
+     * Make a Sentence from an input String. Called by StringParser.
+     * @param term The content of the sentence
+     * @param punc The punctuation (and therefore, type) of the sentence
+     * @param truth The truth value of the sentence, if it is a Judgement (or Goal)
+     * @param base The base of the truth value (for Judgement or Goal)
+     * @return the Sentence generated from the arguments
+     */
+    public static Sentence make(Term term, char punc, TruthValue truth, Base base, Memory memory) {
+        if (term instanceof CompoundTerm)
+            ((CompoundTerm) term).renameVariables();
+        switch (punc) {
+            case Symbols.JUDGMENT_MARK:
+                return new Judgement(term, punc, truth, base, memory);
+            case Symbols.GOAL_MARK:
+                return new Goal(term, punc, truth, base, memory);
+            case Symbols.QUESTION_MARK:
+                return new Question(term, punc, memory);
+            default:
+                return null;
+        }
+    }
+
+    /**
+     * Make a derived Sentence. Called by memory 
+     * @param term The content of the sentence
+     * @param oldS A sample sentence providing the type of the new sentence
+     * @param truth The truth value of the sentence, if it is a Judgement (or Goal)
+     * @param base The base of the truth value (for Judgement or Goal)
+     * @return the Sentence generated from the arguments
+     */
+    public static Sentence make(Sentence oldS, Term term, TruthValue truth, Base base, Memory memory) {
+        if (term instanceof CompoundTerm)
+            ((CompoundTerm) term).renameVariables();
+        if (oldS instanceof Question)
+            return new Question(term, Symbols.QUESTION_MARK, memory);
+        if (oldS instanceof Goal)
+            return new Goal(term, Symbols.GOAL_MARK, truth, base, memory);
+        return new Judgement(term, Symbols.JUDGMENT_MARK, truth, base, memory);
+    }
+    
+    public Term getContent() {
+        return content;
+    }
+
+    public Term cloneContent() {
+        return (Term) content.clone();
+    }
+
+    public TruthValue getTruth() {
+        return null;
+    }
+
+    public Base getBase() {
+        return null;
+    }
+    
+    // distinguish Judgement from Goal
+    public boolean isJudgment() {
+        return (punctuation == Symbols.JUDGMENT_MARK);
+    }
+
+    public boolean isInput() {
+        return input;
+    }
+    
+    public void setInput() {
+        input = true;
+    }
+
+    public Judgement getBestSolution() {
+        return bestSolution;
+    }
+    
+    public void setBestSolution(Judgement judg) {
+        bestSolution = judg;
+        if (input)
+            memory.report(judg, false);        // report answer to input question
+    }
+    
+    // display a sentence
+    public String toString() {
+        StringBuffer s = new StringBuffer();
+        s.append(content.getName());
+        s.append(punctuation + " ");
+        if (truth != null) {
+            s.append(truth.toString()); 
+            s.append(base.toString());
+        }
+        if (bestSolution != null)
+            s.append("BestSolution: " + bestSolution);
+        
+        return s.toString();
+    }
+    
+    // display a sentence in compact form (2 digits)
+    public String toString2() {
+        StringBuffer s = new StringBuffer();
+        s.append(content.getName());
+        s.append(punctuation + " ");
+        if (truth != null) {
+            s.append(truth.toString2()); 
+        }
+        return s.toString();
+    }
+
+	public boolean isGoal() {
+		return (this.punctuation == Symbols.GOAL_MARK);
+	}
+	
+	public boolean isQuestion() {
+		return (this.punctuation == Symbols.QUESTION_MARK);
+	}
+}
diff --git a/open-nars/com/googlecode/opennars/entity/ShortFloat.java b/open-nars/com/googlecode/opennars/entity/ShortFloat.java
new file mode 100644
index 0000000000000000000000000000000000000000..654691d4cd1ac21c7d72066b32f5a35b72dc4109
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/ShortFloat.java
@@ -0,0 +1,78 @@
+/*
+ * ShortFloat.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.entity;
+
+/**
+ * A float value in [0, 1], with 4 digits accuracy.
+ */
+public class ShortFloat implements Cloneable {
+    
+    // the values are saved as short integers (-32768 to 32767, only 0 to 10000 used),
+    // but used as float
+    private short value;
+    
+    public ShortFloat(float v) {
+        setValue(v);
+    }
+    
+    // access value
+    public float getValue() {
+        return (float) (value * 0.0001);
+    }
+
+    public short getShortValue() {
+        return value;
+    }
+    
+    // set new value, rounded, with validity checking
+    public void setValue(float v) {
+        if ((v < 0) || (v > 1))
+            System.out.println("!!! Wrong value: " + v);
+        else
+            value = (short) (v * 10000.0 + 0.5);
+    }
+    
+    public boolean equals(Object that) {
+        return ((that instanceof ShortFloat) && (value == ((ShortFloat) that).getShortValue()));
+    }
+    
+    // full output
+    public String toString() {
+        if (value == 10000)
+            return "1.0000";
+        else {
+            String s = String.valueOf(value);
+            while (s.length() < 4)
+                s = "0" + s;
+            return "0." + s;
+        }
+    }
+    
+    // output with 2 digits, rounded
+    public String toString2() {
+        String s = toString();
+        if (s.length() > 4)
+            return s.substring(0, 4);
+        else
+            return s;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/entity/Task.java b/open-nars/com/googlecode/opennars/entity/Task.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd2943f77f7491b72cc70d205b041c9035e62b50
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/Task.java
@@ -0,0 +1,77 @@
+/*
+ * Task.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.entity;
+
+import com.googlecode.opennars.language.*;
+import com.googlecode.opennars.main.Memory;
+
+/**
+ * A task to be processed.
+ */
+public class Task extends Item {
+    private Sentence sentence;
+    protected boolean structual = false;        // whether it is based on a structual rule
+           
+    public Task(Sentence s, BudgetValue b, Memory memory) {
+        super(b, memory);
+        sentence = s;
+        key = sentence.toString();
+    }
+    
+    public Sentence getSentence() {
+        return sentence;
+    }
+
+    public Term getContent() {
+        return sentence.getContent();
+    }
+
+    public boolean isStructual() {
+        return structual;
+    }
+    
+    public void setStructual() {
+        structual = true;
+    }
+
+    public void merge(Item that) {
+        ((BudgetValue) this).merge(that.getBudget());
+        structual = (structual || ((Task) that).isStructual());
+    }
+
+    public String toString() {
+        StringBuffer s = new StringBuffer();
+        s.append(super.toString());
+        s.append(sentence);
+        return s.toString();
+    }
+
+    public String toString2() {
+        StringBuffer s = new StringBuffer();
+        if (sentence instanceof Question)
+            s.append(sentence);
+        else
+            s.append(((Judgement) sentence).toString2());
+        return s.toString();
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/entity/TaskLink.java b/open-nars/com/googlecode/opennars/entity/TaskLink.java
new file mode 100644
index 0000000000000000000000000000000000000000..45e51f1be834317209c5ef48d9b5243b4aa8aa8d
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/TaskLink.java
@@ -0,0 +1,88 @@
+/*
+ * TaskLink.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.entity;
+
+import java.util.*;
+
+import com.googlecode.opennars.language.Term;
+import com.googlecode.opennars.main.*;
+
+/**
+ * Reference to a Task.
+ * <p>
+ * The reason to separate a Task and a TaskLink is that a Task can be linked from multiple Concepts, with different BudgetValue.
+ */
+public class TaskLink extends TermLink {
+    private static final int RECORD_LENGTH = Parameters.TASK_INFERENCE_RECORD_LENGTH;
+    private Task targetTask;        // now "target" means a term !!!
+    private ArrayList<String> record; // remember the CompositionLinks that has been used recently
+    
+    public TaskLink(Task t, TermLink template, BudgetValue v, Memory memory) {
+        super(v, memory);
+        if (template == null) {
+            type = TermLink.SELF;
+            index = null;
+        } else {
+            type = template.getType();
+            index = template.getIndices();            
+        }
+        targetTask = t;
+        record = new ArrayList<String>(Parameters.TASK_INFERENCE_RECORD_LENGTH);
+        setKey();
+        key += t.getKey();
+    }
+    
+    public Task getTargetTask() {
+        return targetTask;
+    }
+    
+    public ArrayList<String> getRecord() {
+        return record;
+    }
+    
+    public void merge(Item that) {
+        ((BudgetValue) this).merge(that.getBudget());
+        ArrayList<String> v = ((TaskLink) that).getRecord();
+        for (int i = 0; i < v.size(); i++)
+            if (record.size() <= RECORD_LENGTH)
+                record.add(v.get(i));
+    }
+
+    // To check whether a TaskLink can use a TermLink
+    // return false if they intereacted recently
+    // called in CompositionBag only
+    // move into Task ?
+    public boolean novel(TermLink bLink) {
+        Term bTerm = bLink.getTarget();
+        if (bTerm.equals(targetTask.getSentence().getContent()))
+            return false;
+        String key = bLink.getKey();
+        for (int i = 0; i < record.size(); i++)
+            if (key.equals((String) record.get(i)))
+                return false;
+        record.add(key);       // add knowledge reference to record
+//        if (record.size() > RECORD_LENGTH)         // keep a constant length --- allow repeatation
+//            record.remove(0);
+        return true;
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/entity/TermLink.java b/open-nars/com/googlecode/opennars/entity/TermLink.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc6078893b0da34ea50e8bf6eba7498816008308
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/TermLink.java
@@ -0,0 +1,170 @@
+/*
+ * TermLink.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.entity;
+
+import com.googlecode.opennars.language.CompoundTerm;
+import com.googlecode.opennars.language.Term;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A link between a compound term and a component term
+ * <p>
+ * A TermLink links the current Term to a target Term, which is 
+ * either a component of, or compound made from, the current term.
+ * <p>
+ * Both terms are constant.
+ * <p>
+ * The index value(s) indicates the location of the component in the compound.
+ */
+public class TermLink extends Item {
+
+    public static final short SELF = 0;                 // TaskLink only
+    public static final short COMPONENT = 1;
+    public static final short COMPOUND = 2;
+    public static final short COMPONENT_STATEMENT = 3;
+    public static final short COMPOUND_STATEMENT = 4;
+    public static final short COMPONENT_CONDITION = 5;
+    public static final short COMPOUND_CONDITION = 6;
+    public static final short TRANSFORM = 7;            // TaskLink only
+        
+    private Term target;
+    protected short type;
+    protected short[] index;
+    
+    public TermLink(Memory memory) {
+    	super(memory);
+    }
+    
+    /**
+     * Simplest constructor, called in CompoundTerm and Implication
+     * @param t target Term
+     * @param p link type
+     * @param i component index in compound
+     */
+    public TermLink(Term t, short p, int i, Memory memory) {
+    	super(memory);
+        target = t;
+        type = p;
+        index = new short[1];
+        index[0] = (short) i;
+        setKey();
+    }
+
+    public TermLink(Term t, short p, int i, int j, Memory memory) {
+    	super(memory);
+        target = t;
+        type = p;
+        index = new short[2];
+        index[0] = (short) i;
+        index[1] = (short) j;
+        setKey();
+    }
+
+    public TermLink(Term t, short p, int i, int j, int k, Memory memory) {
+    	super(memory);
+        target = t;
+        type = p;
+        index = new short[3];
+        index[0] = (short) i;
+        index[1] = (short) j;
+        index[2] = (short) k;
+        setKey();
+    }
+
+    protected TermLink(BudgetValue v, Memory memory) {
+        super(v, memory);
+    }
+    
+    // the CompotionLink that is actually inserted
+    public TermLink(Term t, TermLink template, BudgetValue v, Memory memory) {
+        super(v, memory);
+        target = t;
+        type = template.getType();
+        if (template.getTarget().equals(target)) 
+            type = reverse(type);
+        index = template.getIndices();
+        setKey();
+    }
+
+    protected void setKey() {
+        String at1, at2;
+        if (toComponent()) {
+            at1 = Symbols.LinkToComponent_at1;
+            at2 = Symbols.LinkToComponent_at2;
+        } else {
+            at1 = Symbols.LinkToCompound_at1;
+            at2 = Symbols.LinkToCompound_at2;            
+        }
+        String in = "T" + type;
+        if (index != null)
+            for (int i = 0; i < index.length; i++) {
+                in += "-" + (index[i]+1);
+            }
+        key = at1 + in + at2;
+        if (target != null)
+            key += target;
+    }
+    
+    public Term getTarget() {
+        return target;
+    }
+
+    public short getType() {
+        return type;
+    }
+    
+    public boolean toComponent() {
+        return ((type % 2) > 0);
+    }
+
+    public int indexLength() {
+        return (index == null)? 0 : index.length;
+    }
+    
+    public short[] getIndices() {
+        return index;
+    }
+    
+    public short getIndex(int i) {
+        if ((index != null) && (i < index.length))
+            return index[i];
+        else
+            return -1;
+    }
+    
+    protected short reverse(short i) {
+        if ((i % 2) == 0)
+            return (short) (i - 1);
+        else
+            return (short) (i + 1);
+    }
+    
+    public String toString() {
+        return (super.toString() + " " + key);
+    }
+
+    public String toString2() {
+        return (super.toString2() + " " + key);
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/entity/TruthValue.java b/open-nars/com/googlecode/opennars/entity/TruthValue.java
new file mode 100644
index 0000000000000000000000000000000000000000..ecf9d719d8e787151599d1ffe2e244b10719b520
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/TruthValue.java
@@ -0,0 +1,81 @@
+/*
+ * TruthValue.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.entity;
+
+import com.googlecode.opennars.language.Term;
+import com.googlecode.opennars.parser.*;
+
+/**
+ * Frequency and confidence.
+ */
+public class TruthValue { // implements Cloneable {
+    public static final char DELIMITER = Symbols.TRUTH_VALUE_MARK;       // default
+    public static final char SEPARATOR = Symbols.VALUE_SEPARATOR;    // default
+    protected ShortFloat frequency;
+    protected ShortFloat confidence;
+        
+    public TruthValue(float f, float c) {
+        frequency = new ShortFloat(f);
+        confidence = new ShortFloat(c);
+    }
+    
+    public TruthValue(TruthValue v) {
+        frequency = new ShortFloat(v.getFrequency());
+        confidence = new ShortFloat(v.getConfidence());
+    }
+        
+    public float getFrequency() {
+        return frequency.getValue();
+    }
+        
+    public float getConfidence() {
+        return confidence.getValue();
+    }
+        
+    public float getExpectation() {
+        return (float) (confidence.getValue() * (frequency.getValue() - 0.5) + 0.5);
+    }
+    
+    public float getExpDifAbs(float e) {
+        return Math.abs(e - getExpectation());
+    }
+    
+    public float getExpDifAbs(TruthValue t) {
+        return getExpDifAbs(t.getExpectation());
+    }
+    
+    public boolean equals(Object that) {
+        return ((that instanceof TruthValue) 
+                && (getFrequency() == ((TruthValue) that).getFrequency())
+                && (getConfidence() == ((TruthValue) that).getConfidence()));
+    }
+    
+    // full output
+    public String toString() {
+        return DELIMITER + frequency.toString() + SEPARATOR + confidence.toString() + DELIMITER;
+    }
+    
+    // short output
+    public String toString2() {
+        return DELIMITER + frequency.toString2() + SEPARATOR + confidence.toString2() + DELIMITER;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/entity/package.html b/open-nars/com/googlecode/opennars/entity/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..ffbdf26feae18dffab1f0cb478624683dbc2e22d
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/entity/package.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+
+Data entities that are independently stored
+
+<h2>Package Specification</h2>
+
+<ul>
+<li>ShortFloats: BudgetValue (priority/durability/quality) and TruthValue (frequency/confidence)</li>
+<li>Base: serial numbers associated to TruthVallue</li>
+<li>Sentence: a Term, a TruthValue, and a Base. A Sentence can be a Judgment, a Goal, or a Question.</li>
+<li>Task: a Sentence to be processed.</li>
+<li>TermLink: built in pair between a compound term and a component term.</li>
+<li>TaskLink: special TermLink refering to a Task, whose Term equals or directly contains the current Term.</li>
+<li>Concept: labeled by a Term, contains a TaskLink bag and a TermLink bag for indirect tasks/beliefs, as well as beliefs/questions/goals directly on the Term.</li>
+<li>Item: Concept, Task, or TermLink</li>
+</ul>    
+
+</body>
+</html>
diff --git a/open-nars/com/googlecode/opennars/inference/BudgetFunctions.java b/open-nars/com/googlecode/opennars/inference/BudgetFunctions.java
new file mode 100644
index 0000000000000000000000000000000000000000..a491a76971d163c557ff49ec38d3d0e666e1596e
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/inference/BudgetFunctions.java
@@ -0,0 +1,239 @@
+/*
+ * BudgetFunctions.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.inference;
+
+import com.googlecode.opennars.entity.*;
+import com.googlecode.opennars.language.Term;
+import com.googlecode.opennars.main.*;
+
+/**
+ * Budget functions controlling the resources allocation
+ */
+public class BudgetFunctions extends UtilityFunctions {    
+    
+	private Memory memory;
+	
+	public BudgetFunctions(Memory memory) {
+		this.memory = memory;
+	}
+	
+    /* ----------------------- Belief evaluation ----------------------- */
+    
+    /**
+     * Determine the quality of a judgment by its truth value
+     * <p>
+     * Mainly decided by confidence, though binary judgment is also preferred
+     * @param t The truth value of a judgment
+     * @return The quality of the judgment, according to truth value only
+     */
+    public  float truthToQuality(TruthValue t) {
+        float freq = t.getFrequency();
+        float conf = t.getConfidence();
+        return and(conf, Math.abs(freq - 0.5f) + freq * 0.5f);
+    }
+
+    /**
+     * Determine the rank of a judgment by its confidence and originality (base length)
+     * <p>
+     * @param judg The judgment to be ranked
+     * @return The rank of the judgment, according to truth value only
+     */
+    public  float rankBelief(Judgement judg) {
+//        TruthValue truth = judg.getTruth();
+//        float quality = truthToQuality(truth);
+        float confidence = judg.getConfidence();
+        float originality = 1.0f / (judg.getBase().length() + 1);
+        return or(confidence, originality);
+    }
+    
+    /* ----- Functions used both in direct and indirect processing of tasks ----- */
+
+    /**
+     * Evaluate the quality of a belief as a solution to a problem, then reward the belief and de-prioritize the problem
+     * @param problem The problem (question or goal) to be solved
+     * @param solution The belief as solution
+     * @param task The task to be immediatedly processed, or null for continued process
+     * @return The budget for the new task which is the belief activated, if necessary
+     */
+     BudgetValue solutionEval(Sentence problem, Judgement solution, Task task) {
+        BudgetValue budget = null;
+        boolean feedbackToLinks = false;
+        if (task == null) {                 // called in continued processing
+            task = memory.currentTask;
+            feedbackToLinks = true;
+        }
+        boolean judgmentTask = task.getSentence().isJudgment();
+        float quality;                      // the quality of the solution
+        if (problem instanceof Question) 
+            quality = solution.solutionQuality((Question) problem);
+        else // problem is goal
+            quality = solution.getTruth().getExpectation();
+        if (judgmentTask)
+            task.incPriority(quality);
+        else {
+            task.setPriority(Math.min(1 - quality, task.getPriority()));
+            budget = new BudgetValue(quality, task.getDurability(), truthToQuality(solution.getTruth()), memory);
+        }
+        if (feedbackToLinks) {
+            TaskLink tLink = memory.currentTaskLink;
+            tLink.setPriority(Math.min(1 - quality, tLink.getPriority()));
+            TermLink bLink = memory.currentBeliefLink;
+            bLink.incPriority(quality);
+        }
+        return budget;
+    }
+
+    /**
+     * Evaluate the quality of a revision, then de-prioritize the premises
+     * @param tTruth The truth value of the judgment in the task
+     * @param bTruth The truth value of the belief
+     * @param truth The truth value of the conclusion of revision
+     * @param task The task to be immediatedly or continuely processed
+     * @return The budget for the new task 
+     */
+     BudgetValue revise(TruthValue tTruth, TruthValue bTruth, TruthValue truth, Task task, boolean feedbackToLinks) {
+        float difT = truth.getExpDifAbs(tTruth);
+        task.decPriority(1 - difT);
+        task.decDurability(1 - difT);
+        if (feedbackToLinks) {
+            TaskLink tLink = memory.currentTaskLink;
+            tLink.decPriority(1 - difT);
+            tLink.decDurability(1 - difT);
+            TermLink bLink = memory.currentBeliefLink;
+            float difB = truth.getExpDifAbs(bTruth);
+            bLink.decPriority(1 - difB);            
+            bLink.decDurability(1 - difB);
+        }
+        float dif = truth.getConfidence() - Math.max(tTruth.getConfidence(), bTruth.getConfidence());
+        float priority = or(dif, task.getPriority());
+        float durability = or(dif, task.getDurability());
+        float quality = truthToQuality(truth);
+        return new BudgetValue(priority, durability, quality, memory);
+    }
+    
+    /* ----------------------- Links ----------------------- */
+    
+    public  BudgetValue distributeAmongLinks(BudgetValue b, int n) {
+        float priority = (float) (b.getPriority() / Math.sqrt(n));
+        return new BudgetValue(priority, b.getDurability(), b.getQuality(), memory);
+    }
+
+    /* ----------------------- Concept ----------------------- */
+
+    /**
+     * Activate a concept by an incoming item (Task, TaskLink, or TermLink)
+     * @param concept The concept
+     * @param budget The budget for the new item 
+     */
+    public  void activate(Concept concept, BudgetValue budget) {
+        float quality = aveAri(concept.getQuality(), budget.getPriority());
+        float oldPri = concept.getPriority();
+        float priority = or(oldPri, quality);
+        float durability = aveAri(concept.getDurability(), budget.getDurability(), oldPri / priority);
+        concept.setPriority(priority);
+        concept.setDurability(durability);
+        concept.setQuality(quality);
+    }
+
+    /* ---------------- Bag functions, on all Items ------------------- */
+    
+    /**
+     * Decrease Priority after an item is used, called in Bag
+     * <p>
+     * After a constant time, p should become d*p.  Since in this period, the item is accessed c*p times, 
+     * each time p-q should multiple d^(1/(c*p)). 
+     * The intuitive meaning of the parameter "forgetRate" is: after this number of times of access, 
+     * priority 1 will become d, it is a system parameter adjustable in run time.
+     *
+     * @param budget The previous budget value
+     * @param forgetRate The budget for the new item
+     */
+    public static  void forget(BudgetValue budget, float forgetRate, float relativeThreshold) {
+        double quality = budget.getQuality() * relativeThreshold;      // re-scaled quality
+        double p = budget.getPriority() - quality;                     // priority above quality
+        if (p > 0)
+            quality += p * Math.pow(budget.getDurability(), 1.0 / (forgetRate * p));    // priority Durability
+        budget.setPriority((float) quality);
+    }
+    
+    /**
+     * Merge an item into another one in a bag, when the two are identical except in budget values
+     * @param baseValue The budget value to be modified
+     * @param adjustValue The budget doing the adjusting
+     */
+    public  void merge(BudgetValue baseValue, BudgetValue adjustValue) {
+        baseValue.incPriority(adjustValue.getPriority());
+        baseValue.setDurability(Math.max(baseValue.getDurability(), adjustValue.getDurability()));
+        baseValue.setQuality(Math.max(baseValue.getQuality(), adjustValue.getQuality()));
+    }
+
+    /* ----- Task derivation in MatchingRules and SyllogisticRules ----- */
+
+    /**
+     * Forward inference result and adjustment
+     * @param truth The truth value of the conclusion
+     * @return The budget value of the conclusion
+     */
+     BudgetValue forward(TruthValue truth) {
+        return budgetInference(truthToQuality(truth), 1);
+    }
+    
+    // backward inference result and adjustment
+    public  BudgetValue backward(TruthValue truth) {
+        return budgetInference(truthToQuality(truth), 1);
+    }
+    
+    public  BudgetValue backwardWeak(TruthValue truth) {
+        return budgetInference(w2c(1) * truthToQuality(truth), 1);
+    }
+
+    /* ----- Task derivation in CompositionalRules and StructuralRules ----- */
+
+    // forward inference with CompoundTerm conclusion and adjustment
+    public  BudgetValue compoundForward(TruthValue truth, Term content) {
+        return budgetInference(truthToQuality(truth), content.getComplexity());
+    }
+    
+    public  BudgetValue compoundBackward(Term content) {
+        return budgetInference(1, content.getComplexity());
+    }
+
+    public  BudgetValue compoundBackwardWeak(Term content) {
+        return budgetInference(w2c(1), content.getComplexity());
+    }
+
+    /* ----- common function for all inference ----- */
+    
+    private  BudgetValue budgetInference(float qual, int complexity) {
+        TaskLink tLink = memory.currentTaskLink;
+        TermLink bLink = memory.currentBeliefLink;
+        float priority = tLink.getPriority();
+        float durability = tLink.getDurability();
+        float quality = (float) (qual / Math.sqrt(complexity));
+        if (bLink != null) {
+            priority = aveAri(priority, bLink.getPriority());
+            durability = aveAri(durability, bLink.getDurability());
+            bLink.incPriority(quality);
+        }
+        return new BudgetValue(and(priority, quality), and(durability, quality), quality, memory);
+    }    
+}
diff --git a/open-nars/com/googlecode/opennars/inference/CompositionalRules.java b/open-nars/com/googlecode/opennars/inference/CompositionalRules.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a6b77b05eabdef8c8d8b4b710abe7601b6a49be
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/inference/CompositionalRules.java
@@ -0,0 +1,370 @@
+/*
+ * CompositionalRules.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.inference;
+
+import com.googlecode.opennars.entity.*;
+import com.googlecode.opennars.language.*;
+import com.googlecode.opennars.main.*;
+import com.googlecode.opennars.parser.*;
+
+/**
+ * Compound term composition and decomposition rules, with two premises.
+ * <p>
+ * Forward inference only, except the last rule (abdDepOuter) can also be used backward.
+ */
+public class CompositionalRules {
+	
+	private Memory memory;
+	private BudgetFunctions budgetfunctions;
+	
+	public CompositionalRules(Memory memory) {
+		this.memory = memory;
+		this.budgetfunctions = new BudgetFunctions(memory);
+	}
+    
+    /* -------------------- intersections and differences -------------------- */
+    
+    /**
+     * {<S ==> M>, <P ==> M>} |- {<(S|P) ==> M>, <(S&P) ==> M>, <(S-P) ==> M>, <(P-S) ==> M>}
+     * 
+     * @param sentence The first premise
+     * @param belief The second premise
+     * @param index The location of the shared term
+     */
+     void composeCompound(Sentence sentence, Judgement belief, int index) {
+        if (!sentence.isJudgment())
+            return;                             // forward only
+        Statement content1 = (Statement) sentence.getContent();
+        Statement content2 = (Statement) belief.getContent();
+        if (content1.getClass() != content2.getClass())
+            return;
+        if (content1.getTemporalOrder() != content2.getTemporalOrder())
+            return;
+        Term component1, component2;
+        component1 = content1.componentAt(1 - index);
+        component2 = content2.componentAt(1 - index);
+        Term component = content1.componentAt(index);
+        if ((component1 instanceof CompoundTerm) && ((CompoundTerm) component1).containAllComponents(component2)) {
+            decomposeCompound((CompoundTerm) component1, component2, component, index, true);
+            return;
+        } else if ((component2 instanceof CompoundTerm) && ((CompoundTerm) component2).containAllComponents(component1)) {
+            decomposeCompound((CompoundTerm) component2, component1, component, index, false);
+            return;
+        }
+        Term t1 = null;
+        Term t2 = null;
+        Term t3 = null;
+        Term t4 = null;
+        TruthValue v1 = sentence.getTruth();
+        TruthValue v2 = belief.getTruth();
+        if (index == 0) {
+            if (content1 instanceof Inheritance) {
+                t1 = IntersectionInt.make(component1, component2, this.memory);
+                t2 = IntersectionExt.make(component1, component2, this.memory);
+                t3 = DifferenceExt.make(component1, component2, this.memory);
+                t4 = DifferenceExt.make(component2, component1, this.memory);
+            } else if (content1 instanceof Implication) {
+                t1 = Disjunction.make(component1, component2, this.memory);
+                t2 = Conjunction.make(component1, component2, this.memory);
+                t3 = Conjunction.make(component1, Negation.make(component2, this.memory), this.memory);
+                t4 = Conjunction.make(component2, Negation.make(component1, this.memory), this.memory);
+            }
+            processComposed(content1, component, t1, TruthFunctions.union(v1, v2));
+            processComposed(content1, component, t2, TruthFunctions.intersection(v1, v2));
+            processComposed(content1, component, t3, TruthFunctions.difference(v1, v2));
+            processComposed(content1, component, t4, TruthFunctions.difference(v2, v1));
+            if (content1.isConstant())
+                introVarDepOuter(content1, content2, index);
+        } else {
+            if (content1 instanceof Inheritance) {
+                t1 = IntersectionExt.make(component1, component2, this.memory);
+                t2 = IntersectionInt.make(component1, component2, this.memory);
+                t3 = DifferenceInt.make(component1, component2, this.memory);
+                t4 = DifferenceInt.make(component2, component1, this.memory);
+            } else if (content1 instanceof Implication) {
+                t1 = Conjunction.make(component1, component2, this.memory);
+                t2 = Disjunction.make(component1, component2, this.memory);
+                t3 = Disjunction.make(component1, Negation.make(component2, this.memory), this.memory);
+                t4 = Disjunction.make(component2, Negation.make(component1, this.memory), this.memory);
+            }
+            processComposed(content1, t1, component, TruthFunctions.union(v1, v2));
+            processComposed(content1, t2, component, TruthFunctions.intersection(v1, v2));
+            processComposed(content1, t3, component, TruthFunctions.difference(v1, v2));
+            processComposed(content1, t4, component, TruthFunctions.difference(v2, v1));
+            if (content1.isConstant())
+                introVarDepOuter(content1, content2, index);
+        }
+    }
+    
+    /**
+     * Finish composing compound term
+     * @param statement Type of the content
+     * @param subject Subject of content
+     * @param predicate Predicate of content
+     * @param truth TruthValue of the content
+     */
+    private  void processComposed(Statement statement, Term subject, Term predicate, TruthValue truth) {
+        if ((subject == null) || (predicate == null)) 
+            return;
+        Term content = Statement.make(statement, subject, predicate, this.memory);
+        if ((content == null) || content.equals(statement) || content.equals(this.memory.currentBelief.getContent()))
+            return;
+        BudgetValue budget = this.budgetfunctions.compoundForward(truth, content);
+        this.memory.doublePremiseTask(budget, content, truth);
+    }
+    
+    /**
+     * {<(S|P) ==> M>, <P ==> M>} |- <S ==> M>
+     * @param compound The compound term to be decomposed
+     * @param component The part of the compound to be removed
+     * @param term1 The other term in the content
+     * @param index The location of the shared term: 0 for subject, 1 for predicate
+     * @param compoundTask Whether the compound comes from the task
+     */
+    private  void decomposeCompound(CompoundTerm compound, Term component, Term term1, int index, boolean compoundTask) {
+        Term term2 = CompoundTerm.reduceComponents(compound, component, this.memory);
+        if (term2 == null)
+            return;
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        Judgement belief = this.memory.currentBelief;
+        Statement oldContent = (Statement) task.getContent();
+        TruthValue v1, v2;
+        if (compoundTask) {
+            v1 = sentence.getTruth();
+            v2 = belief.getTruth();
+        } else {
+            v1 = belief.getTruth();
+            v2 = sentence.getTruth();
+        }
+        TruthValue truth = null;
+        Term content;
+        if (index == 0) {
+            content = Statement.make(oldContent, term1, term2, this.memory);
+            if (content == null)
+                return;
+            if (oldContent instanceof Inheritance) {
+                if (compound instanceof IntersectionExt) {
+                    truth = TruthFunctions.reduceConjunction(v1, v2);
+                } else if (compound instanceof IntersectionInt) {
+                    truth = TruthFunctions.reduceDisjunction(v1, v2);
+                } else if ((compound instanceof SetInt) && (component instanceof SetInt)) {
+                    truth = TruthFunctions.reduceConjunction(v1, v2);
+                } else if ((compound instanceof SetExt) && (component instanceof SetExt)) {
+                    truth = TruthFunctions.reduceDisjunction(v1, v2);
+                } else if (compound instanceof DifferenceExt) {
+                    if (compound.componentAt(0).equals(component)) {
+                        truth = TruthFunctions.reduceDisjunction(v2, v1);
+                    } else {
+                        truth = TruthFunctions.reduceConjunctionNeg(v1, v2);
+                    }
+                }
+            } else if (oldContent instanceof Implication) {
+                if (compound instanceof Conjunction) {
+                    truth = TruthFunctions.reduceConjunction(v1, v2);
+                } else if (compound instanceof Disjunction) {
+                    truth = TruthFunctions.reduceDisjunction(v1, v2);
+                }
+            }
+        } else {
+            content = Statement.make(oldContent, term2, term1, this.memory);
+            if (content == null)
+                return;
+            if (oldContent instanceof Inheritance) {
+                if (compound instanceof IntersectionInt) {
+                    truth = TruthFunctions.reduceConjunction(v1, v2);
+                } else if (compound instanceof IntersectionExt) {
+                    truth = TruthFunctions.reduceDisjunction(v1, v2);
+                } else if ((compound instanceof SetExt) && (component instanceof SetExt)) {
+                    truth = TruthFunctions.reduceConjunction(v1, v2);
+                } else if ((compound instanceof SetInt) && (component instanceof SetInt)) {
+                    truth = TruthFunctions.reduceDisjunction(v1, v2);
+                } else if (compound instanceof DifferenceInt) {
+                    if (compound.componentAt(1).equals(component)) {
+                        truth = TruthFunctions.reduceDisjunction(v2, v1);
+                    } else {
+                        truth = TruthFunctions.reduceConjunctionNeg(v1, v2);
+                    }
+                }
+            } else if (oldContent instanceof Implication) {
+                if (compound instanceof Disjunction) {
+                    truth = TruthFunctions.reduceConjunction(v1, v2);
+                } else if (compound instanceof Conjunction) {
+                    truth = TruthFunctions.reduceDisjunction(v1, v2);
+                }
+            }
+        }
+        BudgetValue budget = this.budgetfunctions.compoundForward(truth, content);
+        this.memory.doublePremiseTask(budget, content, truth);
+    }
+        
+    /**
+     * {(||, S, P), P} |- S
+     * @param compound The compound term to be decomposed
+     * @param component The part of the compound to be removed
+     * @param compoundTask Whether the compound comes from the task
+     */
+     void decomposeStatement(CompoundTerm compound, Term component, boolean compoundTask) {
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        if (!sentence.isJudgment())
+            return;
+        Judgement belief = this.memory.currentBelief;
+        Term content = CompoundTerm.reduceComponents(compound, component, this.memory);
+        if (content == null)
+            return;
+        TruthValue v1, v2;
+        if (compoundTask) {
+            v1 = sentence.getTruth();
+            v2 = belief.getTruth();
+        } else {
+            v1 = belief.getTruth();
+            v2 = sentence.getTruth();
+        }        
+        TruthValue truth = null;
+        if (compound instanceof Conjunction) {
+            if (sentence instanceof Goal) {
+                if (compoundTask)
+                    truth = TruthFunctions.reduceDisjunction(v1, v2);
+                else
+                    return;
+            } else if (sentence instanceof Judgement)
+                truth = TruthFunctions.reduceConjunction(v1, v2);
+        } else if (compound instanceof Disjunction) {
+            if (sentence instanceof Goal) {
+                if (compoundTask)
+                    truth = TruthFunctions.reduceConjunction(v1, v2);
+                else
+                    return;
+            } else if (sentence instanceof Judgement)
+                truth = TruthFunctions.reduceDisjunction(v1, v2);
+        } else
+            return;
+        BudgetValue budget = this.budgetfunctions.compoundForward(truth, content);
+        this.memory.doublePremiseTask(budget, content, truth);
+    }
+    
+    /* ---------------- dependent variable and conjunction ---------------- */
+    
+    /**
+     * {<M --> S>, <M --> P>} |- (&&, <#x() --> S>, <#x() --> P>>
+     * @param premise1 The first premise <M --> P>
+     * @param premise2 The second premise <M --> P>
+     * @param index The location of the shared term: 0 for subject, 1 for predicate
+     */
+    private  Conjunction introVarDep(Statement premise1, Statement premise2, int index) {
+        Statement state1, state2;
+        Variable v1 = new Variable(Symbols.VARIABLE_TAG + "0()");
+        Variable v2 = new Variable(Symbols.VARIABLE_TAG + "0()");
+        if (index == 0) {
+            state1 = Statement.make(premise1, v1, premise1.getPredicate(), this.memory);
+            state2 = Statement.make(premise2, v2, premise2.getPredicate(), this.memory);
+        } else {
+            state1 = Statement.make(premise1, premise1.getSubject(), v1, this.memory);
+            state2 = Statement.make(premise2, premise2.getSubject(), v2, this.memory);
+        }
+        Conjunction content = (Conjunction) Conjunction.make(state1, state2, this.memory);
+        return content;
+    }
+
+    /**
+     * Introduce a dependent variable in an outer-layer conjunction
+     * @param premise1 The first premise <M --> S>
+     * @param premise2 The second premise <M --> P>
+     * @param index The location of the shared term: 0 for subject, 1 for predicate
+     */
+    private  void introVarDepOuter(Statement premise1, Statement premise2, int index) {
+        Term content = introVarDep(premise1, premise2, index);
+        TruthValue v1 = this.memory.currentTask.getSentence().getTruth();
+        TruthValue v2 = this.memory.currentBelief.getTruth();
+        TruthValue truth = TruthFunctions.intersection(v1, v2);
+        BudgetValue budget = this.budgetfunctions.compoundForward(truth, content);
+        this.memory.doublePremiseTask(budget, content, truth);
+    }
+    
+    /**
+     * Introduce a dependent variable in an inner-layer conjunction
+     * @param compound The compound containing the first premise
+     * @param component The first premise <M --> S>
+     * @param premise The second premise <M --> P>
+     */
+     void introVarDepInner(CompoundTerm compound, Term component, Term premise) {
+        if (!(component instanceof Statement) || !(component.getClass() == premise.getClass()))
+            return;
+        Statement premise1 = (Statement) premise;
+        Statement premise2 = (Statement) component;
+        int index;
+        if (premise1.getSubject().equals(premise2.getSubject()))
+            index = 0;
+        else if (premise1.getPredicate().equals(premise2.getPredicate()))
+            index = 1;
+        else
+            return;
+        Term innerContent = introVarDep(premise1, premise2, index);
+        if (innerContent == null)
+            return;
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        Judgement belief = this.memory.currentBelief;
+        Term content = task.getContent();
+        if (compound instanceof Implication)
+            content = Statement.make((Statement) content, compound.componentAt(0), innerContent, this.memory);
+        else if (compound instanceof Conjunction)
+            content = CompoundTerm.replaceComponent(compound, component, innerContent, this.memory);
+        TruthValue truth = null;
+        if (sentence instanceof Goal)
+            truth = TruthFunctions.intersection(belief.getTruth(), sentence.getTruth());    // to be revised
+        else if (sentence instanceof Judgement)
+            truth = TruthFunctions.intersection(belief.getTruth(), sentence.getTruth());
+        else
+            return; // don't do it for questions
+        BudgetValue budget = this.budgetfunctions.compoundForward(truth, content);
+        this.memory.doublePremiseTask(budget, content, truth);
+    }
+
+    /**
+     * {(&&, <#x() --> S>, <#x() --> P>>, <M --> P>} |- <M --> S>
+     * @param compound The compound term to be decomposed
+     * @param component The part of the compound to be removed
+     * @param compoundTask Whether the compound comes from the task
+     */
+     void abdVarDepOuter(CompoundTerm compound, Term component, boolean compoundTask) {
+        Term content = CompoundTerm.reduceComponents(compound, component, this.memory);
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        Judgement belief = this.memory.currentBelief;
+        TruthValue v1 = sentence.getTruth();
+        TruthValue v2 = belief.getTruth();
+        TruthValue truth = null;
+        BudgetValue budget;
+        if (sentence instanceof Question)
+            budget = (compoundTask ? this.budgetfunctions.backward(v2) : this.budgetfunctions.backwardWeak(v2));
+        else {
+            if (sentence instanceof Goal)
+                truth = (compoundTask ? TruthFunctions.desireStrong(v1, v2) : TruthFunctions.desireWeak(v1, v2));
+            else
+                truth = (compoundTask ? TruthFunctions.existAnalogy(v1, v2) : TruthFunctions.existAnalogy(v2, v1));
+            budget = this.budgetfunctions.compoundForward(truth, content);
+        }
+        this.memory.doublePremiseTask(budget, content, truth);
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/inference/MatchingRules.java b/open-nars/com/googlecode/opennars/inference/MatchingRules.java
new file mode 100644
index 0000000000000000000000000000000000000000..0942515533a921439436e925cee08d9c5b846764
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/inference/MatchingRules.java
@@ -0,0 +1,205 @@
+/*
+ * MatchingRules.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.inference;
+
+import com.googlecode.opennars.entity.*;
+import com.googlecode.opennars.language.*;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.*;
+
+/**
+ * Directly process a task by a belief, with only two Terms in both
+ */
+public class MatchingRules {
+	
+	private Memory memory;
+	private BudgetFunctions budgetfunctions;
+	
+	public MatchingRules(Memory memory) {
+		this.memory = memory;
+		this.budgetfunctions = new BudgetFunctions(memory);
+	}
+    
+    /* -------------------- same contents -------------------- */
+    
+    // the task and belief match each other
+    // forward inference only
+    // called only for Figure 0 of syllogism, in ThreeTermRules
+    public  void match(Task task, Judgement belief) {
+        Sentence sentence = task.getSentence();
+        if (sentence.isJudgment())
+            revision(task, belief, true);
+        else
+            trySolution(sentence, belief, null);
+    }
+    
+    // to be rewritten
+    public  void update(Task newBelief, Judgement oldBelief) {
+//        Base label = Base.make(newBelief.getBase(), oldBelief.getBase());
+//        if ((label == null) || (label.length() == 0))
+//            return;
+//        Task updatedNewBelief = (Task) newBelief.clone();
+//        Task updatedOldBelief = (Task) oldBelief.clone();
+//        Term content = oldBelief.getContent();
+//        Term toPast = Past.make(content);
+//        updatedOldBelief.setContent(toPast);
+//        updatedNewBelief.setBase(label);
+//        TruthValue truth = TruthFunctions.revision(newBelief.getTruth(), oldBelief.getTruth());
+//        float confidence = truth.getConfidence();
+//        updatedNewBelief.setConfidence(confidence);
+//        BudgetValue usage = this.budgetfunctions.update(newBelief, oldBelief);
+//        updatedNewBelief.setBudget(usage);
+//        this.memory.derivedTask(updatedNewBelief);
+//        this.memory.derivedTask(updatedOldBelief);
+    }
+    
+    // called from Concept (direct) and match (indirect)
+    public  void revision(Task task, Judgement belief, boolean feedbackToLinks) {
+        Judgement judgement = (Judgement) task.getSentence();
+        TruthValue tTruth = judgement.getTruth();
+        TruthValue bTruth = belief.getTruth();
+        TruthValue truth = TruthFunctions.revision(tTruth, bTruth);
+        BudgetValue budget = this.budgetfunctions.revise(tTruth, bTruth, truth, task, feedbackToLinks);
+        Term content = judgement.getContent();
+        this.memory.doublePremiseTask(budget, content, truth);
+    }
+
+    /**
+     * Check if a Judgement provide a better answer to a Question
+     * @param task The task to be processed
+     */
+    public  void trySolution(Sentence problem, Judgement belief, Task task) {
+        Judgement oldBest = problem.getBestSolution();
+        if (betterSolution(belief, oldBest, problem)) {
+            problem.setBestSolution(belief);
+            BudgetValue budget = this.budgetfunctions.solutionEval(problem, belief, task);
+            if (budget != null)
+                this.memory.activatedTask(budget, belief, problem.isInput());
+        }
+    }
+    
+    // s1 is a better answer to q than s2 is
+    private  boolean betterSolution(Judgement newSol, Judgement oldSol, Sentence problem) {
+        if (oldSol == null)
+            return true;
+        else
+            return (newSol.solutionQuality(problem) > oldSol.solutionQuality(problem));
+    }
+
+    /* -------------------- same terms, difference relations -------------------- */
+    
+    // the task and belief match each other reversely
+    // forward inference only
+    // called only for Figure 5 of syllogism
+    public  void matchReverse() {
+        Task task = this.memory.currentTask;
+        Judgement belief = this.memory.currentBelief;
+        if (task.getContent().getTemporalOrder() != CompoundTerm.temporalReverse(belief.getContent().getTemporalOrder()))
+            return;
+        Sentence sentence = task.getSentence();
+        if (sentence.isJudgment())
+            inferToSym((Judgement) sentence, belief);
+        else
+            conversion();
+    }
+    
+    // Inheritance matches Similarity
+    // forward inference only
+    // called from ThreeTermRules only
+    public  void matchAsymSym(Sentence asym, Sentence sym, int figure) { // (Task task, Sentence belief, int order, boolean inhSim) {
+        CompoundTerm.TemporalOrder order1 = asym.getContent().getTemporalOrder();
+        CompoundTerm.TemporalOrder order2 = sym.getContent().getTemporalOrder();
+        CompoundTerm.TemporalOrder order = CompoundTerm.temporalInferenceWithFigure(order1, order2, figure);
+        if (order == CompoundTerm.TemporalOrder.UNSURE)
+            return;
+        if (this.memory.currentTask.getSentence().isJudgment())
+            inferToAsym((Judgement) asym, (Judgement) sym, order);
+        else {
+            convertRelation();
+        }
+    }
+
+    /* -------------------- two-premise inference rules -------------------- */
+    
+    /**
+     * Produce Similarity/Equivalence from a pire of reversed Inheritance/Implication
+     * @param judgement1 The first premise
+     * @param judgement2 The second premise
+     */
+    private  void inferToSym(Judgement judgement1, Judgement judgement2) {
+        Statement s1 = (Statement) judgement1.getContent();
+        Statement s2 = (Statement) judgement2.getContent();
+        Term t1 = s1.getSubject();
+        Term t2 = s1.getPredicate();
+        Term content;
+        if (s1 instanceof Inheritance)
+            content = Similarity.make(t1, t2, this.memory);
+        else if (s1 instanceof ImplicationAfter)
+            content = EquivalenceAfter.make(t1, t2, this.memory);
+        else if (s1 instanceof ImplicationBefore)
+            content = EquivalenceAfter.make(t2, t1, this.memory);
+        else
+            content = Equivalence.make(t1, t2, this.memory);
+        TruthValue value1 = judgement1.getTruth();
+        TruthValue value2 = judgement2.getTruth();
+        TruthValue truth = TruthFunctions.intersection(value1, value2);
+        BudgetValue budget = this.budgetfunctions.forward(truth);
+        this.memory.doublePremiseTask(budget, content, truth);
+    }
+    
+    /**
+     * Produce an Inheritance/Implication from a Similarity/Equivalence and a reversed Inheritance/Implication
+     * @param asym The asymmetric premise
+     * @param sym The symmetric premise
+     */
+    private  void inferToAsym(Judgement asym, Judgement sym, CompoundTerm.TemporalOrder order) {
+        Statement statement = (Statement) asym.getContent();
+        Term sub = statement.getPredicate();
+        Term pre = statement.getSubject();
+        Statement content = Statement.make(statement, sub, pre, order, this.memory);
+        TruthValue truth = TruthFunctions.reduceConjunction(sym.getTruth(), asym.getTruth());
+        BudgetValue budget = this.budgetfunctions.forward(truth);
+        this.memory.doublePremiseTask(budget, content, truth);
+    }
+
+    /* -------------------- one-premise inference rules -------------------- */
+    
+    /**
+     * Produce an Inheritance/Implication from a reversed Inheritance/Implication
+     */
+    private  void conversion() {
+        TruthValue truth = TruthFunctions.conversion(this.memory.currentBelief.getTruth());
+        BudgetValue budget = this.budgetfunctions.forward(truth);
+        this.memory.singlePremiseTask(truth, budget);
+    }
+    
+    // switch between Inheritance/Implication and Similarity/Equivalence
+    private  void convertRelation() {
+        TruthValue truth = this.memory.currentBelief.getTruth();
+        if (((Statement) this.memory.currentTask.getContent()).isCommutative())
+            truth = TruthFunctions.implied(truth);
+        else
+            truth = TruthFunctions.implying(truth);
+        BudgetValue budget = this.budgetfunctions.forward(truth);
+        this.memory.singlePremiseTask(truth, budget);
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/inference/RuleTables.java b/open-nars/com/googlecode/opennars/inference/RuleTables.java
new file mode 100644
index 0000000000000000000000000000000000000000..a34caefb02c17f3d50f162180f222f833c59bec0
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/inference/RuleTables.java
@@ -0,0 +1,440 @@
+/*
+ * RuleTables.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.inference;
+
+import com.googlecode.opennars.entity.*;
+import com.googlecode.opennars.language.*;
+import com.googlecode.opennars.main.Memory;
+
+/**
+ * Table of inference rules, indexed by the CompositionLinks for the task and the belief.
+ * Used for indirective processing of a task
+ */
+public class RuleTables {
+    
+	private Memory memory;
+	
+	private SyllogisticRules syllogisticrules;
+	private StructuralRules structuralrules;
+	private MatchingRules matchingrules;
+	private CompositionalRules compositionalrules;
+	
+	public RuleTables(Memory memory) {
+		this.memory = memory;
+		this.syllogisticrules = new SyllogisticRules(memory);
+		this.structuralrules = new StructuralRules(memory);
+		this.matchingrules = new MatchingRules(memory);
+		this.compositionalrules = new CompositionalRules(memory);
+	}
+	
+	public MatchingRules getMatchingRules() {
+		return this.matchingrules;
+	}
+	
+    /* ----- inferences with two composition links ----- */
+    
+    public  void reason(TaskLink tLink, TermLink bLink) {
+        Task task = memory.currentTask;
+        Term taskTerm = (Term) task.getContent().clone();         // cloning for substitution
+        Term beliefTerm = (Term) bLink.getTarget().clone();       // cloning for substitution
+        Concept beliefConcept = memory.termToConcept(beliefTerm);
+        Judgement belief = null;
+        if (beliefConcept != null)
+            belief = beliefConcept.getBelief(task);
+        memory.currentBelief = belief;  // may be null
+        if ((belief != null) && (Variable.findSubstitute(Variable.VarType.QUERY, taskTerm, beliefTerm) != null))
+            matchingrules.match(task, belief);
+        short tIndex = tLink.getIndex(0);
+        short bIndex = bLink.getIndex(0);
+        switch(tLink.getType()) {
+            case TermLink.SELF:
+                switch(bLink.getType()) {
+                    case TermLink.COMPONENT:
+                        compoundAndSelf((CompoundTerm) taskTerm, beliefTerm, true);
+                        break;
+                    case TermLink.COMPOUND:
+                        compoundAndSelf((CompoundTerm) beliefTerm, taskTerm, false);
+                        break;
+                    case TermLink.COMPONENT_STATEMENT:  // detachment
+                        if (belief != null)
+                            syllogisticrules.detachment((Statement) taskTerm, null, true, bIndex);
+                        break;
+                    case TermLink.COMPOUND_STATEMENT:   // detachment
+                        if (belief != null)
+                            syllogisticrules.detachment((Statement) beliefTerm, null, false, bIndex); //task, beliefTerm);
+                        break;
+                    case TermLink.COMPONENT_CONDITION:
+                        if (belief != null)
+                            syllogisticrules.conditionalDedInd((Implication) taskTerm, bIndex, beliefTerm, tIndex);
+                        break;
+                    case TermLink.COMPOUND_CONDITION:
+                        if (belief != null)
+                            syllogisticrules.conditionalDedInd((Implication) beliefTerm, bIndex, taskTerm, tIndex);
+                        break;
+                    default:
+                }
+                break;
+            case TermLink.COMPOUND:
+                switch(bLink.getType()) {
+                    case TermLink.COMPOUND:
+                        compoundAndCompound((CompoundTerm) taskTerm, tIndex, (CompoundTerm) beliefTerm, bIndex);
+                        break;
+                    case TermLink.COMPOUND_STATEMENT:
+                        compoundAndStatement((CompoundTerm) taskTerm, tIndex, (Statement) beliefTerm, bIndex, beliefTerm);
+                        break;
+                    default:
+                }
+                break;
+            case TermLink.COMPOUND_STATEMENT:
+                switch(bLink.getType()) {
+                    case TermLink.COMPONENT:
+                        componentAndStatement((CompoundTerm) memory.currentTerm, bIndex, (Statement) taskTerm, tIndex);
+                        break;
+                    case TermLink.COMPOUND:
+                        compoundAndStatement((CompoundTerm) beliefTerm, bIndex, (Statement) taskTerm, tIndex, beliefTerm);
+                        break;
+                    case TermLink.COMPOUND_STATEMENT:
+                        if (belief != null)
+                            syllogisms(tLink, bLink, taskTerm, beliefTerm);
+                        break;
+                    case TermLink.COMPOUND_CONDITION:
+                        if (belief != null)
+                            conditionalDedIndWithVar((Implication) beliefTerm, bIndex, (Statement) taskTerm, tIndex);
+                        break;
+                    default:
+                }
+                break;
+            case TermLink.COMPOUND_CONDITION:
+                switch(bLink.getType()) {
+                    case TermLink.COMPOUND_STATEMENT:
+                        if (belief != null)
+                            conditionalDedIndWithVar((Implication) taskTerm, tIndex, (Statement) beliefTerm, bIndex);
+                        break;
+                    default:
+                }
+                break;
+            default:
+                // to be revised to cover all types
+        }
+    }
+    
+    /* ----- syllogistic inferences ----- */
+    
+    /**
+     * Meta-table of syllogistic rules, indexed by the content classes of the sentence and the belief
+     */
+    private  void syllogisms(TaskLink tLink, TermLink bLink, Term taskTerm, Term beliefTerm) {
+        Sentence sentence = memory.currentTask.getSentence();
+        Judgement belief = memory.currentBelief;
+        int figure;
+        if (taskTerm instanceof Inheritance) {
+            if (beliefTerm instanceof Inheritance) {
+                figure = indexToFigure(tLink, bLink);
+                asymmetricAsymmetric(sentence, belief, figure);
+            } else if (beliefTerm instanceof Similarity) {
+                figure = indexToFigure(tLink, bLink);
+                asymmetricSymmetric(sentence, belief, figure);
+            } else
+                detachmentWithVar((Statement) beliefTerm, false, bLink.getIndex(0), (Statement) taskTerm, belief);
+        } else if (taskTerm instanceof Similarity) {
+            if (beliefTerm instanceof Inheritance) {
+                figure = indexToFigure(bLink, tLink);
+                asymmetricSymmetric(belief, sentence, figure);
+            } else if (beliefTerm instanceof Similarity) {
+                figure = indexToFigure(bLink, tLink);
+                symmetricSymmetric(belief, sentence, figure);
+            }
+        } else if (taskTerm instanceof Implication) {
+            if (beliefTerm instanceof Implication) {
+                figure = indexToFigure(tLink, bLink);
+                asymmetricAsymmetric(sentence, belief, figure);
+            } else if (beliefTerm instanceof Equivalence) {
+                figure = indexToFigure(tLink, bLink);
+                asymmetricSymmetric(sentence, belief, figure);
+            } else if (beliefTerm instanceof Inheritance)
+                detachmentWithVar((Statement) taskTerm, true, tLink.getIndex(0), (Statement) beliefTerm, belief);
+            // or intro 2nd ind var
+        } else if (taskTerm instanceof Equivalence) {
+            if (beliefTerm instanceof Implication) {
+                figure = indexToFigure(bLink, tLink);
+                asymmetricSymmetric(belief, sentence, figure);
+            } else if (beliefTerm instanceof Equivalence) {
+                figure = indexToFigure(bLink, tLink);
+                symmetricSymmetric(belief, sentence, figure);
+            } else if (beliefTerm instanceof Inheritance)
+                detachmentWithVar((Statement) taskTerm, true, tLink.getIndex(0), (Statement) beliefTerm, belief);
+        }
+    }
+    
+    private  int indexToFigure(TermLink link1, TermLink link2) {
+        return (link1.getIndex(0) + 1) * 10 + (link2.getIndex(0) + 1);    // valid value: 11, 12, 21, 22
+    }
+    
+    /**
+     * Syllogistic rules whose both premises are on the same asymmetric relation
+     */
+    private  void asymmetricAsymmetric(Sentence sentence, Judgement belief, int figure) {
+        Statement s1 = (Statement) sentence.cloneContent();
+        Statement s2 = (Statement) belief.cloneContent();
+        Term t1, t2;
+        switch (figure) {
+            case 11:    // induction
+                if (Variable.unify(Variable.VarType.INDEPENDENT, s1.getSubject(), s2.getSubject(), s1, s2)) {
+                    t1 = s2.getPredicate();
+                    t2 = s1.getPredicate();
+                    syllogisticrules.abdIndCom(t1, t2, sentence, belief, figure);
+                    compositionalrules.composeCompound(sentence, belief, 0);
+                }
+                break;
+            case 12:    // deduction
+                if (Variable.unify(Variable.VarType.INDEPENDENT, s1.getSubject(), s2.getPredicate(), s1, s2)) {
+                    t1 = s2.getSubject();
+                    t2 = s1.getPredicate();
+                    if (Variable.unify(Variable.VarType.QUERY, t1, t2, s1, s2))
+                        matchingrules.matchReverse();
+                    else
+                        syllogisticrules.dedExe(t1, t2, sentence, belief);
+                }
+                break;
+            case 21:    // exemplification
+                if (Variable.unify(Variable.VarType.INDEPENDENT, s1.getPredicate(), s2.getSubject(), s1, s2)) {
+                    t1 = s1.getSubject();
+                    t2 = s2.getPredicate();
+                    if (Variable.unify(Variable.VarType.QUERY, t1, t2, s1, s2))
+                        matchingrules.matchReverse();
+                    else
+                        syllogisticrules.dedExe(t1, t2, sentence, belief);
+                }
+                break;
+            case 22:    // abduction
+                if (Variable.unify(Variable.VarType.INDEPENDENT, s1.getPredicate(), s2.getPredicate(), s1, s2)) {
+                    t1 = s1.getSubject();
+                    t2 = s2.getSubject();
+                    if (! syllogisticrules.conditionalAbd(t1, t2, s1, s2)) {         // if conditional abduction, skip the following
+                        syllogisticrules.abdIndCom(t1, t2, sentence, belief, figure);
+                        compositionalrules.composeCompound(sentence, belief, 1);
+                    }
+                }
+                break;
+            default:
+        }
+    }
+    
+    /**
+     * Syllogistic rules whose first premise is on an asymmetric relation, and the second on a symmetric relation
+     */
+    private  void asymmetricSymmetric(Sentence asym, Sentence sym, int figure) {
+        Statement asymSt = (Statement) asym.cloneContent();
+        Statement symSt = (Statement) sym.cloneContent();
+        Term t1, t2;
+        switch (figure) {
+            case 11:
+                if (Variable.unify(Variable.VarType.INDEPENDENT, asymSt.getSubject(), symSt.getSubject(), asymSt, symSt)) {
+                    t1 = asymSt.getPredicate();
+                    t2 = symSt.getPredicate();
+                    if (Variable.unify(Variable.VarType.QUERY, t1, t2, asymSt, symSt))
+                        matchingrules.matchAsymSym(asym, sym, figure); //task, belief, order1 - order2, false);
+                    else
+                        syllogisticrules.analogy(t2, t1, asym, sym, figure);
+                }
+                break;
+            case 12:
+                if (Variable.unify(Variable.VarType.INDEPENDENT, asymSt.getSubject(), symSt.getPredicate(), asymSt, symSt)) {
+                    t1 = asymSt.getPredicate();
+                    t2 = symSt.getSubject();
+                    if (Variable.unify(Variable.VarType.QUERY, t1, t2, asymSt, symSt))
+                        matchingrules.matchAsymSym(asym, sym, figure); //task, belief, order1 - order2, false);
+                    else
+                        syllogisticrules.analogy(t2, t1, asym, sym, figure);
+                }
+                break;
+            case 21:
+                if (Variable.unify(Variable.VarType.INDEPENDENT, asymSt.getPredicate(), symSt.getSubject(), asymSt, symSt)) {
+                    t1 = asymSt.getSubject();
+                    t2 = symSt.getPredicate();
+                    if (Variable.unify(Variable.VarType.QUERY, t1, t2, asymSt, symSt))
+                        matchingrules.matchAsymSym(asym, sym, figure); //task, belief, order1 - order2, false);
+                    else
+                        syllogisticrules.analogy(t1, t2, asym, sym, figure);
+                }
+                break;
+            case 22:
+                if (Variable.unify(Variable.VarType.INDEPENDENT, asymSt.getPredicate(), symSt.getPredicate(), asymSt, symSt)) {
+                    t1 = asymSt.getSubject();
+                    t2 = symSt.getSubject();
+                    if (Variable.unify(Variable.VarType.QUERY, t1, t2, asymSt, symSt))
+                        matchingrules.matchAsymSym(asym, sym, figure); //task, belief, order1 - order2, false);
+                    else
+                        syllogisticrules.analogy(t1, t2, asym, sym, figure);
+                }
+                break;
+        }
+    }
+    
+    /**
+     * Syllogistic rules whose both premises are on the same symmetric relation
+     */
+    private  void symmetricSymmetric(Judgement belief, Sentence sentence, int figure) {
+        Statement s1 = (Statement) belief.cloneContent();
+        Statement s2 = (Statement) sentence.cloneContent();
+        switch (figure) {
+            case 11:
+                if (Variable.unify(Variable.VarType.INDEPENDENT, s1.getSubject(), s2.getSubject(), s1, s2))
+                    syllogisticrules.resemblance(s1.getPredicate(), s2.getPredicate(), belief, sentence, figure);
+                break;
+            case 12:
+                if (Variable.unify(Variable.VarType.INDEPENDENT, s1.getSubject(), s2.getPredicate(), s1, s2))
+                    syllogisticrules.resemblance(s1.getPredicate(), s2.getSubject(), belief, sentence, figure);
+                break;
+            case 21:
+                if (Variable.unify(Variable.VarType.INDEPENDENT, s1.getPredicate(), s2.getSubject(), s1, s2))
+                    syllogisticrules.resemblance(s1.getSubject(), s2.getPredicate(), belief, sentence, figure);
+                break;
+            case 22:
+                if (Variable.unify(Variable.VarType.INDEPENDENT, s1.getPredicate(), s2.getPredicate(), s1, s2))
+                    syllogisticrules.resemblance(s1.getSubject(), s2.getSubject(), belief, sentence, figure);
+                break;
+        }
+    }
+    
+    /* ----- conditional inferences ----- */
+    
+    private  void detachmentWithVar(Statement statement, boolean compoundTask, int index, CompoundTerm compound, Sentence belief) {
+        Term component = statement.componentAt(index);
+        Term inh = (compound instanceof Tense) ? compound.componentAt(0) : compound;
+        if ((component instanceof Inheritance) && (belief != null)) {
+            if (component.isConstant())
+                syllogisticrules.detachment(statement, compound, compoundTask, index);
+            else if (Variable.unify(Variable.VarType.INDEPENDENT, component, inh, statement, compound))
+                syllogisticrules.detachment(statement, compound, compoundTask, index);
+            else if ((statement instanceof Implication) && (memory.currentTask.getSentence().isJudgment())) {
+                syllogisticrules.introVarIndInner(statement, statement.getPredicate(), inh);    // tense???
+                compositionalrules.introVarDepInner(statement, statement.getPredicate(), inh);  // tense???
+            }
+        }
+    }
+    
+    private  void conditionalDedIndWithVar(Implication conditional, short index, Statement statement, short side) {
+        CompoundTerm condition = (CompoundTerm) conditional.getSubject();
+        Term component = condition.componentAt(index);
+        Term component2 = null;
+        if (statement instanceof Inheritance)
+            component2 = statement;
+        else if (statement instanceof Implication)
+            component2 = statement.componentAt(side);
+        if ((component2 != null) && Variable.unify(Variable.VarType.INDEPENDENT, component, component2, conditional, statement))
+            syllogisticrules.conditionalDedInd(conditional, index, statement, -1);
+    }
+    
+    /* ----- structural inferences ----- */
+    
+    private  void compoundAndSelf(CompoundTerm compound, Term component, boolean compoundTask) {
+        if ((compound instanceof Conjunction) || (compound instanceof Disjunction)) {
+            if (memory.currentBelief != null)
+                compositionalrules.decomposeStatement(compound, component, compoundTask);
+            else if (compound.containComponent(component))
+                structuralrules.structuralCompound(compound, component, compoundTask);
+        } else if ((compound instanceof Negation) && !memory.currentTask.isStructual()) {
+            if (compoundTask)
+                structuralrules.transformNegation(((Negation) compound).componentAt(0));
+            else
+                structuralrules.transformNegation(compound);
+        }
+    }
+    
+    private  void compoundAndCompound(CompoundTerm taskTerm, int tIndex, CompoundTerm beliefTerm, int bIndex) {
+        if (taskTerm.getClass() == beliefTerm.getClass()) {
+            if (taskTerm.size() > beliefTerm.size())
+                compoundAndSelf(taskTerm, beliefTerm, true);
+            else if (taskTerm.size() < beliefTerm.size())
+                compoundAndSelf(beliefTerm, taskTerm, false);
+        }
+    }
+    
+    private  void compoundAndStatement(CompoundTerm compound, short index, Statement statement, short side, Term beliefTerm) {
+        Term component = compound.componentAt(index);
+        Task task = memory.currentTask;
+        if (component.getClass() ==  statement.getClass()) {
+            if ((compound instanceof Conjunction) && (memory.currentBelief != null)) {
+                if (Variable.unify(Variable.VarType.DEPENDENT, component, statement, compound, statement))
+                    compositionalrules.abdVarDepOuter(compound, component, statement.equals(beliefTerm));
+                else if (task.getSentence().isJudgment()) {
+                    syllogisticrules.introVarIndInner(compound, component, statement);
+                    compositionalrules.introVarDepInner(compound, component, statement);
+                }
+            }
+        } else {
+            if (compound instanceof Tense) {
+                if (component instanceof Inheritance)
+                    detachmentWithVar(statement, statement.equals(beliefTerm), side, compound, memory.currentBelief);
+                else {
+                    Sentence belief = memory.currentBelief;
+                    if (belief != null)
+                        syllogisticrules.detachment(statement, compound, statement.equals(beliefTerm), side);
+                }
+            } else if (!task.isStructual() && task.getSentence().isJudgment()) {
+                if (statement instanceof Inheritance) {
+                    structuralrules.structuralCompose1(compound, index, statement);
+                    if (!(compound instanceof SetExt) && !(compound instanceof SetInt))
+                        structuralrules.structuralCompose2(compound, index, statement, side);    // {A --> B, A @ (A&C)} |- (A&C) --> (B&C)
+                } else if (statement instanceof Similarity)
+                    structuralrules.structuralCompose2(compound, index, statement, side);    // {A <-> B, A @ (A&C)} |- (A&C) <-> (B&C)
+            }
+        }
+    }
+    
+    private  void componentAndStatement(CompoundTerm compound, short index, Statement statement, short side) {
+        if (!memory.currentTask.isStructual()) {
+            if (statement instanceof Inheritance) {
+                structuralrules.structuralDecompose1(compound, index, statement, side);
+                if (!(compound instanceof SetExt) && !(compound instanceof SetInt))
+                    structuralrules.structuralDecompose2(statement);   // {(C-B) --> (C-A), A @ (C-A)} |- A --> B
+                else
+                    structuralrules.transformSetRelation(compound, statement, side);
+            } else if (statement instanceof Similarity) {
+                structuralrules.structuralDecompose2(statement);   // {(C-B) --> (C-A), A @ (C-A)} |- A --> B
+                if ((compound instanceof SetExt) || (compound instanceof SetInt))
+                    structuralrules.transformSetRelation(compound, statement, side);
+            } else if ((statement instanceof Implication) && (compound instanceof Negation))
+                structuralrules.contraposition(statement);
+        }
+    }
+    
+    /* ----- inference with one composition link ----- */
+    
+    public  void transformTask(Task task,  TaskLink tLink) {          // move to StructuralRules???
+        CompoundTerm content = (CompoundTerm) task.getContent().clone();
+        short[] indices = tLink.getIndices();
+        Term inh = null;
+        if (indices.length == 2) {
+            inh = content;
+        } else if (indices.length == 3) {
+            if ((content instanceof Implication) && (content.componentAt(0) instanceof Conjunction))
+                inh = ((CompoundTerm) content.componentAt(0)).componentAt(indices[0]);
+            else
+                inh = content.componentAt(indices[0]);
+        }
+        if (inh instanceof Inheritance)
+            structuralrules.transformProductImage((Inheritance)inh, content, indices, task);
+    }
+    
+}
diff --git a/open-nars/com/googlecode/opennars/inference/StructuralRules.java b/open-nars/com/googlecode/opennars/inference/StructuralRules.java
new file mode 100644
index 0000000000000000000000000000000000000000..607061a1e9df82328ebb02c7845bb311a80e4b06
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/inference/StructuralRules.java
@@ -0,0 +1,435 @@
+/*
+ * StructuralRules.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.inference;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.*;
+import com.googlecode.opennars.language.*;
+import com.googlecode.opennars.main.*;
+import com.googlecode.opennars.parser.*;
+
+
+/**
+ * Forward inference rules involving compound terms.
+ * Input premises are one sentence and one BeliefLink.
+ */
+public class StructuralRules {
+    
+	private Memory memory;
+	private BudgetFunctions budgetfunctions;
+	
+	public StructuralRules(Memory memory) {
+		this.memory = memory;
+		this.budgetfunctions = new BudgetFunctions(memory);
+	}
+	
+    /* -------------------- transform between compounds and components -------------------- */
+    
+    /**
+     * {<A --> B>} |- <(A&C) --> (B&C)>
+     * @param compound The compound term
+     * @param index The location of the indicated term in the compound
+     * @param statement The premise
+     * @param side The location of the indicated term in the premise
+     */
+     void structuralCompose2(CompoundTerm compound, short index, Statement statement, short side) {
+        Term sub = statement.getSubject();
+        Term pred = statement.getPredicate();
+        ArrayList<Term> components = compound.cloneComponents();
+        if (((side == 0) && components.contains(pred)) || ((side == 1) && components.contains(sub)))
+            return;     // both terms in compound
+        if (side == 0) {
+            sub = compound;
+            components.set(index, pred);
+            pred = CompoundTerm.make(compound, components, this.memory);
+        } else {
+            components.set(index, sub);
+            sub = CompoundTerm.make(compound, components, this.memory);
+            pred = compound;
+        }
+        if ((sub == null) || (pred == null))
+            return;
+        Term content;
+        if (switchOrder(compound, index))
+            content = Statement.make(statement, pred, sub, this.memory);     // {A --> B, A @ (C-A)} |- (C-B) --> (C-A)
+        else
+            content = Statement.make(statement, sub, pred, this.memory);     // the other cases
+        if (content == null)
+            return;
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        TruthValue truth = sentence.getTruth();
+        BudgetValue budget;
+        if (sentence instanceof Question) {
+            budget = this.budgetfunctions.compoundBackwardWeak(content);
+        } else {
+            if (compound.size() > 1) {
+                if (sentence.isJudgment())
+                    truth = TruthFunctions.implying(truth);
+                else // Goal
+                    truth = TruthFunctions.implied(truth);
+            }
+            budget = this.budgetfunctions.compoundForward(truth, content);
+        }
+        this.memory.singlePremiseTask(budget, content, truth);
+    }
+
+    /**
+     * {<(A&C) --> (B&C)>} |- <A --> B>
+     * @param statement The premise
+     */
+     void structuralDecompose2(Statement statement) {
+        Term subj = statement.getSubject();
+        Term pred = statement.getPredicate();
+        if (subj.getClass() != pred.getClass())
+            return;
+        CompoundTerm sub = (CompoundTerm) subj;
+        CompoundTerm pre = (CompoundTerm) pred;
+        if (sub.size() != pre.size())
+            return;
+        int index = -1;
+        Term t1, t2;
+        for (int i = 0; i < sub.size(); i++) {
+            t1 = sub.componentAt(i);
+            t2 = pre.componentAt(i);
+            if (!t1.equals(t2)) {
+                if (index < 0)
+                    index = i;
+                else
+                    return;
+            }
+        }
+        t1 = sub.componentAt(index);
+        t2 = pre.componentAt(index);
+        Term content;
+        if (switchOrder(sub, (short) index)) {
+        	// System.out.println("Switch order: " + t1.toString() + " " + t2.toString());
+            content = Statement.make(statement, t2, t1, this.memory);
+            // System.out.println(content);
+        }
+        else {
+        	// System.out.println("No switch: " + t1.toString() + " " + t2.toString());
+            content = Statement.make(statement, t1, t2, this.memory);
+            // System.out.println(content);
+        }
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        TruthValue truth = sentence.getTruth();
+        BudgetValue budget;
+        if (sentence instanceof Question) {
+            budget = this.budgetfunctions.compoundBackward(content);
+        } else {
+            if (sub.size() > 1) {
+                if (sentence.isJudgment())
+                    truth = TruthFunctions.implied(truth);
+                else // Goal
+                    truth = TruthFunctions.implying(truth);
+            }
+            budget = this.budgetfunctions.compoundForward(truth, content);
+        }
+        this.memory.singlePremiseTask(budget, content, truth);
+    }
+    
+    private  boolean switchOrder(CompoundTerm compound, short index) {
+        return ((((compound instanceof DifferenceExt) || (compound instanceof DifferenceInt)) && (index == 1)) ||
+                ((compound instanceof ImageExt) && (index != ((ImageExt) compound).getRelationIndex())) ||
+                ((compound instanceof ImageInt) && (index != ((ImageInt) compound).getRelationIndex())));
+    }
+    
+    /**
+     * {<A --> B>} |- <A --> (B&C)>
+     * @param compound The compound term
+     * @param index The location of the indicated term in the compound
+     * @param statement The premise
+     */
+     void structuralCompose1(CompoundTerm compound, short index, Statement statement) {
+        if (!this.memory.currentTask.getSentence().isJudgment())
+            return;
+        Term component = compound.componentAt(index);
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        TruthValue truth = sentence.getTruth();
+        Term subj = statement.getSubject();
+        Term pred = statement.getPredicate();
+        if (component.equals(subj)) {
+            if (compound instanceof IntersectionExt)                        // {A --> B, A @ (A&C)} |- (A&C) --> B
+                structuralStatement(compound, pred, TruthFunctions.implying(truth));
+            else if (compound instanceof IntersectionInt)                   // {A --> B, A @ (A|C)} |- (A|C) --> B
+                structuralStatement(compound, pred, TruthFunctions.implied(truth));
+            else if ((compound instanceof DifferenceExt) && (index == 0))   // {A --> B, A @ (A-C)} |- (A-C) --> B
+                structuralStatement(compound, pred, TruthFunctions.implying(truth));
+            else if (compound instanceof DifferenceInt)
+                if (index == 0)                                             // {A --> B, A @ (A~C)} |- (A~C) --> B
+                    structuralStatement(compound, pred, TruthFunctions.implied(truth));
+                else                                                        // {A --> B, A @ (C~A)} |- (C~A) --> B
+                    structuralStatement(compound, pred, TruthFunctions.negImply(truth));
+        } else if (component.equals(pred)) {
+            if (compound instanceof IntersectionExt)                        // {B --> A, A @ (A&C)} |- B --> (A&C)
+                structuralStatement(subj, compound, TruthFunctions.implied(truth));
+            else if (compound instanceof IntersectionInt)                   // {B --> A, A @ (A|C)} |- B --> (A|C)
+                structuralStatement(subj, compound, TruthFunctions.implying(truth));
+            else if (compound instanceof DifferenceExt)
+                if (index == 0)                                             // {B --> A, A @ (A-C)} |- B --> (A-C)
+                    structuralStatement(subj, compound, TruthFunctions.implied(truth));
+                else                                                        // {B --> A, A @ (C-A)} |- B --> (C-A)
+                    structuralStatement(subj, compound, TruthFunctions.negImply(truth));
+            else if ((compound instanceof DifferenceInt) && (index == 0))   // {B --> A, A @ (A~C)} |- B --> (A~C)
+                structuralStatement(subj, compound, TruthFunctions.implying(truth));
+        }
+    }
+    
+    /**
+     * {<(A&C) --> B>} |- <A --> B>
+     * @param compound The compound term
+     * @param index The location of the indicated term in the compound
+     * @param statement The premise
+     * @param side The location of the indicated term in the premise
+     */
+     void structuralDecompose1(CompoundTerm compound, short index, Statement statement, short side) {
+        if (!this.memory.currentTask.getSentence().isJudgment())
+            return;
+        Term component = compound.componentAt(index);
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        TruthValue truth = sentence.getTruth();
+        Term subj = statement.getSubject();
+        Term pred = statement.getPredicate();
+        if (compound.equals(subj)) {
+            if (compound instanceof IntersectionExt)                        // {(A&C) --> B, A @ (A&C)} |- A --> B
+                structuralStatement(component, pred, TruthFunctions.implied(truth));
+            else if (compound instanceof IntersectionInt)                   // {(A|C) --> B, A @ (A|C)} |- A --> B
+                structuralStatement(component, pred, TruthFunctions.implying(truth));
+            else if ((compound instanceof DifferenceExt) && (index == 0))   // {(A-C) --> B, A @ (A-C)} |- A --> B
+                structuralStatement(component, pred, TruthFunctions.implied(truth));
+            else if (compound instanceof DifferenceInt)
+                if (index == 0)                                             // {(A~C) --> B, A @ (A~C)} |- A --> B
+                    structuralStatement(component, pred, TruthFunctions.implying(truth));
+                else                                                        // {(C~A) --> B, A @ (C~A)} |- A --> B
+                    structuralStatement(component, pred, TruthFunctions.negImply(truth));
+        } else if (compound.equals(pred)) {
+            if (compound instanceof IntersectionExt)                        // {B --> (A&C), A @ (A&C)} |- B --> A
+                structuralStatement(subj, component, TruthFunctions.implying(truth));
+            else if (compound instanceof IntersectionInt)                   // {B --> (A&C), A @ (A&C)} |- B --> A
+                structuralStatement(subj, component, TruthFunctions.implied(truth));
+            else if (compound instanceof DifferenceExt)
+                if (index == 0)                                             // {B --> (A-C), A @ (A-C)} |- B --> A
+                    structuralStatement(subj, component, TruthFunctions.implying(truth));
+                else                                                        // {B --> (C-A), A @ (C-A)} |- B --> A
+                    structuralStatement(subj, component, TruthFunctions.negImply(truth));
+            else if ((compound instanceof DifferenceInt) && (index == 0))   // {B --> (A~C), A @ (A~C)} |- B --> A
+                structuralStatement(subj, component, TruthFunctions.implied(truth));
+        }
+    }
+    
+    /**
+     * Common final operations of the above two methods
+     * @param subject The subject of the new task
+     * @param predicate The predicate of the new task
+     * @param truth The truth value of the new task
+     */
+    private  void structuralStatement(Term subject, Term predicate, TruthValue truth) { // Inheritance only?
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        Term content = Statement.make((Statement) task.getContent(), subject, predicate, this.memory);
+        if (content == null)
+            return;
+        BudgetValue budget = this.budgetfunctions.compoundForward(truth, content);
+//        if (sentence instanceof Question)
+//            budget = this.budgetfunctions.compoundBackward(content);
+//        else
+//            budget = this.budgetfunctions.compoundForward(truth, content);
+        this.memory.singlePremiseTask(budget, content, truth);
+    }
+    
+    /* -------------------- set transform -------------------- */
+    
+    /**
+     * {<S --> {P}>} |- <S <-> {P}>
+     * @param compound The set compound
+     * @param statement The premise
+     * @param side The location of the indicated term in the premise
+     */
+     void transformSetRelation(CompoundTerm compound, Statement statement, short side) {
+        if (compound.size() > 1)
+            return;
+        if (statement instanceof Inheritance)
+            if (((compound instanceof SetExt) && (side == 0)) || ((compound instanceof SetInt) && (side == 1)))
+                return;
+        Term sub = statement.getSubject();
+        Term pre = statement.getPredicate();
+        Term content;
+        if (statement instanceof Inheritance) {
+            content = Similarity.make(sub, pre, this.memory);
+        } else {
+            if (((compound instanceof SetExt) && (side == 0)) || ((compound instanceof SetInt) && (side == 1)))
+                content = Inheritance.make(pre, sub, this.memory);
+            else
+                content = Inheritance.make(sub, pre, this.memory);
+        }
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        TruthValue truth = sentence.getTruth();
+        BudgetValue budget;
+        if (sentence instanceof Question)
+            budget = this.budgetfunctions.compoundBackward(content);
+        else
+            budget = this.budgetfunctions.compoundForward(truth, content);
+        this.memory.singlePremiseTask(budget, content, truth);
+    }
+    
+    /* -------------------- products and images transform -------------------- */
+    
+     void transformProductImage(Inheritance inh, CompoundTerm oldContent, short[] indices, Task task) {
+        Term subject = null;
+        Term predicate = null;
+        short index = indices[indices.length - 1];
+        short side = indices[indices.length - 2];
+        CompoundTerm comp = (CompoundTerm) inh.componentAt(side);
+        if (comp instanceof Product) {
+            if (side == 0) {           // Product as subject
+                subject = comp.componentAt(index);
+                predicate = ImageExt.make((Product) comp, inh.getPredicate(), index, this.memory);
+            } else {
+                subject = ImageInt.make((Product) comp, inh.getSubject(), index, this.memory);
+                predicate = comp.componentAt(index);
+            }
+        } else if ((comp instanceof ImageExt) && (side == 1)) {   // ImageExt as predicate
+            if (index == ((ImageExt) comp).getRelationIndex()) {
+                subject = Product.make(comp, inh.getSubject(), index, this.memory);
+                predicate = comp.componentAt(index);
+            } else {
+                subject = comp.componentAt(index);
+                predicate = ImageExt.make((ImageExt) comp, inh.getSubject(), index, this.memory);
+            }
+        } else if ((comp instanceof ImageInt) && (side == 0)) {   // ImageInt as subject
+            if (index == ((ImageInt) comp).getRelationIndex()) {
+                subject = comp.componentAt(index);
+                predicate = Product.make(comp, inh.getPredicate(), index, this.memory);
+            } else {
+                subject = ImageInt.make((ImageInt) comp, inh.getPredicate(), index, this.memory);
+                predicate = comp.componentAt(index);
+            }
+        } else //        if ((subject == null) || (predicate == null))
+            return;
+        Inheritance newInh = Inheritance.make(subject, predicate, this.memory);
+        Term content = null;
+        if (indices.length == 2)
+            content = newInh;
+        else {
+            ArrayList<Term> componentList;
+            if ((oldContent instanceof Implication) && (oldContent.componentAt(0) instanceof Conjunction)) {
+                componentList = ((CompoundTerm) oldContent.componentAt(0)).cloneComponents();
+                componentList.set(indices[0], newInh);
+                Term newCond = Conjunction.make(componentList, this.memory);
+                content = Implication.make(newCond, ((Statement) oldContent).getPredicate(), this.memory);
+            } else
+                componentList = oldContent.cloneComponents();
+            componentList.set(indices[0], newInh);
+            if (oldContent instanceof Conjunction)
+                content = Conjunction.make(componentList, this.memory);
+            else if ((oldContent instanceof Implication) || (oldContent instanceof Equivalence))
+                content = Statement.make((Statement) oldContent, componentList.get(0), componentList.get(1), this.memory);
+        }
+        if (content == null)
+            return;
+        Sentence sentence = task.getSentence();
+        TruthValue truth = sentence.getTruth();
+        BudgetValue budget;
+        if (sentence instanceof Question)
+            budget = this.budgetfunctions.compoundBackward(content);
+        else
+            budget = this.budgetfunctions.compoundForward(truth, content);
+        this.memory.singlePremiseTask(budget, content, truth);
+    }
+    
+    /* --------------- Disjunction and Conjunction transform --------------- */
+    
+    /**
+     * {(&&, A, B)} |- A
+     * @param compound The premise
+     * @param component The recognized component in the premise
+     * @param compoundTask Whether the compound comes from the task
+     */
+     void structuralCompound(CompoundTerm compound, Term component, boolean compoundTask) {
+        Term content = (compoundTask ? component : compound);
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        TruthValue truth = sentence.getTruth();
+        BudgetValue budget;
+        if (sentence instanceof Question) {
+            budget = this.budgetfunctions.compoundBackward(content);
+        } else {
+            if ((sentence.isJudgment()) == (compoundTask == (compound instanceof Conjunction)))
+                truth = TruthFunctions.implying(truth);
+            else
+                truth = TruthFunctions.implied(truth);
+            budget = this.budgetfunctions.compoundForward(sentence.getTruth(), content);
+        }
+        this.memory.singlePremiseTask(budget, content, truth);
+    }
+    
+    /* --------------- Negation related rules --------------- */
+    
+    /**
+     * {A} |- (--, A)
+     * @param content The premise
+     */
+     void transformNegation(Term content) {
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        TruthValue truth = sentence.getTruth();
+        if (sentence instanceof Judgement)
+            truth = TruthFunctions.negation(truth);
+        BudgetValue budget;
+        if (sentence instanceof Question)
+            budget = this.budgetfunctions.compoundBackward(content);
+        else
+            budget = this.budgetfunctions.compoundForward(truth, content);
+        this.memory.singlePremiseTask(budget, content, truth);
+    }
+    
+    /**
+     * {<A ==> B>} |- <(--B) ==> (--A)>
+     * @param statement The premise
+     */
+     void contraposition(Statement statement) {
+        Term subj = statement.getSubject();
+        Term pred = statement.getPredicate();
+        Term content = Statement.make(statement, Negation.make(pred, this.memory), Negation.make(subj, this.memory), CompoundTerm.temporalReverse(statement.getTemporalOrder()), this.memory);
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        TruthValue truth = sentence.getTruth();
+        BudgetValue budget;
+        if (sentence instanceof Question) {
+            if (content instanceof Implication)
+                budget = this.budgetfunctions.compoundBackwardWeak(content);
+            else
+                budget = this.budgetfunctions.compoundBackward(content);
+        } else {
+            if (content instanceof Implication)
+                truth = TruthFunctions.contraposition(truth);
+            budget = this.budgetfunctions.compoundForward(truth, content);
+        }
+        this.memory.singlePremiseTask(budget, content, truth);
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/inference/SyllogisticRules.java b/open-nars/com/googlecode/opennars/inference/SyllogisticRules.java
new file mode 100644
index 0000000000000000000000000000000000000000..28258358a034403642994bb20eafe446107dea3f
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/inference/SyllogisticRules.java
@@ -0,0 +1,512 @@
+/*
+ * SyllogisticRules.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.inference;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.*;
+import com.googlecode.opennars.language.*;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.*;
+
+
+/**
+ * Syllogisms: Inference rules based on the transitivity of the relation.
+ */
+public class SyllogisticRules {
+    
+	private Memory memory;
+	private BudgetFunctions budgetfunctions;
+	
+	public SyllogisticRules(Memory memory) {
+		this.memory = memory;
+		this.budgetfunctions = new BudgetFunctions(memory);
+	}
+	
+    /* --------------- rules used in both first-order inference and higher-order inference --------------- */
+    
+    /**
+     * {<S ==> M>, <M ==> P>} |- {<S ==> P>, <P ==> S>}
+     * @param term1 Subject of the first new task
+     * @param term2 Predicate of the first new task
+     * @param sentence The first premise
+     * @param belief The second premise
+     */
+    void dedExe(Term term1, Term term2, Sentence sentence, Judgement belief) {
+        if (Statement.invalidStatement(term1, term2))
+            return;
+        CompoundTerm.TemporalOrder order1 = sentence.getContent().getTemporalOrder();
+        CompoundTerm.TemporalOrder order2 = belief.getContent().getTemporalOrder();
+        CompoundTerm.TemporalOrder order = CompoundTerm.temporalInference(order1, order2);
+        if (order == CompoundTerm.TemporalOrder.UNSURE)
+            return;
+        Statement content1 = Statement.make((Statement) sentence.getContent(), term1, term2, order, this.memory);
+        Statement content2 = Statement.make((Statement) sentence.getContent(), term2, term1, CompoundTerm.temporalReverse(order), this.memory);
+        TruthValue value1 = sentence.getTruth();
+        TruthValue value2 = belief.getTruth();
+        TruthValue truth1 = null;
+        TruthValue truth2 = null;
+        BudgetValue budget1, budget2;
+        Task task = this.memory.currentTask;
+        if (sentence instanceof Question) {
+            budget1 = this.budgetfunctions.backwardWeak(value2);
+            budget2 = this.budgetfunctions.backwardWeak(value2);
+        } else {
+            if (sentence instanceof Goal) {
+                truth1 = TruthFunctions.desireWeak(value1, value2);
+                truth2 = TruthFunctions.desireWeak(value1, value2);
+            } else {
+                truth1 = TruthFunctions.deduction(value1, value2);
+                truth2 = TruthFunctions.exemplification(value1, value2);
+            }
+            budget1 = this.budgetfunctions.forward(truth1);
+            budget2 = this.budgetfunctions.forward(truth2);
+        }
+        this.memory.doublePremiseTask(budget1, content1, truth1);
+        this.memory.doublePremiseTask(budget2, content2, truth2);
+    }
+    
+    /**
+     * {<M ==> S>, <M ==> P>} |- {<S ==> P>, <P ==> S>, <S <=> P>}
+     * @param term1 Subject of the first new task
+     * @param term2 Predicate of the first new task
+     * @param sentence The first premise
+     * @param belief The second premise
+     * @param figure Locations of the shared term in premises
+     */
+    void abdIndCom(Term term1, Term term2, Sentence sentence, Judgement belief, int figure) {
+        if (Statement.invalidStatement(term1, term2))
+            return;
+        Statement st1 = (Statement) sentence.getContent();
+        Statement st2 = (Statement) belief.getContent();
+        CompoundTerm.TemporalOrder order1 = st1.getTemporalOrder();
+        CompoundTerm.TemporalOrder order2 = st2.getTemporalOrder();
+        CompoundTerm.TemporalOrder order;
+        if (figure == 11)
+            order = CompoundTerm.temporalInference(order1, CompoundTerm.temporalReverse(order2));
+        else
+            order = CompoundTerm.temporalInference(CompoundTerm.temporalReverse(order1), order2);
+        if (order == CompoundTerm.TemporalOrder.UNSURE)
+            return;
+        Statement statement1 = Statement.make(st1, term1, term2, order, this.memory);
+        Statement statement2 = Statement.make(st1, term2, term1, CompoundTerm.temporalReverse(order), this.memory);
+        Statement statement3 = Statement.makeSym(st1, term1, term2, order, this.memory);
+        TruthValue truth1 = null;
+        TruthValue truth2 = null;
+        TruthValue truth3 = null;
+        BudgetValue budget1, budget2, budget3;
+        TruthValue value1 = sentence.getTruth();
+        TruthValue value2 = belief.getTruth();
+        if (sentence instanceof Question) {
+            budget1 = this.budgetfunctions.backward(value2);
+            budget2 = this.budgetfunctions.backwardWeak(value2);
+            budget3 = this.budgetfunctions.backward(value2);
+        } else {
+            if (sentence instanceof Goal) {
+                truth1 = TruthFunctions.desireStrong(value1, value2);
+                truth2 = TruthFunctions.desireWeak(value2, value1);
+                truth3 = TruthFunctions.desireStrong(value1, value2);
+            } else {
+                truth1 = TruthFunctions.abduction(value1, value2);
+                truth2 = TruthFunctions.abduction(value2, value1);
+                truth3 = TruthFunctions.comparison(value1, value2);
+            }
+            budget1 = this.budgetfunctions.forward(truth1);
+            budget2 = this.budgetfunctions.forward(truth2);
+            budget3 = this.budgetfunctions.forward(truth3);
+        }
+        this.memory.doublePremiseTask(budget1, statement1, truth1);
+        this.memory.doublePremiseTask(budget2, statement2, truth2);
+        this.memory.doublePremiseTask(budget3, statement3, truth3);
+        if (statement1.isConstant()) {
+            this.memory.doublePremiseTask(budget1, introVarInd(statement1, st2, st1, figure), truth1);
+            this.memory.doublePremiseTask(budget2, introVarInd(statement2, st1, st2, figure), truth2);
+            this.memory.doublePremiseTask(budget3, introVarInd(statement3, st1, st2, figure), truth3);
+        }
+    }
+    
+    /**
+     * {<S ==> P>, <M <=> P>} |- <S ==> P>
+     * @param term1 Subject of the new task
+     * @param term2 Predicate of the new task
+     * @param asym The asymmetric premise
+     * @param sym The symmetric premise
+     * @param figure Locations of the shared term in premises
+     */
+    void analogy(Term term1, Term term2, Sentence asym, Sentence sym, int figure) {
+        if (Statement.invalidStatement(term1, term2))
+            return;
+        Statement asymSt = (Statement) asym.getContent();
+        Statement symSt = (Statement) sym.getContent();
+        CompoundTerm.TemporalOrder order1 = asymSt.getTemporalOrder();
+        CompoundTerm.TemporalOrder order2 = symSt.getTemporalOrder();
+        CompoundTerm.TemporalOrder order;
+        switch (figure) {
+            case 11:
+            case 12:
+                order = CompoundTerm.temporalInferenceWithFigure(order2, order1, figure);
+                break;
+            case 21:
+            case 22:
+                order = CompoundTerm.temporalInferenceWithFigure(order1, order2, figure);
+                break;
+            default:
+                return;
+        }
+        if (order == CompoundTerm.TemporalOrder.UNSURE)
+            return;
+        Term content = Statement.make(asymSt, term1, term2, order, this.memory);
+        TruthValue truth = null;
+        BudgetValue budget;
+        Sentence sentence = this.memory.currentTask.getSentence();
+        CompoundTerm taskTerm = (CompoundTerm) sentence.getContent();
+        if (sentence instanceof Question) {
+            if (taskTerm.isCommutative())
+                budget = this.budgetfunctions.backwardWeak(asym.getTruth());
+            else
+                budget = this.budgetfunctions.backward(sym.getTruth());
+        } else {
+            if (sentence instanceof Goal) {
+                if (taskTerm.isCommutative())
+                    truth = TruthFunctions.desireWeak(asym.getTruth(), sym.getTruth());
+                else
+                    truth = TruthFunctions.desireStrong(asym.getTruth(), sym.getTruth());
+            } else
+                truth = TruthFunctions.analogy(asym.getTruth(), sym.getTruth());
+            budget = this.budgetfunctions.forward(truth);
+        }
+        this.memory.doublePremiseTask(budget, content, truth);
+    }
+    
+    /**
+     * {<S <=> M>, <M <=> P>} |- <S <=> P>
+     * @param term1 Subject of the new task
+     * @param term2 Predicate of the new task
+     * @param belief The first premise
+     * @param sentence The second premise
+     * @param figure Locations of the shared term in premises
+     */
+    void resemblance(Term term1, Term term2, Judgement belief, Sentence sentence, int figure) {
+        if (Statement.invalidStatement(term1, term2))
+            return;
+        Statement st1 = (Statement) belief.getContent();
+        Statement st2 = (Statement) sentence.getContent();
+        CompoundTerm.TemporalOrder order1 = st1.getTemporalOrder();
+        CompoundTerm.TemporalOrder order2 = st2.getTemporalOrder();
+        CompoundTerm.TemporalOrder order = CompoundTerm.temporalInferenceWithFigure(order1, order2, figure);
+        if (order == CompoundTerm.TemporalOrder.UNSURE)
+            return;
+        Term statement = Statement.make(st1, term1, term2, order, this.memory);
+        TruthValue truth = null;
+        BudgetValue budget;
+        Task task = this.memory.currentTask;
+        if (sentence instanceof Question) {
+            budget = this.budgetfunctions.backward(belief.getTruth());
+        } else {
+            if (sentence instanceof Goal)
+                truth = TruthFunctions.desireStrong(sentence.getTruth(), belief.getTruth());
+            else
+                truth = TruthFunctions.resemblance(belief.getTruth(), sentence.getTruth());
+            budget = this.budgetfunctions.forward(truth);
+        }
+        this.memory.doublePremiseTask(budget, statement, truth);
+    }
+    
+    /* --------------- rules used only in conditional inference --------------- */
+    
+    /**
+     * {<S ==> P>, S} |- P
+     * @param statement The premise statement
+     * @param compound The compound containing the shared component, can be null
+     * @param compoundTask Whether the component comes in the task
+     * @param side The location of the shared term in the statement
+     */
+    void detachment(Statement statement, CompoundTerm compound, boolean compoundTask, int side) {
+        if (!(statement instanceof Implication) && !(statement instanceof Equivalence)) // necessary?
+            return;
+        Sentence sentence = this.memory.currentTask.getSentence();
+        Judgement belief = this.memory.currentBelief;
+        TruthValue value1, value2;
+        if (compoundTask) {
+            value2 = sentence.getTruth();
+            value1 = belief.getTruth();
+        } else {
+            value1 = sentence.getTruth();
+            value2 = belief.getTruth();
+        }
+        TruthValue truth = null;
+        BudgetValue budget;
+        if (sentence instanceof Question) {
+            if (statement instanceof Equivalence)
+                budget = this.budgetfunctions.backward(belief.getTruth());
+            else if (side == 0)
+                budget = this.budgetfunctions.backwardWeak(belief.getTruth());
+            else
+                budget = this.budgetfunctions.backward(belief.getTruth());
+        } else {
+            if (sentence instanceof Goal) {
+                if (statement instanceof Equivalence)
+                    truth = TruthFunctions.desireStrong(value1, value2);
+                else if (side == 0)
+                    truth = TruthFunctions.desireInd(value1, value2);
+                else
+                    truth = TruthFunctions.desireDed(value1, value2);
+            } else {
+                if (statement instanceof Equivalence)
+                    truth = TruthFunctions.analogy(value1, value2);
+                else if (side == 0)
+                    truth = TruthFunctions.deduction(value1, value2);
+                else
+                    truth = TruthFunctions.abduction(value1, value2);
+            }
+            budget = this.budgetfunctions.forward(truth);
+        }
+        Term content = statement.componentAt(1 - side);
+        if (!content.isConstant())
+            return;
+        if ((compound != null) && (compound instanceof Tense)){
+            CompoundTerm.TemporalOrder order1 = compound.getTemporalOrder();
+            CompoundTerm.TemporalOrder order2 = statement.getTemporalOrder();
+            CompoundTerm.TemporalOrder order;
+            if (side == 0)
+                order = CompoundTerm.temporalInference(order1, order2);
+            else
+                order = CompoundTerm.temporalInference(order1, CompoundTerm.temporalReverse(order2));
+            if (order == CompoundTerm.TemporalOrder.UNSURE)
+//                order = order1;
+                return;
+            content = Tense.make(content, order, this.memory);
+        }
+        this.memory.doublePremiseTask(budget, content, truth);
+    }
+    
+    /**
+     * {<(&&, S1, S2) ==> P>, <M ==> S1>} |- <(&&, M, S2) ==> P>
+     * @param premise1 The conditional premise
+     * @param index The location of the shared term in the condition of premise1
+     * @param premise2 The premise which, or part of which, appears in the condition of premise1
+     * @param side The location of the shared term in premise2: 0 for subject, 1 for predicate, -1 for the whole term
+     */
+    void conditionalDedInd(Implication premise1, short index, Term premise2, int side) {
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        Judgement belief = this.memory.currentBelief;
+        Conjunction oldCondition = (Conjunction) premise1.getSubject();
+        CompoundTerm.TemporalOrder order1 = premise1.getTemporalOrder();
+        CompoundTerm.TemporalOrder order2 = premise2.getTemporalOrder();
+        boolean deduction = (side != 0);
+        if (!(order1 == order2))                                    // to be refined to cover tense
+            if (!(deduction && ((side == -1) || (index == 0))))     // don't replace middle conditions
+                return;
+        Term newComponent = null;
+        if (side == 0)
+            newComponent = ((Statement) premise2).getPredicate();
+        else if (side == 1)
+            newComponent = ((Statement) premise2).getSubject();
+        Term newCondition = CompoundTerm.replaceComponent(oldCondition, index, newComponent, this.memory);
+        Term content = Statement.make(premise1, newCondition, premise1.getPredicate(), order1, this.memory);
+        if (content == null)
+            return;
+        TruthValue value1 = sentence.getTruth();
+        TruthValue value2 = belief.getTruth();
+        TruthValue truth = null;
+        BudgetValue budget;
+        boolean conditionalTask = (Variable.findSubstitute(Variable.VarType.INDEPENDENT, premise2, belief.getContent()) != null);
+        if (sentence instanceof Question) {
+            budget = this.budgetfunctions.backwardWeak(value2);
+        } else {
+            if (sentence instanceof Goal) {
+                if (conditionalTask)
+                    truth = TruthFunctions.desireWeak(value1, value2);
+                else if (deduction)
+                    truth = TruthFunctions.desireInd(value1, value2);
+                else
+                    truth = TruthFunctions.desireDed(value1, value2);
+                budget = this.budgetfunctions.forward(truth);
+            } else {
+                if (deduction)
+                    truth = TruthFunctions.deduction(value1, value2);
+                else if (conditionalTask)
+                    truth = TruthFunctions.induction(value2, value1);
+                else
+                    truth = TruthFunctions.induction(value1, value2);
+            }
+            budget = this.budgetfunctions.forward(truth);
+        }
+        this.memory.doublePremiseTask(budget, content, truth);
+    }
+    
+    /**
+     * {<(&&, S1, S2) ==> P>, <(&&, S1, S3) ==> P>} |- <S2 ==> S3>
+     * @param cond1 The condition of the first premise
+     * @param cond2 The condition of the second premise
+     * @param st1 The first premise
+     * @param st2 The second premise
+     * @return Whether there are derived tasks
+     */
+    boolean conditionalAbd(Term cond1, Term cond2, Statement st1, Statement st2) {
+        if (!(st1 instanceof Implication) || !(st2 instanceof Implication))
+            return false;
+        if (!(cond1 instanceof Conjunction) && !(cond2 instanceof Conjunction))
+            return false;
+        CompoundTerm.TemporalOrder order1 = st1.getTemporalOrder();
+        CompoundTerm.TemporalOrder order2 = st2.getTemporalOrder();
+        if (order1 != CompoundTerm.temporalReverse(order2))
+            return false;
+        Term term1 = null;
+        Term term2 = null;
+        if (cond1 instanceof Conjunction) {
+            term1 = CompoundTerm.reduceComponents((Conjunction) cond1, cond2, this.memory);
+        }
+        if (cond2 instanceof Conjunction) {
+            term2 = CompoundTerm.reduceComponents((Conjunction) cond2, cond1, this.memory);
+        }
+        if ((term1 == null) && (term2 == null))
+            return false;
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        Judgement belief = this.memory.currentBelief;
+        TruthValue value1 = sentence.getTruth();
+        TruthValue value2 = belief.getTruth();
+        boolean keepOrder = (Variable.findSubstitute(Variable.VarType.INDEPENDENT, st1, task.getContent()) != null);
+        Term content;
+        TruthValue truth = null;
+        BudgetValue budget;
+        if (term1 != null) {
+            if (term2 != null)
+                content = Statement.make(st2, term2, term1, order2, this.memory);
+            else
+                content = term1;
+            if (sentence instanceof Question) {
+                budget = this.budgetfunctions.backwardWeak(value2);
+            } else {
+                if (sentence instanceof Goal) {
+                    if (keepOrder)
+                        truth = TruthFunctions.desireDed(value1, value2);
+                    else
+                        truth = TruthFunctions.desireInd(value1, value2);
+                } else
+                    truth = TruthFunctions.abduction(value2, value1);
+                budget = this.budgetfunctions.forward(truth);
+            }
+            this.memory.doublePremiseTask(budget, content, truth);
+        }
+        if (term2 != null) {
+            if (term1 != null)
+                content = Statement.make(st1, term1, term2, order1, this.memory);
+            else
+                content = term2;
+            if (sentence instanceof Question) {
+                budget = this.budgetfunctions.backwardWeak(value2);
+            } else {
+                if (sentence instanceof Goal) {
+                    if (keepOrder)
+                        truth = TruthFunctions.desireDed(value1, value2);
+                    else
+                        truth = TruthFunctions.desireInd(value1, value2);
+                } else
+                    truth = TruthFunctions.abduction(value1, value2);
+                budget = this.budgetfunctions.forward(truth);
+            }
+            this.memory.doublePremiseTask(budget, content, truth);
+        }
+        return true;
+    }
+    
+    /* --------------- rules used for independent variable introduction --------------- */
+    
+    /**
+     * {<C ==> <M --> P>>, <M --> S>} |- <(&&,C,<#x --> S>) ==> <#x --> P>>
+     * @param compound The compound statement: Implication or Conjunction
+     * @param component The component to be used as a premise in internal induction
+     * @param premise The second premise, directly used in internal induction
+     */
+    void introVarIndInner(CompoundTerm compound, Term component, Term premise) {
+        Task task = this.memory.currentTask;
+        Sentence sentence = task.getSentence();
+        if (!sentence.isJudgment())
+            return;
+        if (!(component instanceof Statement))
+            return;
+        if (component.getClass() != premise.getClass())
+            return;
+        Variable v1 = new Variable(Symbols.VARIABLE_TAG + "0");
+        Variable v2 = new Variable(Symbols.VARIABLE_TAG + "0");
+        Statement premise1 = (Statement) premise;
+        Statement premise2 = (Statement) component;
+        CompoundTerm.TemporalOrder order1 = premise1.getTemporalOrder();
+        CompoundTerm.TemporalOrder order2 = premise2.getTemporalOrder();
+        if (order1 != CompoundTerm.temporalReverse(order2))
+            return;
+        int figure;
+        if (premise1.getSubject().equals(premise2.getSubject()))
+            figure = 11;
+        else if (premise1.getPredicate().equals(premise2.getPredicate()))
+            figure = 22;
+        else
+            return;
+        Statement innerContent = introVarInd(null, premise1, premise2, figure);
+        if (innerContent == null)
+            return;
+        Sentence belief = this.memory.currentBelief;
+        Term content;
+        if (compound instanceof Implication) {
+            content = Statement.make((Statement) compound, compound.componentAt(0), innerContent, this.memory);
+        } else if (compound instanceof Conjunction) {
+            content = CompoundTerm.replaceComponent(compound, component, innerContent, this.memory);
+        } else
+            return;
+        TruthValue truth;
+        if (premise.equals(sentence.getContent()))
+            truth = TruthFunctions.abduction(sentence.getTruth(), belief.getTruth());
+        else
+            truth = TruthFunctions.abduction(belief.getTruth(), sentence.getTruth());
+        BudgetValue budget = this.budgetfunctions.forward(truth);
+        this.memory.doublePremiseTask(budget, content, truth);
+    }
+    
+    /**
+     * {<M --> S>, <M --> P>} |- <<#x --> S> ==> <#x --> P>>
+     * @param temp The template for the new task <S --> P>
+     * @param premise1 The first premise <M --> P>
+     * @param premise2 The second premise <M --> P>
+     * @param figure The figure indicating the location of the shared term
+     */
+    private Statement introVarInd(Statement temp, Statement premise1, Statement premise2, int figure) {
+        Statement state1, state2;
+        Variable v1 = new Variable(Symbols.VARIABLE_TAG + "0");
+        Variable v2 = new Variable(Symbols.VARIABLE_TAG + "0");
+        if (figure == 11) {
+            state1 = Statement.make(premise1, v1, premise1.getPredicate(), this.memory);
+            state2 = Statement.make(premise2, v2, premise2.getPredicate(), this.memory);
+        } else {
+            state1 = Statement.make(premise1, premise1.getSubject(), v1, this.memory);
+            state2 = Statement.make(premise2, premise2.getSubject(), v2, this.memory);
+        }
+        Statement content;
+        if ((temp == null) || !temp.isCommutative())
+            content = Implication.make(state1, state2, this.memory);
+        else
+            content = Equivalence.make(state1, state2, this.memory);
+        return content;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/inference/TruthFunctions.java b/open-nars/com/googlecode/opennars/inference/TruthFunctions.java
new file mode 100644
index 0000000000000000000000000000000000000000..63fe480cce39c49b466418a72aa95b90b7adde1b
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/inference/TruthFunctions.java
@@ -0,0 +1,369 @@
+/*
+ * TruthFunctions.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.inference;
+
+import com.googlecode.opennars.entity.TruthValue;
+
+/**
+ * All truth value functions used in inference rules 
+ */
+public final class TruthFunctions extends UtilityFunctions {
+    
+    /* ----- Single Argument Functions, called in MatchingRules and StructuralRules ----- */
+
+    /**
+     * {A} |- (--A)
+     * @param v1 Truth value of the premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue negation(TruthValue v1) {
+        float f = 1 - v1.getFrequency();
+        float c = v1.getConfidence();
+        return new TruthValue(f, c);
+    }
+    
+    /**
+     * {<A ==> B>} |- <B ==> A>
+     * @param v1 Truth value of the premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue conversion(TruthValue v1) {
+        float f1 = v1.getFrequency();
+        float c1 = v1.getConfidence();
+        float w = and(f1, c1);
+        float c = w2c(w);
+        return new TruthValue(1, c);
+    }
+    
+    /**
+     * {<A ==> B>} |- <(--, B) ==> (--, A)>
+     * @param v1 Truth value of the premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue contraposition(TruthValue v1) {
+        float f1 = v1.getFrequency();
+        float c1 = v1.getConfidence();
+        float w = and(1-f1, c1);
+        float c = w2c(w);
+        return new TruthValue(0, c);
+    }
+    
+    /**
+     * {<A ==> B>, A} |- B
+     * @param v1 Truth value of the premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue implying(TruthValue v1) {
+        float f1 = v1.getFrequency();
+        float c1 = v1.getConfidence();
+        float c = and(f1, c1);
+        return new TruthValue(f1, c);
+    }
+
+    /**
+     * {<A ==> B>, B} |- A
+     * @param v1 Truth value of the premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue implied(TruthValue v1) {
+        float f1 = v1.getFrequency();
+        float c1 = v1.getConfidence();
+        float c = w2c(c1);
+        return new TruthValue(f1, c);
+    }
+    
+    /**
+     * {<A ==> (--, B)>, A} |- B
+     * @param v1 Truth value of the premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue negImply(TruthValue v1) {
+        return negation(implying(v1));
+    }
+    
+    /* -------------------- called in MatchingRules -------------------- */
+    
+    /**
+     * {<S ==> P>, <S ==> P>} |- <S ==> P>
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue revision(TruthValue v1, TruthValue v2) {
+        float f1 = v1.getFrequency();
+        float f2 = v2.getFrequency();
+        float c1 = v1.getConfidence();
+        float c2 = v2.getConfidence();
+        float w1 = c1 / (1 - c1);
+        float w2 = c2 / (1 - c2);
+        float f = (w1 * f1 + w2 * f2) / (w1 + w2);
+        float c = (w1 + w2) / (w1 + w2 + 1);
+        return new TruthValue(f, c);
+    }
+    
+    /* -------------------- called in SyllogisticRules -------------------- */
+    
+    /**
+     * {<S ==> M>, <M ==> P>} |- <S ==> P>
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue deduction(TruthValue v1, TruthValue v2) {
+        float f1 = v1.getFrequency();
+        float f2 = v2.getFrequency();
+        float c1 = v1.getConfidence();
+        float c2 = v2.getConfidence();
+        float f = and(f1, f2);
+        float c = and(c1, c2, f);
+        return new TruthValue(f, c);
+    }
+    
+    /**
+     * {<S ==> M>, <P ==> M>} |- <S ==> P>
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue abduction(TruthValue v1, TruthValue v2) {
+        float f1 = v1.getFrequency();
+        float f2 = v2.getFrequency();
+        float c1 = v1.getConfidence();
+        float c2 = v2.getConfidence();
+        float w = and(f2, c1, c2);
+        float c = w2c(w);
+        return new TruthValue(f1, c);
+    }
+    
+    /**
+     * {<M ==> S>, <M ==> P>} |- <S ==> P>
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue induction(TruthValue v1, TruthValue v2) {
+        return abduction(v2, v1);
+    }
+    
+    /**
+     * {<M ==> S>, <P ==> M>} |- <S ==> P>
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue exemplification(TruthValue v1, TruthValue v2) {
+        float f1 = v1.getFrequency();
+        float f2 = v2.getFrequency();
+        float c1 = v1.getConfidence();
+        float c2 = v2.getConfidence();
+        float w = and(f1, f2, c1, c2);
+        float c = w2c(w);
+        return new TruthValue(1, c);
+    }
+    
+    /**
+     * {<M ==> S>, <M ==> P>} |- <S <=> P>
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue comparison(TruthValue v1, TruthValue v2) {
+        float f1 = v1.getFrequency();
+        float f2 = v2.getFrequency();
+        float c1 = v1.getConfidence();
+        float c2 = v2.getConfidence();
+        float f0 = or(f1, f2);
+        float f = (f0 == 0) ? 0 : (and(f1, f2) / f0) ;
+        float w = and(f0, c1, c2);
+        float c = w2c(w);
+        return new TruthValue(f, c);
+    }
+    
+    /**
+     * {<S ==> M>, <M <=> P>} |- <S ==> P>
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue analogy(TruthValue v1, TruthValue v2) {
+        float f1 = v1.getFrequency();
+        float f2 = v2.getFrequency();
+        float c1 = v1.getConfidence();
+        float c2 = v2.getConfidence();
+        float f = and(f1, f2);
+        float c0 = and(f2, c2);
+        float c = and(c1, c0, c0);
+        return new TruthValue(f, c);
+    }
+    
+    /**
+     * {<S <=> M>, <M <=> P>} |- <S <=> P>
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue resemblance(TruthValue v1, TruthValue v2) {
+        float f1 = v1.getFrequency();
+        float f2 = v2.getFrequency();
+        float c1 = v1.getConfidence();
+        float c2 = v2.getConfidence();
+        float f = and(f1, f2);
+        float c = and(c1, c2, or(f1, f2));
+        return new TruthValue(f, c);
+    }
+    
+    // -------------------- desire rules -------------------- //
+    
+    // strong backword inference on goals
+    // called in SyllogisticRules and HighOrderRules
+    static TruthValue desireStrong(TruthValue v1, TruthValue v2) {
+        float f1 = v1.getFrequency();
+        float f2 = v2.getFrequency();
+        float c1 = v1.getConfidence();
+        float c2 = v2.getConfidence();
+        float f = and(f1, f2);
+        float c = and(c1, c2, f2);
+        return new TruthValue(f, c);
+    }
+    
+    // weak backword inference on goals
+    // called in SyllogisticRules and HighOrderRules
+    static TruthValue desireWeak(TruthValue v1, TruthValue v2) {
+        float f1 = v1.getFrequency();
+        float f2 = v2.getFrequency();
+        float c1 = v1.getConfidence();
+        float c2 = v2.getConfidence();
+        float f = and(f1, f2);
+        float c = and(c1, c2, f2, w2c(1.0f));
+        return new TruthValue(f, c);
+    }
+    
+    // strong backword inference on goals
+    // called in HighOrderRules only
+    static TruthValue desireDed(TruthValue v1, TruthValue v2) {
+        float f1 = v1.getFrequency();
+        float f2 = v2.getFrequency();
+        float c1 = v1.getConfidence();
+        float c2 = v2.getConfidence();
+        float f = and(f1, f2);
+        float c = and(f, c1, c2);
+        return new TruthValue(f, c);
+    }
+    
+    // called in HighOrderRules only
+    static TruthValue desireInd(TruthValue v1, TruthValue v2) {
+        float f1 = v1.getFrequency();
+        float f2 = v2.getFrequency();
+        float c1 = v1.getConfidence();
+        float c2 = v2.getConfidence();
+        float w = and(f2, c1, c2);
+        float c = w2c(w);
+        return new TruthValue(f1, c);
+    }
+    
+    /* -------------------- called in CompositionalRules -------------------- */
+    
+    /**
+     * {<M --> S>, <M <-> P>} |- <M --> (S|P)>
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue union(TruthValue v1, TruthValue v2) {
+        float f1 = v1.getFrequency();
+        float f2 = v2.getFrequency();
+        float c1 = v1.getConfidence();
+        float c2 = v2.getConfidence();
+        float f = or(f1, f2);
+        float c = or(and(f1, c1), and(f2, c2)) + and(1 - f1, 1 - f2, c1, c2);
+        return new TruthValue(f, c);
+    }
+    
+    /**
+     * {<M --> S>, <M <-> P>} |- <M --> (S&P)>
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue intersection(TruthValue v1, TruthValue v2) {
+        float f1 = v1.getFrequency();
+        float f2 = v2.getFrequency();
+        float c1 = v1.getConfidence();
+        float c2 = v2.getConfidence();
+        float f = and(f1, f2);
+        float c = or(and(1 - f1, c1), and(1 - f2, c2)) + and(f1, f2, c1, c2);
+        return new TruthValue(f, c);
+    }
+    
+    /**
+     * {<M --> S>, <M <-> P>} |- <M --> (S-P)>
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue difference(TruthValue v1, TruthValue v2) {
+        TruthValue v0 = negation(v2);
+        return intersection(v1, v0);
+    }
+    
+    /**
+     * {(||, A, B), (--, B)} |- A
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue reduceDisjunction(TruthValue v1, TruthValue v2) {
+        TruthValue v0 = intersection(v1, negation(v2));
+        return implying(v0);
+    }
+    
+    /**
+     * {(--, (&&, A, B)), B} |- (--, A)
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue reduceConjunction(TruthValue v1, TruthValue v2) {
+        TruthValue v0 = intersection(negation(v1), v2);
+        return negation(implying(v0));
+    }
+    
+    /**
+     * {(--, (&&, A, (--, B))), (--, B)} |- (--, A)
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue reduceConjunctionNeg(TruthValue v1, TruthValue v2) {
+        return reduceConjunction(v1, negation(v2));
+    }
+    
+    /**
+     * {(&&, <#x() ==> M>, <#x() ==> P>), S ==> M} |- <S ==> P>
+     * @param v1 Truth value of the first premise
+     * @param v2 Truth value of the second premise
+     * @return Truth value of the conclusion
+     */
+    static TruthValue existAnalogy(TruthValue v1, TruthValue v2) {
+        return abduction(v1, v2);
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/inference/UtilityFunctions.java b/open-nars/com/googlecode/opennars/inference/UtilityFunctions.java
new file mode 100644
index 0000000000000000000000000000000000000000..ef3075af7a100ae755408fc825d00a73deafef96
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/inference/UtilityFunctions.java
@@ -0,0 +1,58 @@
+/*
+ * UtilityFunctions.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.inference;
+
+import com.googlecode.opennars.main.Parameters;
+
+/**
+ * Common functions on real numbers in [0,1].
+ */
+public class UtilityFunctions {
+
+    // arithmetic average
+    public static float aveAri(float... arr) {
+        float sum = 0;
+        for(int i=0; i<arr.length; i++)
+            sum += arr[i];
+        return sum / arr.length;
+    }
+
+    public static float or(float... arr) {
+        float product = 1;
+        for(int i=0; i<arr.length; i++)
+            product *= (1 - arr[i]);
+        return 1 - product;
+    }
+    
+    public static float and(float... arr) {
+        float product = 1;
+        for(int i=0; i<arr.length; i++)
+            product *= arr[i];
+        return product;
+    }
+    
+    // weight to confidence
+    public static float w2c(float v) {
+        return v / (v + Parameters.NEAR_FUTURE);
+    }    
+}
+
diff --git a/open-nars/com/googlecode/opennars/inference/package.html b/open-nars/com/googlecode/opennars/inference/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..95e3f329d6c7cde84007e0da90daa4e8706d645e
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/inference/package.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+
+The inference rules and control functions
+
+<h2>Package Specification</h2>
+
+Every task is processed in two stages:
+<ol>
+<li>Direct processing by matching, in the concept corresponding to the content, in one step. It happens when the task is inserted into memory.</li>
+<li>Indirect processing by reasoning, in related concepts and unlimited steps. It happens in each inference cycle.</li>
+</ol>
+The transmission from (1) to (2) corresponds to "decision making".
+<p>
+Inference between premises with no shared term can only happen in task buffer, between tasks based on common evidence.
+<p>
+In matching, the new task is compared with all existing direct Tasks in that Concept, to carry out:
+<ul>
+<li>revision: between judgments on non-overlapping evidence</li>
+<li>update: between judgments</li>
+<li>satisfy: between a Judgment and a Question/Goal</li>
+<li>merge: between items of the same type and base</li>
+</ul>
+<p>
+In reasoning, there are two basic types:
+<ol>
+<li>Between a Task and a TermLink (syntatic information)</li>
+<li>Between a Task and a Belief obtained by following a TermLink (semantic information).</li>
+</ol>
+In each case, there may be multiple applicable rules, which will be applied in parallel. For each rule, each conclusion is formed in three stages, to determine (1) the content (as a Term), (2) the truth-value or desire-value, and (3) the budget-value, in that order.
+<p>
+In the system, forward inference (the task is a Judgment) and backward inference (the task is a Question or Goal) are mostly isomorphic to each other, so that the inference rules produce clonclusions with the same content for different types of tasks. However, there are exceptions. For example, backward inference does not generate more complex terms.
+</body>
+</html>
diff --git a/open-nars/com/googlecode/opennars/language/CompoundTerm.java b/open-nars/com/googlecode/opennars/language/CompoundTerm.java
new file mode 100644
index 0000000000000000000000000000000000000000..0aac00e31b6f1bec60f8deac89b5470ee4012a8b
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/CompoundTerm.java
@@ -0,0 +1,638 @@
+/*
+ * CompoundTerm.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A Term with internal structure
+ * <p>
+ * Formed by a term operator with one or more component Terms.
+ * <p>
+ * This abstract class contains default methods for all CompoundTerms.
+ */
+public abstract class CompoundTerm extends Term {
+    
+    /**
+     * list of (direct) components
+     */
+    protected ArrayList<Term> components;
+    
+    /**
+     * list of open variables in the compound
+     */
+    protected ArrayList<Variable> openVariables;    // always necessary?
+    
+    /**
+     * list of closed variables in the compound
+     */
+    protected ArrayList<Variable> closedVariables;    // remove???
+    
+    /**
+     * syntactic complexity of the compound, which is the sum of those of its components plus 1
+     */
+    protected short complexity;
+    
+    
+    // abstract methods
+    public abstract Object clone();
+    public abstract String operator();
+    
+    /* ----- object builders, called from subclasses ----- */
+    
+    /**
+     * default constructor
+     */
+    public CompoundTerm() {}
+    
+    /**
+     * constructor called from subclasses constructors to clone the fields
+     */
+    protected CompoundTerm(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        name = n;
+        components = cs;
+        openVariables = open;
+        closedVariables = closed;
+        complexity = i;
+    }
+    
+    /**
+     * constructor called from subclasses constructors to initialize the fields
+     */
+    protected CompoundTerm(String n, ArrayList<Term> arg) {
+        components = arg;
+        calcComplexity();
+        markVariables();    // set in components, not in this
+        name = makeName();
+    }
+    
+    /**
+     * the complexity of the term is the sum of those of the components plus 1
+     */
+    private void calcComplexity() {
+        Term t;
+        complexity = 1;
+        for (int i = 0; i < components.size(); i++) {
+            t = components.get(i);
+            complexity += t.getComplexity();
+        }
+    }
+    
+    /**
+     * check CompoundTerm operator symbol
+     * @return if the given String is an operator symbol
+     * @param s The String to be checked
+     */
+    public static boolean isOperator(String s, Memory memory) {
+        if (s.length() == 1)
+            return (s.equals(Symbols.INTERSECTION_EXT_OPERATOR) ||
+                    s.equals(Symbols.INTERSECTION_INT_OPERATOR) ||
+                    s.equals(Symbols.DIFFERENCE_EXT_OPERATOR) ||
+                    s.equals(Symbols.DIFFERENCE_INT_OPERATOR) ||
+                    s.equals(Symbols.PRODUCT_OPERATOR) ||
+                    s.equals(Symbols.IMAGE_EXT_OPERATOR) ||
+                    s.equals(Symbols.IMAGE_INT_OPERATOR));
+        if (s.length() == 2)
+            return (s.equals(Symbols.NEGATION_OPERATOR) ||
+                    s.equals(Symbols.DISJUNCTION_OPERATOR) ||
+                    s.equals(Symbols.CONJUNCTION_OPERATOR) ||
+                    s.equals(Symbols.SEQUENCE_OPERATOR) ||
+                    s.equals(Symbols.PARALLEL_OPERATOR) ||
+                    s.equals(Symbols.PAST_OPERATOR) ||
+                    s.equals(Symbols.PRESENT_OPERATOR) ||
+                    s.equals(Symbols.FUTURE_OPERATOR));
+        return isBuiltInOperator(s, memory); // s.length() > 2
+    }
+        
+    public static Term make(String op, ArrayList arg, Memory memory) {
+        if (op.length() == 1) {
+            if (op.equals(Symbols.INTERSECTION_EXT_OPERATOR))
+                return IntersectionExt.make(arg, memory);
+            if (op.equals(Symbols.INTERSECTION_INT_OPERATOR))
+                return IntersectionInt.make(arg, memory);
+            if (op.equals(Symbols.DIFFERENCE_EXT_OPERATOR))
+                return DifferenceExt.make(arg, memory);
+            if (op.equals(Symbols.DIFFERENCE_INT_OPERATOR))
+                return DifferenceInt.make(arg, memory);
+            if (op.equals(Symbols.PRODUCT_OPERATOR))
+                return Product.make(arg, memory);
+            if (op.equals(Symbols.IMAGE_EXT_OPERATOR))
+                return ImageExt.make(arg, memory);
+            if (op.equals(Symbols.IMAGE_INT_OPERATOR))
+                return ImageInt.make(arg, memory);
+        }
+        if (op.length() == 2) {
+            if (op.equals(Symbols.NEGATION_OPERATOR))
+                return Negation.make(arg, memory);
+            if (op.equals(Symbols.DISJUNCTION_OPERATOR))
+                return Disjunction.make(arg, memory);
+            if (op.equals(Symbols.CONJUNCTION_OPERATOR))
+                return Conjunction.make(arg, memory);
+            if (op.equals(Symbols.SEQUENCE_OPERATOR))
+                return ConjunctionSequence.make(arg, memory);
+            if (op.equals(Symbols.PARALLEL_OPERATOR))
+                return ConjunctionSequence.make(arg, memory);
+            if (op.equals(Symbols.FUTURE_OPERATOR))
+                return TenseFuture.make(arg, memory);
+            if (op.equals(Symbols.PRESENT_OPERATOR))
+                return TensePresent.make(arg, memory);
+            if (op.equals(Symbols.PAST_OPERATOR))
+                return TensePast.make(arg, memory);
+        }
+        if (isBuiltInOperator(op, memory)) {
+            // t = Operator.make(op, arg);
+            Term sub = Product.make(arg, memory);
+            Term pre = memory.nameToOperator(op);
+            return Inheritance.make(sub, pre, memory);
+        }
+        return null;
+    }
+
+    /**
+     * check built-in operator name
+     * @return if the given String is an operator name
+     * @param s The String to be checked
+     */
+    private static boolean isBuiltInOperator(String s, Memory memory) {
+        return (s.charAt(0) == Symbols.OPERATOR_TAG) && (memory.nameToOperator(s) != null);
+    }
+    
+    public static Term make(CompoundTerm compound, ArrayList<Term> components, Memory memory) {
+        if (compound instanceof SetExt)
+            return SetExt.make(components, memory);
+        if (compound instanceof SetInt)
+            return SetInt.make(components, memory);
+        if (compound instanceof IntersectionExt)
+            return IntersectionExt.make(components, memory);
+        if (compound instanceof IntersectionInt)
+            return IntersectionInt.make(components, memory);
+        if (compound instanceof DifferenceExt)
+            return DifferenceExt.make(components, memory);
+        if (compound instanceof DifferenceInt)
+            return DifferenceInt.make(components, memory);
+        if (compound instanceof Product)
+            return Product.make(components, memory);
+        if (compound instanceof ImageExt)
+            return ImageExt.make(components, ((ImageExt) compound).getRelationIndex(), memory);
+        if (compound instanceof ImageInt)
+            return ImageInt.make(components, ((ImageInt) compound).getRelationIndex(), memory);
+        if (compound instanceof Disjunction)
+            return Disjunction.make(components, memory);
+        if (compound instanceof ConjunctionSequence)
+            return ConjunctionSequence.make(components, memory);
+        if (compound instanceof ConjunctionParallel)
+            return ConjunctionParallel.make(components, memory);
+        if (compound instanceof Conjunction)
+            return Conjunction.make(components, memory);
+        return null;
+    }
+    
+    /* ----- utilities for name ----- */
+    
+    /**
+     * default method to make the name of the current term from existing fields
+     * @return the name of the term
+     */
+    protected String makeName() {
+        return makeCompoundName(operator(), components);
+    }
+    
+    /**
+     * default method to make the name of a compound term from given fields
+     * @param op the term operator
+     * @param arg the list of components
+     * @return the name of the term
+     */
+    protected static String makeCompoundName(String op, ArrayList<Term> arg) {
+        StringBuffer name = new StringBuffer();
+        name.append(Symbols.COMPOUND_TERM_OPENER);      // also show closed variables???
+        name.append(op);
+        for (int i = 0; i < arg.size(); i++) {
+            name.append(Symbols.ARGUMENT_SEPARATOR);
+            name.append(arg.get(i).getName());
+        }
+        name.append(Symbols.COMPOUND_TERM_CLOSER);
+        return name.toString();
+    }
+    
+    /**
+     * make the name of an ExtensionSet or IntensionSet
+     * @param opener the set opener
+     * @param closer the set closer
+     * @param arg the list of components
+     * @return the name of the term
+     */
+    protected static String makeSetName(char opener, ArrayList<Term> arg, char closer) {
+        StringBuffer name = new StringBuffer();
+        name.append(opener);
+        name.append(arg.get(0).toString());
+        for (int i = 1; i < arg.size(); i++) {
+            name.append(Symbols.ARGUMENT_SEPARATOR);
+            name.append(arg.get(i).getName());
+        }
+        name.append(closer);
+        return name.toString();
+    }
+    
+    /**
+     * default method to make the name of an image term from given fields
+     * @param op the term operator
+     * @param arg the list of components
+     * @param relationIndex the location of the place holder
+     * @return the name of the term
+     */
+    protected static String makeImageName(String op, ArrayList<Term> arg, int relationIndex) {
+        StringBuffer name = new StringBuffer();
+        name.append(Symbols.COMPOUND_TERM_OPENER);
+        name.append(op);
+        name.append(Symbols.ARGUMENT_SEPARATOR);
+        name.append(arg.get(relationIndex).getName());
+        for (int i = 0; i < arg.size(); i++) {
+            name.append(Symbols.ARGUMENT_SEPARATOR);
+            if (i == relationIndex)
+                name.append(Symbols.IMAGE_PLACE_HOLDER);
+            else
+                name.append(arg.get(i).getName());
+        }
+        name.append(Symbols.COMPOUND_TERM_CLOSER);
+        return name.toString();
+    }
+    
+    /**
+     * skip all variable names to produce stable sorting order among components, not for display
+     * @return the constant part of the term name
+     */
+    public String getConstantName() {
+        StringBuffer s = new StringBuffer();
+        s.append(Symbols.COMPOUND_TERM_OPENER);
+        s.append(operator());
+        s.append(Symbols.ARGUMENT_SEPARATOR);
+        for (int i = 0; i < components.size(); i++) {
+            s.append(components.get(i).getConstantName());
+            s.append(Symbols.ARGUMENT_SEPARATOR);
+        }
+        s.append(Symbols.COMPOUND_TERM_CLOSER);
+        return s.toString();
+    }
+    
+    /* ----- utilities for other fields ----- */
+    
+    /**
+     * report the term's syntactic complexity
+     * @return the comlexity value
+     */
+    public int getComplexity() {
+        return complexity;
+    }
+    
+    /**
+     * check if the term contains free variable
+     * @return if the term is a constant
+     */
+    public boolean isConstant() {
+        return (openVariables == null);
+    }
+    
+    /**
+     * check if the order of the components matters
+     * <p>
+     * commutative CompoundTerms: Sets, Intersections;
+     * communative Statements: Similarity, Equivalence;
+     * communative CompoundStatements: Disjunction, Conjunction
+     * @return if the term is a communitive
+     */
+    public boolean isCommutative() {
+        return false;
+    }
+        
+    /**
+     * build a component list from two terms
+     * @param t1 the first component
+     * @param t2 the second component
+     * @return the component list
+     */
+    protected static ArrayList<Term> argumentsToList(Term t1, Term t2) {
+        ArrayList<Term> list = new ArrayList<Term>(2);
+        list.add(t1);
+        list.add(t2);
+        return list;
+    }
+    
+    /* ----- extend Collection methods to component list ----- */
+    
+    /**
+     * get the number of components
+     * @return the size of the component list
+     */
+    public int size() {
+        return components.size();
+    }
+    
+    /**
+     * get a component by index
+     * @param i index of the component
+     * @return the component
+     */
+    public Term componentAt(int i) {
+        return components.get(i);
+    }
+    
+    public ArrayList<Term> getComponents() {
+        return components;
+    }
+    
+    public ArrayList<Term> cloneComponents() {
+        return (ArrayList<Term>) cloneList(components);
+    }
+    
+    /**
+     * deep clone an array list
+     * @return an identical and separate copy of the list
+     */
+    public static ArrayList cloneList(ArrayList original) {
+        if (original == null)
+            return null;
+        ArrayList arr = new ArrayList(original.size());
+        for (int i = 0; i < original.size(); i++)
+            arr.add(((Term) original.get(i)).clone());
+        return arr;
+    }
+    
+    public boolean containComponent(Term t) {
+        return components.contains(t);
+    }
+    
+    public boolean containAllComponents(Term t) {
+        if (getClass() == t.getClass())
+            return components.containsAll(((CompoundTerm) t).getComponents());
+        else
+            return components.contains(t);
+    }
+    
+    /* ----- clone/modify methods ----- */
+    
+    public static Term reduceComponents(CompoundTerm t1, Term t2, Memory memory) {
+        boolean done;
+        ArrayList<Term> list = t1.cloneComponents();
+        if (t1.getClass() == t2.getClass())
+            done = list.removeAll(((CompoundTerm) t2).getComponents());
+        else
+            done = list.remove(t2);
+        return (done ? make(t1, list, memory) : null);
+    }
+
+    public static Term replaceComponent(CompoundTerm compound, int index, Term t, Memory memory) {
+        ArrayList<Term> list = compound.cloneComponents();
+        if (t == null)
+            list.remove(index);
+        else if (compound.getClass() != t.getClass())
+            list.set(index, t);
+        else {
+            ArrayList<Term> list2 = ((CompoundTerm)t).cloneComponents();
+            for (int i = 0; i < list2.size(); i++)
+                list.add(index + i, list2.get(i));
+        }
+        if (compound.isCommutative())
+            Collections.sort(list);
+        return make(compound, list, memory);
+    }
+
+    public static Term replaceComponent(CompoundTerm compound, Term oldComponent, Term newComponent, Memory memory) {
+        ArrayList<Term> list = compound.cloneComponents();
+        int index = list.indexOf(oldComponent);
+        list.remove(index);
+        if (compound.getClass() != newComponent.getClass())
+            list.add(index, newComponent);
+        else {
+            ArrayList<Term> list2 = ((CompoundTerm)newComponent).cloneComponents();
+            for (int i = 0; i < list2.size(); i++)
+                list.add(index + i, list2.get(i));
+        }
+        if (compound.isCommutative())
+            Collections.sort(list);
+        return make(compound, list, memory);
+    }
+   
+    /* ----- variable-related utilities ----- */
+    
+    /**
+     * get the OpenVariables list
+     * @return the open variables list
+     */
+    public ArrayList<Variable> getOpenVariables() {
+        return openVariables;
+    }
+    
+    /**
+     * register open and closed variables in a CompoundTerm
+     * <p>
+     * an open variable only appears in one components, while a closed variable appears in multiple components
+     */
+    private void markVariables() {  // not recursive
+        openVariables = new ArrayList<Variable>();
+        ArrayList<Variable> closedVariables = new ArrayList<Variable>();  // local variable
+        ArrayList<Variable> list;
+        for (Term term : components) {
+            if ((term instanceof Variable) && (((Variable) term).getType() != Variable.VarType.ANONYMOUS)) {
+                openVariables.add((Variable) term);
+            } else if (term instanceof CompoundTerm) {
+                list = ((CompoundTerm) term).getOpenVariables();
+                if (list != null) {
+                    for (Variable var : list) {
+                        if (var.getType() == Variable.VarType.QUERY)
+                            openVariables.add(var);
+                        else {
+                            int i = openVariables.indexOf(var);
+                            if (i >= 0) {           // assume a (independent/dependent) variable appears exactly twice
+                                var.setScope(this);
+                                openVariables.get(i).setScope(this);
+                                openVariables.remove(i);
+                                closedVariables.add(var);
+                            } else
+                                openVariables.add(var);
+                        }
+                    }
+                }
+            }
+        }
+        if (openVariables.size() == 0) // {
+            openVariables = null;
+    }
+    
+    // only called from Sentence
+    public void renameVariables() {
+        renameVariables(new HashMap<String, String>());
+    }
+    
+    /**
+     * Recursively rename variables by their appearing order in the CompoundTerm
+     * <p>
+     * Since each occurance of a variable is processed exactly ones, there will be no confusion between new names and old names.
+     * @param varMap the mapping built so far
+     */
+    protected void renameVariables(HashMap<String, String> varMap) {
+        String oldName, newName;
+        for (Term t : components) {
+            if ((t instanceof Variable) && (((Variable) t).getType() != Variable.VarType.ANONYMOUS)) {
+                oldName = ((Variable) t).getSimpleName();
+                newName = varMap.get(oldName);
+                if (newName == null) {
+                    newName = makeVarName(varMap.size(), (Variable) t);
+                    varMap.put(oldName, newName);
+                }
+                ((Variable) t).setName(newName);
+//            } else if ((t instanceof CompoundTerm) && !(t.isConstant())) {
+            } else if (t instanceof CompoundTerm) {
+                ((CompoundTerm) t).renameVariables(varMap);
+            }
+        }
+        name = makeName();     // type-specific
+    }
+    
+    /**
+     * sequentially generate new variable names
+     * @param size the current size of the variable list
+     * @param v the variable to be renamed
+     * @return a new variable name
+     */
+    private String makeVarName(int size, Variable v) {
+        StringBuffer s = new StringBuffer();
+        Variable.VarType type = v.getType();
+        if (type == Variable.VarType.QUERY)
+            s.append(Symbols.QUERY_VARIABLE_TAG);
+        else
+            s.append(Symbols.VARIABLE_TAG);
+        s.append(size + 1);
+        return s.toString();
+    }
+    
+    public void substituteComponent(HashMap<String,Term> subs, boolean first) {
+        Term t1, t2;
+        String varName;
+        for (int i = 0; i < size(); i++) {
+            t1 = componentAt(i);
+            if (t1 instanceof Variable) {                  // simple Variable
+                varName = ((Variable) t1).getVarName(first);  // name of the variable used in the mapping
+                t2 = subs.get(varName);                       // new Term if exist
+                if (t2 != null) {
+                    components.set(i, t2);
+                }
+            } else if (t1 instanceof CompoundTerm) {              // compound
+                ((CompoundTerm) t1).substituteComponent(subs, first);   // apply substitute to a clone
+            }
+        }
+        markVariables();        // variable status may be changed, so need to re-do this
+        name = makeName();
+    }
+    
+    /* ----- link CompoundTerm and its components ----- */
+    
+    /**
+     * build CompositionalLinks to constant components and subcomponents
+     * <p>
+     * The compound type determines the link type; the component type determines whether to build the link.
+     */
+    public ArrayList<TermLink> prepareComponentLinks(Memory memory) {
+        ArrayList<TermLink> componentLinks = new ArrayList<TermLink>();
+        short type = (this instanceof Statement) ? TermLink.COMPOUND_STATEMENT : TermLink.COMPOUND;   // default
+        prepareComponentLinks(componentLinks, type, this, memory);
+        return componentLinks;
+    }
+    
+    protected void prepareComponentLinks(ArrayList<TermLink> componentLinks, short type, CompoundTerm term, Memory memory) {
+        Term t1, t2, t3;
+        for (int i = 0; i < term.size(); i++) {     // first level components
+            t1 = term.componentAt(i);
+            if (t1.isConstant())                                            // first level
+                componentLinks.add(new TermLink(t1, type, i, memory));
+            if ((this instanceof Implication) && (i == 0) && (t1 instanceof Conjunction)) {
+                ((CompoundTerm) t1).prepareComponentLinks(componentLinks, TermLink.COMPOUND_CONDITION, (CompoundTerm) t1, memory);
+            } else if (t1 instanceof CompoundTerm) {
+                for (int j = 0; j < ((CompoundTerm) t1).size(); j++) {
+                    t2 = ((CompoundTerm) t1).componentAt(j);
+                    if (t2.isConstant()) {                                  // second level
+                        if ((t1 instanceof Product) || (t1 instanceof ImageExt) || (t1 instanceof ImageInt))
+                            componentLinks.add(new TermLink(t2, TermLink.TRANSFORM, i, j, memory));
+                        else
+                            componentLinks.add(new TermLink(t2, type, i, j, memory));
+                    }
+                    if ((t2 instanceof Product) || (t2 instanceof ImageExt) || (t2 instanceof ImageInt)) {
+                        for (int k = 0; k < ((CompoundTerm) t2).size(); k++) {
+                            t3 = ((CompoundTerm) t2).componentAt(k);
+                            if (t3.isConstant()) {                           // third level
+                                componentLinks.add(new TermLink(t3, TermLink.TRANSFORM, i, j, k, memory));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    
+    /* ---------- temporal order among components ---------- */
+    
+    public enum TemporalOrder { BEFORE, WHEN, AFTER, NONE, UNSURE }
+    
+    public static TemporalOrder temporalInference(TemporalOrder t1, TemporalOrder t2) {
+        if ((t1 == TemporalOrder.UNSURE) || (t2 == TemporalOrder.UNSURE))
+            return TemporalOrder.UNSURE;
+        if (t1 == TemporalOrder.NONE)
+            return t2;
+        if (t2 == TemporalOrder.NONE)
+            return t1;
+        if (t1 == TemporalOrder.WHEN)
+            return t2;
+        if (t2 == TemporalOrder.WHEN)
+            return t1;
+        if (t1 == t2)
+            return t1;
+        return TemporalOrder.UNSURE;
+    }
+
+    public static TemporalOrder temporalReverse(TemporalOrder t1) {
+        if (t1 == TemporalOrder.BEFORE)
+            return TemporalOrder.AFTER;
+        if (t1 == TemporalOrder.AFTER)
+            return TemporalOrder.BEFORE;
+        return t1;
+    } 
+    
+    public static TemporalOrder temporalInferenceWithFigure(TemporalOrder order1, TemporalOrder order2, int figure) {
+        switch (figure) {
+        case 11:
+            return temporalInference(temporalReverse(order1), order2);
+        case 12:
+            return temporalInference(temporalReverse(order1), temporalReverse(order2));
+        case 21:
+            return temporalInference(order1, order2);
+        case 22:
+            return temporalInference(order1, temporalReverse(order2));
+        default:
+            return TemporalOrder.UNSURE;
+        }
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/Conjunction.java b/open-nars/com/googlecode/opennars/language/Conjunction.java
new file mode 100644
index 0000000000000000000000000000000000000000..398cf54c3daf5a9b399dfe68fcc741c19474bd36
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Conjunction.java
@@ -0,0 +1,133 @@
+/*
+ * Conjunction.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.inference.*;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.*;
+
+/**
+ * Conjunction of statements
+ */
+public class Conjunction extends CompoundTerm {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    protected Conjunction(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    protected Conjunction(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a Conjunction
+     */
+    public Object clone() {
+        return new Conjunction(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param term1 The first compoment
+     * @param term2 The second compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(Term term1, Term term2, Memory memory) {
+        TreeSet set;
+        if (term1 instanceof Conjunction) {
+            set = new TreeSet(((CompoundTerm) term1).cloneComponents());
+            if (term2 instanceof Conjunction)
+                set.addAll(((CompoundTerm) term2).cloneComponents());   // (&,(&,P,Q),(&,R,S)) = (&,P,Q,R,S)
+            else
+                set.add((Term) term2.clone());                          // (&,(&,P,Q),R) = (&,P,Q,R)
+        } else if (term2 instanceof Conjunction) {
+            set = new TreeSet(((CompoundTerm) term2).cloneComponents()); 
+            set.add((Term) term1.clone());                              // (&,R,(&,P,Q)) = (&,P,Q,R)
+        } else {
+            set = new TreeSet();
+            set.add(term1);         // valid solution???
+            set.add(term2);
+//            set.add((Term) term1.clone());
+//            set.add((Term) term2.clone());
+        }
+        return make(set, memory);
+    }
+    
+    /**
+     * Try to make a new compound from a list of components. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argList the list of arguments
+     */
+    public static Term make(ArrayList<Term> argList, Memory memory) {
+        TreeSet<Term> set = new TreeSet<Term>(argList); // sort/merge arguments
+        return make(set, memory);
+    }
+
+    /**
+     * Try to make a new compound from a set of components. Called by the public make methods.
+     * @param set a set of Term as compoments
+     * @return the Term generated from the arguments
+     */
+    public static Term make(TreeSet<Term> set, Memory memory) {
+        if (set.isEmpty())
+            return null;                         // special case: no component
+        if (set.size() == 1)
+            return set.first();                         // special case: single component
+        ArrayList<Term> argument = new ArrayList<Term>(set);
+        String name = makeCompoundName(Symbols.CONJUNCTION_OPERATOR, argument);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new Conjunction(name, argument);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.CONJUNCTION_OPERATOR;
+    }
+    
+    /**
+     * Check if the compound is communitative.
+     * @return true for communitative
+     */
+    public boolean isCommutative() {
+        return true;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/ConjunctionParallel.java b/open-nars/com/googlecode/opennars/language/ConjunctionParallel.java
new file mode 100644
index 0000000000000000000000000000000000000000..1af046891af47e64322a0a7bf2054e0672ac08a8
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/ConjunctionParallel.java
@@ -0,0 +1,127 @@
+/*
+ * ConjunctionParallel.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.inference.*;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.*;
+
+/**
+ * A parallel conjunction of Statements.
+ */
+public class ConjunctionParallel extends Conjunction {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    protected ConjunctionParallel(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    protected ConjunctionParallel(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a Conjunction
+     */
+    public Object clone() {
+        return new ConjunctionParallel(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param term1 The first compoment
+     * @param term2 The second compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(Term term1, Term term2, Memory memory) {
+        TreeSet set;
+        if (term1 instanceof ConjunctionParallel) {
+            set = new TreeSet(((CompoundTerm) term1).cloneComponents());
+            if (term2 instanceof ConjunctionParallel)
+                set.addAll(((CompoundTerm) term2).cloneComponents());   // (&,(&,P,Q),(&,R,S)) = (&,P,Q,R,S)
+            else
+                set.add((Term) term2.clone());                          // (&,(&,P,Q),R) = (&,P,Q,R)
+        } else if (term2 instanceof ConjunctionParallel) {
+            set = new TreeSet(((CompoundTerm) term2).cloneComponents()); 
+            set.add((Term) term1.clone());                              // (&,R,(&,P,Q)) = (&,P,Q,R)
+        } else {
+            set = new TreeSet();
+            set.add(term1);         // valid solution???
+            set.add(term2);
+        }
+        return make(set, memory);
+    }
+    
+    /**
+     * Try to make a new compound from a list of components. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argList the list of arguments
+     */
+    public static Term make(ArrayList<Term> argList, Memory memory) {
+        TreeSet<Term> set = new TreeSet<Term>(argList); // sort/merge arguments
+        return make(set, memory);
+    }
+
+    /**
+     * Try to make a new compound from a set of components. Called by the public make methods.
+     * @param set a set of Term as compoments
+     * @return the Term generated from the arguments
+     */
+    public static Term make(TreeSet<Term> set, Memory memory) {
+        if (set.isEmpty())
+            return null;                         // special case: no component
+        if (set.size() == 1)
+            return set.first();                         // special case: single component
+        ArrayList<Term> argument = new ArrayList<Term>(set);
+        String name = makeCompoundName(Symbols.CONJUNCTION_OPERATOR, argument);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new ConjunctionParallel(name, argument);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.PARALLEL_OPERATOR;
+    }
+
+    public CompoundTerm.TemporalOrder getTemporalOrder() {
+        return CompoundTerm.TemporalOrder.WHEN;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/ConjunctionSequence.java b/open-nars/com/googlecode/opennars/language/ConjunctionSequence.java
new file mode 100644
index 0000000000000000000000000000000000000000..7b971e4913e80055bb058aba6215592e4a2d2df0
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/ConjunctionSequence.java
@@ -0,0 +1,97 @@
+/*
+ * ConjunctionSequence.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.inference.*;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.*;
+
+/**
+ * A sequential conjunction of Statements.
+ */
+public class ConjunctionSequence extends Conjunction {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private ConjunctionSequence(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private ConjunctionSequence(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a Conjunction
+     */
+    public Object clone() {
+        return new ConjunctionSequence(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+    
+    /**
+     * Try to make a new compound from a list of components. Called by StringParser.
+     * @param argument the list of arguments
+     * @return the Term generated from the arguments
+     */
+    public static Term make(ArrayList<Term> argument, Memory memory) {
+        if (argument.size() == 1)
+            return argument.get(0);
+        String name = makeCompoundName(Symbols.PRODUCT_OPERATOR, argument);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new ConjunctionSequence(name, argument);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.SEQUENCE_OPERATOR;
+    }
+    
+    /**
+     * Check if the compound is communitative.
+     * @return true for communitative
+     */
+    public boolean isCommutative() {
+        return false;
+    }
+
+    public CompoundTerm.TemporalOrder getTemporalOrder() {
+        return CompoundTerm.TemporalOrder.AFTER;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/DifferenceExt.java b/open-nars/com/googlecode/opennars/language/DifferenceExt.java
new file mode 100644
index 0000000000000000000000000000000000000000..59fecd68d14c99c17ae1e5a07de649c402f4cb80
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/DifferenceExt.java
@@ -0,0 +1,105 @@
+/*
+ * DifferenceExt.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A compound term whose extension is the difference of the extensions of its components
+ */
+public class DifferenceExt extends CompoundTerm {
+
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private DifferenceExt(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private DifferenceExt(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a DifferenceExt
+     */
+    public Object clone() {
+        return new DifferenceExt(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+    
+    /**
+     * Try to make a new DifferenceExt. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argList The list of components
+     */     
+    public static Term make(ArrayList<Term> argList, Memory memory) {
+        if (argList.size() == 1)    // special case from CompoundTerm.reduceComponent
+            return argList.get(0);
+        if (argList.size() != 2)
+            return null;
+        String name = makeCompoundName(Symbols.DIFFERENCE_EXT_OPERATOR, argList);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new DifferenceExt(name, argList);
+    }
+
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param t1 The first compoment
+     * @param t2 The second compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(Term t1, Term t2, Memory memory) {
+        if (t1.equals(t2))
+            return null;
+        if ((t1 instanceof SetExt) && (t2 instanceof SetExt)) {
+            TreeSet set = new TreeSet(((CompoundTerm) t1).cloneComponents());
+            set.removeAll(((CompoundTerm) t2).cloneComponents());           // set difference
+            return SetExt.make(set, memory);
+        }
+        ArrayList<Term> list = argumentsToList(t1, t2);
+        return make(list, memory);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.DIFFERENCE_EXT_OPERATOR;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/DifferenceInt.java b/open-nars/com/googlecode/opennars/language/DifferenceInt.java
new file mode 100644
index 0000000000000000000000000000000000000000..acace500c7c9ff05b167affb3bc878e74e5988d4
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/DifferenceInt.java
@@ -0,0 +1,107 @@
+/*
+ * DifferenceInt.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A compound term whose extension is the difference of the intensions of its components
+ */
+public class DifferenceInt extends CompoundTerm {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private DifferenceInt(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private DifferenceInt(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a DifferenceInt
+     */
+    public Object clone() {
+        return new DifferenceInt(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+    
+    /**
+     * Try to make a new DifferenceExt. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argList The list of components
+     */     
+    public static Term make(ArrayList<Term> argList, Memory memory) {
+        if (argList.size() == 1)    // special case from CompoundTerm.reduceComponent
+            return argList.get(0);
+        if (argList.size() != 2)
+            return null;
+        String name = makeCompoundName(Symbols.DIFFERENCE_INT_OPERATOR, argList);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new DifferenceInt(name, argList);
+    }
+
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param t1 The first compoment
+     * @param t2 The second compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(Term t1, Term t2, Memory memory) {
+        if (t1.equals(t2))
+            return null;
+        if ((t1 instanceof SetInt) && (t2 instanceof SetInt)) {
+            TreeSet set = new TreeSet(((CompoundTerm) t1).cloneComponents());
+            set.removeAll(((CompoundTerm) t2).cloneComponents());           // set difference
+            return SetInt.make(set, memory);
+        }
+        ArrayList<Term> list = argumentsToList(t1, t2);
+        return make(list, memory);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.DIFFERENCE_INT_OPERATOR;
+    }
+}
+
+
diff --git a/open-nars/com/googlecode/opennars/language/Disjunction.java b/open-nars/com/googlecode/opennars/language/Disjunction.java
new file mode 100644
index 0000000000000000000000000000000000000000..387f977c71a93e8df1d614663e0a7c389ba7a88b
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Disjunction.java
@@ -0,0 +1,129 @@
+/*
+ * Disjunction.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.inference.*;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.*;
+
+/** 
+ * A disjunction of Statements.
+ */
+public class Disjunction extends CompoundTerm {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private Disjunction(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private Disjunction(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a Disjunction
+     */
+    public Object clone() {
+        return new Disjunction(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+
+    /**
+     * Try to make a new Disjunction from two components. Called by the inference rules.
+     * @param term1 The first compoment
+     * @param term2 The first compoment
+     * @return A Disjunction generated or a Term it reduced to
+     */
+    public static Term make(Term term1, Term term2, Memory memory) {
+        TreeSet set;
+        if (term1 instanceof Disjunction) {
+            set = new TreeSet(((CompoundTerm) term1).cloneComponents());
+            if (term2 instanceof Disjunction)
+                set.addAll(((CompoundTerm) term2).cloneComponents());   // (&,(&,P,Q),(&,R,S)) = (&,P,Q,R,S)
+            else
+                set.add((Term) term2.clone());                          // (&,(&,P,Q),R) = (&,P,Q,R)
+        } else if (term2 instanceof Disjunction) {
+            set = new TreeSet(((CompoundTerm) term2).cloneComponents()); 
+            set.add((Term) term1.clone());                              // (&,R,(&,P,Q)) = (&,P,Q,R)
+        } else {
+            set = new TreeSet();
+            set.add((Term) term1.clone());
+            set.add((Term) term2.clone());
+        }
+        return make(set, memory);
+    }
+    
+    /**
+     * Try to make a new IntersectionExt. Called by StringParser.
+     * @param argList a list of Term as compoments
+     * @return the Term generated from the arguments
+     */
+    public static Term make(ArrayList<Term> argList, Memory memory) {
+        TreeSet<Term> set = new TreeSet<Term>(argList); // sort/merge arguments
+        return make(set, memory);
+    }
+
+    /**
+     * Try to make a new Disjunction from a set of components. Called by the public make methods.
+     * @param set a set of Term as compoments
+     * @return the Term generated from the arguments
+     */
+    public static Term make(TreeSet<Term> set, Memory memory) {
+        if (set.size() == 1)
+            return set.first();                         // special case: single component
+        ArrayList<Term> argument = new ArrayList<Term>(set);
+        String name = makeCompoundName(Symbols.DISJUNCTION_OPERATOR, argument);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new Disjunction(name, argument);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.DISJUNCTION_OPERATOR;
+    }
+
+    /**
+     * Conjunction is communitative.
+     * @return true for communitative
+     */
+    public boolean isCommutative() {
+        return true;
+    }    
+}
diff --git a/open-nars/com/googlecode/opennars/language/Equivalence.java b/open-nars/com/googlecode/opennars/language/Equivalence.java
new file mode 100644
index 0000000000000000000000000000000000000000..e63106bfefa087b42d2559b89cd25a68007ca7e3
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Equivalence.java
@@ -0,0 +1,99 @@
+/*
+ * Equivalence.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A Statement about an Equivalence relation.
+ */
+public class Equivalence extends Statement {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    protected Equivalence(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    protected Equivalence(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a Similarity
+     */
+    public Object clone() {
+        return new Equivalence(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+     
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param subject The first compoment
+     * @param predicate The second compoment
+     * @return A compound generated or null
+     */
+    public static Equivalence make(Term subject, Term predicate, Memory memory) {
+        if (invalidStatement(subject, predicate))
+            return null;
+        if (subject.compareTo(predicate) > 0)
+            return make(predicate, subject, memory);
+        String name = makeStatementName(subject, Symbols.EQUIVALENCE_RELATION, predicate);
+        Term t = memory.nameToListedTerm(name);
+        if (t != null)
+            return (Equivalence) t;
+        ArrayList<Term> argument = argumentsToList(subject, predicate);
+        return new Equivalence(name, argument);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.EQUIVALENCE_RELATION;
+    }
+    
+    /**
+     * Check if the compound is communitative.
+     * @return true for communitative
+     */
+    public boolean isCommutative() {
+        return true;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/EquivalenceAfter.java b/open-nars/com/googlecode/opennars/language/EquivalenceAfter.java
new file mode 100644
index 0000000000000000000000000000000000000000..c9d008d53b94128b4feb5821bef4325c53e0493a
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/EquivalenceAfter.java
@@ -0,0 +1,100 @@
+/*
+ * EquivalenceAfter.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * Temporal Implication relation, predicate after subject.
+ */
+public class EquivalenceAfter extends Equivalence {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    public EquivalenceAfter(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private EquivalenceAfter(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a Similarity
+     */
+    public Object clone() {
+        return new EquivalenceAfter(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+     
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param subject The first compoment
+     * @param predicate The second compoment
+     * @return A compound generated or null
+     */
+    public static EquivalenceAfter make(Term subject, Term predicate, Memory memory) {
+        if (invalidStatement(subject, predicate))
+            return null;
+        String name = makeStatementName(subject, Symbols.EQUIVALENCE_RELATION, predicate);
+        Term t = memory.nameToListedTerm(name);
+        if (t != null)
+            return (EquivalenceAfter) t;
+        ArrayList<Term> argument = argumentsToList(subject, predicate);
+        return new EquivalenceAfter(name, argument);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.EQUIVALENCE_AFTER_RELATION;
+    }
+    
+    /**
+     * Check if the compound is communitative.
+     * @return true for communitative
+     */
+    public boolean isCommutative() {
+        return false;
+    }
+
+    public CompoundTerm.TemporalOrder getTemporalOrder() {
+        return CompoundTerm.TemporalOrder.AFTER;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/EquivalenceWhen.java b/open-nars/com/googlecode/opennars/language/EquivalenceWhen.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6853db83ed2f5ebf5c56fa4ae8e65ea9a305c3f
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/EquivalenceWhen.java
@@ -0,0 +1,95 @@
+/*
+ * EquivalenceWhen.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * Temporal Equivalence relation, concurrent.
+ *
+ */
+public class EquivalenceWhen extends Equivalence {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    public EquivalenceWhen(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private EquivalenceWhen(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a Similarity
+     */
+    public Object clone() {
+        return new EquivalenceWhen(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+     
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param subject The first compoment
+     * @param predicate The second compoment
+     * @return A compound generated or null
+     */
+    public static EquivalenceWhen make(Term subject, Term predicate, Memory memory) {
+        if (invalidStatement(subject, predicate))
+            return null;
+        if (subject.compareTo(predicate) > 0)
+            return make(predicate, subject, memory);
+        String name = makeStatementName(subject, Symbols.EQUIVALENCE_RELATION, predicate);
+        Term t = memory.nameToListedTerm(name);
+        if (t != null)
+            return (EquivalenceWhen) t;
+        ArrayList<Term> argument = argumentsToList(subject, predicate);
+        return new EquivalenceWhen(name, argument);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.EQUIVALENCE_WHEN_RELATION;
+    }
+
+    public CompoundTerm.TemporalOrder getTemporalOrder() {
+        return CompoundTerm.TemporalOrder.WHEN;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/ImageExt.java b/open-nars/com/googlecode/opennars/language/ImageExt.java
new file mode 100644
index 0000000000000000000000000000000000000000..5cd342cb20676faefb1f59f88f2d51a842e70cd7
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/ImageExt.java
@@ -0,0 +1,172 @@
+/*
+ * ImageExt.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * An extension image.
+ * <p>
+ * B --> (/,P,A,_)) iff (*,A,B) --> P
+ * <p>
+ * Internally, it is actually (/,A,P)_1, with an index.
+ */
+public class ImageExt extends CompoundTerm {
+
+    /**
+     * The index of relation in the component list.
+     */
+    private short relationIndex;
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     * @param index The index of relation in the component list
+     */
+    private ImageExt(String n, ArrayList<Term> arg, short index) {
+        super(n, arg);
+        relationIndex = index;
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param complexity syntactic complexity of the compound
+     * @param n The name of the term
+     * @param index The index of relation in the component list
+     */
+    private ImageExt(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short complexity, short index) {
+        super(n, cs, open, closed, complexity);
+        relationIndex = index;
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into an ImageExt
+     */
+    public Object clone() {
+        return new ImageExt(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity, relationIndex);
+    }
+
+     /**
+     * Try to make a new ImageExt. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argList The list of components
+     */
+    public static Term make(ArrayList<Term> argList, Memory memory) {
+        if (argList.size() < 3)
+            return null;
+        Term t;
+        Term relation = argList.get(0);
+        ArrayList<Term> argument = new ArrayList<Term>();
+        int index = 0;
+        for (int j = 1; j < argList.size(); j++) {
+            if (argList.get(j).getName().charAt(0) == Symbols.IMAGE_PLACE_HOLDER) {
+                index = j-1;
+                argument.add(relation);
+            } else
+                argument.add(argList.get(j));
+        }
+        return make(argument, (short) index, memory);
+    }
+
+    /**
+     * Try to make an Image from a Product and a relation. Called by the inference rules.
+     * @param product The product
+     * @param relation The relation
+     * @param index The index of the place-holder
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(Product product, Term relation, short index, Memory memory) {
+        if (relation instanceof Product) {
+            Product p2 = (Product) relation;
+            if ((product.size() == 2) && (p2.size() == 2)) {
+                if ((index == 0) && product.componentAt(1).equals(p2.componentAt(1))) // (/,_,(*,a,b),b) is reduced to a
+                    return p2.componentAt(0);  
+                if ((index == 1) && product.componentAt(0).equals(p2.componentAt(0))) // (/,(*,a,b),a,_) is reduced to b
+                    return p2.componentAt(1);  
+            }
+        }    
+        ArrayList<Term> argument = product.cloneComponents();
+        argument.set(index, relation);
+        return make(argument, index, memory);
+    }
+        
+    /**
+     * Try to make an Image from an existing Image and a component. Called by the inference rules.
+     * @param oldImage The existing Image
+     * @param component The component to be added into the component list
+     * @param index The index of the place-holder in the new Image
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(ImageExt oldImage, Term component, short index, Memory memory) {
+        ArrayList<Term> argList = oldImage.cloneComponents();
+        int oldIndex = oldImage.getRelationIndex();
+        Term relation = argList.get(oldIndex);
+        argList.set(oldIndex, component);
+        argList.set(index, relation);
+        return make(argList, index, memory);
+    }
+    
+    /**
+     * Try to make a new compound from a set of components. Called by the public make methods.
+     * @param argument The argument list
+     * @return the Term generated from the arguments
+     */
+    public static Term make(ArrayList<Term> argument, short index, Memory memory) {
+        String name = makeImageName(Symbols.IMAGE_EXT_OPERATOR, argument, index);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new ImageExt(name, argument, index);
+    }
+    
+    /**
+     * get the index of the relation in the component list
+     * @return the index of relation
+     */
+    public short getRelationIndex() {
+        return relationIndex;
+    }
+    
+    /**
+     * override the default in making the name of the current term from existing fields
+     * @return the name of the term
+     */
+    public String makeName() {
+        return makeImageName(Symbols.IMAGE_EXT_OPERATOR, components, relationIndex);
+    }
+
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.IMAGE_EXT_OPERATOR;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/ImageInt.java b/open-nars/com/googlecode/opennars/language/ImageInt.java
new file mode 100644
index 0000000000000000000000000000000000000000..3e40977b6f84d1bf5839b197ac8217e320492527
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/ImageInt.java
@@ -0,0 +1,172 @@
+/*
+ * ImageInt.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * An intension image.
+ * <p>
+ * (\,P,A,_)) --> B iff P --> (*,A,B)
+ * <p>
+ * Internally, it is actually (\,A,P)_1, with an index.
+ */
+public class ImageInt extends CompoundTerm {
+
+    /**
+     * The index of relation in the component list.
+     */
+    private short relationIndex;
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     * @param index The index of relation in the component list
+     */
+    private ImageInt(String n, ArrayList<Term> arg, short index) {
+        super(n, arg);
+        relationIndex = index;
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param complexity syntactic complexity of the compound
+     * @param n The name of the term
+     * @param index The index of relation in the component list
+     */
+    private ImageInt(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short complexity, short index) {
+        super(n, cs, open, closed, complexity);
+        relationIndex = index;
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into an ImageInt
+     */
+    public Object clone() {
+        return new ImageInt(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity, relationIndex);
+    }
+
+    /**
+     * Try to make a new ImageExt. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argList The list of components
+     */
+    public static Term make(ArrayList<Term> argList, Memory memory) {
+        if (argList.size() < 3)
+            return null;
+        Term t;
+        Term relation = argList.get(0);
+        ArrayList<Term> argument = new ArrayList<Term>();
+        int index = 0;
+        for (int j = 1; j < argList.size(); j++) {
+            if (argList.get(j).getName().charAt(0) == Symbols.IMAGE_PLACE_HOLDER) {
+                index = j-1;
+                argument.add(relation);
+            } else
+                argument.add(argList.get(j));
+        }
+        return make(argument, (short) index, memory);
+    }
+
+    /**
+     * Try to make an Image from a Product and a relation. Called by the inference rules.
+     * @param product The product
+     * @param relation The relation
+     * @param index The index of the place-holder
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(Product product, Term relation, short index, Memory memory) {
+        if (relation instanceof Product) {
+            Product p2 = (Product) relation;
+            if ((product.size() == 2) && (p2.size() == 2)) {
+                if ((index == 0) && product.componentAt(1).equals(p2.componentAt(1))) // (\,_,(*,a,b),b) is reduced to a
+                    return p2.componentAt(0);  
+                if ((index == 1) && product.componentAt(0).equals(p2.componentAt(0))) // (\,(*,a,b),a,_) is reduced to b
+                    return p2.componentAt(1);  
+            }
+        }    
+        ArrayList<Term> argument = product.cloneComponents();
+        argument.set(index, relation);
+        return make(argument, index, memory);
+    }
+        
+    /**
+     * Try to make an Image from an existing Image and a component. Called by the inference rules.
+     * @param oldImage The existing Image
+     * @param component The component to be added into the component list
+     * @param index The index of the place-holder in the new Image
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(ImageInt oldImage, Term component, short index, Memory memory) {
+        ArrayList<Term> argList = oldImage.cloneComponents();
+        int oldIndex = oldImage.getRelationIndex();
+        Term relation = argList.get(oldIndex);
+        argList.set(oldIndex, component);
+        argList.set(index, relation);
+        return make(argList, index, memory);
+    }
+    
+    /**
+     * Try to make a new compound from a set of components. Called by the public make methods.
+     * @param argument The argument list
+     * @return the Term generated from the arguments
+     */
+    public static Term make(ArrayList<Term> argument, short index, Memory memory) {
+        String name = makeImageName(Symbols.IMAGE_INT_OPERATOR, argument, index);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new ImageInt(name, argument, index);
+    }
+    
+    /**
+     * get the index of the relation in the component list
+     * @return the index of relation
+     */
+    public short getRelationIndex() {
+        return relationIndex;
+    }
+    
+    /**
+     * override the default in making the name of the current term from existing fields
+     * @return the name of the term
+     */
+    public String makeName() {
+        return makeImageName(Symbols.IMAGE_INT_OPERATOR, components, relationIndex);
+    }
+
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.IMAGE_INT_OPERATOR;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/Implication.java b/open-nars/com/googlecode/opennars/language/Implication.java
new file mode 100644
index 0000000000000000000000000000000000000000..0e69a326a1977fa781774c09ef62ce68e9d3e23c
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Implication.java
@@ -0,0 +1,93 @@
+/*
+ * Implication.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A Statement about an Inheritance relation.
+ */
+public class Implication extends Statement {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    protected Implication(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    protected Implication(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a SetExt
+     */
+    public Object clone() {
+        return new Implication(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+     
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param subject The first compoment
+     * @param predicate The second compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static Implication make(Term subject, Term predicate, Memory memory) {  // to be extended to check if subject is Conjunction
+        if (invalidStatement(subject, predicate))
+            return null;
+        String name = makeStatementName(subject, Symbols.IMPLICATION_RELATION, predicate);
+        Term t = memory.nameToListedTerm(name);
+        if (t != null)
+            return (Implication) t;
+        if (predicate instanceof Implication) {
+            Term oldCondition = ((Implication) predicate).getSubject();
+            Term newCondition = Conjunction.make(subject, oldCondition, memory);
+            return make(newCondition, ((Implication) predicate).getPredicate(), memory);
+        } else {
+            ArrayList<Term> argument = argumentsToList(subject, predicate);
+            return new Implication(name, argument);
+        }
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.IMPLICATION_RELATION;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/ImplicationAfter.java b/open-nars/com/googlecode/opennars/language/ImplicationAfter.java
new file mode 100644
index 0000000000000000000000000000000000000000..d3cde1818ee016fd553bdb1baf8511e243970ae0
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/ImplicationAfter.java
@@ -0,0 +1,99 @@
+/*
+ * ImplicationAfter.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * Temporal Implication relation, predicate after subject.
+ */
+public class ImplicationAfter extends Implication {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private ImplicationAfter(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private ImplicationAfter(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a SetExt
+     */
+    public Object clone() {
+        return new ImplicationAfter(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+     
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param subject The first compoment
+     * @param predicate The second compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static ImplicationAfter make(Term subject, Term predicate, Memory memory) {  // to be extended to check if subject is Conjunction
+        if (invalidStatement(subject, predicate))
+            return null;
+        String name = makeStatementName(subject, Symbols.IMPLICATION_AFTER_RELATION, predicate);
+        Term t = memory.nameToListedTerm(name);
+        if (t != null)
+            return (ImplicationAfter) t;
+        if (predicate instanceof ImplicationAfter) {
+            Term oldCondition = ((ImplicationAfter) predicate).getSubject();
+            Term newCondition = ConjunctionSequence.make(subject, oldCondition, memory);
+            return make(newCondition, ((ImplicationAfter) predicate).getPredicate(), memory);
+        } else {
+            ArrayList<Term> argument = argumentsToList(subject, predicate);
+            return new ImplicationAfter(name, argument);
+        }
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.IMPLICATION_AFTER_RELATION;
+    }
+
+    // overwrite default
+    public CompoundTerm.TemporalOrder getTemporalOrder() {
+        return CompoundTerm.TemporalOrder.AFTER;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/ImplicationBefore.java b/open-nars/com/googlecode/opennars/language/ImplicationBefore.java
new file mode 100644
index 0000000000000000000000000000000000000000..d93d182943892df3511bf99a25be525075693eba
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/ImplicationBefore.java
@@ -0,0 +1,99 @@
+/*
+ * ImplicationBefore.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * Temporal Implication relation, predicate before subject.
+ */
+public class ImplicationBefore extends Implication {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private ImplicationBefore(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private ImplicationBefore(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a SetExt
+     */
+    public Object clone() {
+        return new ImplicationBefore(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+     
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param subject The first compoment
+     * @param predicate The second compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static ImplicationBefore make(Term subject, Term predicate, Memory memory) {  // to be extended to check if subject is Conjunction
+        if (invalidStatement(subject, predicate))
+            return null;
+        String name = makeStatementName(subject, Symbols.IMPLICATION_BEFORE_RELATION, predicate);
+        Term t = memory.nameToListedTerm(name);
+        if (t != null)
+            return (ImplicationBefore) t;
+        if (predicate instanceof ImplicationBefore) {
+            Term oldCondition = ((ImplicationBefore) predicate).getSubject();
+            Term newCondition = ConjunctionSequence.make(oldCondition, subject, memory);
+            return make(newCondition, ((ImplicationBefore) predicate).getPredicate(), memory);
+        } else {
+            ArrayList<Term> argument = argumentsToList(subject, predicate);
+            return new ImplicationBefore(name, argument);
+        }
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.IMPLICATION_BEFORE_RELATION;
+    }
+
+    // overwrite default
+    public CompoundTerm.TemporalOrder getTemporalOrder() {
+        return CompoundTerm.TemporalOrder.BEFORE;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/ImplicationWhen.java b/open-nars/com/googlecode/opennars/language/ImplicationWhen.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ebffa4a12a9563369f9cd1117dc305e93ea23a3
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/ImplicationWhen.java
@@ -0,0 +1,99 @@
+/*
+ * ImplicationWhen.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * Temporal Implication relation, concurrent.
+ */
+
+public class ImplicationWhen extends Implication {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    protected ImplicationWhen(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    protected ImplicationWhen(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a SetExt
+     */
+    public Object clone() {
+        return new ImplicationWhen(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+     
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param subject The first compoment
+     * @param predicate The second compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static ImplicationWhen make(Term subject, Term predicate, Memory memory) {  // to be extended to check if subject is Conjunction
+        if (invalidStatement(subject, predicate))
+            return null;
+        String name = makeStatementName(subject, Symbols.IMPLICATION_RELATION, predicate);
+        Term t = memory.nameToListedTerm(name);
+        if (t != null)
+            return (ImplicationWhen) t;
+        if (predicate instanceof ImplicationWhen) {
+            Term oldCondition = ((ImplicationWhen) predicate).getSubject();
+            Term newCondition = ConjunctionParallel.make(subject, oldCondition, memory);
+            return make(newCondition, ((ImplicationWhen) predicate).getPredicate(), memory);
+        } else {
+            ArrayList<Term> argument = argumentsToList(subject, predicate);
+            return new ImplicationWhen(name, argument);
+        }
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.IMPLICATION_WHEN_RELATION;
+    }
+
+    public CompoundTerm.TemporalOrder getTemporalOrder() {
+        return CompoundTerm.TemporalOrder.WHEN;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/Inheritance.java b/open-nars/com/googlecode/opennars/language/Inheritance.java
new file mode 100644
index 0000000000000000000000000000000000000000..93a1d2e86f39161daa6da810851469cc3bd1a980
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Inheritance.java
@@ -0,0 +1,90 @@
+/*
+ * Inheritance.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A Statement about an Inheritance relation.
+ */
+public class Inheritance extends Statement {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private Inheritance(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private Inheritance(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a SetExt
+     */
+    public Object clone() {
+        return new Inheritance(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+     
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param subject The first compoment
+     * @param predicate The second compoment
+     * @return A compound generated or null
+     */
+    public static Inheritance make(Term subject, Term predicate, Memory memory) {
+        if (invalidStatement(subject, predicate))
+            return null;
+        String name = makeStatementName(subject, Symbols.INHERITANCE_RELATION, predicate);
+        Term t = memory.nameToListedTerm(name);
+        if (t != null)
+            return (Inheritance) t;
+        ArrayList<Term> argument = argumentsToList(subject, predicate);
+        return new Inheritance(name, argument);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.INHERITANCE_RELATION;
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/language/Instance.java b/open-nars/com/googlecode/opennars/language/Instance.java
new file mode 100644
index 0000000000000000000000000000000000000000..99b718322e310ed904c7611b7af355c7cdb4804b
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Instance.java
@@ -0,0 +1,43 @@
+/*
+ * Instance.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import com.googlecode.opennars.main.Memory;
+
+/**
+ * A Statement about an Instance relation, which is used only in Narsese for I/O, 
+ * and translated into Inheritance for internal use.
+ */
+public abstract class Instance extends Statement {
+    
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * <p>
+     *  A {-- B becomes {A} --> B
+     * @param subject The first compoment
+     * @param predicate The second compoment
+     * @return A compound generated or null
+     */
+    public static Statement make(Term subject, Term predicate, Memory memory) {
+        return Inheritance.make(SetExt.make(subject, memory), predicate, memory);
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/InstanceProperty.java b/open-nars/com/googlecode/opennars/language/InstanceProperty.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc871b588c79f96c032dad6d2333ae1d140b6d89
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/InstanceProperty.java
@@ -0,0 +1,43 @@
+/*
+ * InstanceProperty.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import com.googlecode.opennars.main.Memory;
+
+/**
+ * A Statement about an InstanceProperty relation, which is used only in Narsese for I/O, 
+ * and translated into Inheritance for internal use.
+ */
+public abstract class InstanceProperty extends Statement {
+    
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * <p>
+     *  A {-] B becomes {A} --> [B]
+     * @param subject The first compoment
+     * @param predicate The second compoment
+     * @return A compound generated or null
+     */
+    public static Statement make(Term subject, Term predicate, Memory memory) {
+        return Inheritance.make(SetExt.make(subject, memory), SetInt.make(predicate, memory), memory);
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/IntersectionExt.java b/open-nars/com/googlecode/opennars/language/IntersectionExt.java
new file mode 100644
index 0000000000000000000000000000000000000000..30c3d8b694feb8cfb77c074e669e18e312585c33
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/IntersectionExt.java
@@ -0,0 +1,139 @@
+/*
+ * IntersectionExt.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A compound term whose extension is the intersection of the extensions of its components
+ */
+public class IntersectionExt extends CompoundTerm {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private IntersectionExt(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private IntersectionExt(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a IntersectionExt
+     */
+    public Object clone() {
+        return new IntersectionExt(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+    
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param term1 The first compoment
+     * @param term2 The first compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(Term term1, Term term2, Memory memory) {
+        TreeSet set;
+        if ((term1 instanceof SetInt) && (term2 instanceof SetInt)) {
+            set = new TreeSet(((CompoundTerm) term1).cloneComponents());
+            set.addAll(((CompoundTerm) term2).cloneComponents());           // set union
+            return SetInt.make(set, memory);
+        }
+        if ((term1 instanceof SetExt) && (term2 instanceof SetExt)) {
+            set = new TreeSet(((CompoundTerm) term1).cloneComponents());
+            set.retainAll(((CompoundTerm) term2).cloneComponents());        // set intersection
+            return SetExt.make(set, memory);
+        }
+        if (term1 instanceof IntersectionExt) {
+            set = new TreeSet(((CompoundTerm) term1).cloneComponents());
+            if (term2 instanceof IntersectionExt)
+                set.addAll(((CompoundTerm) term2).cloneComponents());   // (&,(&,P,Q),(&,R,S)) = (&,P,Q,R,S)
+            else
+                set.add((Term) term2.clone());                          // (&,(&,P,Q),R) = (&,P,Q,R)
+        } else if (term2 instanceof IntersectionExt) {
+            set = new TreeSet(((CompoundTerm) term2).cloneComponents());
+            set.add((Term) term1.clone());                              // (&,R,(&,P,Q)) = (&,P,Q,R)
+        } else {
+            set = new TreeSet();
+            set.add((Term) term1.clone());
+            set.add((Term) term2.clone());
+        }
+        return make(set, memory);
+    }
+    
+    /**
+     * Try to make a new IntersectionExt. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argList The list of components
+     */
+    public static Term make(ArrayList<Term> argList, Memory memory) {
+        TreeSet<Term> set = new TreeSet<Term>(argList); // sort/merge arguments
+        return make(set, memory);
+    }
+    
+    /**
+     * Try to make a new compound from a set of components. Called by the public make methods.
+     * @param set a set of Term as compoments
+     * @return the Term generated from the arguments
+     */
+    public static Term make(TreeSet<Term> set, Memory memory) {
+        if (set.size() == 1)
+            return set.first();                         // special case: single component
+        ArrayList<Term> argument = new ArrayList<Term>(set);
+        String name = makeCompoundName(Symbols.INTERSECTION_EXT_OPERATOR, argument);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new IntersectionExt(name, argument);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.INTERSECTION_EXT_OPERATOR;
+    }
+    
+    /**
+     * Check if the compound is communitative.
+     * @return true for communitative
+     */
+    public boolean isCommutative() {
+        return true;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/IntersectionInt.java b/open-nars/com/googlecode/opennars/language/IntersectionInt.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc13e5d7d20a6bd47d962f882b167f3ce79f2d54
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/IntersectionInt.java
@@ -0,0 +1,139 @@
+/*
+ * IntersectionInt.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A compound term whose intension is the intersection of the extensions of its components
+ */
+public class IntersectionInt extends CompoundTerm {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private IntersectionInt(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private IntersectionInt(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a Conjunction
+     */
+    public Object clone() {
+        return new IntersectionInt(name, (ArrayList<Term>) cloneList(components), 
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+    
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param term1 The first compoment
+     * @param term2 The first compoment
+     * @return A compound generated or a term it reduced to
+     */    
+    public static Term make(Term term1, Term term2, Memory memory) {
+        TreeSet set;
+        if ((term1 instanceof SetExt) && (term2 instanceof SetExt)) {
+            set = new TreeSet(((CompoundTerm) term1).cloneComponents());
+            set.addAll(((CompoundTerm) term2).cloneComponents());           // set union
+            return SetExt.make(set, memory);
+        }
+        if ((term1 instanceof SetInt) && (term2 instanceof SetInt)) {
+            set = new TreeSet(((CompoundTerm) term1).cloneComponents());
+            set.retainAll(((CompoundTerm) term2).cloneComponents());        // set intersection
+            return SetInt.make(set, memory);
+        }
+        if (term1 instanceof IntersectionInt) {
+            set = new TreeSet(((CompoundTerm) term1).cloneComponents());
+            if (term2 instanceof IntersectionInt)
+                set.addAll(((CompoundTerm) term2).cloneComponents());   // (|,(|,P,Q),(|,R,S)) = (|,P,Q,R,S)
+            else
+                set.add((Term) term2.clone());                          // (|,(|,P,Q),R) = (|,P,Q,R)
+        } else if (term2 instanceof IntersectionInt) {
+            set = new TreeSet(((CompoundTerm) term2).cloneComponents());
+            set.add((Term) term1.clone());                              // (|,R,(|,P,Q)) = (|,P,Q,R)
+        } else {
+            set = new TreeSet();
+            set.add((Term) term1.clone());
+            set.add((Term) term2.clone());
+        }
+        return make(set, memory);
+    }
+    
+    /**
+     * Try to make a new IntersectionExt. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argList The list of components
+     */
+    public static Term make(ArrayList<Term> argList, Memory memory) {
+        TreeSet<Term> set = new TreeSet<Term>(argList); // sort/merge arguments
+        return make(set, memory);
+    }
+    
+    /**
+     * Try to make a new compound from a set of components. Called by the public make methods.
+     * @param set a set of Term as compoments
+     * @return the Term generated from the arguments
+     */
+    public static Term make(TreeSet<Term> set, Memory memory) {
+        if (set.size() == 1)
+            return set.first();                         // special case: single component
+        ArrayList<Term> argument = new ArrayList<Term>(set);
+        String name = makeCompoundName(Symbols.INTERSECTION_INT_OPERATOR, argument);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new IntersectionInt(name, argument);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.INTERSECTION_INT_OPERATOR;
+    }
+
+    /**
+     * Check if the compound is communitative.
+     * @return true for communitative
+     */
+    public boolean isCommutative() {
+        return true;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/Negation.java b/open-nars/com/googlecode/opennars/language/Negation.java
new file mode 100644
index 0000000000000000000000000000000000000000..81e9ffbdd13531f75f9f1c562109dd8246bec44b
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Negation.java
@@ -0,0 +1,97 @@
+/*
+ * Negation.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A negation of a Statement.
+ */
+public class Negation extends CompoundTerm {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private Negation(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private Negation(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a SetExt
+     */
+    public Object clone() {
+        return new Negation(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+    
+    /**
+     * Try to make a Negation of one component. Called by the inference rules.
+     * @param t The compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(Term t, Memory memory) {
+        if (t instanceof Negation)
+            return (Term) ((CompoundTerm) t).cloneComponents().get(0);         // (--,(--,P)) = P
+        ArrayList<Term> argument = new ArrayList<Term>();
+        argument.add(t);
+        return make(argument, memory);
+    }
+    
+    /**
+     * Try to make a new SetExt. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argument The list of components
+     */
+    public static Term make(ArrayList<Term> argument, Memory memory) {
+        if (argument.size() != 1)
+            return null;
+        String name = makeCompoundName(Symbols.NEGATION_OPERATOR, argument);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new Negation(name, argument);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.NEGATION_OPERATOR;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/Product.java b/open-nars/com/googlecode/opennars/language/Product.java
new file mode 100644
index 0000000000000000000000000000000000000000..dcd51a5d7b203968cb3c5fc109ebd86f32c90b38
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Product.java
@@ -0,0 +1,99 @@
+/*
+ * Product.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A Product is a sequence of terms.
+ */
+public class Product extends CompoundTerm {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private Product(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param complexity syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private Product(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short complexity) {
+        super(n, cs, open, closed, complexity);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into an ImageExt
+     */
+    public Object clone() {
+        return new Product(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+
+     /**
+     * Try to make a new compound. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argument The list of components
+     */
+    public static Term make(ArrayList<Term> argument, Memory memory) {
+        if (argument.size() < 2)
+            return null;
+        String name = makeCompoundName(Symbols.PRODUCT_OPERATOR, argument);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new Product(name, argument);
+    }
+        
+    /**
+     * Try to make a Product from an ImageExt/ImageInt and a component. Called by the inference rules.
+     * @param image The existing Image
+     * @param component The component to be added into the component list
+     * @param index The index of the place-holder in the new Image -- optional parameter
+     * @return A compound generated or a term it reduced to
+     */
+    // for both 
+    public static Term make(CompoundTerm image, Term component, int index, Memory memory) {
+        ArrayList<Term> argument = image.cloneComponents();
+        argument.set(index, component);
+        return make(argument, memory);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.PRODUCT_OPERATOR;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/Property.java b/open-nars/com/googlecode/opennars/language/Property.java
new file mode 100644
index 0000000000000000000000000000000000000000..d5997c8d5da2b777a95d2674bb047a5b22d8e427
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Property.java
@@ -0,0 +1,43 @@
+/*
+ * Property.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import com.googlecode.opennars.main.Memory;
+
+/**
+ * A Statement about a Property relation, which is used only in Narsese for I/O, 
+ * and translated into Inheritance for internal use.
+ */
+public abstract class Property extends Statement {
+    
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * <p>
+     *  A --] B becomes A --> [B]
+     * @param subject The first compoment
+     * @param predicate The second compoment
+     * @return A compound generated or null
+     */
+    public static Statement make(Term subject, Term predicate, Memory memory) {
+        return Inheritance.make(subject, SetInt.make(predicate, memory), memory);
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/SetExt.java b/open-nars/com/googlecode/opennars/language/SetExt.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c42c6843a5eed2902f12ee444652aeeca713202
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/SetExt.java
@@ -0,0 +1,124 @@
+/*
+ * SetExt.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * An extensionally defined set, which contains one or more instances defining the Term.
+ */
+public class SetExt extends CompoundTerm {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private SetExt(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private SetExt(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a SetExt
+     */
+    public Object clone() {
+        return new SetExt(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+    
+    /**
+     * Try to make a new set from one component. Called by the inference rules.
+     * @param t The compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(Term t, Memory memory) {
+        TreeSet<Term> set = new TreeSet<Term>();
+        set.add(t);
+        return make(set, memory);
+    }
+    
+    /**
+     * Try to make a new SetExt. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argList The list of components
+     */
+    public static Term make(ArrayList<Term> argList, Memory memory) {
+        TreeSet<Term> set = new TreeSet<Term>(argList); // sort/merge arguments
+        return make(set, memory);
+    }
+    
+    /**
+     * Try to make a new compound from a set of components. Called by the public make methods.
+     * @param set a set of Term as compoments
+     * @return the Term generated from the arguments
+     */
+    public static Term make(TreeSet<Term> set, Memory memory) {
+        if (set.isEmpty())
+            return null;
+        ArrayList<Term> argument = new ArrayList<Term>(set);
+        String name = makeSetName(Symbols.SET_EXT_OPENER, argument, Symbols.SET_EXT_CLOSER);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new SetExt(name, argument);
+    }
+
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return "" + Symbols.SET_EXT_OPENER;
+    }
+    
+    /**
+     * Check if the compound is communitative.
+     * @return true for communitative
+     */
+    public boolean isCommutative() {
+        return true;
+    }
+
+    /**
+     * Make a String representation of the set, override the default.
+     * @return true for communitative
+     */
+    public String makeName() {
+        return makeSetName(Symbols.SET_EXT_OPENER, components, Symbols.SET_EXT_CLOSER);
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/language/SetInt.java b/open-nars/com/googlecode/opennars/language/SetInt.java
new file mode 100644
index 0000000000000000000000000000000000000000..c7d3554d55e0dd68e0abcbb3c9dbf4c94530c317
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/SetInt.java
@@ -0,0 +1,124 @@
+/*
+ * SetInt.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * An intensionally defined set, which contains one or more instances defining the Term.
+ */
+public class SetInt extends CompoundTerm {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private SetInt(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private SetInt(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a SetInt
+     */
+    public Object clone() {
+        return new SetInt(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+    
+    /**
+     * Try to make a new set from one component. Called by the inference rules.
+     * @param t The compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(Term t, Memory memory) {
+        TreeSet<Term> set = new TreeSet<Term>();
+        set.add(t);
+        return make(set, memory);
+    }
+    
+    /**
+     * Try to make a new SetExt. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argList The list of components
+     */
+    public static Term make(ArrayList<Term> argList, Memory memory) {
+        TreeSet<Term> set = new TreeSet<Term>(argList); // sort/merge arguments
+        return make(set, memory);
+    }
+    
+    /**
+     * Try to make a new compound from a set of components. Called by the public make methods.
+     * @param set a set of Term as compoments
+     * @return the Term generated from the arguments
+     */
+    public static Term make(TreeSet<Term> set, Memory memory) {
+        if (set.isEmpty())
+            return null;
+        ArrayList<Term> argument = new ArrayList<Term>(set);
+        String name = makeSetName(Symbols.SET_INT_OPENER, argument, Symbols.SET_INT_CLOSER);
+        Term t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new SetInt(name, argument);
+    }
+
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return "" + Symbols.SET_INT_OPENER;
+    }
+    
+    /**
+     * Check if the compound is communitative.
+     * @return true for communitative
+     */
+    public boolean isCommutative() {
+        return true;
+    }
+
+    /**
+     * Make a String representation of the set, override the default.
+     * @return true for communitative
+     */
+    public String makeName() {
+        return makeSetName(Symbols.SET_INT_OPENER, components, Symbols.SET_INT_CLOSER);
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/language/Similarity.java b/open-nars/com/googlecode/opennars/language/Similarity.java
new file mode 100644
index 0000000000000000000000000000000000000000..8c0f9a98cc0092b4ff8d345931ba280d60e4c537
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Similarity.java
@@ -0,0 +1,99 @@
+/*
+ * Similarity.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.TermLink;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A Statement about a Similarity relation.
+ */
+public class Similarity extends Statement {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private Similarity(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private Similarity(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a Similarity
+     */
+    public Object clone() {
+        return new Similarity(name, (ArrayList<Term>) cloneList(components), 
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+     
+    /**
+     * Try to make a new compound from two components. Called by the inference rules.
+     * @param subject The first compoment
+     * @param predicate The second compoment
+     * @return A compound generated or null
+     */
+    public static Similarity make(Term subject, Term predicate, Memory memory) {
+        if (invalidStatement(subject, predicate))
+            return null;
+        if (subject.compareTo(predicate) > 0)
+            return make(predicate, subject, memory);
+        String name = makeStatementName(subject, Symbols.SIMILARITY_RELATION, predicate);
+        Term t = memory.nameToListedTerm(name);
+        if (t != null)
+            return (Similarity) t;
+        ArrayList<Term> argument = argumentsToList(subject, predicate);
+        return new Similarity(name, argument);
+    }
+    
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.SIMILARITY_RELATION;
+    }
+    
+    /**
+     * Check if the compound is communitative.
+     * @return true for communitative
+     */
+    public boolean isCommutative() {
+        return true;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/Statement.java b/open-nars/com/googlecode/opennars/language/Statement.java
new file mode 100644
index 0000000000000000000000000000000000000000..9709b6f268bac8da4eb8fedda9546c99bb4b6206
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Statement.java
@@ -0,0 +1,281 @@
+/*
+ * Statement.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.*;
+
+/**
+ * A statement is a compound term, consisting of a subject, a predicate,
+ * and a relation symbol in between. It can be of either first-order or higher-order.
+ */
+public abstract class Statement extends CompoundTerm {
+    
+    /**
+     * default constructor
+     */
+    protected Statement() {}
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    protected Statement(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    protected Statement(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * Make a Statement from String, called by StringParser
+     * @param relation The relation String
+     * @param subject The first component
+     * @param predicate The second component
+     * @return The Statement built
+     */
+    public static Statement make(String relation, Term subject, Term predicate, Memory memory) {
+        if (invalidStatement(subject, predicate))
+            return null;
+        if (relation.equals(Symbols.INHERITANCE_RELATION))
+            return Inheritance.make(subject, predicate, memory);
+        if (relation.equals(Symbols.SIMILARITY_RELATION))
+            return Similarity.make(subject, predicate, memory);
+        if (relation.equals(Symbols.INSTANCE_RELATION))
+            return Instance.make(subject, predicate, memory);
+        if (relation.equals(Symbols.PROPERTY_RELATION))
+            return Property.make(subject, predicate, memory);
+        if (relation.equals(Symbols.INSTANCE_PROPERTY_RELATION))
+            return InstanceProperty.make(subject, predicate, memory);
+        if (relation.equals(Symbols.IMPLICATION_RELATION))
+            return Implication.make(subject, predicate, memory);
+        if (relation.equals(Symbols.EQUIVALENCE_RELATION))
+            return Equivalence.make(subject, predicate, memory);
+        if (relation.equals(Symbols.IMPLICATION_AFTER_RELATION))
+            return ImplicationAfter.make(subject, predicate, memory);
+        if (relation.equals(Symbols.IMPLICATION_WHEN_RELATION))
+            return ImplicationWhen.make(subject, predicate, memory);
+        if (relation.equals(Symbols.IMPLICATION_BEFORE_RELATION))
+            return ImplicationBefore.make(subject, predicate, memory);
+        if (relation.equals(Symbols.EQUIVALENCE_AFTER_RELATION))
+            return EquivalenceAfter.make(subject, predicate, memory);
+        if (relation.equals(Symbols.EQUIVALENCE_WHEN_RELATION))
+            return EquivalenceWhen.make(subject, predicate, memory);
+        return null;
+    }
+    
+    /**
+     * Make a Statement from given components, called by the rules
+     * @return The Statement built
+     * @param sub The first component
+     * @param pred The second component
+     * @param statement A sample statement providing the class type
+     */
+    public static Statement make(Statement statement, Term sub, Term pred, Memory memory) {
+        if (statement instanceof Inheritance)
+            return Inheritance.make(sub, pred, memory);
+        if (statement instanceof Similarity)
+            return Similarity.make(sub, pred, memory);
+        if (statement instanceof ImplicationBefore)
+            return ImplicationBefore.make(sub, pred, memory);
+        if (statement instanceof ImplicationWhen)
+            return ImplicationWhen.make(sub, pred, memory);
+        if (statement instanceof ImplicationAfter)
+            return ImplicationAfter.make(sub, pred, memory);
+        if (statement instanceof Implication)
+            return Implication.make(sub, pred, memory);
+        if (statement instanceof EquivalenceWhen)
+            return EquivalenceWhen.make(sub, pred, memory);
+        if (statement instanceof EquivalenceAfter)
+            return EquivalenceAfter.make(sub, pred, memory);
+        if (statement instanceof Equivalence)
+            return Equivalence.make(sub, pred, memory);
+        return null;
+    }
+    
+    /**
+     * Make a Statement from given components and temporal information, called by the rules
+     * @param statement A sample statement providing the class type
+     * @param sub The first component
+     * @param pred The second component
+     * @param order The temporal order of the statement
+     * @return The Statement built
+     */
+    public static Statement make(Statement statement, Term sub, Term pred, CompoundTerm.TemporalOrder order, Memory memory) {
+        if (order == CompoundTerm.TemporalOrder.UNSURE)
+            return null;
+        if (order == CompoundTerm.TemporalOrder.NONE)
+            return make(statement, sub, pred, memory);
+        if (order == CompoundTerm.TemporalOrder.AFTER) {
+            if (statement instanceof Implication)
+                return ImplicationAfter.make(sub, pred, memory);
+            if (statement instanceof Equivalence)
+                return EquivalenceAfter.make(sub, pred, memory);
+            return null;
+        }
+        if (order == CompoundTerm.TemporalOrder.WHEN) {
+            if (statement instanceof Implication)
+                return ImplicationWhen.make(sub, pred, memory);
+            if (statement instanceof Equivalence)
+                return EquivalenceWhen.make(sub, pred, memory);
+            return null;
+        }
+        if (order == CompoundTerm.TemporalOrder.BEFORE) {
+            if (statement instanceof Implication)
+                return ImplicationBefore.make(sub, pred, memory);
+            if (statement instanceof Equivalence)
+                return EquivalenceAfter.make(pred, sub, memory);
+            return null;
+        }
+        return null;
+    }
+    
+    /**
+     * Make a symmetric Statement from given components and temporal information, called by the rules
+     * @param statement A sample asymmetric statement providing the class type
+     * @param sub The first component
+     * @param pred The second component
+     * @param order The temporal order of the statement
+     * @return The Statement built
+     */
+    public static Statement makeSym(Statement statement, Term sub, Term pred, CompoundTerm.TemporalOrder order, Memory memory) {
+        if (order == CompoundTerm.TemporalOrder.UNSURE)
+            return null;
+        if (order == CompoundTerm.TemporalOrder.NONE) {
+            if (statement instanceof Inheritance)
+                return Similarity.make(sub, pred, memory);
+            if (statement instanceof Implication)
+                return Equivalence.make(sub, pred, memory);
+            return null;
+        }
+        if (order == CompoundTerm.TemporalOrder.AFTER) {
+            if (statement instanceof Implication)
+                return EquivalenceAfter.make(sub, pred, memory);
+            return null;
+        }
+        if (order == CompoundTerm.TemporalOrder.WHEN) {
+            if (statement instanceof Implication)
+                return EquivalenceWhen.make(sub, pred, memory);
+            return null;
+        }
+        if (order == CompoundTerm.TemporalOrder.BEFORE) {
+            if (statement instanceof Implication)
+                return EquivalenceAfter.make(pred, sub, memory);
+            return null;
+        }
+        return null;
+    }
+    
+    /**
+     * check Statement relation symbol
+     * @return if the given String is a relation symbol
+     * @param s0 The String to be checked
+     */
+    public static boolean isRelation(String s0) {
+        String s = s0.trim();
+        if (s.length() != 3)
+            return false;
+        return (s.equals(Symbols.INHERITANCE_RELATION) ||
+                s.equals(Symbols.SIMILARITY_RELATION) ||
+                s.equals(Symbols.INSTANCE_RELATION) ||
+                s.equals(Symbols.PROPERTY_RELATION) ||
+                s.equals(Symbols.INSTANCE_PROPERTY_RELATION) ||
+                s.equals(Symbols.IMPLICATION_RELATION) ||
+                s.equals(Symbols.EQUIVALENCE_RELATION) ||
+                s.equals(Symbols.IMPLICATION_AFTER_RELATION) ||
+                s.equals(Symbols.IMPLICATION_WHEN_RELATION) ||
+                s.equals(Symbols.IMPLICATION_BEFORE_RELATION) ||
+                s.equals(Symbols.EQUIVALENCE_WHEN_RELATION) ||
+                s.equals(Symbols.EQUIVALENCE_AFTER_RELATION) );
+    }
+    
+    /**
+     * override the default in making the name of the current term from existing fields
+     * @return the name of the term
+     */
+    protected String makeName() {
+        return makeStatementName(getSubject(), operator(), getPredicate());
+    }
+    
+    /**
+     * default method to make the name of an image term from given fields
+     * @param subject the first component
+     * @param predicate the second component
+     * @param relation the relation operator
+     * @return the name of the term
+     */
+    protected static String makeStatementName(Term subject, String relation, Term predicate) {
+        StringBuffer name = new StringBuffer();
+        name.append(Symbols.STATEMENT_OPENER);
+        name.append(subject.getName());
+        name.append(' ' + relation + ' ');
+        name.append(predicate.getName());
+        name.append(Symbols.STATEMENT_CLOSER);
+        return name.toString();
+    }
+    
+    /**
+     * check the validity of a potential Statement.
+     * <p>
+     * Minimum requirement: the two terms cannot be the same. To be strengthened.
+     * @param subject the first component
+     * @param predicate the second component
+     * @return Whether the Statement is invalid
+     */
+    public static boolean invalidStatement(Term subject, Term predicate) {
+        if (subject.equals(predicate))
+            return true;
+        if ((subject instanceof CompoundTerm) && ((CompoundTerm) subject).containComponent(predicate))
+            return true;
+        if ((predicate instanceof CompoundTerm) && ((CompoundTerm) predicate).containComponent(subject))
+            return true;
+        return false;
+    }
+    
+    /**
+     * Return the first component of the statement
+     * @return The first component
+     */
+    public Term getSubject() {
+        return components.get(0);
+    }
+        
+    /**
+     * Return the second component of the statement
+     * @return The second component
+     */
+    public Term getPredicate() {
+        return components.get(1);
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/Tense.java b/open-nars/com/googlecode/opennars/language/Tense.java
new file mode 100644
index 0000000000000000000000000000000000000000..63da1898e608bb3deff5be9d4dcfe6951b119544
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Tense.java
@@ -0,0 +1,53 @@
+/*
+ * Tense.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.main.Memory;
+
+/**
+ * Term with temporal relation with "now"
+ */
+public abstract class Tense extends CompoundTerm {
+    
+    protected Tense(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+
+    protected Tense(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+
+    public static Term make(Term content, CompoundTerm.TemporalOrder order, Memory memory) {
+        switch (order) {
+            case AFTER:
+                return TenseFuture.make(content, memory);
+            case WHEN:
+                return TensePresent.make(content, memory);
+            case BEFORE:
+                return TensePast.make(content, memory);
+            default:
+                return content;
+        }
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/TenseFuture.java b/open-nars/com/googlecode/opennars/language/TenseFuture.java
new file mode 100644
index 0000000000000000000000000000000000000000..f8ac936daadec759c4aeeabc08b373d11ef615bd
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/TenseFuture.java
@@ -0,0 +1,106 @@
+/*
+ * TenseFuture.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.*;
+
+/**
+ * Future tense of a Statement.
+ */
+public class TenseFuture extends Tense {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private TenseFuture(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private TenseFuture(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a SetExt
+     */
+    public Object clone() {
+        return new TenseFuture(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+    
+    /**
+     * Try to make a new compound. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argument The list of components
+     */
+    public static Term make(ArrayList<Term> argument, Memory memory) {
+        if (argument.size() != 1) 
+            return null;
+        Term t = argument.get(0);
+        if (t instanceof TenseFuture)
+            return t;         
+        if (t instanceof TensePast)
+            return null;         
+        if (t instanceof TensePresent)
+            t = ((CompoundTerm) t).componentAt(0);         
+        String name = makeCompoundName(Symbols.FUTURE_OPERATOR, argument);
+        t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new TenseFuture(name, argument);
+    }
+    
+    /**
+     * Try to make a compound of one component. Called by the inference rules.
+     * @param t The compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(Term t, Memory memory) {
+        ArrayList<Term> argument = new ArrayList<Term>();
+        argument.add(t);
+        return make(argument, memory);
+    }
+
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.FUTURE_OPERATOR;
+    }
+
+    public CompoundTerm.TemporalOrder getTemporalOrder() {
+        return CompoundTerm.TemporalOrder.AFTER;
+    }
+}
\ No newline at end of file
diff --git a/open-nars/com/googlecode/opennars/language/TensePast.java b/open-nars/com/googlecode/opennars/language/TensePast.java
new file mode 100644
index 0000000000000000000000000000000000000000..48c6cd1e41f04d139f5c086552b8871bb3d9cd45
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/TensePast.java
@@ -0,0 +1,106 @@
+/*
+ * TensePast.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.*;
+
+/**
+ * Past tense of a Statement.
+ */
+public class TensePast extends Tense {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private TensePast(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private TensePast(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a SetExt
+     */
+    public Object clone() {
+        return new TensePast(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+    
+    /**
+     * Try to make a new compound. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argument The list of components
+     */
+    public static Term make(ArrayList<Term> argument, Memory memory) {
+        if (argument.size() != 1) 
+            return null;
+        Term t = argument.get(0);
+        if (t instanceof TensePast)
+            return t;         
+        if (t instanceof TenseFuture)
+            return null;         
+        if (t instanceof TensePresent)
+            t = ((CompoundTerm) t).componentAt(0);         
+        String name = makeCompoundName(Symbols.PAST_OPERATOR, argument);
+        t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new TensePast(name, argument);
+    }
+    
+    /**
+     * Try to make a compound of one component. Called by the inference rules.
+     * @param t The compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(Term t, Memory memory) {
+        ArrayList<Term> argument = new ArrayList<Term>();
+        argument.add(t);
+        return make(argument, memory);
+    }
+
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.PAST_OPERATOR;
+    }
+
+    public CompoundTerm.TemporalOrder getTemporalOrder() {
+        return CompoundTerm.TemporalOrder.BEFORE;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/TensePresent.java b/open-nars/com/googlecode/opennars/language/TensePresent.java
new file mode 100644
index 0000000000000000000000000000000000000000..038f926399b4693999966fc665d40982fb707605
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/TensePresent.java
@@ -0,0 +1,102 @@
+/*
+ * TensePresent.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.*;
+
+/**
+ * Present tense of a Statement.
+ */
+public class TensePresent extends Tense {
+    
+    /**
+     * constructor with partial values, called by make
+     * @param n The name of the term
+     * @param arg The component list of the term
+     */
+    private TensePresent(String n, ArrayList<Term> arg) {
+        super(n, arg);
+    }
+    
+    /**
+     * constructor with full values, called by clone
+     * @param cs component list
+     * @param open open variable list
+     * @param closed closed variable list
+     * @param i syntactic complexity of the compound
+     * @param n The name of the term
+     */
+    private TensePresent(String n, ArrayList<Term> cs, ArrayList<Variable> open, ArrayList<Variable> closed, short i) {
+        super(n, cs, open, closed, i);
+    }
+    
+    /**
+     * override the cloning methed in Object
+     * @return A new object, to be casted into a SetExt
+     */
+    public Object clone() {
+        return new TensePresent(name, (ArrayList<Term>) cloneList(components),
+                (ArrayList<Variable>) cloneList(openVariables), (ArrayList<Variable>) cloneList(closedVariables), complexity);
+    }
+    
+    /**
+     * Try to make a new compound. Called by StringParser.
+     * @return the Term generated from the arguments
+     * @param argument The list of components
+     */
+    public static Term make(ArrayList<Term> argument, Memory memory) {
+        if (argument.size() != 1) 
+            return null;
+        Term t = argument.get(0);
+        if ((t instanceof TensePresent) || (t instanceof TensePast) || (t instanceof TenseFuture))
+            return t;         
+        String name = makeCompoundName(Symbols.PRESENT_OPERATOR, argument);
+        t = memory.nameToListedTerm(name);
+        return (t != null) ? t : new TensePresent(name, argument);
+    }
+    
+    /**
+     * Try to make a compound of one component. Called by the inference rules.
+     * @param t The compoment
+     * @return A compound generated or a term it reduced to
+     */
+    public static Term make(Term t, Memory memory) {
+        ArrayList<Term> argument = new ArrayList<Term>();
+        argument.add(t);
+        return make(argument, memory);
+    }
+
+    /**
+     * get the operator of the term.
+     * @return the operator of the term
+     */
+    public String operator() {
+        return Symbols.PRESENT_OPERATOR;
+    }
+
+    public CompoundTerm.TemporalOrder getTemporalOrder() {
+        return CompoundTerm.TemporalOrder.WHEN;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/Term.java b/open-nars/com/googlecode/opennars/language/Term.java
new file mode 100644
index 0000000000000000000000000000000000000000..41413fee66b784cd49f36e5a928b2c30f66af01a
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Term.java
@@ -0,0 +1,129 @@
+/*
+ * Term.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.inference.SyllogisticRules;
+import com.googlecode.opennars.main.Memory;
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * Term is the basic component of Narsese, and the object of processing in NARS.
+ * <p>
+ * A Term may or may not have an associated Concept containing relations with other Terms. It
+ * is not linked in the Term, because a Concept may be forgot, while the Term exists.
+ */
+public class Term implements Cloneable, Comparable<Term> {
+    /**
+     * A Term is identified uniquely by its name, a sequence of characters in a given alphabet.
+     */
+    protected String name;              // name of the term, an ASCII string (can be changed to Unicode)
+    
+    /**
+     * Default constructor
+     */
+    protected Term() {}
+    
+    /**
+     * Constructor with a given name
+     * @param name A String as the name of the Term
+     */
+    public Term(String name) {
+        this.name = name;
+    }
+    
+    /**
+     * The same as getName, used in display.
+     * @return The name of the term as a String
+     */
+    public final String toString() {
+        return name;
+    }
+    
+    /**
+     * Reporting the name of the current Term.
+     * @return The name of the term as a String
+     */
+    public String getName() {
+        return name;
+    }
+    
+    /**
+     * Default, to be overrided in variable Terms.
+     * @return The name of the term as a String
+     */
+    public String getConstantName() {
+        return name;
+    }
+    
+    /**
+     * Make a new Term with the same name.
+     * @return The new Term
+     */
+    public Object clone() {
+        return new Term(name);
+    }
+    
+    /**
+     * Equal terms have identical name, though not necessarily the same reference.
+     * @return Whether the two Terms are equal
+     * @param that The Term to be compared with the current Term
+     */
+    public boolean equals(Object that) {
+        return (that instanceof Term) && getName().equals(((Term) that).getName());
+    }
+    
+    /**
+     * The default complexity, for constant automic Term, is 1.
+     * @return The conplexity of the term, an integer
+     */
+    public int getComplexity() {
+        return 1;
+    }
+        
+    /**
+     * Check the relative order of two Terms.
+     * @param that The Term to be compared with the current Term
+     * @return The same as compareTo as defined on Strings when the constant parts are compared
+     */
+    public final int compareTo(Term that) {
+        int i = this.getConstantName().compareTo(that.getConstantName());       // based on the constant part first
+        return (i != 0) ? i : this.getName().compareTo(that.getName());
+    }
+    
+    /**
+     * Check whether the current Term can name a Concept.
+     * @return a Term is constant by default
+     */
+    public boolean isConstant() {
+        return true;
+    }
+    
+    public CompoundTerm.TemporalOrder getTemporalOrder() {
+        return CompoundTerm.TemporalOrder.NONE;
+    }
+    
+    public final boolean containQueryVariable() {                           // to be revised
+        return (name.indexOf(Symbols.QUERY_VARIABLE_TAG) >= 0);
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/Variable.java b/open-nars/com/googlecode/opennars/language/Variable.java
new file mode 100644
index 0000000000000000000000000000000000000000..35f2eb2ba1a7c2d2587891b4f218636ded3a1c6d
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/Variable.java
@@ -0,0 +1,234 @@
+/*
+ * Variable.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.language;
+
+import java.util.*;
+
+import com.googlecode.opennars.parser.Symbols;
+
+/**
+ * A variable term.
+ */
+public class Variable extends Term {
+    public enum VarType { INDEPENDENT, DEPENDENT, ANONYMOUS, QUERY }
+    
+    private CompoundTerm scope;
+    private VarType type;
+    
+    public Variable() {
+        super();
+    }
+    
+    public Variable(String s) {
+        name = s;
+        scope = null;
+        char prefix = s.charAt(0);
+        if (prefix == Symbols.QUERY_VARIABLE_TAG)
+            type = VarType.QUERY;
+        else if (s.length() == 1)
+            type = VarType.ANONYMOUS;
+        else if (s.charAt(s.length()-1) == Symbols.COMPOUND_TERM_CLOSER) {
+            type = VarType.DEPENDENT;
+            int i = s.indexOf(Symbols.COMPOUND_TERM_OPENER);
+            name = s.substring(0, i);       // ignore the dependency list
+        } else
+            type = VarType.INDEPENDENT;
+    }
+
+    private Variable(String n, CompoundTerm s, VarType t) {
+        name = n;
+        scope = s;
+        type = t;
+    }
+    
+    /**
+     * Make a new Variable with the same name and type.
+     * @return The new Variable
+     */
+    public Object clone() {
+        return new Variable(name, scope, type);
+    }
+
+    // overwrite default, to be omitted in sorting
+    public String getConstantName() {
+        return ("" + Symbols.VARIABLE_TAG);
+    }
+    
+    /**
+     * Rename a variable temporally to distinguish it from variables in other Terms
+     * @param first Whether it is the first term
+     * @return The new name
+     */
+    public String getVarName(boolean first) {
+        if (first)
+            return Symbols.VARIABLE_TAG + "1" + name;
+        else
+            return Symbols.VARIABLE_TAG + "2" + name;
+    }
+    
+    public void setName(String n) {
+        name = n;
+    }
+    
+    public CompoundTerm getScope() {
+        return scope;
+    }
+    
+    public void setScope(CompoundTerm s) {
+        scope = s;
+    }
+    
+    public VarType getType() {
+        return type;
+    }
+    
+    public void setType(VarType t) {
+        type = t;
+    }
+
+    public boolean equals(Object that) {
+        return (that instanceof Variable) && name.equals(((Variable) that).getSimpleName());
+    }
+
+    public String getSimpleName() {
+        return name;
+    }
+
+    public String getName() {
+        if (type != VarType.DEPENDENT)
+            return name;
+        else {
+            StringBuffer buffer = new StringBuffer(name + "(");
+            if (scope != null) {
+                ArrayList<Variable> dependency = scope.getOpenVariables();
+                if (dependency != null) {
+                    for (Variable v : dependency)
+                        if (v.getType() == VarType.INDEPENDENT)
+                            buffer.append(v.toString());
+                }
+            }
+            buffer.append(")");
+            return buffer.toString();
+        }
+    }
+    
+    public boolean isConstant() {
+        return false;                // overridding default
+    }
+    
+    // move to RuleTable? the last two arguments must be clones
+    /**
+     * To unify two Terms, then apply the substitution to the two compounds
+     * @param type The type of Variable to be unified
+     * @param t1 The first Term to be unified
+     * @param t2 The second Term to be unified
+     * @param compound1 The first compound to be substituted
+     * @param compound2 The second compound to be substituted
+     * @return Whether a unification has been succeeded
+     */
+    public static boolean unify(VarType type, Term t1, Term t2, Term compound1, Term compound2) {
+        if (t1.isConstant() && t1.equals(t2))       // to constant Terms are unified if equals
+            return true;
+        if (!(compound1 instanceof CompoundTerm) || !(compound2 instanceof CompoundTerm))
+            return false;
+        HashMap<String,Term> substitute = findSubstitute(type, t1, t2, new HashMap<String,Term>()); // find substitution
+        if (substitute == null) // not unifiable
+            return false;
+        if (!substitute.isEmpty()) {
+            ((CompoundTerm) compound1).substituteComponent(substitute, true);   // apply the substitution to the first compound
+            ((CompoundTerm) compound2).substituteComponent(substitute, false);  // apply the substitution to the second compound
+        }
+        return true;
+    }
+
+
+    public static HashMap<String,Term> findSubstitute(VarType type, Term term1, Term term2) {
+        return findSubstitute(type, term1, term2, new HashMap<String,Term>());
+    }
+    
+    /**
+     * To find a substitution that can unify two Terms without changing them
+     * @param type The type of Variable to be substituted
+     * @param term1 The first Term to be unified
+     * @param term2 The second Term to be unified
+     * @param subs The substitution formed so far
+     * @return The substitution that unifies the two Terms
+     */
+    private static HashMap<String,Term> findSubstitute(VarType type, Term term1, Term term2, HashMap<String,Term> subs) {
+        Term oldValue, t1, t2;
+        if (term1.equals(term2))    // for constant, also shortcut for variable and compound
+            return subs;
+        if ((term1 instanceof Variable) && (((Variable) term1).getType() == type))  // the first Term is a unifiable Variable
+            return findSubstituteVar(type, (Variable) term1, term2, subs, true);
+        if ((term2 instanceof Variable) && (((Variable) term2).getType() == type))  // the second Term is a unifiable Variable
+            return findSubstituteVar(type, (Variable) term2, term1, subs, false);
+        if (term1 instanceof CompoundTerm) {
+            if (!term1.getClass().equals(term2.getClass()))   // two compounds must be of the same type to be unified
+                return null;
+            if (!(((CompoundTerm) term1).size() == ((CompoundTerm) term2).size())) // two compounds must be of the same size, too
+                return null;
+            for (int i = 0; i < ((CompoundTerm) term1).size(); i++) {   // recursively unify components
+                t1 = ((CompoundTerm) term1).componentAt(i);
+                t2 = ((CompoundTerm) term2).componentAt(i);
+                HashMap<String,Term> newSubs = findSubstitute(type, t1, t2, subs);
+                if (newSubs == null)            // fails in one component means no substitution
+                    return null;
+                subs.putAll(newSubs);       // put new mappings into the table
+            }
+            return subs;     // solve: <x,x,2> and <y,3,y>
+        }
+        return null;
+    }
+    
+    /**
+     * To find a substitution that can unify a Vriable and a Term
+     * @param type The type of Variable to be substituted
+     * @param var The Variable to be unified
+     * @param term The Term to be unified
+     * @param subs The substitution formed so far
+     * @param first If it is the first Term in unify
+     * @return The substitution that unifies the two Terms, as "name-term" pairs
+     */
+    private static HashMap<String,Term> findSubstituteVar(VarType type, Variable var, Term term, HashMap<String,Term> subs, boolean first) {
+        String name1 = var.getVarName(first);    // make a prefixed name for the avriable
+        Term oldTerm = subs.get(name1);          // check if a mapping for that name exist
+        if (oldTerm != null) {                  // processed variable
+            if (first)
+                return findSubstitute(type, oldTerm, term, subs);
+            else
+                return findSubstitute(type, term, oldTerm, subs);
+        } else {                                // novel variable
+            if (term instanceof Variable) {     // the other is also a variable
+                String name2 = ((Variable) term).getVarName(!first);
+                oldTerm = subs.get(name2);       
+                if (oldTerm != null) {          // if the other has a substitute
+                    if (first)
+                        return findSubstitute(type, var, oldTerm, subs);
+                    else
+                        return findSubstitute(type, oldTerm, var, subs);
+                }
+            }
+            subs.put(name1, term);  // check dependency for dependent variable!!!
+            return subs;
+        }
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/language/package.html b/open-nars/com/googlecode/opennars/language/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..4fb4628b371d496d1e8ff4076b32be12470040df
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/language/package.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+
+Terms in Narsese, a formal language
+
+<h2>Package Specification</h2>
+
+NARS 4.3 implements the following formal language, Narsese.
+<pre>
+           &lt;sentence&gt; ::= &lt;judgment&gt;
+                        | &lt;question&gt;
+                        | &lt;goal&gt;
+           &lt;judgment&gt; ::= &lt;statement&gt; &lt;truth-value&gt;
+           &lt;question&gt; ::= &lt;statement&gt;
+               &lt;goal&gt; ::= &lt;statement&gt; &lt;desire-value&gt;
+          &lt;statement&gt; ::= &lt;&lt;term&gt; &lt;relation&gt; &lt;term&gt;&gt;
+                        | &lt;compound-statement&gt;
+                        | &lt;term&gt;
+               &lt;term&gt; ::= &lt;word&gt;
+                        | &lt;variable&gt;
+                        | &lt;compound-term&gt;
+                        | &lt;statement&gt;
+           &lt;relation&gt; ::= -->
+                        | <->
+                        | {--
+                        | --]
+                        | {-]
+                        | ==>
+                        | <=>
+                        | =/>
+                        | =\>
+                        | &lt;/>
+ &lt;compound-statement&gt; ::= (-- &lt;statement&gt;)
+                        | (|| &lt;statement&gt; &lt;statement&gt;<sup>+</sup>)
+                        | (&& &lt;statement&gt; &lt;statement&gt;<sup>+</sup>)
+                        | (&/ &lt;statement&gt; &lt;statement&gt;<sup>+</sup>)
+                        | (/> &lt;statement&gt;)
+                        | (\> &lt;statement&gt;)
+      &lt;compound-term&gt; ::= {&lt;term&gt;<sup>+</sup>}
+                        | [&lt;term&gt;<sup>+</sup>]
+                        | (& &lt;term&gt; &lt;term&gt;<sup>+</sup>)
+                        | (| &lt;term&gt; &lt;term&gt;<sup>+</sup>)
+                        | (- &lt;term&gt; &lt;term&gt;)
+                        | (~ &lt;term&gt; &lt;term&gt;)
+                        | (* &lt;term&gt; &lt;term&gt;<sup>+</sup>)
+                        | (/ &lt;term&gt;<sup>+</sup> _ &lt;term&gt;<sup>*</sup>)
+                        | (\ &lt;term&gt;<sup>+</sup> _ &lt;term&gt;<sup>*</sup>)
+           &lt;variable&gt; ::= &lt;dependent-var&gt;
+                        | &lt;independent-var&gt;
+                        | &lt;query-var&gt;
+      &lt;dependent-var&gt; ::= #&lt;word&gt;(&lt;independent-var&gt;<sup>*</sup>)
+    &lt;independent-var&gt; ::= #&lt;word&gt;
+          &lt;query-var&gt; ::= ?&lt;word&gt;
+               &lt;word&gt; : string in an alphabet
+        &lt;truth-value&gt; : a pair of real numbers in [0, 1] x (0, 1)
+       &lt;desire-value&gt; : a pair of real numbers in [0, 1] x (0, 1)
+</pre>
+
+Major methods in the term classes:
+<ul>
+<li>constructors</li>
+<li>get and set</li>
+<li>clone, compare, and unify</li>
+<li>create and access corresponding concept</li>
+<li>structural operation in compound</li>
+<li>class-specific inference</li>
+</ul>
+
+</body>
+</html>
diff --git a/open-nars/com/googlecode/opennars/main/Memory.java b/open-nars/com/googlecode/opennars/main/Memory.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c73d4de15952729dd9bafe1caee251724edc3cc
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/main/Memory.java
@@ -0,0 +1,462 @@
+/*
+ * Memory.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.main;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.*;
+import com.googlecode.opennars.inference.*;
+import com.googlecode.opennars.language.*;
+import com.googlecode.opennars.operation.Operator;
+import com.googlecode.opennars.parser.*;
+import com.googlecode.opennars.parser.narsese.NarseseParser;
+import com.googlecode.opennars.storage.*;
+
+/**
+ * The memory of the system.
+ */
+public class Memory extends Observable {
+	
+	private Parameters parameters;
+	private RuleTables ruletables;
+	public BudgetFunctions budgetfunctions;
+    
+    /* ---------- all members have limited space ---------- */
+    
+    /**
+     * Concept bag. Containing all Concepts of the system.
+     */
+    private ConceptBag concepts;
+    
+    /**
+     * Operators (built-in terms) table. Accessed by name.
+     */
+    private HashMap<String, Operator> operators;
+    
+    // There is no global Term table, which may ask for unlimited space.
+    
+    /**
+     * List of inference newTasks, to be processed in the next working cycle.
+     */
+    private ArrayList<Task> newTasks;
+    
+    /**
+     * New tasks to be processed in the near future.
+     */
+    private TaskBag taskBuffer;
+    
+    /* ---------- global variables used to reduce method arguments ---------- */
+    
+    /**
+     * Shortcut to the selected Term.
+     */
+    public Term currentTerm;
+    
+    /**
+     * Shortcut to the selected TaskLink.
+     */
+    public TaskLink currentTaskLink;
+    
+    /**
+     * Shortcut to the selected Task.
+     */
+    public Task currentTask;
+    
+    /**
+     * Shortcut to the selected TermLink.
+     */
+    public TermLink currentBeliefLink;
+    
+    /**
+     * Shortcut to the selected belief (Sentence).
+     */
+    public Judgement currentBelief;
+    
+    public Base currentBase;
+    
+    /* ---------- initialization ---------- */
+    
+    /**
+     * Initialize a new memory by creating all members.
+     * <p>
+     * Called in Center.reset only
+     */
+    public Memory() {
+        init();
+        ruletables = new RuleTables(this);
+        budgetfunctions = new BudgetFunctions(this);
+    }
+    
+    public void reset() {
+    	init();
+    }
+    
+    private void init() {
+    	concepts = new ConceptBag();         // initially empty
+        newTasks = new ArrayList<Task>();     // initially empty
+        taskBuffer = new TaskBag();       // initially empty
+        operators = Operator.setOperators(); // with operators created
+        parameters = new Parameters();
+    }
+    
+    /* ---------- access utilities ---------- */
+    
+    /**
+     * Get a Term for a given name of a Concept or Operator, called in StringParser and the make methods of compound terms.
+     * @param name the name of a concept or operator
+     * @return a Term or null (if no Concept/Operator has this name)
+     */
+    public Term nameToListedTerm(String name) {
+        Concept concept = concepts.get(name);
+        if (concept != null)
+            return concept.getTerm();           // Concept associated Term
+        return operators.get(name);
+    }
+    
+    /**
+     * Check if a string is an operator name, called in StringParser only.
+     * @param name the name of a possible operator
+     * @return the corresponding operator or null
+     */
+    public Operator nameToOperator(String name) {
+        return operators.get(name);
+    }
+    
+    /**
+     * Add a new operator with the given name
+     * @param op the operator
+     * @param name the operator's name. Should begin with ^.
+     */
+    public void addOperatorWithName(Operator op, String name) {
+    	operators.put(name, op);
+    }
+    
+    /**
+     * Remove the operator with the given name
+     * @param name the operator's name
+     */
+    public void removeOperatorWithName(String name) {
+    	operators.remove(operators.get(name));
+    }
+    
+    /**
+     * Return the parameters of this reasoner
+     * @return the parameters
+     */
+    public Parameters getParameters() {
+    	return parameters;
+    }
+
+    /**
+     * Return an ArrayList of the Concepts this reasoner knows about
+     * @return the concepts
+     */
+    public ArrayList<Concept> getAllConcepts() {
+    	return this.concepts.getAllContents();
+    }
+    
+    public HashMap<String,Concept> getConceptMap() {
+    	return this.concepts.getNameTable();
+    }
+    
+    public Task getCurrentTask() {
+    	return this.currentTask;
+    }
+    
+    /**
+     * Return an ArrayList of the Tasks this reasoner is working on
+     * @return the tasks
+     */
+    public ArrayList<Task> getAllTasks() {
+    	return this.taskBuffer.getAllContents();
+    }
+
+	/**
+	 * @return the ruletables
+	 */
+	public RuleTables getRuletables() {
+		return ruletables;
+	}
+
+	/**
+     * Get an existing Concept for a given name, called from Term and ConceptWindow.
+     * @param name the name of a concept
+     * @return a Concept or null
+     */
+    public Concept nameToConcept(String name) {
+        return concepts.get(name);
+    }
+    
+    /**
+     * Get an existing Concept for a given Term.
+     * @param term The Term naming a concept
+     * @return a Concept or null
+     */
+    public Concept termToConcept(Term term) {
+        return nameToConcept(term.getName());
+    }
+    
+    /**
+     * Get the Concept associated to a Term, or creat it.
+     * @param term indicating the concept
+     * @return an existing Concept, or a new one
+     */
+    public Concept getConcept(Term term) {
+        String n = term.getName();
+        Concept concept = concepts.get(n);
+        if (concept == null)
+            concept = new Concept(term, this);        // the only place to make a new Concept
+        return concept;
+    }
+    
+    /**
+     * Adjust the activation level of a Concept or Operator, called in Concept only.
+     * @param c the concept to be adusted
+     * @param b the new BudgetValue
+     */
+    public void activateConcept(Concept c, BudgetValue b) {
+        BudgetValue budget;
+        if (concepts.contains(c)) {     // listed Concept
+            concepts.pickOut(c.getKey());
+            this.budgetfunctions.activate(c, b);
+            concepts.putBack(c);
+        } else {                        // new Concept
+            this.budgetfunctions.activate(c, b);
+            concepts.putIn(c);
+        }
+    }
+    
+    /* ---------- new task entries ---------- */
+    
+    // There are three types of new tasks: (1) input, (2) derived, (3) activated
+    // They are all added into the newTasks list, to be processed in the next cycle.
+    // Some of them are reported and/or logged.
+    
+    /**
+     * Input task comes from the InputWindow.
+     * @param str the input line
+     */
+    public void inputStringWithParser(String str, Parser parser) throws InvalidInputException {
+        Task task = parser.parseTask(str, this);       // the only place to call StringParser
+        if (task != null) {
+            if (task.aboveThreshold()) {                       // set a threshold?
+                report(task.getSentence(), true);             // report input
+                newTasks.add(task);       // wait to be processed in the next cycle
+            }
+        }
+    }
+    
+    /**
+     * Input task from some source
+     * @param task the task to add
+     */
+    public void inputTask(Task task) {
+    	if (task != null) {
+            if (task.aboveThreshold()) {                       // set a threshold?
+                report(task.getSentence(), true);             // report input
+                newTasks.add(task);       // wait to be processed in the next cycle
+            }
+        }
+    }
+    
+    /**
+     * Derived task comes from the inference rules.
+     * @param task the derived task
+     */
+    private void derivedTask(Task task) {
+        if (task.aboveThreshold()) {
+            float budget = task.getBudget().singleValue();
+            float minSilent = parameters.SILENT_LEVEL / 100.0f;
+            if (budget > minSilent)
+                report(task.getSentence(), false);        // report significient derived Tasks
+            newTasks.add(task);
+        }
+    }
+    
+    /**
+     * Reporting executed task, called from Concept.directOperation.
+     * @param task the executed task
+     */
+    public void executedTask(Task task) {   // called by the inference rules
+        float budget = task.getBudget().singleValue();
+        float minSilent = parameters.SILENT_LEVEL / 100.0f;
+        if (budget > minSilent)
+            report(task.getSentence(), false);
+    }
+    
+    /**
+     * Activated task comes from MatchingRules.
+     * @param budget The budget value of the new Task
+     * @param sentence The content of the new Task
+     * @param isInput Whether the question is input
+     */
+    public void activatedTask(BudgetValue budget, Sentence sentence, boolean isInput) {
+        Task task = new Task(sentence, budget, this);
+        newTasks.add(task);
+    }
+    
+    /* --------------- new task building --------------- */
+    
+    /**
+     * Shared final operations by all double-premise rules, called from the rules except StructuralRules
+     * @param budget The budget value of the new task
+     * @param content The content of the new task
+     * @param truth The truth value of the new task
+     */
+    public void doublePremiseTask(BudgetValue budget, Term content, TruthValue truth) {
+        Sentence newSentence = Sentence.make(currentTask.getSentence(), content, truth, this.currentBase, this);
+        Task newTask = new Task(newSentence, budget, this);
+        derivedTask(newTask);
+    }
+    
+    /**
+     * Shared final operations by all single-premise rules, called in StructuralRules
+     * @param budget The budget value of the new task
+     * @param content The content of the new task
+     * @param truth The truth value of the new task
+     */
+    public void singlePremiseTask(BudgetValue budget, Term content, TruthValue truth) {
+        Sentence sentence = currentTask.getSentence();
+        Sentence newSentence = Sentence.make(sentence, content, truth, sentence.getBase(), this);
+        Task newTask = new Task(newSentence, budget, this);
+        newTask.setStructual();
+        derivedTask(newTask);
+    }
+
+    /**
+     * Shared final operations by all single-premise rules, called in MatchingRules
+     * @param budget The budget value of the new task
+     * @param truth The truth value of the new task
+     */
+    public void singlePremiseTask(TruthValue truth, BudgetValue budget) {
+        Term content = this.currentTask.getContent();
+        Base base = this.currentBelief.getBase();
+        Sentence newJudgment = Sentence.make(content, Symbols.JUDGMENT_MARK, truth, base, this);
+        Task newTask = new Task(newJudgment, budget, this);
+        newTask.setStructual();
+        derivedTask(newTask);
+    }
+    
+    /* ---------- system working cycle ---------- */
+    
+    /**
+     * An atomic working cycle of the system. Called from Center only.
+     */
+    public void cycle() {
+        processTask();      // tune relative frequency?
+        processConcept();   // use this order to check the new result
+    }
+    
+    /**
+     * Process the newTasks accumulated in the previous cycle, accept input ones
+     * and those that corresponding to existing concepts, plus one from the buffer.
+     */
+    private void processTask() {
+        Task task;
+        int counter = newTasks.size();              // don't include new tasks produced in the current cycle
+        while (counter-- > 0) {                     // process the newTasks of the previous cycle
+            task = (Task) newTasks.remove(0);
+            if (task.getSentence().isInput() || (termToConcept(task.getContent()) != null))  // new input or existing concept
+                immediateProcess(task);                   // immediate process
+            else
+                taskBuffer.putIn(task);             // postponed process
+        }
+        task = (Task) taskBuffer.takeOut();         // select a task from taskBuffer
+        if (task != null)
+            immediateProcess(task);                       // immediate process
+    }
+    
+    /**
+     * Select a concept to fire.
+     */
+    private void processConcept() {
+        Concept currentConcept = (Concept) concepts.takeOut();
+        if (currentConcept != null) {
+            currentTerm = currentConcept.getTerm();
+            concepts.putBack(currentConcept);   // current Concept remains in the bag all the time
+            currentConcept.fire();              // a working cycle
+        }
+    }
+    
+    /* ---------- task / belief insertion ---------- */
+    
+    /**
+     * Imediate processing of a new task
+     * @param task the task to be accepted
+     */
+    private void immediateProcess(Task task) {
+        Term content = task.getContent();
+        if (content.isConstant()) {                        // does not creat concept for Query?
+            Concept c = getConcept(content);
+            c.directProcess(task);
+        }
+        if (task.aboveThreshold())
+            continuedProcess(task, content);
+    }
+
+    /**
+     * Link to a new task from all relevant concepts for distributed processing.
+     * @param task The task to be linked
+     * @param content The content of the task
+     */
+    private void continuedProcess(Task task, Term content) {
+        TaskLink tLink;
+        Concept c1 = null;                      // local Concept
+        BudgetValue budget = task.getBudget();
+        if (content.isConstant()) {
+            c1 = getConcept(content);
+            tLink = new TaskLink(task, null, budget, this);   // link type SELF
+            c1.insertTaskLink(tLink);
+        }
+        if (content instanceof CompoundTerm) {
+            Term component;                     // component term
+            Concept c2;                         // component concept
+            TermLink cLink1, cLink2;     // a pair of compound/component links
+            ArrayList<TermLink> cLinks;  // link list
+            cLinks = (c1 != null) ? c1.getTermLinks() : ((CompoundTerm) content).prepareComponentLinks(this);  // use saved
+            short[] indices;
+            BudgetValue subBudget = this.budgetfunctions.distributeAmongLinks(budget, cLinks.size());
+            if (!subBudget.aboveThreshold())
+                return;
+            for (TermLink cLink0 : cLinks) {
+                component = cLink0.getTarget();
+                c2 = getConcept(component);
+                if (!(task.isStructual() && (cLink0.getType() == TermLink.TRANSFORM))) {
+                    tLink = new TaskLink(task, cLink0, subBudget, this);
+                    c2.insertTaskLink(tLink);               // component link to task
+                }
+            }
+        }
+    }
+    
+    /* ---------- report ---------- */
+    
+    /**
+     * Display selected task.
+     * @param sentence the sentence to be displayed
+     * @param input whether the task is input
+     */
+    public void report(Sentence sentence, boolean input) {
+    	this.setChanged();
+        notifyObservers(sentence);
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/main/Parameters.java b/open-nars/com/googlecode/opennars/main/Parameters.java
new file mode 100644
index 0000000000000000000000000000000000000000..2657b700a1e315b22b29da0dd1a0e4e6ce1b3d42
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/main/Parameters.java
@@ -0,0 +1,103 @@
+/*
+ * Parameters.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.main;
+
+/**
+ * Collected system parameters. To be modified before compiling.
+ */
+public class Parameters {
+    
+    /* ---------- initial values of run-time adjustable parameters ---------- */
+
+    /** Concept decay rate, in [1, 99]. */
+    public static final int CONCEPT_DEFAULT_FORGETTING_CYCLE = 3;
+    /** TaskLink decay rate, in [1, 99]. */
+    public static final int TASK_DEFAULT_FORGETTING_CYCLE = 10;
+    /** CompositionLink decay rate, in [1, 99]. */
+    public static final int BELIEF_DEFAULT_FORGETTING_CYCLE = 50;
+       
+    /** Silent threshold for task reporting, in [0, 100]. */
+    public int SILENT_LEVEL = 100;
+
+    /* ---------- parameters fixed after compiling --- logical ---------- */
+
+    /** Horizon, the amount of evidence coming in the near future. */
+    public static final int NEAR_FUTURE = 1;    // or 2, can be float
+    
+    /** Default confidence of input judgment. */
+    public float DEFAULT_JUDGMENT_CONFIDENCE = (float) 0.9;  // ?
+
+    /* Default priority and durability of input judgment */
+    public  final float DEFAULT_JUDGMENT_PRIORITY = (float) 0.8;
+    public  final float DEFAULT_JUDGMENT_DURABILITY = (float) 0.8;
+    public  final float DEFAULT_GOAL_PRIORITY = (float) 0.9;
+    public  final float DEFAULT_GOAL_DURABILITY = (float) 0.7;
+    public  final float DEFAULT_QUESTION_PRIORITY = (float) 0.9;
+    public  final float DEFAULT_QUESTION_DURABILITY = (float) 0.7;
+    
+//    public  final float TASK_FOR_NEW_CONCEPT_DISCOUNT = (float) 0.2;  // ?
+    
+    // belief component priority rate
+    public  final float DEFAULT_COMPONENT_PRIORITY_RATE = (float) 0.7;
+    
+    /**
+     * Level granularity in Bag, two digits
+     */
+    public static final int BAG_LEVEL = 100;
+    /**
+     * Level separation in Bag, one digit, both for display (run-time adjustable) and management (fixed)
+     */
+    public static final int BAG_THRESHOLD = 10;         
+
+    /* ---------- parameters fixed after compiling --- time management ---------- */
+    
+    // time distribution
+    public static final int COLD_TASK_DELAY_STEPS = 10;                 // ?
+
+    // decay rate, within 100
+    public static final int NEW_TASK_DEFAULT_FORGETTING_CYCLE = 1;        // ?
+
+    // quality updating rate
+    public static final float DEFAULT_QUALITY_UPDATE_RATE = (float) 0.01; // percent of updating
+    
+    // maximum bLinks tried for each tLink (to avoid repeated inference)
+    public static final int MAX_TAKE_OUT_K_LINK = 10;
+    
+    // maximum belief tried for each task (to avoid overlapping evidence)
+    public static final int MAX_TAKE_OUT_BELIEF = 5;
+    
+    /* ---------- parameters fixed after compiling --- space management ---------- */
+
+    // bag size
+    public static final int CONCEPT_BAG_SIZE = 1000;         // vocabulary?
+    public static final int TASK_BUFFER_SIZE = 20;          // "7+-2"?
+    public static final int TASK_BAG_SIZE = 20;              // ?
+    public static final int BELIEF_BAG_SIZE = 100;        // ?
+    
+    // other storage size
+    public static final int MAXMUM_LABEL_RECORD_LENGTH = 16;    // should be pow(2,n)
+    public static final int TASK_INFERENCE_RECORD_LENGTH = 20;  // ?
+    public static final int MAXMUM_BELIEF_LENGTH = 8;      // duplicate links
+    public static final int MAXMUM_GOALS_LENGTH = 5;       // duplicate links
+    
+    public static final float LOAD_FACTOR = 0.5f;   // bag hashtable parameter
+}
diff --git a/open-nars/com/googlecode/opennars/main/Reasoner.java b/open-nars/com/googlecode/opennars/main/Reasoner.java
new file mode 100644
index 0000000000000000000000000000000000000000..3bc63dd423675249ff387e9009e6dcca05f2275d
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/main/Reasoner.java
@@ -0,0 +1,241 @@
+/**
+ * 
+ */
+package com.googlecode.opennars.main;
+
+import java.util.ArrayList;
+import java.util.Observable;
+import java.util.Observer;
+
+import com.googlecode.opennars.entity.BudgetValue;
+import com.googlecode.opennars.entity.Concept;
+import com.googlecode.opennars.entity.Sentence;
+import com.googlecode.opennars.entity.Task;
+import com.googlecode.opennars.operation.Operator;
+import com.googlecode.opennars.parser.InvalidInputException;
+import com.googlecode.opennars.parser.Parser;
+import com.googlecode.opennars.parser.narsese.NarseseParser;
+
+/**
+ * The Reasoner class implements a threaded NARS reasoner.
+ * @author jgeldart
+ *
+ */
+public class Reasoner extends Observable implements Observer, Runnable {
+	
+	private Thread thread;
+	private Memory memory;
+	private Parser parser;
+	private ArrayList<Task> inputQueue;
+	
+	/**
+	 * Create a new reasoner using default settings
+	 */
+	public Reasoner() {
+		parser = new NarseseParser();
+		memory = new Memory();
+		memory.addObserver(this);
+		inputQueue = new ArrayList<Task>();
+	}
+	
+	/**
+	 * Creates a new reasoner with the given string parser
+	 * @param parser
+	 */
+	public Reasoner(Parser parser) {
+		super();
+		this.parser = parser;
+	}
+	
+	/**
+	 * Start the reasoner thread
+	 */
+	public void start() {
+		if(thread == null) {
+			thread = new Thread(this);
+			thread.start();
+		}
+	}
+	
+	/**
+	 * Stop the reasoner thread
+	 */
+	public void stop() {
+		thread = null;
+	}
+	
+	/**
+	 * Perform a single reasoning step
+	 */
+	public void step() {
+		try {
+			Task task = this.getTask();
+			if(task != null)
+				memory.inputTask(task);
+			memory.cycle();
+		} catch (Exception e) {
+			if(e instanceof InvalidInputException) {
+				this.hasChanged();
+				this.notifyObservers(e);
+			}
+			else {
+				//System.err.println(e.toString());
+				e.printStackTrace();
+			}
+		}
+	}
+	
+	/**
+	 * Reset the reasoner back to 'factory defaults'
+	 */
+	public void reset() {
+		memory.reset();
+	}
+	
+	/* ----- communicating ----- */
+	
+	/**
+	 * Tell the reasoner a sentence string which is parsed using the chosen parser
+	 * @param sent the sentence
+	 */
+	public synchronized void tellSentenceString(String sent) {
+		try {
+			Task task = parser.parseTask(sent, memory);
+			inputQueue.add(task);
+		}
+		catch (InvalidInputException e) {
+			this.setChanged();
+			this.notifyObservers(e);
+		}
+	}
+	
+	/**
+	 * Tell the reasoner a sentence with the given budget for working with it
+	 * @param sent the sentence
+	 * @param budget the budget
+	 */
+	public synchronized void tellSentence(Sentence sent, BudgetValue budget) {
+		Task task = new Task(sent, budget, memory);
+		inputQueue.add(task);
+	}
+	
+	/**
+	 * Tell the reasoner a sentence with the given priority, durability and quality needed
+	 * to allocate resources to the task
+	 * @param sent the sentence
+	 * @param priority the priority
+	 * @param durability the durability
+	 * @param quality the quality
+	 */
+	public synchronized void tellSentence(Sentence sent, float priority, float durability, float quality) {
+		Task task = new Task(sent, new BudgetValue(priority, durability, quality, memory), memory);
+		inputQueue.add(task);
+	}
+
+	private synchronized Task getTask() {
+		try {
+			return inputQueue.remove(0);
+		}
+		catch (IndexOutOfBoundsException e) {
+			return null;
+		}
+	}
+	
+	/* ----- setters and getters ----- */
+	
+	/**
+	 * Get the memory
+	 */
+	public Memory getMemory() {
+		return memory;
+	}
+	
+	/**
+	 * Returns the parser used to parse sentence strings
+	 * @return the parser
+	 */
+	public Parser getParser() {
+		return parser;
+	}
+	
+	/**
+	 * Set the parser used to parse sentence strings
+	 * @param parser the parser
+	 */
+	public void setParser(Parser parser) {
+		this.parser = parser;
+	}
+	
+	/**
+	 * Get the reasoner's parameters
+	 * @return the parameters
+	 */
+	public Parameters getParameters() {
+		return memory.getParameters();
+	}
+	
+	/**
+	 * Get all the concepts this reasoner currently knows about
+	 * @return the concepts
+	 */
+	public ArrayList<Concept> getConcepts() {
+		return memory.getAllConcepts();
+	}
+	
+	/**
+	 * Get all the tasks this reasoner currently knows about
+	 * @return the tasks
+	 */
+	public ArrayList<Task> getTasks() {
+		return memory.getAllTasks();
+	}
+	
+	/**
+	 * Get the current reasoning task
+	 * @return the task
+	 */
+	public Task getCurrentTask() {
+		return memory.getCurrentTask();
+	}
+	
+	/**
+	 * Fetch the operator with the given name
+	 * @param name the operator's name
+	 * @return the operator
+	 */
+	public Operator getOperatorWithName(String name) {
+		return memory.nameToOperator(name);
+	}
+	
+	/**
+	 * Add the operator with the given name
+	 * @param op the operator
+	 * @param name the name
+	 */
+	public void addOperatorWithName(Operator op, String name) {
+		memory.addOperatorWithName(op, name);
+	}
+	
+	/* ------ internals ------ */
+
+	/* (non-Javadoc)
+	 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
+	 */
+	public void update(Observable o, Object arg) {
+		this.setChanged();
+		this.notifyObservers(arg);
+	}
+
+	public void run() {
+		Thread thisThread = Thread.currentThread();
+		while(thread == thisThread) {
+			try {
+				Thread.sleep(10);
+			} catch (InterruptedException e) {
+				
+			}
+			step();
+		}
+	}
+	
+}
diff --git a/open-nars/com/googlecode/opennars/main/package.html b/open-nars/com/googlecode/opennars/main/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..e2da9b9a4a7d0ca465462dede2e9eb7d766be9f8
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/main/package.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+
+Top-level classes of the system
+
+<h2>Package Specification</h2>
+
+This package contains the top classes of the system.
+<p>
+<tt>NARS</tt> defines the application and applet. When NARS runs as an applet, it is for demonstration only, and certain functionalities are blocked.
+<p>
+<tt>Parameters</tt> collects all system parameters, which can be edited before compiling.
+<p>
+<tt>Memory</tt> maintains the work space of the system, including
+<ul>
+<li>a bag of concept,</li>
+<li>a look-up table of all built-in operators,</li>
+<li>a queue for new results to be processed in each cycle,</li>
+<li>a task buffer for new results to be processed in the future.</li>
+</ul>
+Each of the above occupies constant space.
+<p>
+Memory and all of its variables are static, so each is unique, and can be referred by name anywhere in the system.
+
+</body>
+</html>
diff --git a/open-nars/com/googlecode/opennars/operation/GoTo.java b/open-nars/com/googlecode/opennars/operation/GoTo.java
new file mode 100644
index 0000000000000000000000000000000000000000..d222204ad7faeca87182182508e799ce13f67948
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/operation/GoTo.java
@@ -0,0 +1,41 @@
+/*
+ * GoTo.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.operation;
+
+import java.io.*;
+
+import com.googlecode.opennars.entity.Task;
+
+/**
+ * A class used in testing only.
+ */
+public class GoTo extends Operator {
+    public GoTo(String name) {
+        super(name);
+    }
+    
+    public Object execute(Task task) {
+        System.out.println("EXECUTE in " + name + " " + task);
+        return null;
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/operation/Open.java b/open-nars/com/googlecode/opennars/operation/Open.java
new file mode 100644
index 0000000000000000000000000000000000000000..b6f7bbb5020b7997f6033dbb923def3057baa4e6
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/operation/Open.java
@@ -0,0 +1,42 @@
+/*
+ * Open.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.operation;
+
+import java.io.*;
+
+import com.googlecode.opennars.entity.Task;
+
+/**
+ * A class used in testing only.
+ */
+public class Open extends Operator {
+    public Open(String name) {
+        super(name);
+    }
+
+    public Object execute(Task task) {
+        System.out.println("EXECUTE in " + name + " " + task);
+        return null;
+    }
+}
+
+
diff --git a/open-nars/com/googlecode/opennars/operation/Operator.java b/open-nars/com/googlecode/opennars/operation/Operator.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a394b3842bff45e44e1881a3bfefda0660e5a4d
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/operation/Operator.java
@@ -0,0 +1,53 @@
+/*
+ * Operator.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.operation;
+
+import java.util.*;
+import java.io.*;
+
+import com.googlecode.opennars.entity.Task;
+import com.googlecode.opennars.language.Term;
+
+/**
+ * An individual operator that can be execute by the system.
+ * The only file to modify when adding a new operator into NARS
+ */
+public abstract class Operator extends Term {
+    public Operator(String name) {
+        super(name);
+    }
+    
+    // required method for every operation
+    public abstract Object execute(Task task);
+
+    // register the operators in the memory
+    // the only method to modify when adding a new operator into NARS
+    // an operator should contain at least two characters after "^""
+    public static HashMap<String, Operator> setOperators() {
+        HashMap<String, Operator> table = new HashMap<String, Operator>();
+        table.put("^go-to", new GoTo("^go-to"));
+        table.put("^pick", new Pick("^pick"));
+        table.put("^open", new Open("^open"));
+        return table;
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/operation/Pick.java b/open-nars/com/googlecode/opennars/operation/Pick.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc2c6eaa90e46bfb12362d42aea5561dbcfeec29
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/operation/Pick.java
@@ -0,0 +1,40 @@
+/*
+ * Pick.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.operation;
+
+import java.io.*;
+
+import com.googlecode.opennars.entity.Task;
+
+/**
+ * A class used in testing only.
+ */
+public class Pick extends Operator {
+    public Pick(String name) {
+        super(name);
+    }
+
+    public Object execute(Task task) {
+        System.out.println("EXECUTE in " + name + " " + task);
+        return null;
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/operation/package.html b/open-nars/com/googlecode/opennars/operation/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..903b31203a9da4310d4412a2c4cb432c81c6dee0
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/operation/package.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+
+Built-in operators
+
+<h2>Package Specification</h2>
+
+The built-in operator classes are all subclasses of <tt>Operator</tt>, which extends <tt>Term</tt>.
+<p>
+Each built-in operator must implement a method <tt>execute</tt>, which takes a Task as argument.
+<p>
+All built-in operators are registered in class <tt>Operator</tt>.
+
+</body>
+</html>
diff --git a/open-nars/com/googlecode/opennars/overview.html b/open-nars/com/googlecode/opennars/overview.html
new file mode 100644
index 0000000000000000000000000000000000000000..8dbb004da0ae960b0adb15b5ded96c5728325eaf
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/overview.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+    <head>NARS</head>
+    <body bgcolor="white">
+
+        NARS overview
+
+        <h2>Package Specification</h2>
+
+        The code for distribution is in <tt>NARS.jar</tt>, which works both as an application (full mode) and an applet 
+        (demo mode, with simplified display).
+
+    </body>
+</html>
diff --git a/open-nars/com/googlecode/opennars/parser/InvalidInputException.java b/open-nars/com/googlecode/opennars/parser/InvalidInputException.java
new file mode 100644
index 0000000000000000000000000000000000000000..6b3aa5f2ed9f6c7d20a1c43f6df804c17525d429
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/parser/InvalidInputException.java
@@ -0,0 +1,31 @@
+package com.googlecode.opennars.parser;
+
+/**
+ * An input exception from a NARS parser.
+ * @author jgeldart
+ *
+ */
+public class InvalidInputException extends Exception {
+
+	/**
+	 * Autogenerated serial code
+	 */
+	private static final long serialVersionUID = 325617403436238787L;
+
+	public InvalidInputException() {
+		super("Unknown input error");
+	}
+
+	public InvalidInputException(String message) {
+		super(message);
+	}
+
+	public InvalidInputException(Throwable cause) {
+		super(cause);
+	}
+
+	public InvalidInputException(String message, Throwable cause) {
+		super(message, cause);
+	}
+
+}
diff --git a/open-nars/com/googlecode/opennars/parser/Parser.java b/open-nars/com/googlecode/opennars/parser/Parser.java
new file mode 100644
index 0000000000000000000000000000000000000000..2589a36a62244e1f3c5ba4abcbd555e6e05a84b0
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/parser/Parser.java
@@ -0,0 +1,17 @@
+package com.googlecode.opennars.parser;
+
+import com.googlecode.opennars.entity.Task;
+import com.googlecode.opennars.main.Memory;
+
+public abstract class Parser extends Symbols {
+
+	/**
+	 * The only public (static) method of the class, called from Memory.inputTask.
+	 * @param buffer the single-line input String
+	 * @param memory the memory object doing the parsing
+	 * @return an input Task, or null if the input line cannot be parsed into a Task
+	 * @throws InvalidInputException 
+	 */
+	public abstract Task parseTask(String input, Memory memory) throws InvalidInputException;
+	
+}
\ No newline at end of file
diff --git a/open-nars/com/googlecode/opennars/parser/loan/loan.g b/open-nars/com/googlecode/opennars/parser/loan/loan.g
new file mode 100644
index 0000000000000000000000000000000000000000..e76fa96af9beb65a0d3da0deeccb6e5206963036
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/parser/loan/loan.g
@@ -0,0 +1,474 @@
+grammar loan;
+
+options {
+	output = AST;
+}
+
+// $<Parser
+
+document 
+	:	base_rule? (at_rule | sentence)* EOF;
+	
+base_rule 
+	:	AT_BASE^ IRI_REF DOT!
+	;
+
+at_rule :	AT_IMPORT^ IRI_REF DOT!
+	|	AT_PREFIX^ PNAME_NS IRI_REF DOT!
+	|	AT_DELAY^ LPAREN! INTEGER RPAREN! DOT!
+	;
+
+sentence 
+	:	statement (judgement^|question^|goal^)
+	;
+	
+judgement 
+	:	DOT^ truthvalue?
+	;
+	
+goal	:	EXCLAMATION^ truthvalue?
+	;
+	
+question 
+	:	QUESTION^
+	;
+	
+truthvalue 
+	:	PERCENT! (DECIMAL | INTEGER) (SEMICOLON DECIMAL)? PERCENT!;
+
+statement 
+	:	unary_statement ((CONJ^ | SEMICOLON^ | COMMA^ | DISJ^) unary_statement)*
+	;
+	
+unary_statement 
+	:	NOT simple_statement
+	|	PAST simple_statement
+	|	PRESENT simple_statement
+	|	FUTURE simple_statement
+	|	simple_statement
+	;
+	
+simple_statement 
+	:	term ((INHERITANCE^ | SIMILARITY^ | INSTANCE^ | PROPERTY^ | INSTANCE_PROPERTY^ | IMPLICATION^ | IMPLICATION_PRED^ | IMPLICATION_RETRO^ | IMPLICATION_CONC^ | EQUIVALENCE^ | EQUIVALENCE_PRED^ | EQUIVALENCE_CONC^) term)?
+	;
+	
+	
+term 	:	difference ((AMPERSAND^ | BAR^) difference)*
+	;
+
+ext_set :	OPEN_BRACE^ (term (COMMA! term)*)? CLOSE_BRACE!
+	;
+	
+int_set :	LBRACKET^ (term (COMMA! term)*)? RBRACKET!
+	;
+	
+difference 
+	:	product ((MINUS^ | TILDE^) product)*
+	;
+	
+product :	atomic_term (STAR^ atomic_term)*
+	;
+
+atomic_term 
+	:	ext_set
+	|	int_set
+	|	LPAREN! statement RPAREN!
+	|	variable
+	|	iriRef
+	|	literal
+	;
+	
+variable 
+	:	query_variable
+	|	statement_variable
+	;
+	
+query_variable 
+	:	QUERY_VAR
+	;
+	
+statement_variable 
+	:	STM_VAR
+	;
+	
+	
+	
+literal
+	:	numericLiteral
+	|	booleanLiteral
+	|	string
+	;
+	
+numericLiteral
+    : numericLiteralUnsigned | numericLiteralPositive | numericLiteralNegative
+    ;
+
+numericLiteralUnsigned
+    : INTEGER
+    | DECIMAL
+    | DOUBLE
+    ;
+
+numericLiteralPositive
+    : INTEGER_POSITIVE
+    | DECIMAL_POSITIVE
+    | DOUBLE_POSITIVE
+    ;
+
+numericLiteralNegative
+    : INTEGER_NEGATIVE
+    | DECIMAL_NEGATIVE
+    | DOUBLE_NEGATIVE
+    ;
+
+booleanLiteral
+    : TRUE
+    | FALSE
+    ;
+
+string
+    : STRING_LITERAL1
+    | STRING_LITERAL2
+    | STRING_LITERAL_LONG1
+    | STRING_LITERAL_LONG2
+    ;
+
+iriRef
+    : IRI_REF
+    | prefixedName
+    ;
+
+prefixedName
+    : PNAME_LN
+    | PNAME_NS
+    ;
+
+
+// $>
+
+// $<Lexer
+
+WS
+    : (' '| '\t'| EOL)+ { $channel=HIDDEN; }
+    ;
+
+AT_IMPORT 
+	:	'@import'
+	;
+	
+AT_PREFIX 
+	:	'@prefix'
+	;
+	
+AT_BASE :	'@base'
+	;
+	
+AT_DELAY 
+	:	'@delay'
+	;
+
+protected    
+INHERITANCE 
+	:	'-->';
+
+protected	
+SIMILARITY
+	:	'<->';
+	
+protected
+INSTANCE 
+	:	'}->'
+	;
+	
+protected
+PROPERTY
+	:	'--['
+	;
+	
+protected
+INSTANCE_PROPERTY 
+	:	'}-['
+	;
+	
+protected
+IMPLICATION 
+	:	'==>'
+	;
+	
+protected
+IMPLICATION_PRED 
+	:	'=/>'
+	;
+	
+protected
+IMPLICATION_RETRO 
+	:	'=\\>'
+	;
+	
+protected
+IMPLICATION_CONC
+	:	'=|>'
+	;
+	
+protected
+EQUIVALENCE 
+	:	'<=>'
+	;
+	
+protected
+EQUIVALENCE_PRED 
+	:	'</>'
+	;
+	
+protected
+EQUIVALENCE_CONC 
+	:	'<|>'
+	;
+	
+NOT	:	'!!'
+	;
+	
+PAST	:	'\\>'
+	;
+	
+PRESENT	:	'|>'
+	;
+	
+FUTURE 	:	'/>'
+	;
+	
+CONJ	:	'&&'
+	;
+
+DISJ	:	'||'
+	;
+
+OPEN_BRACE
+	:	'{'
+	;
+
+CLOSE_BRACE
+	:	'}'
+	;
+	
+LPAREN	:	'('
+	;
+	
+RPAREN	:	')'
+	;
+	
+LBRACKET 
+	:	'['
+	;
+
+RBRACKET 
+	:	']'
+	;
+	
+
+
+PNAME_NS
+    : p=PN_PREFIX? ':'
+    ;
+
+PNAME_LN
+    : PNAME_NS PN_LOCAL
+    ;
+
+TRUE
+    : ('T'|'t')('R'|'r')('U'|'u')('E'|'e')
+    ;
+
+FALSE
+    : ('F'|'f')('A'|'a')('L'|'l')('S'|'s')('E'|'e')
+    ;
+
+IRI_REF
+    : LANGLE ( options {greedy=false;} : ~(LANGLE | RANGLE | '"' | OPEN_BRACE | CLOSE_BRACE | '|' | '^' | '\\' | '`' | ('\u0000'..'\u0020')) )* RANGLE { setText($text.substring(1, $text.length() - 1)); }
+    ;
+
+LANGTAG
+    : '@' PN_CHARS_BASE+ (MINUS (PN_CHARS_BASE DIGIT)+)*
+    ;
+    
+QUERY_VAR 
+	:	'?' PN_LOCAL
+	;
+	
+STM_VAR :	'#' PN_LOCAL ('(' (PN_LOCAL (',' PN_LOCAL)*)? ')')?
+	;
+
+INTEGER
+    : DIGIT+
+    ;
+
+DECIMAL
+    : DIGIT+ DOT DIGIT*
+    | DOT DIGIT+
+    ;
+
+DOUBLE
+    : DIGIT+ DOT DIGIT* EXPONENT
+    | DOT DIGIT+ EXPONENT
+    | DIGIT+ EXPONENT
+    ;
+
+INTEGER_POSITIVE
+    : PLUS INTEGER
+    ;
+
+DECIMAL_POSITIVE
+    : PLUS DECIMAL
+    ;
+
+DOUBLE_POSITIVE
+    : PLUS DOUBLE
+    ;
+
+INTEGER_NEGATIVE
+    : MINUS INTEGER
+    ;
+
+DECIMAL_NEGATIVE
+    : MINUS DECIMAL
+    ;
+
+DOUBLE_NEGATIVE
+    : MINUS DOUBLE
+    ;
+
+fragment
+EXPONENT
+    : ('e'|'E') (PLUS|MINUS)? DIGIT+
+    ;
+
+STRING_LITERAL1
+    : '\'' ( options {greedy=false;} : ~('\u0027' | '\u005C' | '\u000A' | '\u000D') | ECHAR )* '\''
+    ;
+
+STRING_LITERAL2
+    : '"'  ( options {greedy=false;} : ~('\u0022' | '\u005C' | '\u000A' | '\u000D') | ECHAR )* '"'
+    ;
+
+STRING_LITERAL_LONG1
+    :   '\'\'\'' ( options {greedy=false;} : ( '\'' | '\'\'' )? ( ~('\''|'\\') | ECHAR ) )* '\'\'\''
+    ;
+
+STRING_LITERAL_LONG2
+    :   '"""' ( options {greedy=false;} : ( '"' | '""' )? ( ~('"'|'\\') | ECHAR ) )* '"""'
+    ;
+
+fragment
+ECHAR
+    : '\\' ('t' | 'b' | 'n' | 'r' | 'f' | '\\' | '"' | '\'')
+    ;
+
+fragment
+PN_CHARS_U
+    : PN_CHARS_BASE | '_'
+    ;
+
+fragment
+VARNAME
+    : ( PN_CHARS_U | DIGIT ) ( PN_CHARS_U | DIGIT | '\u00B7' | '\u0300'..'\u036F' | '\u203F'..'\u2040' )*
+    ;
+
+fragment
+PN_CHARS
+    : PN_CHARS_U
+    | MINUS
+    | DIGIT
+    | '\u00B7' 
+    | '\u0300'..'\u036F'
+    | '\u203F'..'\u2040'
+    ;
+
+fragment
+PN_PREFIX
+    : PN_CHARS_BASE ((PN_CHARS|DOT)* PN_CHARS)?
+    ;
+
+fragment
+PN_LOCAL
+    : ( PN_CHARS_U | DIGIT ) ((PN_CHARS)* PN_CHARS)?
+    ;
+
+fragment
+PN_CHARS_BASE
+    : 'A'..'Z'
+    | 'a'..'z'
+    | '\u00C0'..'\u00D6'
+    | '\u00D8'..'\u00F6'
+    | '\u00F8'..'\u02FF'
+    | '\u0370'..'\u037D'
+    | '\u037F'..'\u1FFF'
+    | '\u200C'..'\u200D'
+    | '\u2070'..'\u218F'
+    | '\u2C00'..'\u2FEF'
+    | '\u3001'..'\uD7FF'
+    | '\uF900'..'\uFDCF'
+    | '\uFDF0'..'\uFFFD'
+    ;
+
+fragment
+DIGIT
+    : '0'..'9'
+    ;
+
+COMMENT 
+    : '//' ( options{greedy=false;} : .)* EOL { $channel=HIDDEN; }
+    ;
+
+fragment
+EOL
+    : '\n' | '\r'
+    ;
+
+REFERENCE
+    : '^^';
+ 
+EXCLAMATION
+	:	'!';
+	
+QUESTION 
+	:	'?';
+ 
+DOT	:	'.'
+	;
+	
+COMMA	:	','
+	;
+	
+//COLON	:	':'
+//	;
+	
+SEMICOLON
+	:	';'
+	;
+	
+AMPERSAND
+	:	'&';
+	
+BAR	:	'|'
+	;
+	
+LANGLE	:	'<'
+	;
+	
+RANGLE 	:	'>'
+	;
+	
+PERCENT	:	'%'
+	;
+	
+PLUS	:	'+'
+	;
+	
+MINUS	:	'-'
+	;
+	
+STAR	:	'*'
+	;
+	
+TILDE 	:	'~'
+	;
diff --git a/open-nars/com/googlecode/opennars/parser/loan/loan.tokens b/open-nars/com/googlecode/opennars/parser/loan/loan.tokens
new file mode 100644
index 0000000000000000000000000000000000000000..61763b197e8c714eb0a221aa3e9eb5ce02434fee
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/parser/loan/loan.tokens
@@ -0,0 +1,76 @@
+COMMA=20
+PN_CHARS_U=75
+MINUS=44
+PERCENT=16
+AT_PREFIX=8
+OPEN_BRACE=40
+DOUBLE=49
+AT_BASE=4
+EQUIVALENCE=35
+FALSE=57
+PN_CHARS_BASE=69
+EQUIVALENCE_CONC=37
+QUERY_VAR=47
+AT_DELAY=10
+LBRACKET=42
+INHERITANCE=26
+INSTANCE=28
+TILDE=45
+DECIMAL=17
+QUESTION=15
+CONJ=19
+DISJ=21
+IMPLICATION=31
+DOT=6
+STM_VAR=48
+RANGLE=68
+INTEGER=12
+IMPLICATION_RETRO=33
+FUTURE=25
+RBRACKET=43
+RPAREN=13
+PN_PREFIX=65
+EQUIVALENCE_PRED=36
+LANGLE=67
+LPAREN=11
+INSTANCE_PROPERTY=30
+ECHAR=74
+PLUS=73
+DIGIT=70
+AMPERSAND=38
+INTEGER_NEGATIVE=53
+PNAME_NS=9
+PAST=23
+SIMILARITY=27
+PROPERTY=29
+DECIMAL_POSITIVE=51
+STRING_LITERAL_LONG1=60
+IMPLICATION_PRED=32
+WS=64
+PNAME_LN=62
+LANGTAG=71
+EXCLAMATION=14
+PN_LOCAL=66
+VARNAME=76
+CLOSE_BRACE=41
+COMMENT=78
+PN_CHARS=77
+PRESENT=24
+AT_IMPORT=7
+STRING_LITERAL_LONG2=61
+DOUBLE_NEGATIVE=55
+EXPONENT=72
+SEMICOLON=18
+BAR=39
+DECIMAL_NEGATIVE=54
+IRI_REF=5
+DOUBLE_POSITIVE=52
+REFERENCE=79
+EOL=63
+INTEGER_POSITIVE=50
+STAR=46
+NOT=22
+STRING_LITERAL2=59
+TRUE=56
+STRING_LITERAL1=58
+IMPLICATION_CONC=34
diff --git a/open-nars/com/googlecode/opennars/parser/loan/loanLexer.java b/open-nars/com/googlecode/opennars/parser/loan/loanLexer.java
new file mode 100644
index 0000000000000000000000000000000000000000..865e1e24877e240d7626b4e53881b04889d17cdf
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/parser/loan/loanLexer.java
@@ -0,0 +1,3574 @@
+package com.googlecode.opennars.parser.loan;
+
+import org.antlr.runtime.*;
+import java.util.Stack;
+import java.util.List;
+import java.util.ArrayList;
+
+public class loanLexer extends Lexer {
+    public static final int COMMA=20;
+    public static final int PN_CHARS_U=75;
+    public static final int MINUS=44;
+    public static final int AT_PREFIX=8;
+    public static final int PERCENT=16;
+    public static final int OPEN_BRACE=40;
+    public static final int DOUBLE=49;
+    public static final int EQUIVALENCE=35;
+    public static final int AT_BASE=4;
+    public static final int FALSE=57;
+    public static final int EQUIVALENCE_CONC=37;
+    public static final int PN_CHARS_BASE=69;
+    public static final int QUERY_VAR=47;
+    public static final int AT_DELAY=10;
+    public static final int LBRACKET=42;
+    public static final int INHERITANCE=26;
+    public static final int INSTANCE=28;
+    public static final int TILDE=45;
+    public static final int DECIMAL=17;
+    public static final int QUESTION=15;
+    public static final int CONJ=19;
+    public static final int DISJ=21;
+    public static final int IMPLICATION=31;
+    public static final int DOT=6;
+    public static final int STM_VAR=48;
+    public static final int RANGLE=68;
+    public static final int INTEGER=12;
+    public static final int IMPLICATION_RETRO=33;
+    public static final int FUTURE=25;
+    public static final int RBRACKET=43;
+    public static final int RPAREN=13;
+    public static final int PN_PREFIX=65;
+    public static final int EQUIVALENCE_PRED=36;
+    public static final int LANGLE=67;
+    public static final int LPAREN=11;
+    public static final int INSTANCE_PROPERTY=30;
+    public static final int ECHAR=74;
+    public static final int PLUS=73;
+    public static final int DIGIT=70;
+    public static final int AMPERSAND=38;
+    public static final int PAST=23;
+    public static final int PNAME_NS=9;
+    public static final int INTEGER_NEGATIVE=53;
+    public static final int SIMILARITY=27;
+    public static final int PROPERTY=29;
+    public static final int DECIMAL_POSITIVE=51;
+    public static final int STRING_LITERAL_LONG1=60;
+    public static final int IMPLICATION_PRED=32;
+    public static final int WS=64;
+    public static final int PNAME_LN=62;
+    public static final int EXCLAMATION=14;
+    public static final int LANGTAG=71;
+    public static final int PN_LOCAL=66;
+    public static final int CLOSE_BRACE=41;
+    public static final int VARNAME=76;
+    public static final int COMMENT=78;
+    public static final int PN_CHARS=77;
+    public static final int PRESENT=24;
+    public static final int AT_IMPORT=7;
+    public static final int DOUBLE_NEGATIVE=55;
+    public static final int STRING_LITERAL_LONG2=61;
+    public static final int SEMICOLON=18;
+    public static final int EXPONENT=72;
+    public static final int BAR=39;
+    public static final int DECIMAL_NEGATIVE=54;
+    public static final int IRI_REF=5;
+    public static final int EOF=-1;
+    public static final int DOUBLE_POSITIVE=52;
+    public static final int EOL=63;
+    public static final int REFERENCE=79;
+    public static final int Tokens=80;
+    public static final int INTEGER_POSITIVE=50;
+    public static final int STAR=46;
+    public static final int NOT=22;
+    public static final int TRUE=56;
+    public static final int STRING_LITERAL2=59;
+    public static final int STRING_LITERAL1=58;
+    public static final int IMPLICATION_CONC=34;
+    public loanLexer() {;} 
+    public loanLexer(CharStream input) {
+        super(input);
+    }
+    public String getGrammarFileName() { return "/Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g"; }
+
+    // $ANTLR start WS
+    public final void mWS() throws RecognitionException {
+        try {
+            int _type = WS;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:152:5: ( ( ' ' | '\\t' | EOL )+ )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:152:7: ( ' ' | '\\t' | EOL )+
+            {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:152:7: ( ' ' | '\\t' | EOL )+
+            int cnt1=0;
+            loop1:
+            do {
+                int alt1=2;
+                int LA1_0 = input.LA(1);
+
+                if ( ((LA1_0>='\t' && LA1_0<='\n')||LA1_0=='\r'||LA1_0==' ') ) {
+                    alt1=1;
+                }
+
+
+                switch (alt1) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+            	    {
+            	    if ( (input.LA(1)>='\t' && input.LA(1)<='\n')||input.LA(1)=='\r'||input.LA(1)==' ' ) {
+            	        input.consume();
+
+            	    }
+            	    else {
+            	        MismatchedSetException mse =
+            	            new MismatchedSetException(null,input);
+            	        recover(mse);    throw mse;
+            	    }
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    if ( cnt1 >= 1 ) break loop1;
+                        EarlyExitException eee =
+                            new EarlyExitException(1, input);
+                        throw eee;
+                }
+                cnt1++;
+            } while (true);
+
+             channel=HIDDEN; 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end WS
+
+    // $ANTLR start AT_IMPORT
+    public final void mAT_IMPORT() throws RecognitionException {
+        try {
+            int _type = AT_IMPORT;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:156:2: ( '@import' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:156:4: '@import'
+            {
+            match("@import"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end AT_IMPORT
+
+    // $ANTLR start AT_PREFIX
+    public final void mAT_PREFIX() throws RecognitionException {
+        try {
+            int _type = AT_PREFIX;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:160:2: ( '@prefix' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:160:4: '@prefix'
+            {
+            match("@prefix"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end AT_PREFIX
+
+    // $ANTLR start AT_BASE
+    public final void mAT_BASE() throws RecognitionException {
+        try {
+            int _type = AT_BASE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:163:9: ( '@base' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:163:11: '@base'
+            {
+            match("@base"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end AT_BASE
+
+    // $ANTLR start AT_DELAY
+    public final void mAT_DELAY() throws RecognitionException {
+        try {
+            int _type = AT_DELAY;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:167:2: ( '@delay' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:167:4: '@delay'
+            {
+            match("@delay"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end AT_DELAY
+
+    // $ANTLR start INHERITANCE
+    public final void mINHERITANCE() throws RecognitionException {
+        try {
+            int _type = INHERITANCE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:172:2: ( '-->' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:172:4: '-->'
+            {
+            match("-->"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end INHERITANCE
+
+    // $ANTLR start SIMILARITY
+    public final void mSIMILARITY() throws RecognitionException {
+        try {
+            int _type = SIMILARITY;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:176:2: ( '<->' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:176:4: '<->'
+            {
+            match("<->"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end SIMILARITY
+
+    // $ANTLR start INSTANCE
+    public final void mINSTANCE() throws RecognitionException {
+        try {
+            int _type = INSTANCE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:180:2: ( '}->' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:180:4: '}->'
+            {
+            match("}->"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end INSTANCE
+
+    // $ANTLR start PROPERTY
+    public final void mPROPERTY() throws RecognitionException {
+        try {
+            int _type = PROPERTY;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:185:2: ( '--[' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:185:4: '--['
+            {
+            match("--["); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end PROPERTY
+
+    // $ANTLR start INSTANCE_PROPERTY
+    public final void mINSTANCE_PROPERTY() throws RecognitionException {
+        try {
+            int _type = INSTANCE_PROPERTY;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:190:2: ( '}-[' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:190:4: '}-['
+            {
+            match("}-["); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end INSTANCE_PROPERTY
+
+    // $ANTLR start IMPLICATION
+    public final void mIMPLICATION() throws RecognitionException {
+        try {
+            int _type = IMPLICATION;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:195:2: ( '==>' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:195:4: '==>'
+            {
+            match("==>"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end IMPLICATION
+
+    // $ANTLR start IMPLICATION_PRED
+    public final void mIMPLICATION_PRED() throws RecognitionException {
+        try {
+            int _type = IMPLICATION_PRED;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:200:2: ( '=/>' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:200:4: '=/>'
+            {
+            match("=/>"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end IMPLICATION_PRED
+
+    // $ANTLR start IMPLICATION_RETRO
+    public final void mIMPLICATION_RETRO() throws RecognitionException {
+        try {
+            int _type = IMPLICATION_RETRO;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:205:2: ( '=\\\\>' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:205:4: '=\\\\>'
+            {
+            match("=\\>"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end IMPLICATION_RETRO
+
+    // $ANTLR start IMPLICATION_CONC
+    public final void mIMPLICATION_CONC() throws RecognitionException {
+        try {
+            int _type = IMPLICATION_CONC;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:210:2: ( '=|>' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:210:4: '=|>'
+            {
+            match("=|>"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end IMPLICATION_CONC
+
+    // $ANTLR start EQUIVALENCE
+    public final void mEQUIVALENCE() throws RecognitionException {
+        try {
+            int _type = EQUIVALENCE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:215:2: ( '<=>' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:215:4: '<=>'
+            {
+            match("<=>"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end EQUIVALENCE
+
+    // $ANTLR start EQUIVALENCE_PRED
+    public final void mEQUIVALENCE_PRED() throws RecognitionException {
+        try {
+            int _type = EQUIVALENCE_PRED;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:220:2: ( '</>' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:220:4: '</>'
+            {
+            match("</>"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end EQUIVALENCE_PRED
+
+    // $ANTLR start EQUIVALENCE_CONC
+    public final void mEQUIVALENCE_CONC() throws RecognitionException {
+        try {
+            int _type = EQUIVALENCE_CONC;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:225:2: ( '<|>' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:225:4: '<|>'
+            {
+            match("<|>"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end EQUIVALENCE_CONC
+
+    // $ANTLR start NOT
+    public final void mNOT() throws RecognitionException {
+        try {
+            int _type = NOT;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:228:5: ( '!!' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:228:7: '!!'
+            {
+            match("!!"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end NOT
+
+    // $ANTLR start PAST
+    public final void mPAST() throws RecognitionException {
+        try {
+            int _type = PAST;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:231:6: ( '\\\\>' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:231:8: '\\\\>'
+            {
+            match("\\>"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end PAST
+
+    // $ANTLR start PRESENT
+    public final void mPRESENT() throws RecognitionException {
+        try {
+            int _type = PRESENT;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:234:9: ( '|>' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:234:11: '|>'
+            {
+            match("|>"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end PRESENT
+
+    // $ANTLR start FUTURE
+    public final void mFUTURE() throws RecognitionException {
+        try {
+            int _type = FUTURE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:237:9: ( '/>' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:237:11: '/>'
+            {
+            match("/>"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end FUTURE
+
+    // $ANTLR start CONJ
+    public final void mCONJ() throws RecognitionException {
+        try {
+            int _type = CONJ;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:240:6: ( '&&' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:240:8: '&&'
+            {
+            match("&&"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end CONJ
+
+    // $ANTLR start DISJ
+    public final void mDISJ() throws RecognitionException {
+        try {
+            int _type = DISJ;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:243:6: ( '||' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:243:8: '||'
+            {
+            match("||"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end DISJ
+
+    // $ANTLR start OPEN_BRACE
+    public final void mOPEN_BRACE() throws RecognitionException {
+        try {
+            int _type = OPEN_BRACE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:247:2: ( '{' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:247:4: '{'
+            {
+            match('{'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end OPEN_BRACE
+
+    // $ANTLR start CLOSE_BRACE
+    public final void mCLOSE_BRACE() throws RecognitionException {
+        try {
+            int _type = CLOSE_BRACE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:251:2: ( '}' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:251:4: '}'
+            {
+            match('}'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end CLOSE_BRACE
+
+    // $ANTLR start LPAREN
+    public final void mLPAREN() throws RecognitionException {
+        try {
+            int _type = LPAREN;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:254:8: ( '(' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:254:10: '('
+            {
+            match('('); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end LPAREN
+
+    // $ANTLR start RPAREN
+    public final void mRPAREN() throws RecognitionException {
+        try {
+            int _type = RPAREN;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:257:8: ( ')' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:257:10: ')'
+            {
+            match(')'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end RPAREN
+
+    // $ANTLR start LBRACKET
+    public final void mLBRACKET() throws RecognitionException {
+        try {
+            int _type = LBRACKET;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:261:2: ( '[' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:261:4: '['
+            {
+            match('['); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end LBRACKET
+
+    // $ANTLR start RBRACKET
+    public final void mRBRACKET() throws RecognitionException {
+        try {
+            int _type = RBRACKET;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:265:2: ( ']' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:265:4: ']'
+            {
+            match(']'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end RBRACKET
+
+    // $ANTLR start PNAME_NS
+    public final void mPNAME_NS() throws RecognitionException {
+        try {
+            int _type = PNAME_NS;
+            Token p=null;
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:271:5: ( (p= PN_PREFIX )? ':' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:271:7: (p= PN_PREFIX )? ':'
+            {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:271:8: (p= PN_PREFIX )?
+            int alt2=2;
+            int LA2_0 = input.LA(1);
+
+            if ( ((LA2_0>='A' && LA2_0<='Z')||(LA2_0>='a' && LA2_0<='z')||(LA2_0>='\u00C0' && LA2_0<='\u00D6')||(LA2_0>='\u00D8' && LA2_0<='\u00F6')||(LA2_0>='\u00F8' && LA2_0<='\u02FF')||(LA2_0>='\u0370' && LA2_0<='\u037D')||(LA2_0>='\u037F' && LA2_0<='\u1FFF')||(LA2_0>='\u200C' && LA2_0<='\u200D')||(LA2_0>='\u2070' && LA2_0<='\u218F')||(LA2_0>='\u2C00' && LA2_0<='\u2FEF')||(LA2_0>='\u3001' && LA2_0<='\uD7FF')||(LA2_0>='\uF900' && LA2_0<='\uFDCF')||(LA2_0>='\uFDF0' && LA2_0<='\uFFFD')) ) {
+                alt2=1;
+            }
+            switch (alt2) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:271:8: p= PN_PREFIX
+                    {
+                    int pStart439 = getCharIndex();
+                    mPN_PREFIX(); 
+                    p = new CommonToken(input, Token.INVALID_TOKEN_TYPE, Token.DEFAULT_CHANNEL, pStart439, getCharIndex()-1);
+
+                    }
+                    break;
+
+            }
+
+            match(':'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end PNAME_NS
+
+    // $ANTLR start PNAME_LN
+    public final void mPNAME_LN() throws RecognitionException {
+        try {
+            int _type = PNAME_LN;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:275:5: ( PNAME_NS PN_LOCAL )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:275:7: PNAME_NS PN_LOCAL
+            {
+            mPNAME_NS(); 
+            mPN_LOCAL(); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end PNAME_LN
+
+    // $ANTLR start TRUE
+    public final void mTRUE() throws RecognitionException {
+        try {
+            int _type = TRUE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:279:5: ( ( 'T' | 't' ) ( 'R' | 'r' ) ( 'U' | 'u' ) ( 'E' | 'e' ) )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:279:7: ( 'T' | 't' ) ( 'R' | 'r' ) ( 'U' | 'u' ) ( 'E' | 'e' )
+            {
+            if ( input.LA(1)=='T'||input.LA(1)=='t' ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+            if ( input.LA(1)=='R'||input.LA(1)=='r' ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+            if ( input.LA(1)=='U'||input.LA(1)=='u' ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+            if ( input.LA(1)=='E'||input.LA(1)=='e' ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end TRUE
+
+    // $ANTLR start FALSE
+    public final void mFALSE() throws RecognitionException {
+        try {
+            int _type = FALSE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:283:5: ( ( 'F' | 'f' ) ( 'A' | 'a' ) ( 'L' | 'l' ) ( 'S' | 's' ) ( 'E' | 'e' ) )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:283:7: ( 'F' | 'f' ) ( 'A' | 'a' ) ( 'L' | 'l' ) ( 'S' | 's' ) ( 'E' | 'e' )
+            {
+            if ( input.LA(1)=='F'||input.LA(1)=='f' ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+            if ( input.LA(1)=='A'||input.LA(1)=='a' ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+            if ( input.LA(1)=='L'||input.LA(1)=='l' ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+            if ( input.LA(1)=='S'||input.LA(1)=='s' ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+            if ( input.LA(1)=='E'||input.LA(1)=='e' ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end FALSE
+
+    // $ANTLR start IRI_REF
+    public final void mIRI_REF() throws RecognitionException {
+        try {
+            int _type = IRI_REF;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:287:5: ( LANGLE ( options {greedy=false; } : ~ ( LANGLE | RANGLE | '\"' | OPEN_BRACE | CLOSE_BRACE | '|' | '^' | '\\\\' | '`' | ( '\\u0000' .. '\\u0020' ) ) )* RANGLE )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:287:7: LANGLE ( options {greedy=false; } : ~ ( LANGLE | RANGLE | '\"' | OPEN_BRACE | CLOSE_BRACE | '|' | '^' | '\\\\' | '`' | ( '\\u0000' .. '\\u0020' ) ) )* RANGLE
+            {
+            mLANGLE(); 
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:287:14: ( options {greedy=false; } : ~ ( LANGLE | RANGLE | '\"' | OPEN_BRACE | CLOSE_BRACE | '|' | '^' | '\\\\' | '`' | ( '\\u0000' .. '\\u0020' ) ) )*
+            loop3:
+            do {
+                int alt3=2;
+                int LA3_0 = input.LA(1);
+
+                if ( (LA3_0=='>') ) {
+                    alt3=2;
+                }
+                else if ( (LA3_0=='!'||(LA3_0>='#' && LA3_0<=';')||LA3_0=='='||(LA3_0>='?' && LA3_0<='[')||LA3_0==']'||LA3_0=='_'||(LA3_0>='a' && LA3_0<='z')||(LA3_0>='~' && LA3_0<='\uFFFE')) ) {
+                    alt3=1;
+                }
+
+
+                switch (alt3) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:287:42: ~ ( LANGLE | RANGLE | '\"' | OPEN_BRACE | CLOSE_BRACE | '|' | '^' | '\\\\' | '`' | ( '\\u0000' .. '\\u0020' ) )
+            	    {
+            	    if ( input.LA(1)=='!'||(input.LA(1)>='#' && input.LA(1)<=';')||input.LA(1)=='='||(input.LA(1)>='?' && input.LA(1)<='[')||input.LA(1)==']'||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z')||(input.LA(1)>='~' && input.LA(1)<='\uFFFE') ) {
+            	        input.consume();
+
+            	    }
+            	    else {
+            	        MismatchedSetException mse =
+            	            new MismatchedSetException(null,input);
+            	        recover(mse);    throw mse;
+            	    }
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop3;
+                }
+            } while (true);
+
+            mRANGLE(); 
+             setText(getText().substring(1, getText().length() - 1)); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end IRI_REF
+
+    // $ANTLR start LANGTAG
+    public final void mLANGTAG() throws RecognitionException {
+        try {
+            int _type = LANGTAG;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:291:5: ( '@' ( PN_CHARS_BASE )+ ( MINUS ( PN_CHARS_BASE DIGIT )+ )* )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:291:7: '@' ( PN_CHARS_BASE )+ ( MINUS ( PN_CHARS_BASE DIGIT )+ )*
+            {
+            match('@'); 
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:291:11: ( PN_CHARS_BASE )+
+            int cnt4=0;
+            loop4:
+            do {
+                int alt4=2;
+                int LA4_0 = input.LA(1);
+
+                if ( ((LA4_0>='A' && LA4_0<='Z')||(LA4_0>='a' && LA4_0<='z')||(LA4_0>='\u00C0' && LA4_0<='\u00D6')||(LA4_0>='\u00D8' && LA4_0<='\u00F6')||(LA4_0>='\u00F8' && LA4_0<='\u02FF')||(LA4_0>='\u0370' && LA4_0<='\u037D')||(LA4_0>='\u037F' && LA4_0<='\u1FFF')||(LA4_0>='\u200C' && LA4_0<='\u200D')||(LA4_0>='\u2070' && LA4_0<='\u218F')||(LA4_0>='\u2C00' && LA4_0<='\u2FEF')||(LA4_0>='\u3001' && LA4_0<='\uD7FF')||(LA4_0>='\uF900' && LA4_0<='\uFDCF')||(LA4_0>='\uFDF0' && LA4_0<='\uFFFD')) ) {
+                    alt4=1;
+                }
+
+
+                switch (alt4) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:291:11: PN_CHARS_BASE
+            	    {
+            	    mPN_CHARS_BASE(); 
+
+            	    }
+            	    break;
+
+            	default :
+            	    if ( cnt4 >= 1 ) break loop4;
+                        EarlyExitException eee =
+                            new EarlyExitException(4, input);
+                        throw eee;
+                }
+                cnt4++;
+            } while (true);
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:291:26: ( MINUS ( PN_CHARS_BASE DIGIT )+ )*
+            loop6:
+            do {
+                int alt6=2;
+                int LA6_0 = input.LA(1);
+
+                if ( (LA6_0=='-') ) {
+                    alt6=1;
+                }
+
+
+                switch (alt6) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:291:27: MINUS ( PN_CHARS_BASE DIGIT )+
+            	    {
+            	    mMINUS(); 
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:291:33: ( PN_CHARS_BASE DIGIT )+
+            	    int cnt5=0;
+            	    loop5:
+            	    do {
+            	        int alt5=2;
+            	        int LA5_0 = input.LA(1);
+
+            	        if ( ((LA5_0>='A' && LA5_0<='Z')||(LA5_0>='a' && LA5_0<='z')||(LA5_0>='\u00C0' && LA5_0<='\u00D6')||(LA5_0>='\u00D8' && LA5_0<='\u00F6')||(LA5_0>='\u00F8' && LA5_0<='\u02FF')||(LA5_0>='\u0370' && LA5_0<='\u037D')||(LA5_0>='\u037F' && LA5_0<='\u1FFF')||(LA5_0>='\u200C' && LA5_0<='\u200D')||(LA5_0>='\u2070' && LA5_0<='\u218F')||(LA5_0>='\u2C00' && LA5_0<='\u2FEF')||(LA5_0>='\u3001' && LA5_0<='\uD7FF')||(LA5_0>='\uF900' && LA5_0<='\uFDCF')||(LA5_0>='\uFDF0' && LA5_0<='\uFFFD')) ) {
+            	            alt5=1;
+            	        }
+
+
+            	        switch (alt5) {
+            	    	case 1 :
+            	    	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:291:34: PN_CHARS_BASE DIGIT
+            	    	    {
+            	    	    mPN_CHARS_BASE(); 
+            	    	    mDIGIT(); 
+
+            	    	    }
+            	    	    break;
+
+            	    	default :
+            	    	    if ( cnt5 >= 1 ) break loop5;
+            	                EarlyExitException eee =
+            	                    new EarlyExitException(5, input);
+            	                throw eee;
+            	        }
+            	        cnt5++;
+            	    } while (true);
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop6;
+                }
+            } while (true);
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end LANGTAG
+
+    // $ANTLR start QUERY_VAR
+    public final void mQUERY_VAR() throws RecognitionException {
+        try {
+            int _type = QUERY_VAR;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:295:2: ( '?' PN_LOCAL )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:295:4: '?' PN_LOCAL
+            {
+            match('?'); 
+            mPN_LOCAL(); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end QUERY_VAR
+
+    // $ANTLR start STM_VAR
+    public final void mSTM_VAR() throws RecognitionException {
+        try {
+            int _type = STM_VAR;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:298:9: ( '#' PN_LOCAL ( '(' ( PN_LOCAL ( ',' PN_LOCAL )* )? ')' )? )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:298:11: '#' PN_LOCAL ( '(' ( PN_LOCAL ( ',' PN_LOCAL )* )? ')' )?
+            {
+            match('#'); 
+            mPN_LOCAL(); 
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:298:24: ( '(' ( PN_LOCAL ( ',' PN_LOCAL )* )? ')' )?
+            int alt9=2;
+            int LA9_0 = input.LA(1);
+
+            if ( (LA9_0=='(') ) {
+                alt9=1;
+            }
+            switch (alt9) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:298:25: '(' ( PN_LOCAL ( ',' PN_LOCAL )* )? ')'
+                    {
+                    match('('); 
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:298:29: ( PN_LOCAL ( ',' PN_LOCAL )* )?
+                    int alt8=2;
+                    int LA8_0 = input.LA(1);
+
+                    if ( ((LA8_0>='0' && LA8_0<='9')||(LA8_0>='A' && LA8_0<='Z')||LA8_0=='_'||(LA8_0>='a' && LA8_0<='z')||(LA8_0>='\u00C0' && LA8_0<='\u00D6')||(LA8_0>='\u00D8' && LA8_0<='\u00F6')||(LA8_0>='\u00F8' && LA8_0<='\u02FF')||(LA8_0>='\u0370' && LA8_0<='\u037D')||(LA8_0>='\u037F' && LA8_0<='\u1FFF')||(LA8_0>='\u200C' && LA8_0<='\u200D')||(LA8_0>='\u2070' && LA8_0<='\u218F')||(LA8_0>='\u2C00' && LA8_0<='\u2FEF')||(LA8_0>='\u3001' && LA8_0<='\uD7FF')||(LA8_0>='\uF900' && LA8_0<='\uFDCF')||(LA8_0>='\uFDF0' && LA8_0<='\uFFFD')) ) {
+                        alt8=1;
+                    }
+                    switch (alt8) {
+                        case 1 :
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:298:30: PN_LOCAL ( ',' PN_LOCAL )*
+                            {
+                            mPN_LOCAL(); 
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:298:39: ( ',' PN_LOCAL )*
+                            loop7:
+                            do {
+                                int alt7=2;
+                                int LA7_0 = input.LA(1);
+
+                                if ( (LA7_0==',') ) {
+                                    alt7=1;
+                                }
+
+
+                                switch (alt7) {
+                            	case 1 :
+                            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:298:40: ',' PN_LOCAL
+                            	    {
+                            	    match(','); 
+                            	    mPN_LOCAL(); 
+
+                            	    }
+                            	    break;
+
+                            	default :
+                            	    break loop7;
+                                }
+                            } while (true);
+
+
+                            }
+                            break;
+
+                    }
+
+                    match(')'); 
+
+                    }
+                    break;
+
+            }
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end STM_VAR
+
+    // $ANTLR start INTEGER
+    public final void mINTEGER() throws RecognitionException {
+        try {
+            int _type = INTEGER;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:302:5: ( ( DIGIT )+ )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:302:7: ( DIGIT )+
+            {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:302:7: ( DIGIT )+
+            int cnt10=0;
+            loop10:
+            do {
+                int alt10=2;
+                int LA10_0 = input.LA(1);
+
+                if ( ((LA10_0>='0' && LA10_0<='9')) ) {
+                    alt10=1;
+                }
+
+
+                switch (alt10) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:302:7: DIGIT
+            	    {
+            	    mDIGIT(); 
+
+            	    }
+            	    break;
+
+            	default :
+            	    if ( cnt10 >= 1 ) break loop10;
+                        EarlyExitException eee =
+                            new EarlyExitException(10, input);
+                        throw eee;
+                }
+                cnt10++;
+            } while (true);
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end INTEGER
+
+    // $ANTLR start DECIMAL
+    public final void mDECIMAL() throws RecognitionException {
+        try {
+            int _type = DECIMAL;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:306:5: ( ( DIGIT )+ DOT ( DIGIT )* | DOT ( DIGIT )+ )
+            int alt14=2;
+            int LA14_0 = input.LA(1);
+
+            if ( ((LA14_0>='0' && LA14_0<='9')) ) {
+                alt14=1;
+            }
+            else if ( (LA14_0=='.') ) {
+                alt14=2;
+            }
+            else {
+                NoViableAltException nvae =
+                    new NoViableAltException("305:1: DECIMAL : ( ( DIGIT )+ DOT ( DIGIT )* | DOT ( DIGIT )+ );", 14, 0, input);
+
+                throw nvae;
+            }
+            switch (alt14) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:306:7: ( DIGIT )+ DOT ( DIGIT )*
+                    {
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:306:7: ( DIGIT )+
+                    int cnt11=0;
+                    loop11:
+                    do {
+                        int alt11=2;
+                        int LA11_0 = input.LA(1);
+
+                        if ( ((LA11_0>='0' && LA11_0<='9')) ) {
+                            alt11=1;
+                        }
+
+
+                        switch (alt11) {
+                    	case 1 :
+                    	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:306:7: DIGIT
+                    	    {
+                    	    mDIGIT(); 
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    if ( cnt11 >= 1 ) break loop11;
+                                EarlyExitException eee =
+                                    new EarlyExitException(11, input);
+                                throw eee;
+                        }
+                        cnt11++;
+                    } while (true);
+
+                    mDOT(); 
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:306:18: ( DIGIT )*
+                    loop12:
+                    do {
+                        int alt12=2;
+                        int LA12_0 = input.LA(1);
+
+                        if ( ((LA12_0>='0' && LA12_0<='9')) ) {
+                            alt12=1;
+                        }
+
+
+                        switch (alt12) {
+                    	case 1 :
+                    	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:306:18: DIGIT
+                    	    {
+                    	    mDIGIT(); 
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    break loop12;
+                        }
+                    } while (true);
+
+
+                    }
+                    break;
+                case 2 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:307:7: DOT ( DIGIT )+
+                    {
+                    mDOT(); 
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:307:11: ( DIGIT )+
+                    int cnt13=0;
+                    loop13:
+                    do {
+                        int alt13=2;
+                        int LA13_0 = input.LA(1);
+
+                        if ( ((LA13_0>='0' && LA13_0<='9')) ) {
+                            alt13=1;
+                        }
+
+
+                        switch (alt13) {
+                    	case 1 :
+                    	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:307:11: DIGIT
+                    	    {
+                    	    mDIGIT(); 
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    if ( cnt13 >= 1 ) break loop13;
+                                EarlyExitException eee =
+                                    new EarlyExitException(13, input);
+                                throw eee;
+                        }
+                        cnt13++;
+                    } while (true);
+
+
+                    }
+                    break;
+
+            }
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end DECIMAL
+
+    // $ANTLR start DOUBLE
+    public final void mDOUBLE() throws RecognitionException {
+        try {
+            int _type = DOUBLE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:311:5: ( ( DIGIT )+ DOT ( DIGIT )* EXPONENT | DOT ( DIGIT )+ EXPONENT | ( DIGIT )+ EXPONENT )
+            int alt19=3;
+            alt19 = dfa19.predict(input);
+            switch (alt19) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:311:7: ( DIGIT )+ DOT ( DIGIT )* EXPONENT
+                    {
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:311:7: ( DIGIT )+
+                    int cnt15=0;
+                    loop15:
+                    do {
+                        int alt15=2;
+                        int LA15_0 = input.LA(1);
+
+                        if ( ((LA15_0>='0' && LA15_0<='9')) ) {
+                            alt15=1;
+                        }
+
+
+                        switch (alt15) {
+                    	case 1 :
+                    	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:311:7: DIGIT
+                    	    {
+                    	    mDIGIT(); 
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    if ( cnt15 >= 1 ) break loop15;
+                                EarlyExitException eee =
+                                    new EarlyExitException(15, input);
+                                throw eee;
+                        }
+                        cnt15++;
+                    } while (true);
+
+                    mDOT(); 
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:311:18: ( DIGIT )*
+                    loop16:
+                    do {
+                        int alt16=2;
+                        int LA16_0 = input.LA(1);
+
+                        if ( ((LA16_0>='0' && LA16_0<='9')) ) {
+                            alt16=1;
+                        }
+
+
+                        switch (alt16) {
+                    	case 1 :
+                    	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:311:18: DIGIT
+                    	    {
+                    	    mDIGIT(); 
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    break loop16;
+                        }
+                    } while (true);
+
+                    mEXPONENT(); 
+
+                    }
+                    break;
+                case 2 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:312:7: DOT ( DIGIT )+ EXPONENT
+                    {
+                    mDOT(); 
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:312:11: ( DIGIT )+
+                    int cnt17=0;
+                    loop17:
+                    do {
+                        int alt17=2;
+                        int LA17_0 = input.LA(1);
+
+                        if ( ((LA17_0>='0' && LA17_0<='9')) ) {
+                            alt17=1;
+                        }
+
+
+                        switch (alt17) {
+                    	case 1 :
+                    	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:312:11: DIGIT
+                    	    {
+                    	    mDIGIT(); 
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    if ( cnt17 >= 1 ) break loop17;
+                                EarlyExitException eee =
+                                    new EarlyExitException(17, input);
+                                throw eee;
+                        }
+                        cnt17++;
+                    } while (true);
+
+                    mEXPONENT(); 
+
+                    }
+                    break;
+                case 3 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:313:7: ( DIGIT )+ EXPONENT
+                    {
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:313:7: ( DIGIT )+
+                    int cnt18=0;
+                    loop18:
+                    do {
+                        int alt18=2;
+                        int LA18_0 = input.LA(1);
+
+                        if ( ((LA18_0>='0' && LA18_0<='9')) ) {
+                            alt18=1;
+                        }
+
+
+                        switch (alt18) {
+                    	case 1 :
+                    	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:313:7: DIGIT
+                    	    {
+                    	    mDIGIT(); 
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    if ( cnt18 >= 1 ) break loop18;
+                                EarlyExitException eee =
+                                    new EarlyExitException(18, input);
+                                throw eee;
+                        }
+                        cnt18++;
+                    } while (true);
+
+                    mEXPONENT(); 
+
+                    }
+                    break;
+
+            }
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end DOUBLE
+
+    // $ANTLR start INTEGER_POSITIVE
+    public final void mINTEGER_POSITIVE() throws RecognitionException {
+        try {
+            int _type = INTEGER_POSITIVE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:317:5: ( PLUS INTEGER )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:317:7: PLUS INTEGER
+            {
+            mPLUS(); 
+            mINTEGER(); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end INTEGER_POSITIVE
+
+    // $ANTLR start DECIMAL_POSITIVE
+    public final void mDECIMAL_POSITIVE() throws RecognitionException {
+        try {
+            int _type = DECIMAL_POSITIVE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:321:5: ( PLUS DECIMAL )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:321:7: PLUS DECIMAL
+            {
+            mPLUS(); 
+            mDECIMAL(); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end DECIMAL_POSITIVE
+
+    // $ANTLR start DOUBLE_POSITIVE
+    public final void mDOUBLE_POSITIVE() throws RecognitionException {
+        try {
+            int _type = DOUBLE_POSITIVE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:325:5: ( PLUS DOUBLE )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:325:7: PLUS DOUBLE
+            {
+            mPLUS(); 
+            mDOUBLE(); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end DOUBLE_POSITIVE
+
+    // $ANTLR start INTEGER_NEGATIVE
+    public final void mINTEGER_NEGATIVE() throws RecognitionException {
+        try {
+            int _type = INTEGER_NEGATIVE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:329:5: ( MINUS INTEGER )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:329:7: MINUS INTEGER
+            {
+            mMINUS(); 
+            mINTEGER(); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end INTEGER_NEGATIVE
+
+    // $ANTLR start DECIMAL_NEGATIVE
+    public final void mDECIMAL_NEGATIVE() throws RecognitionException {
+        try {
+            int _type = DECIMAL_NEGATIVE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:333:5: ( MINUS DECIMAL )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:333:7: MINUS DECIMAL
+            {
+            mMINUS(); 
+            mDECIMAL(); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end DECIMAL_NEGATIVE
+
+    // $ANTLR start DOUBLE_NEGATIVE
+    public final void mDOUBLE_NEGATIVE() throws RecognitionException {
+        try {
+            int _type = DOUBLE_NEGATIVE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:337:5: ( MINUS DOUBLE )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:337:7: MINUS DOUBLE
+            {
+            mMINUS(); 
+            mDOUBLE(); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end DOUBLE_NEGATIVE
+
+    // $ANTLR start EXPONENT
+    public final void mEXPONENT() throws RecognitionException {
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:342:5: ( ( 'e' | 'E' ) ( PLUS | MINUS )? ( DIGIT )+ )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:342:7: ( 'e' | 'E' ) ( PLUS | MINUS )? ( DIGIT )+
+            {
+            if ( input.LA(1)=='E'||input.LA(1)=='e' ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:342:17: ( PLUS | MINUS )?
+            int alt20=2;
+            int LA20_0 = input.LA(1);
+
+            if ( (LA20_0=='+'||LA20_0=='-') ) {
+                alt20=1;
+            }
+            switch (alt20) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+                    {
+                    if ( input.LA(1)=='+'||input.LA(1)=='-' ) {
+                        input.consume();
+
+                    }
+                    else {
+                        MismatchedSetException mse =
+                            new MismatchedSetException(null,input);
+                        recover(mse);    throw mse;
+                    }
+
+
+                    }
+                    break;
+
+            }
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:342:31: ( DIGIT )+
+            int cnt21=0;
+            loop21:
+            do {
+                int alt21=2;
+                int LA21_0 = input.LA(1);
+
+                if ( ((LA21_0>='0' && LA21_0<='9')) ) {
+                    alt21=1;
+                }
+
+
+                switch (alt21) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:342:31: DIGIT
+            	    {
+            	    mDIGIT(); 
+
+            	    }
+            	    break;
+
+            	default :
+            	    if ( cnt21 >= 1 ) break loop21;
+                        EarlyExitException eee =
+                            new EarlyExitException(21, input);
+                        throw eee;
+                }
+                cnt21++;
+            } while (true);
+
+
+            }
+
+        }
+        finally {
+        }
+    }
+    // $ANTLR end EXPONENT
+
+    // $ANTLR start STRING_LITERAL1
+    public final void mSTRING_LITERAL1() throws RecognitionException {
+        try {
+            int _type = STRING_LITERAL1;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:346:5: ( '\\'' ( options {greedy=false; } : ~ ( '\\u0027' | '\\u005C' | '\\u000A' | '\\u000D' ) | ECHAR )* '\\'' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:346:7: '\\'' ( options {greedy=false; } : ~ ( '\\u0027' | '\\u005C' | '\\u000A' | '\\u000D' ) | ECHAR )* '\\''
+            {
+            match('\''); 
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:346:12: ( options {greedy=false; } : ~ ( '\\u0027' | '\\u005C' | '\\u000A' | '\\u000D' ) | ECHAR )*
+            loop22:
+            do {
+                int alt22=3;
+                int LA22_0 = input.LA(1);
+
+                if ( (LA22_0=='\'') ) {
+                    alt22=3;
+                }
+                else if ( ((LA22_0>='\u0000' && LA22_0<='\t')||(LA22_0>='\u000B' && LA22_0<='\f')||(LA22_0>='\u000E' && LA22_0<='&')||(LA22_0>='(' && LA22_0<='[')||(LA22_0>=']' && LA22_0<='\uFFFE')) ) {
+                    alt22=1;
+                }
+                else if ( (LA22_0=='\\') ) {
+                    alt22=2;
+                }
+
+
+                switch (alt22) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:346:40: ~ ( '\\u0027' | '\\u005C' | '\\u000A' | '\\u000D' )
+            	    {
+            	    if ( (input.LA(1)>='\u0000' && input.LA(1)<='\t')||(input.LA(1)>='\u000B' && input.LA(1)<='\f')||(input.LA(1)>='\u000E' && input.LA(1)<='&')||(input.LA(1)>='(' && input.LA(1)<='[')||(input.LA(1)>=']' && input.LA(1)<='\uFFFE') ) {
+            	        input.consume();
+
+            	    }
+            	    else {
+            	        MismatchedSetException mse =
+            	            new MismatchedSetException(null,input);
+            	        recover(mse);    throw mse;
+            	    }
+
+
+            	    }
+            	    break;
+            	case 2 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:346:87: ECHAR
+            	    {
+            	    mECHAR(); 
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop22;
+                }
+            } while (true);
+
+            match('\''); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end STRING_LITERAL1
+
+    // $ANTLR start STRING_LITERAL2
+    public final void mSTRING_LITERAL2() throws RecognitionException {
+        try {
+            int _type = STRING_LITERAL2;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:350:5: ( '\"' ( options {greedy=false; } : ~ ( '\\u0022' | '\\u005C' | '\\u000A' | '\\u000D' ) | ECHAR )* '\"' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:350:7: '\"' ( options {greedy=false; } : ~ ( '\\u0022' | '\\u005C' | '\\u000A' | '\\u000D' ) | ECHAR )* '\"'
+            {
+            match('\"'); 
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:350:12: ( options {greedy=false; } : ~ ( '\\u0022' | '\\u005C' | '\\u000A' | '\\u000D' ) | ECHAR )*
+            loop23:
+            do {
+                int alt23=3;
+                int LA23_0 = input.LA(1);
+
+                if ( (LA23_0=='\"') ) {
+                    alt23=3;
+                }
+                else if ( ((LA23_0>='\u0000' && LA23_0<='\t')||(LA23_0>='\u000B' && LA23_0<='\f')||(LA23_0>='\u000E' && LA23_0<='!')||(LA23_0>='#' && LA23_0<='[')||(LA23_0>=']' && LA23_0<='\uFFFE')) ) {
+                    alt23=1;
+                }
+                else if ( (LA23_0=='\\') ) {
+                    alt23=2;
+                }
+
+
+                switch (alt23) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:350:40: ~ ( '\\u0022' | '\\u005C' | '\\u000A' | '\\u000D' )
+            	    {
+            	    if ( (input.LA(1)>='\u0000' && input.LA(1)<='\t')||(input.LA(1)>='\u000B' && input.LA(1)<='\f')||(input.LA(1)>='\u000E' && input.LA(1)<='!')||(input.LA(1)>='#' && input.LA(1)<='[')||(input.LA(1)>=']' && input.LA(1)<='\uFFFE') ) {
+            	        input.consume();
+
+            	    }
+            	    else {
+            	        MismatchedSetException mse =
+            	            new MismatchedSetException(null,input);
+            	        recover(mse);    throw mse;
+            	    }
+
+
+            	    }
+            	    break;
+            	case 2 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:350:87: ECHAR
+            	    {
+            	    mECHAR(); 
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop23;
+                }
+            } while (true);
+
+            match('\"'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end STRING_LITERAL2
+
+    // $ANTLR start STRING_LITERAL_LONG1
+    public final void mSTRING_LITERAL_LONG1() throws RecognitionException {
+        try {
+            int _type = STRING_LITERAL_LONG1;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:354:5: ( '\\'\\'\\'' ( options {greedy=false; } : ( '\\'' | '\\'\\'' )? (~ ( '\\'' | '\\\\' ) | ECHAR ) )* '\\'\\'\\'' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:354:9: '\\'\\'\\'' ( options {greedy=false; } : ( '\\'' | '\\'\\'' )? (~ ( '\\'' | '\\\\' ) | ECHAR ) )* '\\'\\'\\''
+            {
+            match("\'\'\'"); 
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:354:18: ( options {greedy=false; } : ( '\\'' | '\\'\\'' )? (~ ( '\\'' | '\\\\' ) | ECHAR ) )*
+            loop26:
+            do {
+                int alt26=2;
+                int LA26_0 = input.LA(1);
+
+                if ( (LA26_0=='\'') ) {
+                    int LA26_1 = input.LA(2);
+
+                    if ( (LA26_1=='\'') ) {
+                        int LA26_3 = input.LA(3);
+
+                        if ( (LA26_3=='\'') ) {
+                            alt26=2;
+                        }
+                        else if ( ((LA26_3>='\u0000' && LA26_3<='&')||(LA26_3>='(' && LA26_3<='\uFFFE')) ) {
+                            alt26=1;
+                        }
+
+
+                    }
+                    else if ( ((LA26_1>='\u0000' && LA26_1<='&')||(LA26_1>='(' && LA26_1<='\uFFFE')) ) {
+                        alt26=1;
+                    }
+
+
+                }
+                else if ( ((LA26_0>='\u0000' && LA26_0<='&')||(LA26_0>='(' && LA26_0<='\uFFFE')) ) {
+                    alt26=1;
+                }
+
+
+                switch (alt26) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:354:46: ( '\\'' | '\\'\\'' )? (~ ( '\\'' | '\\\\' ) | ECHAR )
+            	    {
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:354:46: ( '\\'' | '\\'\\'' )?
+            	    int alt24=3;
+            	    int LA24_0 = input.LA(1);
+
+            	    if ( (LA24_0=='\'') ) {
+            	        int LA24_1 = input.LA(2);
+
+            	        if ( (LA24_1=='\'') ) {
+            	            alt24=2;
+            	        }
+            	        else if ( ((LA24_1>='\u0000' && LA24_1<='&')||(LA24_1>='(' && LA24_1<='\uFFFE')) ) {
+            	            alt24=1;
+            	        }
+            	    }
+            	    switch (alt24) {
+            	        case 1 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:354:48: '\\''
+            	            {
+            	            match('\''); 
+
+            	            }
+            	            break;
+            	        case 2 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:354:55: '\\'\\''
+            	            {
+            	            match("\'\'"); 
+
+
+            	            }
+            	            break;
+
+            	    }
+
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:354:65: (~ ( '\\'' | '\\\\' ) | ECHAR )
+            	    int alt25=2;
+            	    int LA25_0 = input.LA(1);
+
+            	    if ( ((LA25_0>='\u0000' && LA25_0<='&')||(LA25_0>='(' && LA25_0<='[')||(LA25_0>=']' && LA25_0<='\uFFFE')) ) {
+            	        alt25=1;
+            	    }
+            	    else if ( (LA25_0=='\\') ) {
+            	        alt25=2;
+            	    }
+            	    else {
+            	        NoViableAltException nvae =
+            	            new NoViableAltException("354:65: (~ ( '\\'' | '\\\\' ) | ECHAR )", 25, 0, input);
+
+            	        throw nvae;
+            	    }
+            	    switch (alt25) {
+            	        case 1 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:354:67: ~ ( '\\'' | '\\\\' )
+            	            {
+            	            if ( (input.LA(1)>='\u0000' && input.LA(1)<='&')||(input.LA(1)>='(' && input.LA(1)<='[')||(input.LA(1)>=']' && input.LA(1)<='\uFFFE') ) {
+            	                input.consume();
+
+            	            }
+            	            else {
+            	                MismatchedSetException mse =
+            	                    new MismatchedSetException(null,input);
+            	                recover(mse);    throw mse;
+            	            }
+
+
+            	            }
+            	            break;
+            	        case 2 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:354:82: ECHAR
+            	            {
+            	            mECHAR(); 
+
+            	            }
+            	            break;
+
+            	    }
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop26;
+                }
+            } while (true);
+
+            match("\'\'\'"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end STRING_LITERAL_LONG1
+
+    // $ANTLR start STRING_LITERAL_LONG2
+    public final void mSTRING_LITERAL_LONG2() throws RecognitionException {
+        try {
+            int _type = STRING_LITERAL_LONG2;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:358:5: ( '\"\"\"' ( options {greedy=false; } : ( '\"' | '\"\"' )? (~ ( '\"' | '\\\\' ) | ECHAR ) )* '\"\"\"' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:358:9: '\"\"\"' ( options {greedy=false; } : ( '\"' | '\"\"' )? (~ ( '\"' | '\\\\' ) | ECHAR ) )* '\"\"\"'
+            {
+            match("\"\"\""); 
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:358:15: ( options {greedy=false; } : ( '\"' | '\"\"' )? (~ ( '\"' | '\\\\' ) | ECHAR ) )*
+            loop29:
+            do {
+                int alt29=2;
+                int LA29_0 = input.LA(1);
+
+                if ( (LA29_0=='\"') ) {
+                    int LA29_1 = input.LA(2);
+
+                    if ( (LA29_1=='\"') ) {
+                        int LA29_3 = input.LA(3);
+
+                        if ( (LA29_3=='\"') ) {
+                            alt29=2;
+                        }
+                        else if ( ((LA29_3>='\u0000' && LA29_3<='!')||(LA29_3>='#' && LA29_3<='\uFFFE')) ) {
+                            alt29=1;
+                        }
+
+
+                    }
+                    else if ( ((LA29_1>='\u0000' && LA29_1<='!')||(LA29_1>='#' && LA29_1<='\uFFFE')) ) {
+                        alt29=1;
+                    }
+
+
+                }
+                else if ( ((LA29_0>='\u0000' && LA29_0<='!')||(LA29_0>='#' && LA29_0<='\uFFFE')) ) {
+                    alt29=1;
+                }
+
+
+                switch (alt29) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:358:43: ( '\"' | '\"\"' )? (~ ( '\"' | '\\\\' ) | ECHAR )
+            	    {
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:358:43: ( '\"' | '\"\"' )?
+            	    int alt27=3;
+            	    int LA27_0 = input.LA(1);
+
+            	    if ( (LA27_0=='\"') ) {
+            	        int LA27_1 = input.LA(2);
+
+            	        if ( (LA27_1=='\"') ) {
+            	            alt27=2;
+            	        }
+            	        else if ( ((LA27_1>='\u0000' && LA27_1<='!')||(LA27_1>='#' && LA27_1<='\uFFFE')) ) {
+            	            alt27=1;
+            	        }
+            	    }
+            	    switch (alt27) {
+            	        case 1 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:358:45: '\"'
+            	            {
+            	            match('\"'); 
+
+            	            }
+            	            break;
+            	        case 2 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:358:51: '\"\"'
+            	            {
+            	            match("\"\""); 
+
+
+            	            }
+            	            break;
+
+            	    }
+
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:358:59: (~ ( '\"' | '\\\\' ) | ECHAR )
+            	    int alt28=2;
+            	    int LA28_0 = input.LA(1);
+
+            	    if ( ((LA28_0>='\u0000' && LA28_0<='!')||(LA28_0>='#' && LA28_0<='[')||(LA28_0>=']' && LA28_0<='\uFFFE')) ) {
+            	        alt28=1;
+            	    }
+            	    else if ( (LA28_0=='\\') ) {
+            	        alt28=2;
+            	    }
+            	    else {
+            	        NoViableAltException nvae =
+            	            new NoViableAltException("358:59: (~ ( '\"' | '\\\\' ) | ECHAR )", 28, 0, input);
+
+            	        throw nvae;
+            	    }
+            	    switch (alt28) {
+            	        case 1 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:358:61: ~ ( '\"' | '\\\\' )
+            	            {
+            	            if ( (input.LA(1)>='\u0000' && input.LA(1)<='!')||(input.LA(1)>='#' && input.LA(1)<='[')||(input.LA(1)>=']' && input.LA(1)<='\uFFFE') ) {
+            	                input.consume();
+
+            	            }
+            	            else {
+            	                MismatchedSetException mse =
+            	                    new MismatchedSetException(null,input);
+            	                recover(mse);    throw mse;
+            	            }
+
+
+            	            }
+            	            break;
+            	        case 2 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:358:75: ECHAR
+            	            {
+            	            mECHAR(); 
+
+            	            }
+            	            break;
+
+            	    }
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop29;
+                }
+            } while (true);
+
+            match("\"\"\""); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end STRING_LITERAL_LONG2
+
+    // $ANTLR start ECHAR
+    public final void mECHAR() throws RecognitionException {
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:363:5: ( '\\\\' ( 't' | 'b' | 'n' | 'r' | 'f' | '\\\\' | '\"' | '\\'' ) )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:363:7: '\\\\' ( 't' | 'b' | 'n' | 'r' | 'f' | '\\\\' | '\"' | '\\'' )
+            {
+            match('\\'); 
+            if ( input.LA(1)=='\"'||input.LA(1)=='\''||input.LA(1)=='\\'||input.LA(1)=='b'||input.LA(1)=='f'||input.LA(1)=='n'||input.LA(1)=='r'||input.LA(1)=='t' ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+
+            }
+
+        }
+        finally {
+        }
+    }
+    // $ANTLR end ECHAR
+
+    // $ANTLR start PN_CHARS_U
+    public final void mPN_CHARS_U() throws RecognitionException {
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:368:5: ( PN_CHARS_BASE | '_' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+            {
+            if ( (input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z')||(input.LA(1)>='\u00C0' && input.LA(1)<='\u00D6')||(input.LA(1)>='\u00D8' && input.LA(1)<='\u00F6')||(input.LA(1)>='\u00F8' && input.LA(1)<='\u02FF')||(input.LA(1)>='\u0370' && input.LA(1)<='\u037D')||(input.LA(1)>='\u037F' && input.LA(1)<='\u1FFF')||(input.LA(1)>='\u200C' && input.LA(1)<='\u200D')||(input.LA(1)>='\u2070' && input.LA(1)<='\u218F')||(input.LA(1)>='\u2C00' && input.LA(1)<='\u2FEF')||(input.LA(1)>='\u3001' && input.LA(1)<='\uD7FF')||(input.LA(1)>='\uF900' && input.LA(1)<='\uFDCF')||(input.LA(1)>='\uFDF0' && input.LA(1)<='\uFFFD') ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+
+            }
+
+        }
+        finally {
+        }
+    }
+    // $ANTLR end PN_CHARS_U
+
+    // $ANTLR start VARNAME
+    public final void mVARNAME() throws RecognitionException {
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:373:5: ( ( PN_CHARS_U | DIGIT ) ( PN_CHARS_U | DIGIT | '\\u00B7' | '\\u0300' .. '\\u036F' | '\\u203F' .. '\\u2040' )* )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:373:7: ( PN_CHARS_U | DIGIT ) ( PN_CHARS_U | DIGIT | '\\u00B7' | '\\u0300' .. '\\u036F' | '\\u203F' .. '\\u2040' )*
+            {
+            if ( (input.LA(1)>='0' && input.LA(1)<='9')||(input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z')||(input.LA(1)>='\u00C0' && input.LA(1)<='\u00D6')||(input.LA(1)>='\u00D8' && input.LA(1)<='\u00F6')||(input.LA(1)>='\u00F8' && input.LA(1)<='\u02FF')||(input.LA(1)>='\u0370' && input.LA(1)<='\u037D')||(input.LA(1)>='\u037F' && input.LA(1)<='\u1FFF')||(input.LA(1)>='\u200C' && input.LA(1)<='\u200D')||(input.LA(1)>='\u2070' && input.LA(1)<='\u218F')||(input.LA(1)>='\u2C00' && input.LA(1)<='\u2FEF')||(input.LA(1)>='\u3001' && input.LA(1)<='\uD7FF')||(input.LA(1)>='\uF900' && input.LA(1)<='\uFDCF')||(input.LA(1)>='\uFDF0' && input.LA(1)<='\uFFFD') ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:373:30: ( PN_CHARS_U | DIGIT | '\\u00B7' | '\\u0300' .. '\\u036F' | '\\u203F' .. '\\u2040' )*
+            loop30:
+            do {
+                int alt30=2;
+                int LA30_0 = input.LA(1);
+
+                if ( ((LA30_0>='0' && LA30_0<='9')||(LA30_0>='A' && LA30_0<='Z')||LA30_0=='_'||(LA30_0>='a' && LA30_0<='z')||LA30_0=='\u00B7'||(LA30_0>='\u00C0' && LA30_0<='\u00D6')||(LA30_0>='\u00D8' && LA30_0<='\u00F6')||(LA30_0>='\u00F8' && LA30_0<='\u037D')||(LA30_0>='\u037F' && LA30_0<='\u1FFF')||(LA30_0>='\u200C' && LA30_0<='\u200D')||(LA30_0>='\u203F' && LA30_0<='\u2040')||(LA30_0>='\u2070' && LA30_0<='\u218F')||(LA30_0>='\u2C00' && LA30_0<='\u2FEF')||(LA30_0>='\u3001' && LA30_0<='\uD7FF')||(LA30_0>='\uF900' && LA30_0<='\uFDCF')||(LA30_0>='\uFDF0' && LA30_0<='\uFFFD')) ) {
+                    alt30=1;
+                }
+
+
+                switch (alt30) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+            	    {
+            	    if ( (input.LA(1)>='0' && input.LA(1)<='9')||(input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z')||input.LA(1)=='\u00B7'||(input.LA(1)>='\u00C0' && input.LA(1)<='\u00D6')||(input.LA(1)>='\u00D8' && input.LA(1)<='\u00F6')||(input.LA(1)>='\u00F8' && input.LA(1)<='\u037D')||(input.LA(1)>='\u037F' && input.LA(1)<='\u1FFF')||(input.LA(1)>='\u200C' && input.LA(1)<='\u200D')||(input.LA(1)>='\u203F' && input.LA(1)<='\u2040')||(input.LA(1)>='\u2070' && input.LA(1)<='\u218F')||(input.LA(1)>='\u2C00' && input.LA(1)<='\u2FEF')||(input.LA(1)>='\u3001' && input.LA(1)<='\uD7FF')||(input.LA(1)>='\uF900' && input.LA(1)<='\uFDCF')||(input.LA(1)>='\uFDF0' && input.LA(1)<='\uFFFD') ) {
+            	        input.consume();
+
+            	    }
+            	    else {
+            	        MismatchedSetException mse =
+            	            new MismatchedSetException(null,input);
+            	        recover(mse);    throw mse;
+            	    }
+
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop30;
+                }
+            } while (true);
+
+
+            }
+
+        }
+        finally {
+        }
+    }
+    // $ANTLR end VARNAME
+
+    // $ANTLR start PN_CHARS
+    public final void mPN_CHARS() throws RecognitionException {
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:378:5: ( PN_CHARS_U | MINUS | DIGIT | '\\u00B7' | '\\u0300' .. '\\u036F' | '\\u203F' .. '\\u2040' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+            {
+            if ( input.LA(1)=='-'||(input.LA(1)>='0' && input.LA(1)<='9')||(input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z')||input.LA(1)=='\u00B7'||(input.LA(1)>='\u00C0' && input.LA(1)<='\u00D6')||(input.LA(1)>='\u00D8' && input.LA(1)<='\u00F6')||(input.LA(1)>='\u00F8' && input.LA(1)<='\u037D')||(input.LA(1)>='\u037F' && input.LA(1)<='\u1FFF')||(input.LA(1)>='\u200C' && input.LA(1)<='\u200D')||(input.LA(1)>='\u203F' && input.LA(1)<='\u2040')||(input.LA(1)>='\u2070' && input.LA(1)<='\u218F')||(input.LA(1)>='\u2C00' && input.LA(1)<='\u2FEF')||(input.LA(1)>='\u3001' && input.LA(1)<='\uD7FF')||(input.LA(1)>='\uF900' && input.LA(1)<='\uFDCF')||(input.LA(1)>='\uFDF0' && input.LA(1)<='\uFFFD') ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+
+            }
+
+        }
+        finally {
+        }
+    }
+    // $ANTLR end PN_CHARS
+
+    // $ANTLR start PN_PREFIX
+    public final void mPN_PREFIX() throws RecognitionException {
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:388:5: ( PN_CHARS_BASE ( ( PN_CHARS | DOT )* PN_CHARS )? )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:388:7: PN_CHARS_BASE ( ( PN_CHARS | DOT )* PN_CHARS )?
+            {
+            mPN_CHARS_BASE(); 
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:388:21: ( ( PN_CHARS | DOT )* PN_CHARS )?
+            int alt32=2;
+            int LA32_0 = input.LA(1);
+
+            if ( ((LA32_0>='-' && LA32_0<='.')||(LA32_0>='0' && LA32_0<='9')||(LA32_0>='A' && LA32_0<='Z')||LA32_0=='_'||(LA32_0>='a' && LA32_0<='z')||LA32_0=='\u00B7'||(LA32_0>='\u00C0' && LA32_0<='\u00D6')||(LA32_0>='\u00D8' && LA32_0<='\u00F6')||(LA32_0>='\u00F8' && LA32_0<='\u037D')||(LA32_0>='\u037F' && LA32_0<='\u1FFF')||(LA32_0>='\u200C' && LA32_0<='\u200D')||(LA32_0>='\u203F' && LA32_0<='\u2040')||(LA32_0>='\u2070' && LA32_0<='\u218F')||(LA32_0>='\u2C00' && LA32_0<='\u2FEF')||(LA32_0>='\u3001' && LA32_0<='\uD7FF')||(LA32_0>='\uF900' && LA32_0<='\uFDCF')||(LA32_0>='\uFDF0' && LA32_0<='\uFFFD')) ) {
+                alt32=1;
+            }
+            switch (alt32) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:388:22: ( PN_CHARS | DOT )* PN_CHARS
+                    {
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:388:22: ( PN_CHARS | DOT )*
+                    loop31:
+                    do {
+                        int alt31=2;
+                        int LA31_0 = input.LA(1);
+
+                        if ( (LA31_0=='-'||(LA31_0>='0' && LA31_0<='9')||(LA31_0>='A' && LA31_0<='Z')||LA31_0=='_'||(LA31_0>='a' && LA31_0<='z')||LA31_0=='\u00B7'||(LA31_0>='\u00C0' && LA31_0<='\u00D6')||(LA31_0>='\u00D8' && LA31_0<='\u00F6')||(LA31_0>='\u00F8' && LA31_0<='\u037D')||(LA31_0>='\u037F' && LA31_0<='\u1FFF')||(LA31_0>='\u200C' && LA31_0<='\u200D')||(LA31_0>='\u203F' && LA31_0<='\u2040')||(LA31_0>='\u2070' && LA31_0<='\u218F')||(LA31_0>='\u2C00' && LA31_0<='\u2FEF')||(LA31_0>='\u3001' && LA31_0<='\uD7FF')||(LA31_0>='\uF900' && LA31_0<='\uFDCF')||(LA31_0>='\uFDF0' && LA31_0<='\uFFFD')) ) {
+                            int LA31_1 = input.LA(2);
+
+                            if ( ((LA31_1>='-' && LA31_1<='.')||(LA31_1>='0' && LA31_1<='9')||(LA31_1>='A' && LA31_1<='Z')||LA31_1=='_'||(LA31_1>='a' && LA31_1<='z')||LA31_1=='\u00B7'||(LA31_1>='\u00C0' && LA31_1<='\u00D6')||(LA31_1>='\u00D8' && LA31_1<='\u00F6')||(LA31_1>='\u00F8' && LA31_1<='\u037D')||(LA31_1>='\u037F' && LA31_1<='\u1FFF')||(LA31_1>='\u200C' && LA31_1<='\u200D')||(LA31_1>='\u203F' && LA31_1<='\u2040')||(LA31_1>='\u2070' && LA31_1<='\u218F')||(LA31_1>='\u2C00' && LA31_1<='\u2FEF')||(LA31_1>='\u3001' && LA31_1<='\uD7FF')||(LA31_1>='\uF900' && LA31_1<='\uFDCF')||(LA31_1>='\uFDF0' && LA31_1<='\uFFFD')) ) {
+                                alt31=1;
+                            }
+
+
+                        }
+                        else if ( (LA31_0=='.') ) {
+                            alt31=1;
+                        }
+
+
+                        switch (alt31) {
+                    	case 1 :
+                    	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+                    	    {
+                    	    if ( (input.LA(1)>='-' && input.LA(1)<='.')||(input.LA(1)>='0' && input.LA(1)<='9')||(input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z')||input.LA(1)=='\u00B7'||(input.LA(1)>='\u00C0' && input.LA(1)<='\u00D6')||(input.LA(1)>='\u00D8' && input.LA(1)<='\u00F6')||(input.LA(1)>='\u00F8' && input.LA(1)<='\u037D')||(input.LA(1)>='\u037F' && input.LA(1)<='\u1FFF')||(input.LA(1)>='\u200C' && input.LA(1)<='\u200D')||(input.LA(1)>='\u203F' && input.LA(1)<='\u2040')||(input.LA(1)>='\u2070' && input.LA(1)<='\u218F')||(input.LA(1)>='\u2C00' && input.LA(1)<='\u2FEF')||(input.LA(1)>='\u3001' && input.LA(1)<='\uD7FF')||(input.LA(1)>='\uF900' && input.LA(1)<='\uFDCF')||(input.LA(1)>='\uFDF0' && input.LA(1)<='\uFFFD') ) {
+                    	        input.consume();
+
+                    	    }
+                    	    else {
+                    	        MismatchedSetException mse =
+                    	            new MismatchedSetException(null,input);
+                    	        recover(mse);    throw mse;
+                    	    }
+
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    break loop31;
+                        }
+                    } while (true);
+
+                    mPN_CHARS(); 
+
+                    }
+                    break;
+
+            }
+
+
+            }
+
+        }
+        finally {
+        }
+    }
+    // $ANTLR end PN_PREFIX
+
+    // $ANTLR start PN_LOCAL
+    public final void mPN_LOCAL() throws RecognitionException {
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:393:5: ( ( PN_CHARS_U | DIGIT ) ( ( PN_CHARS )* PN_CHARS )? )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:393:7: ( PN_CHARS_U | DIGIT ) ( ( PN_CHARS )* PN_CHARS )?
+            {
+            if ( (input.LA(1)>='0' && input.LA(1)<='9')||(input.LA(1)>='A' && input.LA(1)<='Z')||input.LA(1)=='_'||(input.LA(1)>='a' && input.LA(1)<='z')||(input.LA(1)>='\u00C0' && input.LA(1)<='\u00D6')||(input.LA(1)>='\u00D8' && input.LA(1)<='\u00F6')||(input.LA(1)>='\u00F8' && input.LA(1)<='\u02FF')||(input.LA(1)>='\u0370' && input.LA(1)<='\u037D')||(input.LA(1)>='\u037F' && input.LA(1)<='\u1FFF')||(input.LA(1)>='\u200C' && input.LA(1)<='\u200D')||(input.LA(1)>='\u2070' && input.LA(1)<='\u218F')||(input.LA(1)>='\u2C00' && input.LA(1)<='\u2FEF')||(input.LA(1)>='\u3001' && input.LA(1)<='\uD7FF')||(input.LA(1)>='\uF900' && input.LA(1)<='\uFDCF')||(input.LA(1)>='\uFDF0' && input.LA(1)<='\uFFFD') ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:393:30: ( ( PN_CHARS )* PN_CHARS )?
+            int alt34=2;
+            int LA34_0 = input.LA(1);
+
+            if ( (LA34_0=='-'||(LA34_0>='0' && LA34_0<='9')||(LA34_0>='A' && LA34_0<='Z')||LA34_0=='_'||(LA34_0>='a' && LA34_0<='z')||LA34_0=='\u00B7'||(LA34_0>='\u00C0' && LA34_0<='\u00D6')||(LA34_0>='\u00D8' && LA34_0<='\u00F6')||(LA34_0>='\u00F8' && LA34_0<='\u037D')||(LA34_0>='\u037F' && LA34_0<='\u1FFF')||(LA34_0>='\u200C' && LA34_0<='\u200D')||(LA34_0>='\u203F' && LA34_0<='\u2040')||(LA34_0>='\u2070' && LA34_0<='\u218F')||(LA34_0>='\u2C00' && LA34_0<='\u2FEF')||(LA34_0>='\u3001' && LA34_0<='\uD7FF')||(LA34_0>='\uF900' && LA34_0<='\uFDCF')||(LA34_0>='\uFDF0' && LA34_0<='\uFFFD')) ) {
+                alt34=1;
+            }
+            switch (alt34) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:393:31: ( PN_CHARS )* PN_CHARS
+                    {
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:393:31: ( PN_CHARS )*
+                    loop33:
+                    do {
+                        int alt33=2;
+                        int LA33_0 = input.LA(1);
+
+                        if ( (LA33_0=='-'||(LA33_0>='0' && LA33_0<='9')||(LA33_0>='A' && LA33_0<='Z')||LA33_0=='_'||(LA33_0>='a' && LA33_0<='z')||LA33_0=='\u00B7'||(LA33_0>='\u00C0' && LA33_0<='\u00D6')||(LA33_0>='\u00D8' && LA33_0<='\u00F6')||(LA33_0>='\u00F8' && LA33_0<='\u037D')||(LA33_0>='\u037F' && LA33_0<='\u1FFF')||(LA33_0>='\u200C' && LA33_0<='\u200D')||(LA33_0>='\u203F' && LA33_0<='\u2040')||(LA33_0>='\u2070' && LA33_0<='\u218F')||(LA33_0>='\u2C00' && LA33_0<='\u2FEF')||(LA33_0>='\u3001' && LA33_0<='\uD7FF')||(LA33_0>='\uF900' && LA33_0<='\uFDCF')||(LA33_0>='\uFDF0' && LA33_0<='\uFFFD')) ) {
+                            int LA33_1 = input.LA(2);
+
+                            if ( (LA33_1=='-'||(LA33_1>='0' && LA33_1<='9')||(LA33_1>='A' && LA33_1<='Z')||LA33_1=='_'||(LA33_1>='a' && LA33_1<='z')||LA33_1=='\u00B7'||(LA33_1>='\u00C0' && LA33_1<='\u00D6')||(LA33_1>='\u00D8' && LA33_1<='\u00F6')||(LA33_1>='\u00F8' && LA33_1<='\u037D')||(LA33_1>='\u037F' && LA33_1<='\u1FFF')||(LA33_1>='\u200C' && LA33_1<='\u200D')||(LA33_1>='\u203F' && LA33_1<='\u2040')||(LA33_1>='\u2070' && LA33_1<='\u218F')||(LA33_1>='\u2C00' && LA33_1<='\u2FEF')||(LA33_1>='\u3001' && LA33_1<='\uD7FF')||(LA33_1>='\uF900' && LA33_1<='\uFDCF')||(LA33_1>='\uFDF0' && LA33_1<='\uFFFD')) ) {
+                                alt33=1;
+                            }
+
+
+                        }
+
+
+                        switch (alt33) {
+                    	case 1 :
+                    	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:393:32: PN_CHARS
+                    	    {
+                    	    mPN_CHARS(); 
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    break loop33;
+                        }
+                    } while (true);
+
+                    mPN_CHARS(); 
+
+                    }
+                    break;
+
+            }
+
+
+            }
+
+        }
+        finally {
+        }
+    }
+    // $ANTLR end PN_LOCAL
+
+    // $ANTLR start PN_CHARS_BASE
+    public final void mPN_CHARS_BASE() throws RecognitionException {
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:398:5: ( 'A' .. 'Z' | 'a' .. 'z' | '\\u00C0' .. '\\u00D6' | '\\u00D8' .. '\\u00F6' | '\\u00F8' .. '\\u02FF' | '\\u0370' .. '\\u037D' | '\\u037F' .. '\\u1FFF' | '\\u200C' .. '\\u200D' | '\\u2070' .. '\\u218F' | '\\u2C00' .. '\\u2FEF' | '\\u3001' .. '\\uD7FF' | '\\uF900' .. '\\uFDCF' | '\\uFDF0' .. '\\uFFFD' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+            {
+            if ( (input.LA(1)>='A' && input.LA(1)<='Z')||(input.LA(1)>='a' && input.LA(1)<='z')||(input.LA(1)>='\u00C0' && input.LA(1)<='\u00D6')||(input.LA(1)>='\u00D8' && input.LA(1)<='\u00F6')||(input.LA(1)>='\u00F8' && input.LA(1)<='\u02FF')||(input.LA(1)>='\u0370' && input.LA(1)<='\u037D')||(input.LA(1)>='\u037F' && input.LA(1)<='\u1FFF')||(input.LA(1)>='\u200C' && input.LA(1)<='\u200D')||(input.LA(1)>='\u2070' && input.LA(1)<='\u218F')||(input.LA(1)>='\u2C00' && input.LA(1)<='\u2FEF')||(input.LA(1)>='\u3001' && input.LA(1)<='\uD7FF')||(input.LA(1)>='\uF900' && input.LA(1)<='\uFDCF')||(input.LA(1)>='\uFDF0' && input.LA(1)<='\uFFFD') ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+
+            }
+
+        }
+        finally {
+        }
+    }
+    // $ANTLR end PN_CHARS_BASE
+
+    // $ANTLR start DIGIT
+    public final void mDIGIT() throws RecognitionException {
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:415:5: ( '0' .. '9' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:415:7: '0' .. '9'
+            {
+            matchRange('0','9'); 
+
+            }
+
+        }
+        finally {
+        }
+    }
+    // $ANTLR end DIGIT
+
+    // $ANTLR start COMMENT
+    public final void mCOMMENT() throws RecognitionException {
+        try {
+            int _type = COMMENT;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:419:5: ( '//' ( options {greedy=false; } : . )* EOL )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:419:7: '//' ( options {greedy=false; } : . )* EOL
+            {
+            match("//"); 
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:419:12: ( options {greedy=false; } : . )*
+            loop35:
+            do {
+                int alt35=2;
+                int LA35_0 = input.LA(1);
+
+                if ( (LA35_0=='\n'||LA35_0=='\r') ) {
+                    alt35=2;
+                }
+                else if ( ((LA35_0>='\u0000' && LA35_0<='\t')||(LA35_0>='\u000B' && LA35_0<='\f')||(LA35_0>='\u000E' && LA35_0<='\uFFFE')) ) {
+                    alt35=1;
+                }
+
+
+                switch (alt35) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:419:39: .
+            	    {
+            	    matchAny(); 
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop35;
+                }
+            } while (true);
+
+            mEOL(); 
+             channel=HIDDEN; 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end COMMENT
+
+    // $ANTLR start EOL
+    public final void mEOL() throws RecognitionException {
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:424:5: ( '\\n' | '\\r' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+            {
+            if ( input.LA(1)=='\n'||input.LA(1)=='\r' ) {
+                input.consume();
+
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recover(mse);    throw mse;
+            }
+
+
+            }
+
+        }
+        finally {
+        }
+    }
+    // $ANTLR end EOL
+
+    // $ANTLR start REFERENCE
+    public final void mREFERENCE() throws RecognitionException {
+        try {
+            int _type = REFERENCE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:428:5: ( '^^' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:428:7: '^^'
+            {
+            match("^^"); 
+
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end REFERENCE
+
+    // $ANTLR start EXCLAMATION
+    public final void mEXCLAMATION() throws RecognitionException {
+        try {
+            int _type = EXCLAMATION;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:431:2: ( '!' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:431:4: '!'
+            {
+            match('!'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end EXCLAMATION
+
+    // $ANTLR start QUESTION
+    public final void mQUESTION() throws RecognitionException {
+        try {
+            int _type = QUESTION;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:434:2: ( '?' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:434:4: '?'
+            {
+            match('?'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end QUESTION
+
+    // $ANTLR start DOT
+    public final void mDOT() throws RecognitionException {
+        try {
+            int _type = DOT;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:436:5: ( '.' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:436:7: '.'
+            {
+            match('.'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end DOT
+
+    // $ANTLR start COMMA
+    public final void mCOMMA() throws RecognitionException {
+        try {
+            int _type = COMMA;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:439:7: ( ',' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:439:9: ','
+            {
+            match(','); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end COMMA
+
+    // $ANTLR start SEMICOLON
+    public final void mSEMICOLON() throws RecognitionException {
+        try {
+            int _type = SEMICOLON;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:446:2: ( ';' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:446:4: ';'
+            {
+            match(';'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end SEMICOLON
+
+    // $ANTLR start AMPERSAND
+    public final void mAMPERSAND() throws RecognitionException {
+        try {
+            int _type = AMPERSAND;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:450:2: ( '&' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:450:4: '&'
+            {
+            match('&'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end AMPERSAND
+
+    // $ANTLR start BAR
+    public final void mBAR() throws RecognitionException {
+        try {
+            int _type = BAR;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:452:5: ( '|' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:452:7: '|'
+            {
+            match('|'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end BAR
+
+    // $ANTLR start LANGLE
+    public final void mLANGLE() throws RecognitionException {
+        try {
+            int _type = LANGLE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:455:8: ( '<' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:455:10: '<'
+            {
+            match('<'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end LANGLE
+
+    // $ANTLR start RANGLE
+    public final void mRANGLE() throws RecognitionException {
+        try {
+            int _type = RANGLE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:458:9: ( '>' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:458:11: '>'
+            {
+            match('>'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end RANGLE
+
+    // $ANTLR start PERCENT
+    public final void mPERCENT() throws RecognitionException {
+        try {
+            int _type = PERCENT;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:461:9: ( '%' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:461:11: '%'
+            {
+            match('%'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end PERCENT
+
+    // $ANTLR start PLUS
+    public final void mPLUS() throws RecognitionException {
+        try {
+            int _type = PLUS;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:464:6: ( '+' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:464:8: '+'
+            {
+            match('+'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end PLUS
+
+    // $ANTLR start MINUS
+    public final void mMINUS() throws RecognitionException {
+        try {
+            int _type = MINUS;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:467:7: ( '-' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:467:9: '-'
+            {
+            match('-'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end MINUS
+
+    // $ANTLR start STAR
+    public final void mSTAR() throws RecognitionException {
+        try {
+            int _type = STAR;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:470:6: ( '*' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:470:8: '*'
+            {
+            match('*'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end STAR
+
+    // $ANTLR start TILDE
+    public final void mTILDE() throws RecognitionException {
+        try {
+            int _type = TILDE;
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:473:8: ( '~' )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:473:10: '~'
+            {
+            match('~'); 
+
+            }
+
+            this.type = _type;
+        }
+        finally {
+        }
+    }
+    // $ANTLR end TILDE
+
+    public void mTokens() throws RecognitionException {
+        // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:8: ( WS | AT_IMPORT | AT_PREFIX | AT_BASE | AT_DELAY | INHERITANCE | SIMILARITY | INSTANCE | PROPERTY | INSTANCE_PROPERTY | IMPLICATION | IMPLICATION_PRED | IMPLICATION_RETRO | IMPLICATION_CONC | EQUIVALENCE | EQUIVALENCE_PRED | EQUIVALENCE_CONC | NOT | PAST | PRESENT | FUTURE | CONJ | DISJ | OPEN_BRACE | CLOSE_BRACE | LPAREN | RPAREN | LBRACKET | RBRACKET | PNAME_NS | PNAME_LN | TRUE | FALSE | IRI_REF | LANGTAG | QUERY_VAR | STM_VAR | INTEGER | DECIMAL | DOUBLE | INTEGER_POSITIVE | DECIMAL_POSITIVE | DOUBLE_POSITIVE | INTEGER_NEGATIVE | DECIMAL_NEGATIVE | DOUBLE_NEGATIVE | STRING_LITERAL1 | STRING_LITERAL2 | STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2 | COMMENT | REFERENCE | EXCLAMATION | QUESTION | DOT | COMMA | SEMICOLON | AMPERSAND | BAR | LANGLE | RANGLE | PERCENT | PLUS | MINUS | STAR | TILDE )
+        int alt36=66;
+        alt36 = dfa36.predict(input);
+        switch (alt36) {
+            case 1 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:10: WS
+                {
+                mWS(); 
+
+                }
+                break;
+            case 2 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:13: AT_IMPORT
+                {
+                mAT_IMPORT(); 
+
+                }
+                break;
+            case 3 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:23: AT_PREFIX
+                {
+                mAT_PREFIX(); 
+
+                }
+                break;
+            case 4 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:33: AT_BASE
+                {
+                mAT_BASE(); 
+
+                }
+                break;
+            case 5 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:41: AT_DELAY
+                {
+                mAT_DELAY(); 
+
+                }
+                break;
+            case 6 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:50: INHERITANCE
+                {
+                mINHERITANCE(); 
+
+                }
+                break;
+            case 7 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:62: SIMILARITY
+                {
+                mSIMILARITY(); 
+
+                }
+                break;
+            case 8 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:73: INSTANCE
+                {
+                mINSTANCE(); 
+
+                }
+                break;
+            case 9 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:82: PROPERTY
+                {
+                mPROPERTY(); 
+
+                }
+                break;
+            case 10 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:91: INSTANCE_PROPERTY
+                {
+                mINSTANCE_PROPERTY(); 
+
+                }
+                break;
+            case 11 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:109: IMPLICATION
+                {
+                mIMPLICATION(); 
+
+                }
+                break;
+            case 12 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:121: IMPLICATION_PRED
+                {
+                mIMPLICATION_PRED(); 
+
+                }
+                break;
+            case 13 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:138: IMPLICATION_RETRO
+                {
+                mIMPLICATION_RETRO(); 
+
+                }
+                break;
+            case 14 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:156: IMPLICATION_CONC
+                {
+                mIMPLICATION_CONC(); 
+
+                }
+                break;
+            case 15 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:173: EQUIVALENCE
+                {
+                mEQUIVALENCE(); 
+
+                }
+                break;
+            case 16 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:185: EQUIVALENCE_PRED
+                {
+                mEQUIVALENCE_PRED(); 
+
+                }
+                break;
+            case 17 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:202: EQUIVALENCE_CONC
+                {
+                mEQUIVALENCE_CONC(); 
+
+                }
+                break;
+            case 18 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:219: NOT
+                {
+                mNOT(); 
+
+                }
+                break;
+            case 19 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:223: PAST
+                {
+                mPAST(); 
+
+                }
+                break;
+            case 20 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:228: PRESENT
+                {
+                mPRESENT(); 
+
+                }
+                break;
+            case 21 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:236: FUTURE
+                {
+                mFUTURE(); 
+
+                }
+                break;
+            case 22 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:243: CONJ
+                {
+                mCONJ(); 
+
+                }
+                break;
+            case 23 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:248: DISJ
+                {
+                mDISJ(); 
+
+                }
+                break;
+            case 24 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:253: OPEN_BRACE
+                {
+                mOPEN_BRACE(); 
+
+                }
+                break;
+            case 25 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:264: CLOSE_BRACE
+                {
+                mCLOSE_BRACE(); 
+
+                }
+                break;
+            case 26 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:276: LPAREN
+                {
+                mLPAREN(); 
+
+                }
+                break;
+            case 27 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:283: RPAREN
+                {
+                mRPAREN(); 
+
+                }
+                break;
+            case 28 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:290: LBRACKET
+                {
+                mLBRACKET(); 
+
+                }
+                break;
+            case 29 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:299: RBRACKET
+                {
+                mRBRACKET(); 
+
+                }
+                break;
+            case 30 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:308: PNAME_NS
+                {
+                mPNAME_NS(); 
+
+                }
+                break;
+            case 31 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:317: PNAME_LN
+                {
+                mPNAME_LN(); 
+
+                }
+                break;
+            case 32 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:326: TRUE
+                {
+                mTRUE(); 
+
+                }
+                break;
+            case 33 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:331: FALSE
+                {
+                mFALSE(); 
+
+                }
+                break;
+            case 34 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:337: IRI_REF
+                {
+                mIRI_REF(); 
+
+                }
+                break;
+            case 35 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:345: LANGTAG
+                {
+                mLANGTAG(); 
+
+                }
+                break;
+            case 36 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:353: QUERY_VAR
+                {
+                mQUERY_VAR(); 
+
+                }
+                break;
+            case 37 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:363: STM_VAR
+                {
+                mSTM_VAR(); 
+
+                }
+                break;
+            case 38 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:371: INTEGER
+                {
+                mINTEGER(); 
+
+                }
+                break;
+            case 39 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:379: DECIMAL
+                {
+                mDECIMAL(); 
+
+                }
+                break;
+            case 40 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:387: DOUBLE
+                {
+                mDOUBLE(); 
+
+                }
+                break;
+            case 41 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:394: INTEGER_POSITIVE
+                {
+                mINTEGER_POSITIVE(); 
+
+                }
+                break;
+            case 42 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:411: DECIMAL_POSITIVE
+                {
+                mDECIMAL_POSITIVE(); 
+
+                }
+                break;
+            case 43 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:428: DOUBLE_POSITIVE
+                {
+                mDOUBLE_POSITIVE(); 
+
+                }
+                break;
+            case 44 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:444: INTEGER_NEGATIVE
+                {
+                mINTEGER_NEGATIVE(); 
+
+                }
+                break;
+            case 45 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:461: DECIMAL_NEGATIVE
+                {
+                mDECIMAL_NEGATIVE(); 
+
+                }
+                break;
+            case 46 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:478: DOUBLE_NEGATIVE
+                {
+                mDOUBLE_NEGATIVE(); 
+
+                }
+                break;
+            case 47 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:494: STRING_LITERAL1
+                {
+                mSTRING_LITERAL1(); 
+
+                }
+                break;
+            case 48 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:510: STRING_LITERAL2
+                {
+                mSTRING_LITERAL2(); 
+
+                }
+                break;
+            case 49 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:526: STRING_LITERAL_LONG1
+                {
+                mSTRING_LITERAL_LONG1(); 
+
+                }
+                break;
+            case 50 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:547: STRING_LITERAL_LONG2
+                {
+                mSTRING_LITERAL_LONG2(); 
+
+                }
+                break;
+            case 51 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:568: COMMENT
+                {
+                mCOMMENT(); 
+
+                }
+                break;
+            case 52 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:576: REFERENCE
+                {
+                mREFERENCE(); 
+
+                }
+                break;
+            case 53 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:586: EXCLAMATION
+                {
+                mEXCLAMATION(); 
+
+                }
+                break;
+            case 54 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:598: QUESTION
+                {
+                mQUESTION(); 
+
+                }
+                break;
+            case 55 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:607: DOT
+                {
+                mDOT(); 
+
+                }
+                break;
+            case 56 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:611: COMMA
+                {
+                mCOMMA(); 
+
+                }
+                break;
+            case 57 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:617: SEMICOLON
+                {
+                mSEMICOLON(); 
+
+                }
+                break;
+            case 58 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:627: AMPERSAND
+                {
+                mAMPERSAND(); 
+
+                }
+                break;
+            case 59 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:637: BAR
+                {
+                mBAR(); 
+
+                }
+                break;
+            case 60 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:641: LANGLE
+                {
+                mLANGLE(); 
+
+                }
+                break;
+            case 61 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:648: RANGLE
+                {
+                mRANGLE(); 
+
+                }
+                break;
+            case 62 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:655: PERCENT
+                {
+                mPERCENT(); 
+
+                }
+                break;
+            case 63 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:663: PLUS
+                {
+                mPLUS(); 
+
+                }
+                break;
+            case 64 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:668: MINUS
+                {
+                mMINUS(); 
+
+                }
+                break;
+            case 65 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:674: STAR
+                {
+                mSTAR(); 
+
+                }
+                break;
+            case 66 :
+                // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:1:679: TILDE
+                {
+                mTILDE(); 
+
+                }
+                break;
+
+        }
+
+    }
+
+
+    protected DFA19 dfa19 = new DFA19(this);
+    protected DFA36 dfa36 = new DFA36(this);
+    static final String DFA19_eotS =
+        "\5\uffff";
+    static final String DFA19_eofS =
+        "\5\uffff";
+    static final String DFA19_minS =
+        "\2\56\3\uffff";
+    static final String DFA19_maxS =
+        "\1\71\1\145\3\uffff";
+    static final String DFA19_acceptS =
+        "\2\uffff\1\2\1\1\1\3";
+    static final String DFA19_specialS =
+        "\5\uffff}>";
+    static final String[] DFA19_transitionS = {
+            "\1\2\1\uffff\12\1",
+            "\1\3\1\uffff\12\1\13\uffff\1\4\37\uffff\1\4",
+            "",
+            "",
+            ""
+    };
+
+    static final short[] DFA19_eot = DFA.unpackEncodedString(DFA19_eotS);
+    static final short[] DFA19_eof = DFA.unpackEncodedString(DFA19_eofS);
+    static final char[] DFA19_min = DFA.unpackEncodedStringToUnsignedChars(DFA19_minS);
+    static final char[] DFA19_max = DFA.unpackEncodedStringToUnsignedChars(DFA19_maxS);
+    static final short[] DFA19_accept = DFA.unpackEncodedString(DFA19_acceptS);
+    static final short[] DFA19_special = DFA.unpackEncodedString(DFA19_specialS);
+    static final short[][] DFA19_transition;
+
+    static {
+        int numStates = DFA19_transitionS.length;
+        DFA19_transition = new short[numStates][];
+        for (int i=0; i<numStates; i++) {
+            DFA19_transition[i] = DFA.unpackEncodedString(DFA19_transitionS[i]);
+        }
+    }
+
+    class DFA19 extends DFA {
+
+        public DFA19(BaseRecognizer recognizer) {
+            this.recognizer = recognizer;
+            this.decisionNumber = 19;
+            this.eot = DFA19_eot;
+            this.eof = DFA19_eof;
+            this.min = DFA19_min;
+            this.max = DFA19_max;
+            this.accept = DFA19_accept;
+            this.special = DFA19_special;
+            this.transition = DFA19_transition;
+        }
+        public String getDescription() {
+            return "310:1: DOUBLE : ( ( DIGIT )+ DOT ( DIGIT )* EXPONENT | DOT ( DIGIT )+ EXPONENT | ( DIGIT )+ EXPONENT );";
+        }
+    }
+    static final String DFA36_eotS =
+        "\3\uffff\1\51\1\60\1\63\1\uffff\1\71\1\uffff\1\74\1\uffff\1\100"+
+        "\6\uffff\1\104\2\uffff\1\107\1\uffff\1\111\1\114\1\116\11\uffff"+
+        "\4\47\3\uffff\1\133\37\uffff\1\146\2\uffff\1\146\1\uffff\1\150\1"+
+        "\uffff\1\122\1\uffff\1\124\1\uffff\4\47\3\uffff\1\162\1\uffff\1"+
+        "\162\10\uffff\1\146\1\uffff\1\171\1\uffff\1\171\2\uffff\4\47\1\uffff"+
+        "\1\162\3\uffff\1\177\2\uffff\1\171\3\47\1\u0084\1\uffff\1\u0085"+
+        "\2\47\1\u0088\2\uffff\1\u0089\1\u008a\3\uffff";
+    static final String DFA36_eofS =
+        "\u008b\uffff";
+    static final String DFA36_minS =
+        "\1\11\1\uffff\1\101\1\55\1\41\1\55\1\57\1\41\1\uffff\1\76\1\57\1"+
+        "\46\5\uffff\1\55\1\60\2\55\1\60\1\uffff\1\56\1\60\1\56\2\0\7\uffff"+
+        "\1\155\1\162\1\145\1\141\1\uffff\1\76\1\uffff\1\56\1\60\2\41\1\uffff"+
+        "\1\41\2\uffff\1\76\16\uffff\3\55\2\uffff\1\55\3\uffff\1\60\2\uffff"+
+        "\1\60\1\uffff\1\56\1\60\1\47\1\uffff\1\42\1\uffff\1\160\1\145\1"+
+        "\154\1\163\3\uffff\1\60\1\uffff\1\60\5\uffff\2\55\1\uffff\1\60\1"+
+        "\uffff\1\60\1\uffff\1\60\2\uffff\1\157\1\146\1\141\1\145\1\uffff"+
+        "\1\60\3\uffff\2\55\1\uffff\1\60\1\162\1\151\1\171\1\55\1\uffff\1"+
+        "\55\1\164\1\170\1\55\2\uffff\2\55\3\uffff";
+    static final String DFA36_maxS =
+        "\1\ufffd\1\uffff\1\ufffd\1\71\1\ufffe\1\55\1\174\1\41\1\uffff\1"+
+        "\174\1\76\1\46\5\uffff\5\ufffd\1\uffff\1\145\2\71\2\ufffe\7\uffff"+
+        "\1\155\1\162\1\145\1\141\1\uffff\1\133\1\uffff\1\145\1\71\2\ufffe"+
+        "\1\uffff\1\ufffe\2\uffff\1\133\16\uffff\3\ufffd\2\uffff\1\ufffd"+
+        "\3\uffff\1\145\2\uffff\1\145\1\uffff\1\145\1\71\1\47\1\uffff\1\42"+
+        "\1\uffff\1\160\1\145\1\154\1\163\3\uffff\1\145\1\uffff\1\145\5\uffff"+
+        "\2\ufffd\1\uffff\1\145\1\uffff\1\145\1\uffff\1\145\2\uffff\1\157"+
+        "\1\146\1\141\1\145\1\uffff\1\145\3\uffff\2\ufffd\1\uffff\1\145\1"+
+        "\162\1\151\1\171\1\ufffd\1\uffff\1\ufffd\1\164\1\170\1\ufffd\2\uffff"+
+        "\2\ufffd\3\uffff";
+    static final String DFA36_acceptS =
+        "\1\uffff\1\1\6\uffff\1\23\3\uffff\1\30\1\32\1\33\1\34\1\35\5\uffff"+
+        "\1\45\5\uffff\1\64\1\70\1\71\1\75\1\76\1\101\1\102\4\uffff\1\43"+
+        "\1\uffff\1\100\4\uffff\1\21\1\uffff\1\74\1\42\1\uffff\1\31\1\14"+
+        "\1\13\1\15\1\16\1\22\1\65\1\24\1\27\1\73\1\25\1\63\1\26\1\72\3\uffff"+
+        "\1\36\1\37\1\uffff\1\66\1\44\1\46\1\uffff\1\50\1\67\1\uffff\1\77"+
+        "\3\uffff\1\57\1\uffff\1\60\4\uffff\1\11\1\6\1\54\1\uffff\1\56\1"+
+        "\uffff\1\17\1\7\1\20\1\12\1\10\2\uffff\1\47\1\uffff\1\51\1\uffff"+
+        "\1\53\1\uffff\1\61\1\62\4\uffff\1\55\1\uffff\1\17\1\7\1\20\2\uffff"+
+        "\1\52\5\uffff\1\40\4\uffff\1\4\1\41\2\uffff\1\5\1\2\1\3";
+    static final String DFA36_specialS =
+        "\u008b\uffff}>";
+    static final String[] DFA36_transitionS = {
+            "\2\1\2\uffff\1\1\22\uffff\1\1\1\7\1\33\1\26\1\uffff\1\40\1\13"+
+            "\1\32\1\15\1\16\1\41\1\31\1\35\1\3\1\30\1\12\12\27\1\22\1\36"+
+            "\1\4\1\6\1\37\1\25\1\2\5\24\1\23\15\24\1\21\6\24\1\17\1\10\1"+
+            "\20\1\34\2\uffff\5\24\1\23\15\24\1\21\6\24\1\14\1\11\1\5\1\42"+
+            "\101\uffff\27\24\1\uffff\37\24\1\uffff\u0208\24\160\uffff\16"+
+            "\24\1\uffff\u1c81\24\14\uffff\2\24\142\uffff\u0120\24\u0a70"+
+            "\uffff\u03f0\24\21\uffff\ua7ff\24\u2100\uffff\u04d0\24\40\uffff"+
+            "\u020e\24",
+            "",
+            "\32\47\6\uffff\1\47\1\46\1\47\1\45\4\47\1\43\6\47\1\44\12\47"+
+            "\105\uffff\27\47\1\uffff\37\47\1\uffff\u0208\47\160\uffff\16"+
+            "\47\1\uffff\u1c81\47\14\uffff\2\47\142\uffff\u0120\47\u0a70"+
+            "\uffff\u03f0\47\21\uffff\ua7ff\47\u2100\uffff\u04d0\47\40\uffff"+
+            "\u020e\47",
+            "\1\50\1\53\1\uffff\12\52",
+            "\1\61\1\uffff\12\61\1\55\1\61\1\57\14\61\1\uffff\1\54\36\61"+
+            "\1\uffff\1\61\1\uffff\1\61\1\uffff\32\61\1\uffff\1\56\1\uffff"+
+            "\uff81\61",
+            "\1\62",
+            "\1\64\15\uffff\1\65\36\uffff\1\66\37\uffff\1\67",
+            "\1\70",
+            "",
+            "\1\72\75\uffff\1\73",
+            "\1\76\16\uffff\1\75",
+            "\1\77",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\1\102\1\103\1\uffff\12\102\1\22\6\uffff\21\102\1\101\10\102"+
+            "\4\uffff\1\102\1\uffff\21\102\1\101\10\102\74\uffff\1\102\10"+
+            "\uffff\27\102\1\uffff\37\102\1\uffff\u0286\102\1\uffff\u1c81"+
+            "\102\14\uffff\2\102\61\uffff\2\102\57\uffff\u0120\102\u0a70"+
+            "\uffff\u03f0\102\21\uffff\ua7ff\102\u2100\uffff\u04d0\102\40"+
+            "\uffff\u020e\102",
+            "\12\105\7\uffff\32\105\4\uffff\1\105\1\uffff\32\105\105\uffff"+
+            "\27\105\1\uffff\37\105\1\uffff\u0208\105\160\uffff\16\105\1"+
+            "\uffff\u1c81\105\14\uffff\2\105\142\uffff\u0120\105\u0a70\uffff"+
+            "\u03f0\105\21\uffff\ua7ff\105\u2100\uffff\u04d0\105\40\uffff"+
+            "\u020e\105",
+            "\1\102\1\103\1\uffff\12\102\1\22\6\uffff\1\106\31\102\4\uffff"+
+            "\1\102\1\uffff\1\106\31\102\74\uffff\1\102\10\uffff\27\102\1"+
+            "\uffff\37\102\1\uffff\u0286\102\1\uffff\u1c81\102\14\uffff\2"+
+            "\102\61\uffff\2\102\57\uffff\u0120\102\u0a70\uffff\u03f0\102"+
+            "\21\uffff\ua7ff\102\u2100\uffff\u04d0\102\40\uffff\u020e\102",
+            "\1\102\1\103\1\uffff\12\102\1\22\6\uffff\32\102\4\uffff\1\102"+
+            "\1\uffff\32\102\74\uffff\1\102\10\uffff\27\102\1\uffff\37\102"+
+            "\1\uffff\u0286\102\1\uffff\u1c81\102\14\uffff\2\102\61\uffff"+
+            "\2\102\57\uffff\u0120\102\u0a70\uffff\u03f0\102\21\uffff\ua7ff"+
+            "\102\u2100\uffff\u04d0\102\40\uffff\u020e\102",
+            "\12\110\7\uffff\32\110\4\uffff\1\110\1\uffff\32\110\105\uffff"+
+            "\27\110\1\uffff\37\110\1\uffff\u0208\110\160\uffff\16\110\1"+
+            "\uffff\u1c81\110\14\uffff\2\110\142\uffff\u0120\110\u0a70\uffff"+
+            "\u03f0\110\21\uffff\ua7ff\110\u2100\uffff\u04d0\110\40\uffff"+
+            "\u020e\110",
+            "",
+            "\1\112\1\uffff\12\27\13\uffff\1\113\37\uffff\1\113",
+            "\12\115",
+            "\1\120\1\uffff\12\117",
+            "\12\122\1\uffff\2\122\1\uffff\31\122\1\121\uffd7\122",
+            "\12\124\1\uffff\2\124\1\uffff\24\124\1\123\uffdc\124",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\1\125",
+            "\1\126",
+            "\1\127",
+            "\1\130",
+            "",
+            "\1\132\34\uffff\1\131",
+            "",
+            "\1\134\1\uffff\12\52\13\uffff\1\135\37\uffff\1\135",
+            "\12\136",
+            "\1\61\1\uffff\31\61\1\uffff\1\61\1\137\35\61\1\uffff\1\61\1"+
+            "\uffff\1\61\1\uffff\32\61\3\uffff\uff81\61",
+            "\1\61\1\uffff\31\61\1\uffff\1\61\1\140\35\61\1\uffff\1\61\1"+
+            "\uffff\1\61\1\uffff\32\61\3\uffff\uff81\61",
+            "",
+            "\1\61\1\uffff\31\61\1\uffff\1\61\1\141\35\61\1\uffff\1\61\1"+
+            "\uffff\1\61\1\uffff\32\61\3\uffff\uff81\61",
+            "",
+            "",
+            "\1\143\34\uffff\1\142",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\1\102\1\103\1\uffff\12\102\1\22\6\uffff\24\102\1\144\5\102"+
+            "\4\uffff\1\102\1\uffff\24\102\1\144\5\102\74\uffff\1\102\10"+
+            "\uffff\27\102\1\uffff\37\102\1\uffff\u0286\102\1\uffff\u1c81"+
+            "\102\14\uffff\2\102\61\uffff\2\102\57\uffff\u0120\102\u0a70"+
+            "\uffff\u03f0\102\21\uffff\ua7ff\102\u2100\uffff\u04d0\102\40"+
+            "\uffff\u020e\102",
+            "\1\102\1\103\1\uffff\12\102\1\22\6\uffff\32\102\4\uffff\1\102"+
+            "\1\uffff\32\102\74\uffff\1\102\10\uffff\27\102\1\uffff\37\102"+
+            "\1\uffff\u0286\102\1\uffff\u1c81\102\14\uffff\2\102\61\uffff"+
+            "\2\102\57\uffff\u0120\102\u0a70\uffff\u03f0\102\21\uffff\ua7ff"+
+            "\102\u2100\uffff\u04d0\102\40\uffff\u020e\102",
+            "\1\102\1\103\1\uffff\12\102\7\uffff\32\102\4\uffff\1\102\1\uffff"+
+            "\32\102\74\uffff\1\102\10\uffff\27\102\1\uffff\37\102\1\uffff"+
+            "\u0286\102\1\uffff\u1c81\102\14\uffff\2\102\61\uffff\2\102\57"+
+            "\uffff\u0120\102\u0a70\uffff\u03f0\102\21\uffff\ua7ff\102\u2100"+
+            "\uffff\u04d0\102\40\uffff\u020e\102",
+            "",
+            "",
+            "\1\102\1\103\1\uffff\12\102\1\22\6\uffff\13\102\1\145\16\102"+
+            "\4\uffff\1\102\1\uffff\13\102\1\145\16\102\74\uffff\1\102\10"+
+            "\uffff\27\102\1\uffff\37\102\1\uffff\u0286\102\1\uffff\u1c81"+
+            "\102\14\uffff\2\102\61\uffff\2\102\57\uffff\u0120\102\u0a70"+
+            "\uffff\u03f0\102\21\uffff\ua7ff\102\u2100\uffff\u04d0\102\40"+
+            "\uffff\u020e\102",
+            "",
+            "",
+            "",
+            "\12\147\13\uffff\1\113\37\uffff\1\113",
+            "",
+            "",
+            "\12\115\13\uffff\1\113\37\uffff\1\113",
+            "",
+            "\1\151\1\uffff\12\117\13\uffff\1\152\37\uffff\1\152",
+            "\12\153",
+            "\1\154",
+            "",
+            "\1\155",
+            "",
+            "\1\156",
+            "\1\157",
+            "\1\160",
+            "\1\161",
+            "",
+            "",
+            "",
+            "\12\163\13\uffff\1\135\37\uffff\1\135",
+            "",
+            "\12\136\13\uffff\1\135\37\uffff\1\135",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\1\102\1\103\1\uffff\12\102\1\22\6\uffff\4\102\1\167\25\102"+
+            "\4\uffff\1\102\1\uffff\4\102\1\167\25\102\74\uffff\1\102\10"+
+            "\uffff\27\102\1\uffff\37\102\1\uffff\u0286\102\1\uffff\u1c81"+
+            "\102\14\uffff\2\102\61\uffff\2\102\57\uffff\u0120\102\u0a70"+
+            "\uffff\u03f0\102\21\uffff\ua7ff\102\u2100\uffff\u04d0\102\40"+
+            "\uffff\u020e\102",
+            "\1\102\1\103\1\uffff\12\102\1\22\6\uffff\22\102\1\170\7\102"+
+            "\4\uffff\1\102\1\uffff\22\102\1\170\7\102\74\uffff\1\102\10"+
+            "\uffff\27\102\1\uffff\37\102\1\uffff\u0286\102\1\uffff\u1c81"+
+            "\102\14\uffff\2\102\61\uffff\2\102\57\uffff\u0120\102\u0a70"+
+            "\uffff\u03f0\102\21\uffff\ua7ff\102\u2100\uffff\u04d0\102\40"+
+            "\uffff\u020e\102",
+            "",
+            "\12\147\13\uffff\1\113\37\uffff\1\113",
+            "",
+            "\12\172\13\uffff\1\152\37\uffff\1\152",
+            "",
+            "\12\153\13\uffff\1\152\37\uffff\1\152",
+            "",
+            "",
+            "\1\173",
+            "\1\174",
+            "\1\175",
+            "\1\176",
+            "",
+            "\12\163\13\uffff\1\135\37\uffff\1\135",
+            "",
+            "",
+            "",
+            "\1\102\1\103\1\uffff\12\102\1\22\6\uffff\32\102\4\uffff\1\102"+
+            "\1\uffff\32\102\74\uffff\1\102\10\uffff\27\102\1\uffff\37\102"+
+            "\1\uffff\u0286\102\1\uffff\u1c81\102\14\uffff\2\102\61\uffff"+
+            "\2\102\57\uffff\u0120\102\u0a70\uffff\u03f0\102\21\uffff\ua7ff"+
+            "\102\u2100\uffff\u04d0\102\40\uffff\u020e\102",
+            "\1\102\1\103\1\uffff\12\102\1\22\6\uffff\4\102\1\u0080\25\102"+
+            "\4\uffff\1\102\1\uffff\4\102\1\u0080\25\102\74\uffff\1\102\10"+
+            "\uffff\27\102\1\uffff\37\102\1\uffff\u0286\102\1\uffff\u1c81"+
+            "\102\14\uffff\2\102\61\uffff\2\102\57\uffff\u0120\102\u0a70"+
+            "\uffff\u03f0\102\21\uffff\ua7ff\102\u2100\uffff\u04d0\102\40"+
+            "\uffff\u020e\102",
+            "",
+            "\12\172\13\uffff\1\152\37\uffff\1\152",
+            "\1\u0081",
+            "\1\u0082",
+            "\1\u0083",
+            "\1\47\23\uffff\32\47\6\uffff\32\47\105\uffff\27\47\1\uffff\37"+
+            "\47\1\uffff\u0208\47\160\uffff\16\47\1\uffff\u1c81\47\14\uffff"+
+            "\2\47\142\uffff\u0120\47\u0a70\uffff\u03f0\47\21\uffff\ua7ff"+
+            "\47\u2100\uffff\u04d0\47\40\uffff\u020e\47",
+            "",
+            "\1\102\1\103\1\uffff\12\102\1\22\6\uffff\32\102\4\uffff\1\102"+
+            "\1\uffff\32\102\74\uffff\1\102\10\uffff\27\102\1\uffff\37\102"+
+            "\1\uffff\u0286\102\1\uffff\u1c81\102\14\uffff\2\102\61\uffff"+
+            "\2\102\57\uffff\u0120\102\u0a70\uffff\u03f0\102\21\uffff\ua7ff"+
+            "\102\u2100\uffff\u04d0\102\40\uffff\u020e\102",
+            "\1\u0086",
+            "\1\u0087",
+            "\1\47\23\uffff\32\47\6\uffff\32\47\105\uffff\27\47\1\uffff\37"+
+            "\47\1\uffff\u0208\47\160\uffff\16\47\1\uffff\u1c81\47\14\uffff"+
+            "\2\47\142\uffff\u0120\47\u0a70\uffff\u03f0\47\21\uffff\ua7ff"+
+            "\47\u2100\uffff\u04d0\47\40\uffff\u020e\47",
+            "",
+            "",
+            "\1\47\23\uffff\32\47\6\uffff\32\47\105\uffff\27\47\1\uffff\37"+
+            "\47\1\uffff\u0208\47\160\uffff\16\47\1\uffff\u1c81\47\14\uffff"+
+            "\2\47\142\uffff\u0120\47\u0a70\uffff\u03f0\47\21\uffff\ua7ff"+
+            "\47\u2100\uffff\u04d0\47\40\uffff\u020e\47",
+            "\1\47\23\uffff\32\47\6\uffff\32\47\105\uffff\27\47\1\uffff\37"+
+            "\47\1\uffff\u0208\47\160\uffff\16\47\1\uffff\u1c81\47\14\uffff"+
+            "\2\47\142\uffff\u0120\47\u0a70\uffff\u03f0\47\21\uffff\ua7ff"+
+            "\47\u2100\uffff\u04d0\47\40\uffff\u020e\47",
+            "",
+            "",
+            ""
+    };
+
+    static final short[] DFA36_eot = DFA.unpackEncodedString(DFA36_eotS);
+    static final short[] DFA36_eof = DFA.unpackEncodedString(DFA36_eofS);
+    static final char[] DFA36_min = DFA.unpackEncodedStringToUnsignedChars(DFA36_minS);
+    static final char[] DFA36_max = DFA.unpackEncodedStringToUnsignedChars(DFA36_maxS);
+    static final short[] DFA36_accept = DFA.unpackEncodedString(DFA36_acceptS);
+    static final short[] DFA36_special = DFA.unpackEncodedString(DFA36_specialS);
+    static final short[][] DFA36_transition;
+
+    static {
+        int numStates = DFA36_transitionS.length;
+        DFA36_transition = new short[numStates][];
+        for (int i=0; i<numStates; i++) {
+            DFA36_transition[i] = DFA.unpackEncodedString(DFA36_transitionS[i]);
+        }
+    }
+
+    class DFA36 extends DFA {
+
+        public DFA36(BaseRecognizer recognizer) {
+            this.recognizer = recognizer;
+            this.decisionNumber = 36;
+            this.eot = DFA36_eot;
+            this.eof = DFA36_eof;
+            this.min = DFA36_min;
+            this.max = DFA36_max;
+            this.accept = DFA36_accept;
+            this.special = DFA36_special;
+            this.transition = DFA36_transition;
+        }
+        public String getDescription() {
+            return "1:1: Tokens : ( WS | AT_IMPORT | AT_PREFIX | AT_BASE | AT_DELAY | INHERITANCE | SIMILARITY | INSTANCE | PROPERTY | INSTANCE_PROPERTY | IMPLICATION | IMPLICATION_PRED | IMPLICATION_RETRO | IMPLICATION_CONC | EQUIVALENCE | EQUIVALENCE_PRED | EQUIVALENCE_CONC | NOT | PAST | PRESENT | FUTURE | CONJ | DISJ | OPEN_BRACE | CLOSE_BRACE | LPAREN | RPAREN | LBRACKET | RBRACKET | PNAME_NS | PNAME_LN | TRUE | FALSE | IRI_REF | LANGTAG | QUERY_VAR | STM_VAR | INTEGER | DECIMAL | DOUBLE | INTEGER_POSITIVE | DECIMAL_POSITIVE | DOUBLE_POSITIVE | INTEGER_NEGATIVE | DECIMAL_NEGATIVE | DOUBLE_NEGATIVE | STRING_LITERAL1 | STRING_LITERAL2 | STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2 | COMMENT | REFERENCE | EXCLAMATION | QUESTION | DOT | COMMA | SEMICOLON | AMPERSAND | BAR | LANGLE | RANGLE | PERCENT | PLUS | MINUS | STAR | TILDE );";
+        }
+    }
+ 
+
+}
\ No newline at end of file
diff --git a/open-nars/com/googlecode/opennars/parser/loan/loanParser.java b/open-nars/com/googlecode/opennars/parser/loan/loanParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..b70c73316a1141e30a0fec94c0723a9299a73c29
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/parser/loan/loanParser.java
@@ -0,0 +1,3160 @@
+package com.googlecode.opennars.parser.loan;
+
+import org.antlr.runtime.*;
+import java.util.Stack;
+import java.util.List;
+import java.util.ArrayList;
+
+
+import org.antlr.runtime.tree.*;
+
+public class loanParser extends Parser {
+    public static final String[] tokenNames = new String[] {
+        "<invalid>", "<EOR>", "<DOWN>", "<UP>", "AT_BASE", "IRI_REF", "DOT", "AT_IMPORT", "AT_PREFIX", "PNAME_NS", "AT_DELAY", "LPAREN", "INTEGER", "RPAREN", "EXCLAMATION", "QUESTION", "PERCENT", "DECIMAL", "SEMICOLON", "CONJ", "COMMA", "DISJ", "NOT", "PAST", "PRESENT", "FUTURE", "INHERITANCE", "SIMILARITY", "INSTANCE", "PROPERTY", "INSTANCE_PROPERTY", "IMPLICATION", "IMPLICATION_PRED", "IMPLICATION_RETRO", "IMPLICATION_CONC", "EQUIVALENCE", "EQUIVALENCE_PRED", "EQUIVALENCE_CONC", "AMPERSAND", "BAR", "OPEN_BRACE", "CLOSE_BRACE", "LBRACKET", "RBRACKET", "MINUS", "TILDE", "STAR", "QUERY_VAR", "STM_VAR", "DOUBLE", "INTEGER_POSITIVE", "DECIMAL_POSITIVE", "DOUBLE_POSITIVE", "INTEGER_NEGATIVE", "DECIMAL_NEGATIVE", "DOUBLE_NEGATIVE", "TRUE", "FALSE", "STRING_LITERAL1", "STRING_LITERAL2", "STRING_LITERAL_LONG1", "STRING_LITERAL_LONG2", "PNAME_LN", "EOL", "WS", "PN_PREFIX", "PN_LOCAL", "LANGLE", "RANGLE", "PN_CHARS_BASE", "DIGIT", "LANGTAG", "EXPONENT", "PLUS", "ECHAR", "PN_CHARS_U", "VARNAME", "PN_CHARS", "COMMENT", "REFERENCE"
+    };
+    public static final int COMMA=20;
+    public static final int PN_CHARS_U=75;
+    public static final int MINUS=44;
+    public static final int PERCENT=16;
+    public static final int AT_PREFIX=8;
+    public static final int OPEN_BRACE=40;
+    public static final int DOUBLE=49;
+    public static final int AT_BASE=4;
+    public static final int EQUIVALENCE=35;
+    public static final int FALSE=57;
+    public static final int PN_CHARS_BASE=69;
+    public static final int EQUIVALENCE_CONC=37;
+    public static final int QUERY_VAR=47;
+    public static final int AT_DELAY=10;
+    public static final int LBRACKET=42;
+    public static final int INHERITANCE=26;
+    public static final int INSTANCE=28;
+    public static final int TILDE=45;
+    public static final int DECIMAL=17;
+    public static final int QUESTION=15;
+    public static final int CONJ=19;
+    public static final int DISJ=21;
+    public static final int IMPLICATION=31;
+    public static final int DOT=6;
+    public static final int STM_VAR=48;
+    public static final int RANGLE=68;
+    public static final int INTEGER=12;
+    public static final int IMPLICATION_RETRO=33;
+    public static final int FUTURE=25;
+    public static final int RBRACKET=43;
+    public static final int RPAREN=13;
+    public static final int PN_PREFIX=65;
+    public static final int EQUIVALENCE_PRED=36;
+    public static final int LANGLE=67;
+    public static final int LPAREN=11;
+    public static final int INSTANCE_PROPERTY=30;
+    public static final int ECHAR=74;
+    public static final int PLUS=73;
+    public static final int DIGIT=70;
+    public static final int AMPERSAND=38;
+    public static final int INTEGER_NEGATIVE=53;
+    public static final int PNAME_NS=9;
+    public static final int PAST=23;
+    public static final int SIMILARITY=27;
+    public static final int PROPERTY=29;
+    public static final int DECIMAL_POSITIVE=51;
+    public static final int STRING_LITERAL_LONG1=60;
+    public static final int IMPLICATION_PRED=32;
+    public static final int WS=64;
+    public static final int PNAME_LN=62;
+    public static final int LANGTAG=71;
+    public static final int EXCLAMATION=14;
+    public static final int PN_LOCAL=66;
+    public static final int VARNAME=76;
+    public static final int CLOSE_BRACE=41;
+    public static final int COMMENT=78;
+    public static final int PN_CHARS=77;
+    public static final int PRESENT=24;
+    public static final int AT_IMPORT=7;
+    public static final int STRING_LITERAL_LONG2=61;
+    public static final int DOUBLE_NEGATIVE=55;
+    public static final int EXPONENT=72;
+    public static final int SEMICOLON=18;
+    public static final int BAR=39;
+    public static final int DECIMAL_NEGATIVE=54;
+    public static final int EOF=-1;
+    public static final int IRI_REF=5;
+    public static final int DOUBLE_POSITIVE=52;
+    public static final int REFERENCE=79;
+    public static final int EOL=63;
+    public static final int INTEGER_POSITIVE=50;
+    public static final int STAR=46;
+    public static final int NOT=22;
+    public static final int STRING_LITERAL2=59;
+    public static final int TRUE=56;
+    public static final int STRING_LITERAL1=58;
+    public static final int IMPLICATION_CONC=34;
+
+        public loanParser(TokenStream input) {
+            super(input);
+        }
+        
+    protected TreeAdaptor adaptor = new CommonTreeAdaptor();
+
+    public void setTreeAdaptor(TreeAdaptor adaptor) {
+        this.adaptor = adaptor;
+    }
+    public TreeAdaptor getTreeAdaptor() {
+        return adaptor;
+    }
+
+    public String[] getTokenNames() { return tokenNames; }
+    public String getGrammarFileName() { return "/Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g"; }
+
+
+    public static class document_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start document
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:9:1: document : ( base_rule )? ( at_rule | sentence )* EOF ;
+    public final document_return document() throws RecognitionException {
+        document_return retval = new document_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token EOF4=null;
+        base_rule_return base_rule1 = null;
+
+        at_rule_return at_rule2 = null;
+
+        sentence_return sentence3 = null;
+
+
+        Object EOF4_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:10:2: ( ( base_rule )? ( at_rule | sentence )* EOF )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:10:4: ( base_rule )? ( at_rule | sentence )* EOF
+            {
+            root_0 = (Object)adaptor.nil();
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:10:4: ( base_rule )?
+            int alt1=2;
+            int LA1_0 = input.LA(1);
+
+            if ( (LA1_0==AT_BASE) ) {
+                alt1=1;
+            }
+            switch (alt1) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:10:4: base_rule
+                    {
+                    pushFollow(FOLLOW_base_rule_in_document27);
+                    base_rule1=base_rule();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, base_rule1.getTree());
+
+                    }
+                    break;
+
+            }
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:10:15: ( at_rule | sentence )*
+            loop2:
+            do {
+                int alt2=3;
+                int LA2_0 = input.LA(1);
+
+                if ( ((LA2_0>=AT_IMPORT && LA2_0<=AT_PREFIX)||LA2_0==AT_DELAY) ) {
+                    alt2=1;
+                }
+                else if ( (LA2_0==IRI_REF||LA2_0==PNAME_NS||(LA2_0>=LPAREN && LA2_0<=INTEGER)||LA2_0==DECIMAL||(LA2_0>=NOT && LA2_0<=FUTURE)||LA2_0==OPEN_BRACE||LA2_0==LBRACKET||(LA2_0>=QUERY_VAR && LA2_0<=PNAME_LN)) ) {
+                    alt2=2;
+                }
+
+
+                switch (alt2) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:10:16: at_rule
+            	    {
+            	    pushFollow(FOLLOW_at_rule_in_document31);
+            	    at_rule2=at_rule();
+            	    _fsp--;
+
+            	    adaptor.addChild(root_0, at_rule2.getTree());
+
+            	    }
+            	    break;
+            	case 2 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:10:26: sentence
+            	    {
+            	    pushFollow(FOLLOW_sentence_in_document35);
+            	    sentence3=sentence();
+            	    _fsp--;
+
+            	    adaptor.addChild(root_0, sentence3.getTree());
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop2;
+                }
+            } while (true);
+
+            EOF4=(Token)input.LT(1);
+            match(input,EOF,FOLLOW_EOF_in_document39); 
+            EOF4_tree = (Object)adaptor.create(EOF4);
+            adaptor.addChild(root_0, EOF4_tree);
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end document
+
+    public static class base_rule_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start base_rule
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:12:1: base_rule : AT_BASE IRI_REF DOT ;
+    public final base_rule_return base_rule() throws RecognitionException {
+        base_rule_return retval = new base_rule_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token AT_BASE5=null;
+        Token IRI_REF6=null;
+        Token DOT7=null;
+
+        Object AT_BASE5_tree=null;
+        Object IRI_REF6_tree=null;
+        Object DOT7_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:13:2: ( AT_BASE IRI_REF DOT )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:13:4: AT_BASE IRI_REF DOT
+            {
+            root_0 = (Object)adaptor.nil();
+
+            AT_BASE5=(Token)input.LT(1);
+            match(input,AT_BASE,FOLLOW_AT_BASE_in_base_rule50); 
+            AT_BASE5_tree = (Object)adaptor.create(AT_BASE5);
+            root_0 = (Object)adaptor.becomeRoot(AT_BASE5_tree, root_0);
+
+            IRI_REF6=(Token)input.LT(1);
+            match(input,IRI_REF,FOLLOW_IRI_REF_in_base_rule53); 
+            IRI_REF6_tree = (Object)adaptor.create(IRI_REF6);
+            adaptor.addChild(root_0, IRI_REF6_tree);
+
+            DOT7=(Token)input.LT(1);
+            match(input,DOT,FOLLOW_DOT_in_base_rule55); 
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end base_rule
+
+    public static class at_rule_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start at_rule
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:16:1: at_rule : ( AT_IMPORT IRI_REF DOT | AT_PREFIX PNAME_NS IRI_REF DOT | AT_DELAY LPAREN INTEGER RPAREN DOT );
+    public final at_rule_return at_rule() throws RecognitionException {
+        at_rule_return retval = new at_rule_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token AT_IMPORT8=null;
+        Token IRI_REF9=null;
+        Token DOT10=null;
+        Token AT_PREFIX11=null;
+        Token PNAME_NS12=null;
+        Token IRI_REF13=null;
+        Token DOT14=null;
+        Token AT_DELAY15=null;
+        Token LPAREN16=null;
+        Token INTEGER17=null;
+        Token RPAREN18=null;
+        Token DOT19=null;
+
+        Object AT_IMPORT8_tree=null;
+        Object IRI_REF9_tree=null;
+        Object DOT10_tree=null;
+        Object AT_PREFIX11_tree=null;
+        Object PNAME_NS12_tree=null;
+        Object IRI_REF13_tree=null;
+        Object DOT14_tree=null;
+        Object AT_DELAY15_tree=null;
+        Object LPAREN16_tree=null;
+        Object INTEGER17_tree=null;
+        Object RPAREN18_tree=null;
+        Object DOT19_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:16:9: ( AT_IMPORT IRI_REF DOT | AT_PREFIX PNAME_NS IRI_REF DOT | AT_DELAY LPAREN INTEGER RPAREN DOT )
+            int alt3=3;
+            switch ( input.LA(1) ) {
+            case AT_IMPORT:
+                {
+                alt3=1;
+                }
+                break;
+            case AT_PREFIX:
+                {
+                alt3=2;
+                }
+                break;
+            case AT_DELAY:
+                {
+                alt3=3;
+                }
+                break;
+            default:
+                NoViableAltException nvae =
+                    new NoViableAltException("16:1: at_rule : ( AT_IMPORT IRI_REF DOT | AT_PREFIX PNAME_NS IRI_REF DOT | AT_DELAY LPAREN INTEGER RPAREN DOT );", 3, 0, input);
+
+                throw nvae;
+            }
+
+            switch (alt3) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:16:11: AT_IMPORT IRI_REF DOT
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    AT_IMPORT8=(Token)input.LT(1);
+                    match(input,AT_IMPORT,FOLLOW_AT_IMPORT_in_at_rule66); 
+                    AT_IMPORT8_tree = (Object)adaptor.create(AT_IMPORT8);
+                    root_0 = (Object)adaptor.becomeRoot(AT_IMPORT8_tree, root_0);
+
+                    IRI_REF9=(Token)input.LT(1);
+                    match(input,IRI_REF,FOLLOW_IRI_REF_in_at_rule69); 
+                    IRI_REF9_tree = (Object)adaptor.create(IRI_REF9);
+                    adaptor.addChild(root_0, IRI_REF9_tree);
+
+                    DOT10=(Token)input.LT(1);
+                    match(input,DOT,FOLLOW_DOT_in_at_rule71); 
+
+                    }
+                    break;
+                case 2 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:17:4: AT_PREFIX PNAME_NS IRI_REF DOT
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    AT_PREFIX11=(Token)input.LT(1);
+                    match(input,AT_PREFIX,FOLLOW_AT_PREFIX_in_at_rule77); 
+                    AT_PREFIX11_tree = (Object)adaptor.create(AT_PREFIX11);
+                    root_0 = (Object)adaptor.becomeRoot(AT_PREFIX11_tree, root_0);
+
+                    PNAME_NS12=(Token)input.LT(1);
+                    match(input,PNAME_NS,FOLLOW_PNAME_NS_in_at_rule80); 
+                    PNAME_NS12_tree = (Object)adaptor.create(PNAME_NS12);
+                    adaptor.addChild(root_0, PNAME_NS12_tree);
+
+                    IRI_REF13=(Token)input.LT(1);
+                    match(input,IRI_REF,FOLLOW_IRI_REF_in_at_rule82); 
+                    IRI_REF13_tree = (Object)adaptor.create(IRI_REF13);
+                    adaptor.addChild(root_0, IRI_REF13_tree);
+
+                    DOT14=(Token)input.LT(1);
+                    match(input,DOT,FOLLOW_DOT_in_at_rule84); 
+
+                    }
+                    break;
+                case 3 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:18:4: AT_DELAY LPAREN INTEGER RPAREN DOT
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    AT_DELAY15=(Token)input.LT(1);
+                    match(input,AT_DELAY,FOLLOW_AT_DELAY_in_at_rule90); 
+                    AT_DELAY15_tree = (Object)adaptor.create(AT_DELAY15);
+                    root_0 = (Object)adaptor.becomeRoot(AT_DELAY15_tree, root_0);
+
+                    LPAREN16=(Token)input.LT(1);
+                    match(input,LPAREN,FOLLOW_LPAREN_in_at_rule93); 
+                    INTEGER17=(Token)input.LT(1);
+                    match(input,INTEGER,FOLLOW_INTEGER_in_at_rule96); 
+                    INTEGER17_tree = (Object)adaptor.create(INTEGER17);
+                    adaptor.addChild(root_0, INTEGER17_tree);
+
+                    RPAREN18=(Token)input.LT(1);
+                    match(input,RPAREN,FOLLOW_RPAREN_in_at_rule98); 
+                    DOT19=(Token)input.LT(1);
+                    match(input,DOT,FOLLOW_DOT_in_at_rule101); 
+
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end at_rule
+
+    public static class sentence_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start sentence
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:21:1: sentence : statement ( judgement | question | goal ) ;
+    public final sentence_return sentence() throws RecognitionException {
+        sentence_return retval = new sentence_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        statement_return statement20 = null;
+
+        judgement_return judgement21 = null;
+
+        question_return question22 = null;
+
+        goal_return goal23 = null;
+
+
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:22:2: ( statement ( judgement | question | goal ) )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:22:4: statement ( judgement | question | goal )
+            {
+            root_0 = (Object)adaptor.nil();
+
+            pushFollow(FOLLOW_statement_in_sentence114);
+            statement20=statement();
+            _fsp--;
+
+            adaptor.addChild(root_0, statement20.getTree());
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:22:14: ( judgement | question | goal )
+            int alt4=3;
+            switch ( input.LA(1) ) {
+            case DOT:
+                {
+                alt4=1;
+                }
+                break;
+            case QUESTION:
+                {
+                alt4=2;
+                }
+                break;
+            case EXCLAMATION:
+                {
+                alt4=3;
+                }
+                break;
+            default:
+                NoViableAltException nvae =
+                    new NoViableAltException("22:14: ( judgement | question | goal )", 4, 0, input);
+
+                throw nvae;
+            }
+
+            switch (alt4) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:22:15: judgement
+                    {
+                    pushFollow(FOLLOW_judgement_in_sentence117);
+                    judgement21=judgement();
+                    _fsp--;
+
+                    root_0 = (Object)adaptor.becomeRoot(judgement21.getTree(), root_0);
+
+                    }
+                    break;
+                case 2 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:22:26: question
+                    {
+                    pushFollow(FOLLOW_question_in_sentence120);
+                    question22=question();
+                    _fsp--;
+
+                    root_0 = (Object)adaptor.becomeRoot(question22.getTree(), root_0);
+
+                    }
+                    break;
+                case 3 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:22:36: goal
+                    {
+                    pushFollow(FOLLOW_goal_in_sentence123);
+                    goal23=goal();
+                    _fsp--;
+
+                    root_0 = (Object)adaptor.becomeRoot(goal23.getTree(), root_0);
+
+                    }
+                    break;
+
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end sentence
+
+    public static class judgement_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start judgement
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:25:1: judgement : DOT ( truthvalue )? ;
+    public final judgement_return judgement() throws RecognitionException {
+        judgement_return retval = new judgement_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token DOT24=null;
+        truthvalue_return truthvalue25 = null;
+
+
+        Object DOT24_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:26:2: ( DOT ( truthvalue )? )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:26:4: DOT ( truthvalue )?
+            {
+            root_0 = (Object)adaptor.nil();
+
+            DOT24=(Token)input.LT(1);
+            match(input,DOT,FOLLOW_DOT_in_judgement138); 
+            DOT24_tree = (Object)adaptor.create(DOT24);
+            root_0 = (Object)adaptor.becomeRoot(DOT24_tree, root_0);
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:26:9: ( truthvalue )?
+            int alt5=2;
+            int LA5_0 = input.LA(1);
+
+            if ( (LA5_0==PERCENT) ) {
+                alt5=1;
+            }
+            switch (alt5) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:26:9: truthvalue
+                    {
+                    pushFollow(FOLLOW_truthvalue_in_judgement141);
+                    truthvalue25=truthvalue();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, truthvalue25.getTree());
+
+                    }
+                    break;
+
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end judgement
+
+    public static class goal_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start goal
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:29:1: goal : EXCLAMATION ( truthvalue )? ;
+    public final goal_return goal() throws RecognitionException {
+        goal_return retval = new goal_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token EXCLAMATION26=null;
+        truthvalue_return truthvalue27 = null;
+
+
+        Object EXCLAMATION26_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:29:6: ( EXCLAMATION ( truthvalue )? )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:29:8: EXCLAMATION ( truthvalue )?
+            {
+            root_0 = (Object)adaptor.nil();
+
+            EXCLAMATION26=(Token)input.LT(1);
+            match(input,EXCLAMATION,FOLLOW_EXCLAMATION_in_goal153); 
+            EXCLAMATION26_tree = (Object)adaptor.create(EXCLAMATION26);
+            root_0 = (Object)adaptor.becomeRoot(EXCLAMATION26_tree, root_0);
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:29:21: ( truthvalue )?
+            int alt6=2;
+            int LA6_0 = input.LA(1);
+
+            if ( (LA6_0==PERCENT) ) {
+                alt6=1;
+            }
+            switch (alt6) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:29:21: truthvalue
+                    {
+                    pushFollow(FOLLOW_truthvalue_in_goal156);
+                    truthvalue27=truthvalue();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, truthvalue27.getTree());
+
+                    }
+                    break;
+
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end goal
+
+    public static class question_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start question
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:32:1: question : QUESTION ;
+    public final question_return question() throws RecognitionException {
+        question_return retval = new question_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token QUESTION28=null;
+
+        Object QUESTION28_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:33:2: ( QUESTION )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:33:4: QUESTION
+            {
+            root_0 = (Object)adaptor.nil();
+
+            QUESTION28=(Token)input.LT(1);
+            match(input,QUESTION,FOLLOW_QUESTION_in_question170); 
+            QUESTION28_tree = (Object)adaptor.create(QUESTION28);
+            root_0 = (Object)adaptor.becomeRoot(QUESTION28_tree, root_0);
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end question
+
+    public static class truthvalue_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start truthvalue
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:36:1: truthvalue : PERCENT ( DECIMAL | INTEGER ) ( SEMICOLON DECIMAL )? PERCENT ;
+    public final truthvalue_return truthvalue() throws RecognitionException {
+        truthvalue_return retval = new truthvalue_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token PERCENT29=null;
+        Token set30=null;
+        Token SEMICOLON31=null;
+        Token DECIMAL32=null;
+        Token PERCENT33=null;
+
+        Object PERCENT29_tree=null;
+        Object set30_tree=null;
+        Object SEMICOLON31_tree=null;
+        Object DECIMAL32_tree=null;
+        Object PERCENT33_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:37:2: ( PERCENT ( DECIMAL | INTEGER ) ( SEMICOLON DECIMAL )? PERCENT )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:37:4: PERCENT ( DECIMAL | INTEGER ) ( SEMICOLON DECIMAL )? PERCENT
+            {
+            root_0 = (Object)adaptor.nil();
+
+            PERCENT29=(Token)input.LT(1);
+            match(input,PERCENT,FOLLOW_PERCENT_in_truthvalue184); 
+            set30=(Token)input.LT(1);
+            if ( input.LA(1)==INTEGER||input.LA(1)==DECIMAL ) {
+                input.consume();
+                adaptor.addChild(root_0, adaptor.create(set30));
+                errorRecovery=false;
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recoverFromMismatchedSet(input,mse,FOLLOW_set_in_truthvalue187);    throw mse;
+            }
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:37:33: ( SEMICOLON DECIMAL )?
+            int alt7=2;
+            int LA7_0 = input.LA(1);
+
+            if ( (LA7_0==SEMICOLON) ) {
+                alt7=1;
+            }
+            switch (alt7) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:37:34: SEMICOLON DECIMAL
+                    {
+                    SEMICOLON31=(Token)input.LT(1);
+                    match(input,SEMICOLON,FOLLOW_SEMICOLON_in_truthvalue196); 
+                    SEMICOLON31_tree = (Object)adaptor.create(SEMICOLON31);
+                    adaptor.addChild(root_0, SEMICOLON31_tree);
+
+                    DECIMAL32=(Token)input.LT(1);
+                    match(input,DECIMAL,FOLLOW_DECIMAL_in_truthvalue198); 
+                    DECIMAL32_tree = (Object)adaptor.create(DECIMAL32);
+                    adaptor.addChild(root_0, DECIMAL32_tree);
+
+
+                    }
+                    break;
+
+            }
+
+            PERCENT33=(Token)input.LT(1);
+            match(input,PERCENT,FOLLOW_PERCENT_in_truthvalue202); 
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end truthvalue
+
+    public static class statement_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start statement
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:39:1: statement : unary_statement ( ( CONJ | SEMICOLON | COMMA | DISJ ) unary_statement )* ;
+    public final statement_return statement() throws RecognitionException {
+        statement_return retval = new statement_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token CONJ35=null;
+        Token SEMICOLON36=null;
+        Token COMMA37=null;
+        Token DISJ38=null;
+        unary_statement_return unary_statement34 = null;
+
+        unary_statement_return unary_statement39 = null;
+
+
+        Object CONJ35_tree=null;
+        Object SEMICOLON36_tree=null;
+        Object COMMA37_tree=null;
+        Object DISJ38_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:40:2: ( unary_statement ( ( CONJ | SEMICOLON | COMMA | DISJ ) unary_statement )* )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:40:4: unary_statement ( ( CONJ | SEMICOLON | COMMA | DISJ ) unary_statement )*
+            {
+            root_0 = (Object)adaptor.nil();
+
+            pushFollow(FOLLOW_unary_statement_in_statement213);
+            unary_statement34=unary_statement();
+            _fsp--;
+
+            adaptor.addChild(root_0, unary_statement34.getTree());
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:40:20: ( ( CONJ | SEMICOLON | COMMA | DISJ ) unary_statement )*
+            loop9:
+            do {
+                int alt9=2;
+                int LA9_0 = input.LA(1);
+
+                if ( ((LA9_0>=SEMICOLON && LA9_0<=DISJ)) ) {
+                    alt9=1;
+                }
+
+
+                switch (alt9) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:40:21: ( CONJ | SEMICOLON | COMMA | DISJ ) unary_statement
+            	    {
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:40:21: ( CONJ | SEMICOLON | COMMA | DISJ )
+            	    int alt8=4;
+            	    switch ( input.LA(1) ) {
+            	    case CONJ:
+            	        {
+            	        alt8=1;
+            	        }
+            	        break;
+            	    case SEMICOLON:
+            	        {
+            	        alt8=2;
+            	        }
+            	        break;
+            	    case COMMA:
+            	        {
+            	        alt8=3;
+            	        }
+            	        break;
+            	    case DISJ:
+            	        {
+            	        alt8=4;
+            	        }
+            	        break;
+            	    default:
+            	        NoViableAltException nvae =
+            	            new NoViableAltException("40:21: ( CONJ | SEMICOLON | COMMA | DISJ )", 8, 0, input);
+
+            	        throw nvae;
+            	    }
+
+            	    switch (alt8) {
+            	        case 1 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:40:22: CONJ
+            	            {
+            	            CONJ35=(Token)input.LT(1);
+            	            match(input,CONJ,FOLLOW_CONJ_in_statement217); 
+            	            CONJ35_tree = (Object)adaptor.create(CONJ35);
+            	            root_0 = (Object)adaptor.becomeRoot(CONJ35_tree, root_0);
+
+
+            	            }
+            	            break;
+            	        case 2 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:40:30: SEMICOLON
+            	            {
+            	            SEMICOLON36=(Token)input.LT(1);
+            	            match(input,SEMICOLON,FOLLOW_SEMICOLON_in_statement222); 
+            	            SEMICOLON36_tree = (Object)adaptor.create(SEMICOLON36);
+            	            root_0 = (Object)adaptor.becomeRoot(SEMICOLON36_tree, root_0);
+
+
+            	            }
+            	            break;
+            	        case 3 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:40:43: COMMA
+            	            {
+            	            COMMA37=(Token)input.LT(1);
+            	            match(input,COMMA,FOLLOW_COMMA_in_statement227); 
+            	            COMMA37_tree = (Object)adaptor.create(COMMA37);
+            	            root_0 = (Object)adaptor.becomeRoot(COMMA37_tree, root_0);
+
+
+            	            }
+            	            break;
+            	        case 4 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:40:52: DISJ
+            	            {
+            	            DISJ38=(Token)input.LT(1);
+            	            match(input,DISJ,FOLLOW_DISJ_in_statement232); 
+            	            DISJ38_tree = (Object)adaptor.create(DISJ38);
+            	            root_0 = (Object)adaptor.becomeRoot(DISJ38_tree, root_0);
+
+
+            	            }
+            	            break;
+
+            	    }
+
+            	    pushFollow(FOLLOW_unary_statement_in_statement236);
+            	    unary_statement39=unary_statement();
+            	    _fsp--;
+
+            	    adaptor.addChild(root_0, unary_statement39.getTree());
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop9;
+                }
+            } while (true);
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end statement
+
+    public static class unary_statement_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start unary_statement
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:43:1: unary_statement : ( NOT simple_statement | PAST simple_statement | PRESENT simple_statement | FUTURE simple_statement | simple_statement );
+    public final unary_statement_return unary_statement() throws RecognitionException {
+        unary_statement_return retval = new unary_statement_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token NOT40=null;
+        Token PAST42=null;
+        Token PRESENT44=null;
+        Token FUTURE46=null;
+        simple_statement_return simple_statement41 = null;
+
+        simple_statement_return simple_statement43 = null;
+
+        simple_statement_return simple_statement45 = null;
+
+        simple_statement_return simple_statement47 = null;
+
+        simple_statement_return simple_statement48 = null;
+
+
+        Object NOT40_tree=null;
+        Object PAST42_tree=null;
+        Object PRESENT44_tree=null;
+        Object FUTURE46_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:44:2: ( NOT simple_statement | PAST simple_statement | PRESENT simple_statement | FUTURE simple_statement | simple_statement )
+            int alt10=5;
+            switch ( input.LA(1) ) {
+            case NOT:
+                {
+                alt10=1;
+                }
+                break;
+            case PAST:
+                {
+                alt10=2;
+                }
+                break;
+            case PRESENT:
+                {
+                alt10=3;
+                }
+                break;
+            case FUTURE:
+                {
+                alt10=4;
+                }
+                break;
+            case IRI_REF:
+            case PNAME_NS:
+            case LPAREN:
+            case INTEGER:
+            case DECIMAL:
+            case OPEN_BRACE:
+            case LBRACKET:
+            case QUERY_VAR:
+            case STM_VAR:
+            case DOUBLE:
+            case INTEGER_POSITIVE:
+            case DECIMAL_POSITIVE:
+            case DOUBLE_POSITIVE:
+            case INTEGER_NEGATIVE:
+            case DECIMAL_NEGATIVE:
+            case DOUBLE_NEGATIVE:
+            case TRUE:
+            case FALSE:
+            case STRING_LITERAL1:
+            case STRING_LITERAL2:
+            case STRING_LITERAL_LONG1:
+            case STRING_LITERAL_LONG2:
+            case PNAME_LN:
+                {
+                alt10=5;
+                }
+                break;
+            default:
+                NoViableAltException nvae =
+                    new NoViableAltException("43:1: unary_statement : ( NOT simple_statement | PAST simple_statement | PRESENT simple_statement | FUTURE simple_statement | simple_statement );", 10, 0, input);
+
+                throw nvae;
+            }
+
+            switch (alt10) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:44:4: NOT simple_statement
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    NOT40=(Token)input.LT(1);
+                    match(input,NOT,FOLLOW_NOT_in_unary_statement251); 
+                    NOT40_tree = (Object)adaptor.create(NOT40);
+                    adaptor.addChild(root_0, NOT40_tree);
+
+                    pushFollow(FOLLOW_simple_statement_in_unary_statement253);
+                    simple_statement41=simple_statement();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, simple_statement41.getTree());
+
+                    }
+                    break;
+                case 2 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:45:4: PAST simple_statement
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    PAST42=(Token)input.LT(1);
+                    match(input,PAST,FOLLOW_PAST_in_unary_statement258); 
+                    PAST42_tree = (Object)adaptor.create(PAST42);
+                    adaptor.addChild(root_0, PAST42_tree);
+
+                    pushFollow(FOLLOW_simple_statement_in_unary_statement260);
+                    simple_statement43=simple_statement();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, simple_statement43.getTree());
+
+                    }
+                    break;
+                case 3 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:46:4: PRESENT simple_statement
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    PRESENT44=(Token)input.LT(1);
+                    match(input,PRESENT,FOLLOW_PRESENT_in_unary_statement265); 
+                    PRESENT44_tree = (Object)adaptor.create(PRESENT44);
+                    adaptor.addChild(root_0, PRESENT44_tree);
+
+                    pushFollow(FOLLOW_simple_statement_in_unary_statement267);
+                    simple_statement45=simple_statement();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, simple_statement45.getTree());
+
+                    }
+                    break;
+                case 4 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:47:4: FUTURE simple_statement
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    FUTURE46=(Token)input.LT(1);
+                    match(input,FUTURE,FOLLOW_FUTURE_in_unary_statement272); 
+                    FUTURE46_tree = (Object)adaptor.create(FUTURE46);
+                    adaptor.addChild(root_0, FUTURE46_tree);
+
+                    pushFollow(FOLLOW_simple_statement_in_unary_statement274);
+                    simple_statement47=simple_statement();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, simple_statement47.getTree());
+
+                    }
+                    break;
+                case 5 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:48:4: simple_statement
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_simple_statement_in_unary_statement279);
+                    simple_statement48=simple_statement();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, simple_statement48.getTree());
+
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end unary_statement
+
+    public static class simple_statement_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start simple_statement
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:51:1: simple_statement : term ( ( INHERITANCE | SIMILARITY | INSTANCE | PROPERTY | INSTANCE_PROPERTY | IMPLICATION | IMPLICATION_PRED | IMPLICATION_RETRO | IMPLICATION_CONC | EQUIVALENCE | EQUIVALENCE_PRED | EQUIVALENCE_CONC ) term )? ;
+    public final simple_statement_return simple_statement() throws RecognitionException {
+        simple_statement_return retval = new simple_statement_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token INHERITANCE50=null;
+        Token SIMILARITY51=null;
+        Token INSTANCE52=null;
+        Token PROPERTY53=null;
+        Token INSTANCE_PROPERTY54=null;
+        Token IMPLICATION55=null;
+        Token IMPLICATION_PRED56=null;
+        Token IMPLICATION_RETRO57=null;
+        Token IMPLICATION_CONC58=null;
+        Token EQUIVALENCE59=null;
+        Token EQUIVALENCE_PRED60=null;
+        Token EQUIVALENCE_CONC61=null;
+        term_return term49 = null;
+
+        term_return term62 = null;
+
+
+        Object INHERITANCE50_tree=null;
+        Object SIMILARITY51_tree=null;
+        Object INSTANCE52_tree=null;
+        Object PROPERTY53_tree=null;
+        Object INSTANCE_PROPERTY54_tree=null;
+        Object IMPLICATION55_tree=null;
+        Object IMPLICATION_PRED56_tree=null;
+        Object IMPLICATION_RETRO57_tree=null;
+        Object IMPLICATION_CONC58_tree=null;
+        Object EQUIVALENCE59_tree=null;
+        Object EQUIVALENCE_PRED60_tree=null;
+        Object EQUIVALENCE_CONC61_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:2: ( term ( ( INHERITANCE | SIMILARITY | INSTANCE | PROPERTY | INSTANCE_PROPERTY | IMPLICATION | IMPLICATION_PRED | IMPLICATION_RETRO | IMPLICATION_CONC | EQUIVALENCE | EQUIVALENCE_PRED | EQUIVALENCE_CONC ) term )? )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:4: term ( ( INHERITANCE | SIMILARITY | INSTANCE | PROPERTY | INSTANCE_PROPERTY | IMPLICATION | IMPLICATION_PRED | IMPLICATION_RETRO | IMPLICATION_CONC | EQUIVALENCE | EQUIVALENCE_PRED | EQUIVALENCE_CONC ) term )?
+            {
+            root_0 = (Object)adaptor.nil();
+
+            pushFollow(FOLLOW_term_in_simple_statement292);
+            term49=term();
+            _fsp--;
+
+            adaptor.addChild(root_0, term49.getTree());
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:9: ( ( INHERITANCE | SIMILARITY | INSTANCE | PROPERTY | INSTANCE_PROPERTY | IMPLICATION | IMPLICATION_PRED | IMPLICATION_RETRO | IMPLICATION_CONC | EQUIVALENCE | EQUIVALENCE_PRED | EQUIVALENCE_CONC ) term )?
+            int alt12=2;
+            int LA12_0 = input.LA(1);
+
+            if ( ((LA12_0>=INHERITANCE && LA12_0<=EQUIVALENCE_CONC)) ) {
+                alt12=1;
+            }
+            switch (alt12) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:10: ( INHERITANCE | SIMILARITY | INSTANCE | PROPERTY | INSTANCE_PROPERTY | IMPLICATION | IMPLICATION_PRED | IMPLICATION_RETRO | IMPLICATION_CONC | EQUIVALENCE | EQUIVALENCE_PRED | EQUIVALENCE_CONC ) term
+                    {
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:10: ( INHERITANCE | SIMILARITY | INSTANCE | PROPERTY | INSTANCE_PROPERTY | IMPLICATION | IMPLICATION_PRED | IMPLICATION_RETRO | IMPLICATION_CONC | EQUIVALENCE | EQUIVALENCE_PRED | EQUIVALENCE_CONC )
+                    int alt11=12;
+                    switch ( input.LA(1) ) {
+                    case INHERITANCE:
+                        {
+                        alt11=1;
+                        }
+                        break;
+                    case SIMILARITY:
+                        {
+                        alt11=2;
+                        }
+                        break;
+                    case INSTANCE:
+                        {
+                        alt11=3;
+                        }
+                        break;
+                    case PROPERTY:
+                        {
+                        alt11=4;
+                        }
+                        break;
+                    case INSTANCE_PROPERTY:
+                        {
+                        alt11=5;
+                        }
+                        break;
+                    case IMPLICATION:
+                        {
+                        alt11=6;
+                        }
+                        break;
+                    case IMPLICATION_PRED:
+                        {
+                        alt11=7;
+                        }
+                        break;
+                    case IMPLICATION_RETRO:
+                        {
+                        alt11=8;
+                        }
+                        break;
+                    case IMPLICATION_CONC:
+                        {
+                        alt11=9;
+                        }
+                        break;
+                    case EQUIVALENCE:
+                        {
+                        alt11=10;
+                        }
+                        break;
+                    case EQUIVALENCE_PRED:
+                        {
+                        alt11=11;
+                        }
+                        break;
+                    case EQUIVALENCE_CONC:
+                        {
+                        alt11=12;
+                        }
+                        break;
+                    default:
+                        NoViableAltException nvae =
+                            new NoViableAltException("52:10: ( INHERITANCE | SIMILARITY | INSTANCE | PROPERTY | INSTANCE_PROPERTY | IMPLICATION | IMPLICATION_PRED | IMPLICATION_RETRO | IMPLICATION_CONC | EQUIVALENCE | EQUIVALENCE_PRED | EQUIVALENCE_CONC )", 11, 0, input);
+
+                        throw nvae;
+                    }
+
+                    switch (alt11) {
+                        case 1 :
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:11: INHERITANCE
+                            {
+                            INHERITANCE50=(Token)input.LT(1);
+                            match(input,INHERITANCE,FOLLOW_INHERITANCE_in_simple_statement296); 
+                            INHERITANCE50_tree = (Object)adaptor.create(INHERITANCE50);
+                            root_0 = (Object)adaptor.becomeRoot(INHERITANCE50_tree, root_0);
+
+
+                            }
+                            break;
+                        case 2 :
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:26: SIMILARITY
+                            {
+                            SIMILARITY51=(Token)input.LT(1);
+                            match(input,SIMILARITY,FOLLOW_SIMILARITY_in_simple_statement301); 
+                            SIMILARITY51_tree = (Object)adaptor.create(SIMILARITY51);
+                            root_0 = (Object)adaptor.becomeRoot(SIMILARITY51_tree, root_0);
+
+
+                            }
+                            break;
+                        case 3 :
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:40: INSTANCE
+                            {
+                            INSTANCE52=(Token)input.LT(1);
+                            match(input,INSTANCE,FOLLOW_INSTANCE_in_simple_statement306); 
+                            INSTANCE52_tree = (Object)adaptor.create(INSTANCE52);
+                            root_0 = (Object)adaptor.becomeRoot(INSTANCE52_tree, root_0);
+
+
+                            }
+                            break;
+                        case 4 :
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:52: PROPERTY
+                            {
+                            PROPERTY53=(Token)input.LT(1);
+                            match(input,PROPERTY,FOLLOW_PROPERTY_in_simple_statement311); 
+                            PROPERTY53_tree = (Object)adaptor.create(PROPERTY53);
+                            root_0 = (Object)adaptor.becomeRoot(PROPERTY53_tree, root_0);
+
+
+                            }
+                            break;
+                        case 5 :
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:64: INSTANCE_PROPERTY
+                            {
+                            INSTANCE_PROPERTY54=(Token)input.LT(1);
+                            match(input,INSTANCE_PROPERTY,FOLLOW_INSTANCE_PROPERTY_in_simple_statement316); 
+                            INSTANCE_PROPERTY54_tree = (Object)adaptor.create(INSTANCE_PROPERTY54);
+                            root_0 = (Object)adaptor.becomeRoot(INSTANCE_PROPERTY54_tree, root_0);
+
+
+                            }
+                            break;
+                        case 6 :
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:85: IMPLICATION
+                            {
+                            IMPLICATION55=(Token)input.LT(1);
+                            match(input,IMPLICATION,FOLLOW_IMPLICATION_in_simple_statement321); 
+                            IMPLICATION55_tree = (Object)adaptor.create(IMPLICATION55);
+                            root_0 = (Object)adaptor.becomeRoot(IMPLICATION55_tree, root_0);
+
+
+                            }
+                            break;
+                        case 7 :
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:100: IMPLICATION_PRED
+                            {
+                            IMPLICATION_PRED56=(Token)input.LT(1);
+                            match(input,IMPLICATION_PRED,FOLLOW_IMPLICATION_PRED_in_simple_statement326); 
+                            IMPLICATION_PRED56_tree = (Object)adaptor.create(IMPLICATION_PRED56);
+                            root_0 = (Object)adaptor.becomeRoot(IMPLICATION_PRED56_tree, root_0);
+
+
+                            }
+                            break;
+                        case 8 :
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:120: IMPLICATION_RETRO
+                            {
+                            IMPLICATION_RETRO57=(Token)input.LT(1);
+                            match(input,IMPLICATION_RETRO,FOLLOW_IMPLICATION_RETRO_in_simple_statement331); 
+                            IMPLICATION_RETRO57_tree = (Object)adaptor.create(IMPLICATION_RETRO57);
+                            root_0 = (Object)adaptor.becomeRoot(IMPLICATION_RETRO57_tree, root_0);
+
+
+                            }
+                            break;
+                        case 9 :
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:141: IMPLICATION_CONC
+                            {
+                            IMPLICATION_CONC58=(Token)input.LT(1);
+                            match(input,IMPLICATION_CONC,FOLLOW_IMPLICATION_CONC_in_simple_statement336); 
+                            IMPLICATION_CONC58_tree = (Object)adaptor.create(IMPLICATION_CONC58);
+                            root_0 = (Object)adaptor.becomeRoot(IMPLICATION_CONC58_tree, root_0);
+
+
+                            }
+                            break;
+                        case 10 :
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:161: EQUIVALENCE
+                            {
+                            EQUIVALENCE59=(Token)input.LT(1);
+                            match(input,EQUIVALENCE,FOLLOW_EQUIVALENCE_in_simple_statement341); 
+                            EQUIVALENCE59_tree = (Object)adaptor.create(EQUIVALENCE59);
+                            root_0 = (Object)adaptor.becomeRoot(EQUIVALENCE59_tree, root_0);
+
+
+                            }
+                            break;
+                        case 11 :
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:176: EQUIVALENCE_PRED
+                            {
+                            EQUIVALENCE_PRED60=(Token)input.LT(1);
+                            match(input,EQUIVALENCE_PRED,FOLLOW_EQUIVALENCE_PRED_in_simple_statement346); 
+                            EQUIVALENCE_PRED60_tree = (Object)adaptor.create(EQUIVALENCE_PRED60);
+                            root_0 = (Object)adaptor.becomeRoot(EQUIVALENCE_PRED60_tree, root_0);
+
+
+                            }
+                            break;
+                        case 12 :
+                            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:52:196: EQUIVALENCE_CONC
+                            {
+                            EQUIVALENCE_CONC61=(Token)input.LT(1);
+                            match(input,EQUIVALENCE_CONC,FOLLOW_EQUIVALENCE_CONC_in_simple_statement351); 
+                            EQUIVALENCE_CONC61_tree = (Object)adaptor.create(EQUIVALENCE_CONC61);
+                            root_0 = (Object)adaptor.becomeRoot(EQUIVALENCE_CONC61_tree, root_0);
+
+
+                            }
+                            break;
+
+                    }
+
+                    pushFollow(FOLLOW_term_in_simple_statement355);
+                    term62=term();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, term62.getTree());
+
+                    }
+                    break;
+
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end simple_statement
+
+    public static class term_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start term
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:56:1: term : difference ( ( AMPERSAND | BAR ) difference )* ;
+    public final term_return term() throws RecognitionException {
+        term_return retval = new term_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token AMPERSAND64=null;
+        Token BAR65=null;
+        difference_return difference63 = null;
+
+        difference_return difference66 = null;
+
+
+        Object AMPERSAND64_tree=null;
+        Object BAR65_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:56:7: ( difference ( ( AMPERSAND | BAR ) difference )* )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:56:9: difference ( ( AMPERSAND | BAR ) difference )*
+            {
+            root_0 = (Object)adaptor.nil();
+
+            pushFollow(FOLLOW_difference_in_term371);
+            difference63=difference();
+            _fsp--;
+
+            adaptor.addChild(root_0, difference63.getTree());
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:56:20: ( ( AMPERSAND | BAR ) difference )*
+            loop14:
+            do {
+                int alt14=2;
+                int LA14_0 = input.LA(1);
+
+                if ( ((LA14_0>=AMPERSAND && LA14_0<=BAR)) ) {
+                    alt14=1;
+                }
+
+
+                switch (alt14) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:56:21: ( AMPERSAND | BAR ) difference
+            	    {
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:56:21: ( AMPERSAND | BAR )
+            	    int alt13=2;
+            	    int LA13_0 = input.LA(1);
+
+            	    if ( (LA13_0==AMPERSAND) ) {
+            	        alt13=1;
+            	    }
+            	    else if ( (LA13_0==BAR) ) {
+            	        alt13=2;
+            	    }
+            	    else {
+            	        NoViableAltException nvae =
+            	            new NoViableAltException("56:21: ( AMPERSAND | BAR )", 13, 0, input);
+
+            	        throw nvae;
+            	    }
+            	    switch (alt13) {
+            	        case 1 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:56:22: AMPERSAND
+            	            {
+            	            AMPERSAND64=(Token)input.LT(1);
+            	            match(input,AMPERSAND,FOLLOW_AMPERSAND_in_term375); 
+            	            AMPERSAND64_tree = (Object)adaptor.create(AMPERSAND64);
+            	            root_0 = (Object)adaptor.becomeRoot(AMPERSAND64_tree, root_0);
+
+
+            	            }
+            	            break;
+            	        case 2 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:56:35: BAR
+            	            {
+            	            BAR65=(Token)input.LT(1);
+            	            match(input,BAR,FOLLOW_BAR_in_term380); 
+            	            BAR65_tree = (Object)adaptor.create(BAR65);
+            	            root_0 = (Object)adaptor.becomeRoot(BAR65_tree, root_0);
+
+
+            	            }
+            	            break;
+
+            	    }
+
+            	    pushFollow(FOLLOW_difference_in_term384);
+            	    difference66=difference();
+            	    _fsp--;
+
+            	    adaptor.addChild(root_0, difference66.getTree());
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop14;
+                }
+            } while (true);
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end term
+
+    public static class ext_set_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start ext_set
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:59:1: ext_set : OPEN_BRACE ( term ( COMMA term )* )? CLOSE_BRACE ;
+    public final ext_set_return ext_set() throws RecognitionException {
+        ext_set_return retval = new ext_set_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token OPEN_BRACE67=null;
+        Token COMMA69=null;
+        Token CLOSE_BRACE71=null;
+        term_return term68 = null;
+
+        term_return term70 = null;
+
+
+        Object OPEN_BRACE67_tree=null;
+        Object COMMA69_tree=null;
+        Object CLOSE_BRACE71_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:59:9: ( OPEN_BRACE ( term ( COMMA term )* )? CLOSE_BRACE )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:59:11: OPEN_BRACE ( term ( COMMA term )* )? CLOSE_BRACE
+            {
+            root_0 = (Object)adaptor.nil();
+
+            OPEN_BRACE67=(Token)input.LT(1);
+            match(input,OPEN_BRACE,FOLLOW_OPEN_BRACE_in_ext_set396); 
+            OPEN_BRACE67_tree = (Object)adaptor.create(OPEN_BRACE67);
+            root_0 = (Object)adaptor.becomeRoot(OPEN_BRACE67_tree, root_0);
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:59:23: ( term ( COMMA term )* )?
+            int alt16=2;
+            int LA16_0 = input.LA(1);
+
+            if ( (LA16_0==IRI_REF||LA16_0==PNAME_NS||(LA16_0>=LPAREN && LA16_0<=INTEGER)||LA16_0==DECIMAL||LA16_0==OPEN_BRACE||LA16_0==LBRACKET||(LA16_0>=QUERY_VAR && LA16_0<=PNAME_LN)) ) {
+                alt16=1;
+            }
+            switch (alt16) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:59:24: term ( COMMA term )*
+                    {
+                    pushFollow(FOLLOW_term_in_ext_set400);
+                    term68=term();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, term68.getTree());
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:59:29: ( COMMA term )*
+                    loop15:
+                    do {
+                        int alt15=2;
+                        int LA15_0 = input.LA(1);
+
+                        if ( (LA15_0==COMMA) ) {
+                            alt15=1;
+                        }
+
+
+                        switch (alt15) {
+                    	case 1 :
+                    	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:59:30: COMMA term
+                    	    {
+                    	    COMMA69=(Token)input.LT(1);
+                    	    match(input,COMMA,FOLLOW_COMMA_in_ext_set403); 
+                    	    pushFollow(FOLLOW_term_in_ext_set406);
+                    	    term70=term();
+                    	    _fsp--;
+
+                    	    adaptor.addChild(root_0, term70.getTree());
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    break loop15;
+                        }
+                    } while (true);
+
+
+                    }
+                    break;
+
+            }
+
+            CLOSE_BRACE71=(Token)input.LT(1);
+            match(input,CLOSE_BRACE,FOLLOW_CLOSE_BRACE_in_ext_set412); 
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end ext_set
+
+    public static class int_set_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start int_set
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:62:1: int_set : LBRACKET ( term ( COMMA term )* )? RBRACKET ;
+    public final int_set_return int_set() throws RecognitionException {
+        int_set_return retval = new int_set_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token LBRACKET72=null;
+        Token COMMA74=null;
+        Token RBRACKET76=null;
+        term_return term73 = null;
+
+        term_return term75 = null;
+
+
+        Object LBRACKET72_tree=null;
+        Object COMMA74_tree=null;
+        Object RBRACKET76_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:62:9: ( LBRACKET ( term ( COMMA term )* )? RBRACKET )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:62:11: LBRACKET ( term ( COMMA term )* )? RBRACKET
+            {
+            root_0 = (Object)adaptor.nil();
+
+            LBRACKET72=(Token)input.LT(1);
+            match(input,LBRACKET,FOLLOW_LBRACKET_in_int_set424); 
+            LBRACKET72_tree = (Object)adaptor.create(LBRACKET72);
+            root_0 = (Object)adaptor.becomeRoot(LBRACKET72_tree, root_0);
+
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:62:21: ( term ( COMMA term )* )?
+            int alt18=2;
+            int LA18_0 = input.LA(1);
+
+            if ( (LA18_0==IRI_REF||LA18_0==PNAME_NS||(LA18_0>=LPAREN && LA18_0<=INTEGER)||LA18_0==DECIMAL||LA18_0==OPEN_BRACE||LA18_0==LBRACKET||(LA18_0>=QUERY_VAR && LA18_0<=PNAME_LN)) ) {
+                alt18=1;
+            }
+            switch (alt18) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:62:22: term ( COMMA term )*
+                    {
+                    pushFollow(FOLLOW_term_in_int_set428);
+                    term73=term();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, term73.getTree());
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:62:27: ( COMMA term )*
+                    loop17:
+                    do {
+                        int alt17=2;
+                        int LA17_0 = input.LA(1);
+
+                        if ( (LA17_0==COMMA) ) {
+                            alt17=1;
+                        }
+
+
+                        switch (alt17) {
+                    	case 1 :
+                    	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:62:28: COMMA term
+                    	    {
+                    	    COMMA74=(Token)input.LT(1);
+                    	    match(input,COMMA,FOLLOW_COMMA_in_int_set431); 
+                    	    pushFollow(FOLLOW_term_in_int_set434);
+                    	    term75=term();
+                    	    _fsp--;
+
+                    	    adaptor.addChild(root_0, term75.getTree());
+
+                    	    }
+                    	    break;
+
+                    	default :
+                    	    break loop17;
+                        }
+                    } while (true);
+
+
+                    }
+                    break;
+
+            }
+
+            RBRACKET76=(Token)input.LT(1);
+            match(input,RBRACKET,FOLLOW_RBRACKET_in_int_set440); 
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end int_set
+
+    public static class difference_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start difference
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:65:1: difference : product ( ( MINUS | TILDE ) product )* ;
+    public final difference_return difference() throws RecognitionException {
+        difference_return retval = new difference_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token MINUS78=null;
+        Token TILDE79=null;
+        product_return product77 = null;
+
+        product_return product80 = null;
+
+
+        Object MINUS78_tree=null;
+        Object TILDE79_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:66:2: ( product ( ( MINUS | TILDE ) product )* )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:66:4: product ( ( MINUS | TILDE ) product )*
+            {
+            root_0 = (Object)adaptor.nil();
+
+            pushFollow(FOLLOW_product_in_difference454);
+            product77=product();
+            _fsp--;
+
+            adaptor.addChild(root_0, product77.getTree());
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:66:12: ( ( MINUS | TILDE ) product )*
+            loop20:
+            do {
+                int alt20=2;
+                int LA20_0 = input.LA(1);
+
+                if ( ((LA20_0>=MINUS && LA20_0<=TILDE)) ) {
+                    alt20=1;
+                }
+
+
+                switch (alt20) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:66:13: ( MINUS | TILDE ) product
+            	    {
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:66:13: ( MINUS | TILDE )
+            	    int alt19=2;
+            	    int LA19_0 = input.LA(1);
+
+            	    if ( (LA19_0==MINUS) ) {
+            	        alt19=1;
+            	    }
+            	    else if ( (LA19_0==TILDE) ) {
+            	        alt19=2;
+            	    }
+            	    else {
+            	        NoViableAltException nvae =
+            	            new NoViableAltException("66:13: ( MINUS | TILDE )", 19, 0, input);
+
+            	        throw nvae;
+            	    }
+            	    switch (alt19) {
+            	        case 1 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:66:14: MINUS
+            	            {
+            	            MINUS78=(Token)input.LT(1);
+            	            match(input,MINUS,FOLLOW_MINUS_in_difference458); 
+            	            MINUS78_tree = (Object)adaptor.create(MINUS78);
+            	            root_0 = (Object)adaptor.becomeRoot(MINUS78_tree, root_0);
+
+
+            	            }
+            	            break;
+            	        case 2 :
+            	            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:66:23: TILDE
+            	            {
+            	            TILDE79=(Token)input.LT(1);
+            	            match(input,TILDE,FOLLOW_TILDE_in_difference463); 
+            	            TILDE79_tree = (Object)adaptor.create(TILDE79);
+            	            root_0 = (Object)adaptor.becomeRoot(TILDE79_tree, root_0);
+
+
+            	            }
+            	            break;
+
+            	    }
+
+            	    pushFollow(FOLLOW_product_in_difference467);
+            	    product80=product();
+            	    _fsp--;
+
+            	    adaptor.addChild(root_0, product80.getTree());
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop20;
+                }
+            } while (true);
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end difference
+
+    public static class product_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start product
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:69:1: product : atomic_term ( STAR atomic_term )* ;
+    public final product_return product() throws RecognitionException {
+        product_return retval = new product_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token STAR82=null;
+        atomic_term_return atomic_term81 = null;
+
+        atomic_term_return atomic_term83 = null;
+
+
+        Object STAR82_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:69:9: ( atomic_term ( STAR atomic_term )* )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:69:11: atomic_term ( STAR atomic_term )*
+            {
+            root_0 = (Object)adaptor.nil();
+
+            pushFollow(FOLLOW_atomic_term_in_product480);
+            atomic_term81=atomic_term();
+            _fsp--;
+
+            adaptor.addChild(root_0, atomic_term81.getTree());
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:69:23: ( STAR atomic_term )*
+            loop21:
+            do {
+                int alt21=2;
+                int LA21_0 = input.LA(1);
+
+                if ( (LA21_0==STAR) ) {
+                    alt21=1;
+                }
+
+
+                switch (alt21) {
+            	case 1 :
+            	    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:69:24: STAR atomic_term
+            	    {
+            	    STAR82=(Token)input.LT(1);
+            	    match(input,STAR,FOLLOW_STAR_in_product483); 
+            	    STAR82_tree = (Object)adaptor.create(STAR82);
+            	    root_0 = (Object)adaptor.becomeRoot(STAR82_tree, root_0);
+
+            	    pushFollow(FOLLOW_atomic_term_in_product486);
+            	    atomic_term83=atomic_term();
+            	    _fsp--;
+
+            	    adaptor.addChild(root_0, atomic_term83.getTree());
+
+            	    }
+            	    break;
+
+            	default :
+            	    break loop21;
+                }
+            } while (true);
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end product
+
+    public static class atomic_term_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start atomic_term
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:72:1: atomic_term : ( ext_set | int_set | LPAREN statement RPAREN | variable | iriRef | literal );
+    public final atomic_term_return atomic_term() throws RecognitionException {
+        atomic_term_return retval = new atomic_term_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token LPAREN86=null;
+        Token RPAREN88=null;
+        ext_set_return ext_set84 = null;
+
+        int_set_return int_set85 = null;
+
+        statement_return statement87 = null;
+
+        variable_return variable89 = null;
+
+        iriRef_return iriRef90 = null;
+
+        literal_return literal91 = null;
+
+
+        Object LPAREN86_tree=null;
+        Object RPAREN88_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:73:2: ( ext_set | int_set | LPAREN statement RPAREN | variable | iriRef | literal )
+            int alt22=6;
+            switch ( input.LA(1) ) {
+            case OPEN_BRACE:
+                {
+                alt22=1;
+                }
+                break;
+            case LBRACKET:
+                {
+                alt22=2;
+                }
+                break;
+            case LPAREN:
+                {
+                alt22=3;
+                }
+                break;
+            case QUERY_VAR:
+            case STM_VAR:
+                {
+                alt22=4;
+                }
+                break;
+            case IRI_REF:
+            case PNAME_NS:
+            case PNAME_LN:
+                {
+                alt22=5;
+                }
+                break;
+            case INTEGER:
+            case DECIMAL:
+            case DOUBLE:
+            case INTEGER_POSITIVE:
+            case DECIMAL_POSITIVE:
+            case DOUBLE_POSITIVE:
+            case INTEGER_NEGATIVE:
+            case DECIMAL_NEGATIVE:
+            case DOUBLE_NEGATIVE:
+            case TRUE:
+            case FALSE:
+            case STRING_LITERAL1:
+            case STRING_LITERAL2:
+            case STRING_LITERAL_LONG1:
+            case STRING_LITERAL_LONG2:
+                {
+                alt22=6;
+                }
+                break;
+            default:
+                NoViableAltException nvae =
+                    new NoViableAltException("72:1: atomic_term : ( ext_set | int_set | LPAREN statement RPAREN | variable | iriRef | literal );", 22, 0, input);
+
+                throw nvae;
+            }
+
+            switch (alt22) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:73:4: ext_set
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_ext_set_in_atomic_term500);
+                    ext_set84=ext_set();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, ext_set84.getTree());
+
+                    }
+                    break;
+                case 2 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:74:4: int_set
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_int_set_in_atomic_term505);
+                    int_set85=int_set();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, int_set85.getTree());
+
+                    }
+                    break;
+                case 3 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:75:4: LPAREN statement RPAREN
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    LPAREN86=(Token)input.LT(1);
+                    match(input,LPAREN,FOLLOW_LPAREN_in_atomic_term510); 
+                    pushFollow(FOLLOW_statement_in_atomic_term513);
+                    statement87=statement();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, statement87.getTree());
+                    RPAREN88=(Token)input.LT(1);
+                    match(input,RPAREN,FOLLOW_RPAREN_in_atomic_term515); 
+
+                    }
+                    break;
+                case 4 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:76:4: variable
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_variable_in_atomic_term521);
+                    variable89=variable();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, variable89.getTree());
+
+                    }
+                    break;
+                case 5 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:77:4: iriRef
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_iriRef_in_atomic_term526);
+                    iriRef90=iriRef();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, iriRef90.getTree());
+
+                    }
+                    break;
+                case 6 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:78:4: literal
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_literal_in_atomic_term531);
+                    literal91=literal();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, literal91.getTree());
+
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end atomic_term
+
+    public static class variable_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start variable
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:81:1: variable : ( query_variable | statement_variable );
+    public final variable_return variable() throws RecognitionException {
+        variable_return retval = new variable_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        query_variable_return query_variable92 = null;
+
+        statement_variable_return statement_variable93 = null;
+
+
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:82:2: ( query_variable | statement_variable )
+            int alt23=2;
+            int LA23_0 = input.LA(1);
+
+            if ( (LA23_0==QUERY_VAR) ) {
+                alt23=1;
+            }
+            else if ( (LA23_0==STM_VAR) ) {
+                alt23=2;
+            }
+            else {
+                NoViableAltException nvae =
+                    new NoViableAltException("81:1: variable : ( query_variable | statement_variable );", 23, 0, input);
+
+                throw nvae;
+            }
+            switch (alt23) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:82:4: query_variable
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_query_variable_in_variable544);
+                    query_variable92=query_variable();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, query_variable92.getTree());
+
+                    }
+                    break;
+                case 2 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:83:4: statement_variable
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_statement_variable_in_variable549);
+                    statement_variable93=statement_variable();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, statement_variable93.getTree());
+
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end variable
+
+    public static class query_variable_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start query_variable
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:86:1: query_variable : QUERY_VAR ;
+    public final query_variable_return query_variable() throws RecognitionException {
+        query_variable_return retval = new query_variable_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token QUERY_VAR94=null;
+
+        Object QUERY_VAR94_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:87:2: ( QUERY_VAR )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:87:4: QUERY_VAR
+            {
+            root_0 = (Object)adaptor.nil();
+
+            QUERY_VAR94=(Token)input.LT(1);
+            match(input,QUERY_VAR,FOLLOW_QUERY_VAR_in_query_variable562); 
+            QUERY_VAR94_tree = (Object)adaptor.create(QUERY_VAR94);
+            adaptor.addChild(root_0, QUERY_VAR94_tree);
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end query_variable
+
+    public static class statement_variable_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start statement_variable
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:90:1: statement_variable : STM_VAR ;
+    public final statement_variable_return statement_variable() throws RecognitionException {
+        statement_variable_return retval = new statement_variable_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token STM_VAR95=null;
+
+        Object STM_VAR95_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:91:2: ( STM_VAR )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:91:4: STM_VAR
+            {
+            root_0 = (Object)adaptor.nil();
+
+            STM_VAR95=(Token)input.LT(1);
+            match(input,STM_VAR,FOLLOW_STM_VAR_in_statement_variable575); 
+            STM_VAR95_tree = (Object)adaptor.create(STM_VAR95);
+            adaptor.addChild(root_0, STM_VAR95_tree);
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end statement_variable
+
+    public static class literal_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start literal
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:96:1: literal : ( numericLiteral | booleanLiteral | string );
+    public final literal_return literal() throws RecognitionException {
+        literal_return retval = new literal_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        numericLiteral_return numericLiteral96 = null;
+
+        booleanLiteral_return booleanLiteral97 = null;
+
+        string_return string98 = null;
+
+
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:97:2: ( numericLiteral | booleanLiteral | string )
+            int alt24=3;
+            switch ( input.LA(1) ) {
+            case INTEGER:
+            case DECIMAL:
+            case DOUBLE:
+            case INTEGER_POSITIVE:
+            case DECIMAL_POSITIVE:
+            case DOUBLE_POSITIVE:
+            case INTEGER_NEGATIVE:
+            case DECIMAL_NEGATIVE:
+            case DOUBLE_NEGATIVE:
+                {
+                alt24=1;
+                }
+                break;
+            case TRUE:
+            case FALSE:
+                {
+                alt24=2;
+                }
+                break;
+            case STRING_LITERAL1:
+            case STRING_LITERAL2:
+            case STRING_LITERAL_LONG1:
+            case STRING_LITERAL_LONG2:
+                {
+                alt24=3;
+                }
+                break;
+            default:
+                NoViableAltException nvae =
+                    new NoViableAltException("96:1: literal : ( numericLiteral | booleanLiteral | string );", 24, 0, input);
+
+                throw nvae;
+            }
+
+            switch (alt24) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:97:4: numericLiteral
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_numericLiteral_in_literal591);
+                    numericLiteral96=numericLiteral();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, numericLiteral96.getTree());
+
+                    }
+                    break;
+                case 2 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:98:4: booleanLiteral
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_booleanLiteral_in_literal596);
+                    booleanLiteral97=booleanLiteral();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, booleanLiteral97.getTree());
+
+                    }
+                    break;
+                case 3 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:99:4: string
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_string_in_literal601);
+                    string98=string();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, string98.getTree());
+
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end literal
+
+    public static class numericLiteral_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start numericLiteral
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:102:1: numericLiteral : ( numericLiteralUnsigned | numericLiteralPositive | numericLiteralNegative );
+    public final numericLiteral_return numericLiteral() throws RecognitionException {
+        numericLiteral_return retval = new numericLiteral_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        numericLiteralUnsigned_return numericLiteralUnsigned99 = null;
+
+        numericLiteralPositive_return numericLiteralPositive100 = null;
+
+        numericLiteralNegative_return numericLiteralNegative101 = null;
+
+
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:103:5: ( numericLiteralUnsigned | numericLiteralPositive | numericLiteralNegative )
+            int alt25=3;
+            switch ( input.LA(1) ) {
+            case INTEGER:
+            case DECIMAL:
+            case DOUBLE:
+                {
+                alt25=1;
+                }
+                break;
+            case INTEGER_POSITIVE:
+            case DECIMAL_POSITIVE:
+            case DOUBLE_POSITIVE:
+                {
+                alt25=2;
+                }
+                break;
+            case INTEGER_NEGATIVE:
+            case DECIMAL_NEGATIVE:
+            case DOUBLE_NEGATIVE:
+                {
+                alt25=3;
+                }
+                break;
+            default:
+                NoViableAltException nvae =
+                    new NoViableAltException("102:1: numericLiteral : ( numericLiteralUnsigned | numericLiteralPositive | numericLiteralNegative );", 25, 0, input);
+
+                throw nvae;
+            }
+
+            switch (alt25) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:103:7: numericLiteralUnsigned
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_numericLiteralUnsigned_in_numericLiteral616);
+                    numericLiteralUnsigned99=numericLiteralUnsigned();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, numericLiteralUnsigned99.getTree());
+
+                    }
+                    break;
+                case 2 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:103:32: numericLiteralPositive
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_numericLiteralPositive_in_numericLiteral620);
+                    numericLiteralPositive100=numericLiteralPositive();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, numericLiteralPositive100.getTree());
+
+                    }
+                    break;
+                case 3 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:103:57: numericLiteralNegative
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_numericLiteralNegative_in_numericLiteral624);
+                    numericLiteralNegative101=numericLiteralNegative();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, numericLiteralNegative101.getTree());
+
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end numericLiteral
+
+    public static class numericLiteralUnsigned_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start numericLiteralUnsigned
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:106:1: numericLiteralUnsigned : ( INTEGER | DECIMAL | DOUBLE );
+    public final numericLiteralUnsigned_return numericLiteralUnsigned() throws RecognitionException {
+        numericLiteralUnsigned_return retval = new numericLiteralUnsigned_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token set102=null;
+
+        Object set102_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:107:5: ( INTEGER | DECIMAL | DOUBLE )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+            {
+            root_0 = (Object)adaptor.nil();
+
+            set102=(Token)input.LT(1);
+            if ( input.LA(1)==INTEGER||input.LA(1)==DECIMAL||input.LA(1)==DOUBLE ) {
+                input.consume();
+                adaptor.addChild(root_0, adaptor.create(set102));
+                errorRecovery=false;
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recoverFromMismatchedSet(input,mse,FOLLOW_set_in_numericLiteralUnsigned0);    throw mse;
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end numericLiteralUnsigned
+
+    public static class numericLiteralPositive_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start numericLiteralPositive
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:112:1: numericLiteralPositive : ( INTEGER_POSITIVE | DECIMAL_POSITIVE | DOUBLE_POSITIVE );
+    public final numericLiteralPositive_return numericLiteralPositive() throws RecognitionException {
+        numericLiteralPositive_return retval = new numericLiteralPositive_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token set103=null;
+
+        Object set103_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:113:5: ( INTEGER_POSITIVE | DECIMAL_POSITIVE | DOUBLE_POSITIVE )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+            {
+            root_0 = (Object)adaptor.nil();
+
+            set103=(Token)input.LT(1);
+            if ( (input.LA(1)>=INTEGER_POSITIVE && input.LA(1)<=DOUBLE_POSITIVE) ) {
+                input.consume();
+                adaptor.addChild(root_0, adaptor.create(set103));
+                errorRecovery=false;
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recoverFromMismatchedSet(input,mse,FOLLOW_set_in_numericLiteralPositive0);    throw mse;
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end numericLiteralPositive
+
+    public static class numericLiteralNegative_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start numericLiteralNegative
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:118:1: numericLiteralNegative : ( INTEGER_NEGATIVE | DECIMAL_NEGATIVE | DOUBLE_NEGATIVE );
+    public final numericLiteralNegative_return numericLiteralNegative() throws RecognitionException {
+        numericLiteralNegative_return retval = new numericLiteralNegative_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token set104=null;
+
+        Object set104_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:119:5: ( INTEGER_NEGATIVE | DECIMAL_NEGATIVE | DOUBLE_NEGATIVE )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+            {
+            root_0 = (Object)adaptor.nil();
+
+            set104=(Token)input.LT(1);
+            if ( (input.LA(1)>=INTEGER_NEGATIVE && input.LA(1)<=DOUBLE_NEGATIVE) ) {
+                input.consume();
+                adaptor.addChild(root_0, adaptor.create(set104));
+                errorRecovery=false;
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recoverFromMismatchedSet(input,mse,FOLLOW_set_in_numericLiteralNegative0);    throw mse;
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end numericLiteralNegative
+
+    public static class booleanLiteral_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start booleanLiteral
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:124:1: booleanLiteral : ( TRUE | FALSE );
+    public final booleanLiteral_return booleanLiteral() throws RecognitionException {
+        booleanLiteral_return retval = new booleanLiteral_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token set105=null;
+
+        Object set105_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:125:5: ( TRUE | FALSE )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+            {
+            root_0 = (Object)adaptor.nil();
+
+            set105=(Token)input.LT(1);
+            if ( (input.LA(1)>=TRUE && input.LA(1)<=FALSE) ) {
+                input.consume();
+                adaptor.addChild(root_0, adaptor.create(set105));
+                errorRecovery=false;
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recoverFromMismatchedSet(input,mse,FOLLOW_set_in_booleanLiteral0);    throw mse;
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end booleanLiteral
+
+    public static class string_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start string
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:129:1: string : ( STRING_LITERAL1 | STRING_LITERAL2 | STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2 );
+    public final string_return string() throws RecognitionException {
+        string_return retval = new string_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token set106=null;
+
+        Object set106_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:130:5: ( STRING_LITERAL1 | STRING_LITERAL2 | STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2 )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+            {
+            root_0 = (Object)adaptor.nil();
+
+            set106=(Token)input.LT(1);
+            if ( (input.LA(1)>=STRING_LITERAL1 && input.LA(1)<=STRING_LITERAL_LONG2) ) {
+                input.consume();
+                adaptor.addChild(root_0, adaptor.create(set106));
+                errorRecovery=false;
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recoverFromMismatchedSet(input,mse,FOLLOW_set_in_string0);    throw mse;
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end string
+
+    public static class iriRef_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start iriRef
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:136:1: iriRef : ( IRI_REF | prefixedName );
+    public final iriRef_return iriRef() throws RecognitionException {
+        iriRef_return retval = new iriRef_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token IRI_REF107=null;
+        prefixedName_return prefixedName108 = null;
+
+
+        Object IRI_REF107_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:137:5: ( IRI_REF | prefixedName )
+            int alt26=2;
+            int LA26_0 = input.LA(1);
+
+            if ( (LA26_0==IRI_REF) ) {
+                alt26=1;
+            }
+            else if ( (LA26_0==PNAME_NS||LA26_0==PNAME_LN) ) {
+                alt26=2;
+            }
+            else {
+                NoViableAltException nvae =
+                    new NoViableAltException("136:1: iriRef : ( IRI_REF | prefixedName );", 26, 0, input);
+
+                throw nvae;
+            }
+            switch (alt26) {
+                case 1 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:137:7: IRI_REF
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    IRI_REF107=(Token)input.LT(1);
+                    match(input,IRI_REF,FOLLOW_IRI_REF_in_iriRef806); 
+                    IRI_REF107_tree = (Object)adaptor.create(IRI_REF107);
+                    adaptor.addChild(root_0, IRI_REF107_tree);
+
+
+                    }
+                    break;
+                case 2 :
+                    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:138:7: prefixedName
+                    {
+                    root_0 = (Object)adaptor.nil();
+
+                    pushFollow(FOLLOW_prefixedName_in_iriRef814);
+                    prefixedName108=prefixedName();
+                    _fsp--;
+
+                    adaptor.addChild(root_0, prefixedName108.getTree());
+
+                    }
+                    break;
+
+            }
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end iriRef
+
+    public static class prefixedName_return extends ParserRuleReturnScope {
+        Object tree;
+        public Object getTree() { return tree; }
+    };
+
+    // $ANTLR start prefixedName
+    // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:141:1: prefixedName : ( PNAME_LN | PNAME_NS );
+    public final prefixedName_return prefixedName() throws RecognitionException {
+        prefixedName_return retval = new prefixedName_return();
+        retval.start = input.LT(1);
+
+        Object root_0 = null;
+
+        Token set109=null;
+
+        Object set109_tree=null;
+
+        try {
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:142:5: ( PNAME_LN | PNAME_NS )
+            // /Users/jgeldart/Documents/Eclipse/open-nars/com/googlecode/opennars/parser/loan/loan.g:
+            {
+            root_0 = (Object)adaptor.nil();
+
+            set109=(Token)input.LT(1);
+            if ( input.LA(1)==PNAME_NS||input.LA(1)==PNAME_LN ) {
+                input.consume();
+                adaptor.addChild(root_0, adaptor.create(set109));
+                errorRecovery=false;
+            }
+            else {
+                MismatchedSetException mse =
+                    new MismatchedSetException(null,input);
+                recoverFromMismatchedSet(input,mse,FOLLOW_set_in_prefixedName0);    throw mse;
+            }
+
+
+            }
+
+            retval.stop = input.LT(-1);
+
+                retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+                adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+        }
+        catch (RecognitionException re) {
+            reportError(re);
+            recover(input,re);
+        }
+        finally {
+        }
+        return retval;
+    }
+    // $ANTLR end prefixedName
+
+
+ 
+
+    public static final BitSet FOLLOW_base_rule_in_document27 = new BitSet(new long[]{0x7FFF850003C21FA0L});
+    public static final BitSet FOLLOW_at_rule_in_document31 = new BitSet(new long[]{0x7FFF850003C21FA0L});
+    public static final BitSet FOLLOW_sentence_in_document35 = new BitSet(new long[]{0x7FFF850003C21FA0L});
+    public static final BitSet FOLLOW_EOF_in_document39 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_AT_BASE_in_base_rule50 = new BitSet(new long[]{0x0000000000000020L});
+    public static final BitSet FOLLOW_IRI_REF_in_base_rule53 = new BitSet(new long[]{0x0000000000000040L});
+    public static final BitSet FOLLOW_DOT_in_base_rule55 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_AT_IMPORT_in_at_rule66 = new BitSet(new long[]{0x0000000000000020L});
+    public static final BitSet FOLLOW_IRI_REF_in_at_rule69 = new BitSet(new long[]{0x0000000000000040L});
+    public static final BitSet FOLLOW_DOT_in_at_rule71 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_AT_PREFIX_in_at_rule77 = new BitSet(new long[]{0x0000000000000200L});
+    public static final BitSet FOLLOW_PNAME_NS_in_at_rule80 = new BitSet(new long[]{0x0000000000000020L});
+    public static final BitSet FOLLOW_IRI_REF_in_at_rule82 = new BitSet(new long[]{0x0000000000000040L});
+    public static final BitSet FOLLOW_DOT_in_at_rule84 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_AT_DELAY_in_at_rule90 = new BitSet(new long[]{0x0000000000000800L});
+    public static final BitSet FOLLOW_LPAREN_in_at_rule93 = new BitSet(new long[]{0x0000000000001000L});
+    public static final BitSet FOLLOW_INTEGER_in_at_rule96 = new BitSet(new long[]{0x0000000000002000L});
+    public static final BitSet FOLLOW_RPAREN_in_at_rule98 = new BitSet(new long[]{0x0000000000000040L});
+    public static final BitSet FOLLOW_DOT_in_at_rule101 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_statement_in_sentence114 = new BitSet(new long[]{0x000000000000C040L});
+    public static final BitSet FOLLOW_judgement_in_sentence117 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_question_in_sentence120 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_goal_in_sentence123 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_DOT_in_judgement138 = new BitSet(new long[]{0x0000000000010002L});
+    public static final BitSet FOLLOW_truthvalue_in_judgement141 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_EXCLAMATION_in_goal153 = new BitSet(new long[]{0x0000000000010002L});
+    public static final BitSet FOLLOW_truthvalue_in_goal156 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_QUESTION_in_question170 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_PERCENT_in_truthvalue184 = new BitSet(new long[]{0x0000000000021000L});
+    public static final BitSet FOLLOW_set_in_truthvalue187 = new BitSet(new long[]{0x0000000000050000L});
+    public static final BitSet FOLLOW_SEMICOLON_in_truthvalue196 = new BitSet(new long[]{0x0000000000020000L});
+    public static final BitSet FOLLOW_DECIMAL_in_truthvalue198 = new BitSet(new long[]{0x0000000000010000L});
+    public static final BitSet FOLLOW_PERCENT_in_truthvalue202 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_unary_statement_in_statement213 = new BitSet(new long[]{0x00000000003C0002L});
+    public static final BitSet FOLLOW_CONJ_in_statement217 = new BitSet(new long[]{0x7FFF850003C21A20L});
+    public static final BitSet FOLLOW_SEMICOLON_in_statement222 = new BitSet(new long[]{0x7FFF850003C21A20L});
+    public static final BitSet FOLLOW_COMMA_in_statement227 = new BitSet(new long[]{0x7FFF850003C21A20L});
+    public static final BitSet FOLLOW_DISJ_in_statement232 = new BitSet(new long[]{0x7FFF850003C21A20L});
+    public static final BitSet FOLLOW_unary_statement_in_statement236 = new BitSet(new long[]{0x00000000003C0002L});
+    public static final BitSet FOLLOW_NOT_in_unary_statement251 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_simple_statement_in_unary_statement253 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_PAST_in_unary_statement258 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_simple_statement_in_unary_statement260 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_PRESENT_in_unary_statement265 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_simple_statement_in_unary_statement267 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_FUTURE_in_unary_statement272 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_simple_statement_in_unary_statement274 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_simple_statement_in_unary_statement279 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_term_in_simple_statement292 = new BitSet(new long[]{0x0000003FFC000002L});
+    public static final BitSet FOLLOW_INHERITANCE_in_simple_statement296 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_SIMILARITY_in_simple_statement301 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_INSTANCE_in_simple_statement306 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_PROPERTY_in_simple_statement311 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_INSTANCE_PROPERTY_in_simple_statement316 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_IMPLICATION_in_simple_statement321 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_IMPLICATION_PRED_in_simple_statement326 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_IMPLICATION_RETRO_in_simple_statement331 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_IMPLICATION_CONC_in_simple_statement336 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_EQUIVALENCE_in_simple_statement341 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_EQUIVALENCE_PRED_in_simple_statement346 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_EQUIVALENCE_CONC_in_simple_statement351 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_term_in_simple_statement355 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_difference_in_term371 = new BitSet(new long[]{0x000000C000000002L});
+    public static final BitSet FOLLOW_AMPERSAND_in_term375 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_BAR_in_term380 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_difference_in_term384 = new BitSet(new long[]{0x000000C000000002L});
+    public static final BitSet FOLLOW_OPEN_BRACE_in_ext_set396 = new BitSet(new long[]{0x7FFF870000021A20L});
+    public static final BitSet FOLLOW_term_in_ext_set400 = new BitSet(new long[]{0x0000020000100000L});
+    public static final BitSet FOLLOW_COMMA_in_ext_set403 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_term_in_ext_set406 = new BitSet(new long[]{0x0000020000100000L});
+    public static final BitSet FOLLOW_CLOSE_BRACE_in_ext_set412 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_LBRACKET_in_int_set424 = new BitSet(new long[]{0x7FFF8D0000021A20L});
+    public static final BitSet FOLLOW_term_in_int_set428 = new BitSet(new long[]{0x0000080000100000L});
+    public static final BitSet FOLLOW_COMMA_in_int_set431 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_term_in_int_set434 = new BitSet(new long[]{0x0000080000100000L});
+    public static final BitSet FOLLOW_RBRACKET_in_int_set440 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_product_in_difference454 = new BitSet(new long[]{0x0000300000000002L});
+    public static final BitSet FOLLOW_MINUS_in_difference458 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_TILDE_in_difference463 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_product_in_difference467 = new BitSet(new long[]{0x0000300000000002L});
+    public static final BitSet FOLLOW_atomic_term_in_product480 = new BitSet(new long[]{0x0000400000000002L});
+    public static final BitSet FOLLOW_STAR_in_product483 = new BitSet(new long[]{0x7FFF850000021A20L});
+    public static final BitSet FOLLOW_atomic_term_in_product486 = new BitSet(new long[]{0x0000400000000002L});
+    public static final BitSet FOLLOW_ext_set_in_atomic_term500 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_int_set_in_atomic_term505 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_LPAREN_in_atomic_term510 = new BitSet(new long[]{0x7FFF850003C21A20L});
+    public static final BitSet FOLLOW_statement_in_atomic_term513 = new BitSet(new long[]{0x0000000000002000L});
+    public static final BitSet FOLLOW_RPAREN_in_atomic_term515 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_variable_in_atomic_term521 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_iriRef_in_atomic_term526 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_literal_in_atomic_term531 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_query_variable_in_variable544 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_statement_variable_in_variable549 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_QUERY_VAR_in_query_variable562 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_STM_VAR_in_statement_variable575 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_numericLiteral_in_literal591 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_booleanLiteral_in_literal596 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_string_in_literal601 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_numericLiteralUnsigned_in_numericLiteral616 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_numericLiteralPositive_in_numericLiteral620 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_numericLiteralNegative_in_numericLiteral624 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_set_in_numericLiteralUnsigned0 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_set_in_numericLiteralPositive0 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_set_in_numericLiteralNegative0 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_set_in_booleanLiteral0 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_set_in_string0 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_IRI_REF_in_iriRef806 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_prefixedName_in_iriRef814 = new BitSet(new long[]{0x0000000000000002L});
+    public static final BitSet FOLLOW_set_in_prefixedName0 = new BitSet(new long[]{0x0000000000000002L});
+
+}
\ No newline at end of file
diff --git a/open-nars/com/googlecode/opennars/parser/narsese/NarseseParser.java b/open-nars/com/googlecode/opennars/parser/narsese/NarseseParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..20c9f1fb46645c2bc5726c8dd724116cb1c24ea8
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/parser/narsese/NarseseParser.java
@@ -0,0 +1,385 @@
+/*
+ * StringParser.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.parser.narsese;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.*;
+import com.googlecode.opennars.language.*;
+import com.googlecode.opennars.main.*;
+import com.googlecode.opennars.parser.InvalidInputException;
+import com.googlecode.opennars.parser.Parser;
+
+
+/**
+ * Parse input String into Task.
+ */
+public class NarseseParser extends Parser {
+        
+    /**
+     * return the prefex of a task string that contains a BudgetValue
+     * @return a String containing a BudgetValue
+     * @param s the input in a StringBuffer
+     * @throws com.googlecode.opennars.parser.NarseseParser.InvalidInputException if the input cannot be parsed into a BudgetValue
+     */
+    static String getBudgetString(StringBuffer s) throws InvalidInputException {
+        if (s.charAt(0) != BUDGET_VALUE_MARK) // use default
+            return null;  // null values
+        int i = s.indexOf(BUDGET_VALUE_MARK + "", 1);    // looking for the end
+        if (i < 0) // no matching closer
+            throw new InvalidInputException("missing budget closer");
+        String budgetString = s.substring(1, i).trim();
+        if (budgetString.length() == 0) // empty usage
+            throw new InvalidInputException("empty budget");
+        s.delete(0, i+1);                 // remaining input to be processed outside
+        return budgetString;
+    }
+    
+    /**
+     * return the postfex of a task string that contains a TruthValue
+     * @return a String containing a TruthValue
+     * @param s the input in a StringBuffer
+     * @throws com.googlecode.opennars.parser.NarseseParser.InvalidInputException if the input cannot be parsed into a TruthValue
+     */
+    static String getTruthString(StringBuffer s) throws InvalidInputException {
+        int last = s.length()-1;
+        if (s.charAt(last) != TRUTH_VALUE_MARK)     // use default
+            return null;
+        int first = s.indexOf(TRUTH_VALUE_MARK + "");    // looking for the beginning
+        if (first == last) // no matching closer
+            throw new InvalidInputException("missing truth mark");
+        String truthString = s.substring(first+1, last).trim();
+        if (truthString.length() == 0) // empty usage
+            throw new InvalidInputException("empty truth");
+        s.delete(first, last+1);                 // remaining input to be processed outside
+        return truthString;
+    }
+    
+    /**
+     * parse the input String into a TruthValue (or DesireValue)
+     * @param s input String
+     * @param type Task type
+     * @param memory the memory object being inserted into
+     * @throws com.googlecode.opennars.parser.NarseseParser.InvalidInputException If the String cannot be parsed into a TruthValue
+     * @return the input TruthValue
+     */
+    static TruthValue parseTruth(String s, char type, Memory memory) throws InvalidInputException {
+        if (type == QUESTION_MARK)
+            return null;
+        float frequency = 1.0f;
+        float confidence = memory.getParameters().DEFAULT_JUDGMENT_CONFIDENCE;
+        if (s != null) {
+            int i = s.indexOf(VALUE_SEPARATOR);
+            if (i < 0)
+                frequency = Float.parseFloat(s);
+            else {
+                frequency = Float.parseFloat(s.substring(0,i));
+                confidence = Float.parseFloat(s.substring(i+1));
+            }
+        }
+        return new TruthValue(frequency, confidence);
+    }
+    
+    /**
+     * parse the input String into a BudgetValue
+     * @param s input String
+     * @param punctuation Task punctuation
+     * @param truth the TruthValue of the task
+     * @param memory the memory object being inserted into
+     * 
+     * @return the input BudgetValue
+     * @throws com.googlecode.opennars.parser.NarseseParser.InvalidInputException If the String cannot be parsed into a BudgetValue
+     */
+    static BudgetValue parseBudget(String s, char punctuation, TruthValue truth, Memory memory) throws InvalidInputException {
+        float priority, durability;
+        switch (punctuation) {
+            case JUDGMENT_MARK:
+                priority = memory.getParameters().DEFAULT_JUDGMENT_PRIORITY;
+                durability = memory.getParameters().DEFAULT_JUDGMENT_DURABILITY;
+                break;
+            case GOAL_MARK:
+                priority = memory.getParameters().DEFAULT_GOAL_PRIORITY;
+                durability = memory.getParameters().DEFAULT_GOAL_DURABILITY;
+                break;
+            case QUESTION_MARK:
+                priority = memory.getParameters().DEFAULT_QUESTION_PRIORITY;
+                durability = memory.getParameters().DEFAULT_QUESTION_DURABILITY;
+                break;
+            default:
+                throw new InvalidInputException("unknown punctuation");
+        }
+        if (s != null) { // overrite default
+            int i = s.indexOf(VALUE_SEPARATOR);
+            if (i < 0) {        // default durability
+                priority = Float.parseFloat(s);
+            } else {
+                priority = Float.parseFloat(s.substring(0, i));
+                durability = Float.parseFloat(s.substring(i+1));
+            }
+        }
+        float quality = (punctuation == QUESTION_MARK) ? 1 : memory.budgetfunctions.truthToQuality(truth);
+        return new BudgetValue(priority, durability, quality, memory);
+    }
+    
+    /* ---------- parse String into term ---------- */
+    
+    /**
+     * Top-level method that parse a Term in general, which may recursively call itself.
+     * <p>
+     * There are 5 valid cases:
+     * 1. (Op, A1, ..., An) is a common CompoundTerm (including CompoundStatement);
+     * 2. {A1, ..., An} is an SetExt;
+     * 3. [A1, ..., An] is an SetInt;
+     * 4. <T1 Re T2> is a Statement (including higher-order Statement);
+     * 5. otherwise it is a simple term.
+     * @param s0 the String to be parsed
+     * @param memory the memory object being inserted into
+     * @throws com.googlecode.opennars.parser.NarseseParser.InvalidInputException the String cannot be parsed into a Term
+     * @return the Term generated from the String
+     */
+    static Term parseTerm(String s0, Memory memory) throws InvalidInputException {
+        String s = s0.trim();
+        if (s.length() == 0)
+            throw new InvalidInputException("missing content");
+        Term t = memory.nameToListedTerm(s);    // existing constant or operator
+        if (t != null)
+            return t;                           // existing Term
+        int index = s.length()-1;
+        char first = s.charAt(0);
+        char last = s.charAt(index);
+        switch (first) {
+            case COMPOUND_TERM_OPENER:
+                if (last == COMPOUND_TERM_CLOSER)
+                    return parseCompoundTerm(s.substring(1, index), memory);
+                else
+                    throw new InvalidInputException("missing CompoundTerm closer");
+            case SET_EXT_OPENER:
+                if (last == SET_EXT_CLOSER)
+                    return SetExt.make(parseArguments(s.substring(1, index) + ARGUMENT_SEPARATOR, memory), memory);
+                else
+                    throw new InvalidInputException("missing ExtensionSet closer");
+            case SET_INT_OPENER:
+                if (last == SET_INT_CLOSER)
+                    return SetInt.make(parseArguments(s.substring(1, index) + ARGUMENT_SEPARATOR, memory), memory);
+                else
+                    throw new InvalidInputException("missing IntensionSet closer");
+            case STATEMENT_OPENER:
+                if (last == STATEMENT_CLOSER)
+                    return parseStatement(s.substring(1, index), memory);
+                else
+                    throw new InvalidInputException("missing Statement closer");
+            default:
+                return parseSimpleTerm(s);
+        }
+    }
+    
+    /**
+     * Parse a Term that has no internal structure.
+     * <p>
+     * The Term can be a constant or a variable.
+     * @param s0 the String to be parsed
+     * @throws com.googlecode.opennars.parser.NarseseParser.InvalidInputException the String cannot be parsed into a Term
+     * @return the Term generated from the String
+     */
+    private static Term parseSimpleTerm(String s0) throws InvalidInputException {
+        String s = s0.trim();
+        if (s.length() == 0)
+            throw new InvalidInputException("missing term");
+        if (s.contains(" "))                // invalid characters in a name
+            throw new InvalidInputException("invalid term");
+        Term term;
+        char prefix = s.charAt(0);
+        if ((prefix == VARIABLE_TAG) || (prefix == QUERY_VARIABLE_TAG)) {
+            term = new Variable(s);         // the only place to directly call this constructor
+        } else
+            term = new Term(s);             // the only place to directly call this constructor
+        return term;
+    }
+    
+    /**
+     * Parse a String to create a Statement.
+     * @return the Statement generated from the String
+     * @param s0 The input String to be parsed
+     * @param memory the memory object being inserted into
+     * @throws com.googlecode.opennars.parser.NarseseParser.InvalidInputException the String cannot be parsed into a Term
+     */
+    private static Statement parseStatement(String s0, Memory memory) throws InvalidInputException {
+        String s = s0.trim();
+        int i = topRelation(s);
+        if (i < 0)
+            throw new InvalidInputException("invalid statement");
+        String relation = s.substring(i, i+3);
+        Term subject = parseTerm(s.substring(0, i), memory);
+        Term predicate = parseTerm(s.substring(i+3), memory);
+        Statement t = Statement.make(relation, subject, predicate, memory);
+        if (t == null)
+            throw new InvalidInputException("invalid statement");
+        return t;
+    }
+    
+    /**
+     * Parse a String to create a CompoundTerm.
+     * @return the Term generated from the String
+     * @param s0 The String to be parsed
+     * @param memory the memory object being inserted into
+     * @throws com.googlecode.opennars.parser.NarseseParser.InvalidInputException the String cannot be parsed into a Term
+     */
+    private static Term parseCompoundTerm(String s0, Memory memory) throws InvalidInputException {
+        String s = s0.trim();
+        int firstSeparator = s.indexOf(ARGUMENT_SEPARATOR);
+        String op = s.substring(0, firstSeparator).trim();
+        if (!CompoundTerm.isOperator(op, memory))
+            throw new InvalidInputException("unknown operator: " + op);
+        ArrayList<Term> arg = parseArguments(s.substring(firstSeparator+1) + ARGUMENT_SEPARATOR, memory);
+        Term t = CompoundTerm.make(op, arg, memory);
+        if (t == null)
+            throw new InvalidInputException("invalid compound term");
+        return t;
+    }
+    
+    /**
+     * Parse a String into the argument list of a CompoundTerm.
+     * @return the arguments in an ArrayList
+     * @param s0 The String to be parsed
+     * @param memory the memory object being inserted into
+     * @throws com.googlecode.opennars.parser.NarseseParser.InvalidInputException the String cannot be parsed into an argument list
+     */
+    private static ArrayList<Term> parseArguments(String s0, Memory memory) throws InvalidInputException {
+        String s = s0.trim();
+        ArrayList<Term> list = new ArrayList<Term>();
+        int start = 0;
+        int end = 0;
+        Term t;
+        while (end < s.length()-1) {
+            end = nextSeparator(s, start);
+            t = parseTerm(s.substring(start, end), memory);     // recursive call
+            list.add(t);
+            start = end+1;
+        }
+        if (list.isEmpty())
+            throw new InvalidInputException("null argument");
+        return list;
+    }
+    
+    /* ---------- locate top-level substring ---------- */
+    
+    /**
+     * Locate the first top-level separator in a CompoundTerm
+     * @return the index of the next seperator in a String
+     * @param s The String to be parsed
+     * @param first The starting index
+     */
+    private static int nextSeparator(String s, int first) {
+        int levelCounter = 0;
+        int i = first;
+        while (i < s.length()-1) {
+            if (isOpener(s, i))
+                levelCounter++;
+            else if (isCloser(s, i))
+                levelCounter--;
+            else if (s.charAt(i) == ARGUMENT_SEPARATOR)
+                if (levelCounter == 0)
+                    break;
+            i++;
+        }
+        return i;
+    }
+    
+    /**
+     * locate the top-level relation in a statement
+     * @return the index of the top-level relation
+     * @param s The String to be parsed
+     */
+    private static int topRelation(String s) {      // need efficiency improvement
+        int levelCounter = 0;
+        int i = 0;
+        while (i < s.length()-3) {    // don't need to check the last 3 characters
+            if ((levelCounter == 0) && (Statement.isRelation(s.substring(i, i+3))))
+                return i;
+            if (isOpener(s, i))
+                levelCounter++;
+            else if (isCloser(s, i))
+                levelCounter--;
+            i++;
+        }
+        return -1;
+    }
+        
+    /* ---------- recognize symbols ---------- */
+        
+    /**
+     * check CompoundTerm opener symbol
+     * @return if the given String is an opener symbol
+     * @param s The String to be checked
+     * @param i The starting index
+     */
+    private static boolean isOpener(String s, int i) {
+        char c = s.charAt(i);
+        boolean b = (c == COMPOUND_TERM_OPENER) ||
+                (c == SET_EXT_OPENER) ||
+                (c == SET_INT_OPENER) ||
+                (c == STATEMENT_OPENER);
+        if (!b)
+            return false;
+        if (i+3 <= s.length() && Statement.isRelation(s.substring(i, i+3)))
+            return false;
+        return true;
+    }
+    
+    /**
+     * check CompoundTerm closer symbol
+     * @return if the given String is a closer symbol
+     * @param s The String to be checked
+     * @param i The starting index
+     */
+    private static boolean isCloser(String s, int i) {
+        char c = s.charAt(i);
+        boolean b = (c == COMPOUND_TERM_CLOSER) ||
+                (c == SET_EXT_CLOSER) ||
+                (c == SET_INT_CLOSER) ||
+                (c == STATEMENT_CLOSER);
+        if (!b)
+            return false;
+        if (i >= 2 && Statement.isRelation(s.substring(i-2, i+1)))
+            return false;
+        return true;
+    }
+
+	public Task parseTask(String input, Memory memory) throws InvalidInputException {
+		StringBuffer buffer = new StringBuffer(input);
+        String budgetString = getBudgetString(buffer);
+        String truthString = getTruthString(buffer);
+        String str = buffer.toString().trim();
+        int last = str.length() - 1;
+        char punc = str.charAt(last);
+        TruthValue truth = parseTruth(truthString, punc, memory);
+        BudgetValue budget = parseBudget(budgetString, punc, truth, memory);
+        Term content = parseTerm(str.substring(0,last), memory);
+        Base base = (punc == QUESTION_MARK) ? null : new Base();
+        Sentence sentence = Sentence.make(content, punc, truth, base, memory);
+        if (sentence == null)
+            throw new InvalidInputException("invalid sentence");
+        sentence.setInput();
+        Task task = new Task(sentence, budget, memory);
+        return task;
+	}
+}
diff --git a/open-nars/com/googlecode/opennars/storage/Bag.java b/open-nars/com/googlecode/opennars/storage/Bag.java
new file mode 100644
index 0000000000000000000000000000000000000000..97c5a6c3bceb60369e95e765d87037872a0158e0
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/storage/Bag.java
@@ -0,0 +1,213 @@
+/*
+ * Bag.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.storage;
+
+import java.util.*;
+
+import com.googlecode.opennars.entity.Item;
+import com.googlecode.opennars.inference.BudgetFunctions;
+import com.googlecode.opennars.main.Parameters;
+
+
+/**
+ * A Bag is a storage with a constant capacity and maintains an internal priority
+ * distribution for retrieval.
+ * 
+ * Each entity in a bag must extend Item, which is a UsageValue with a key.
+ *
+ * A name table is used to merge duplicate items.
+ *
+ * The bag space is divided by a threshold, above which is mainly time management,
+ *   and below, space mamagement.
+ *   Differences: (1) level selection vs. item selection, (2) decay rate
+ */
+public abstract class Bag<Type extends Item> {
+    
+    protected static final int TOTAL_LEVEL = Parameters.BAG_LEVEL;          // priority levels
+    protected static final int THRESHOLD = Parameters.BAG_THRESHOLD;        // firing threshold
+    protected static final float RELATIVE_THRESHOLD = (float) THRESHOLD / (float) TOTAL_LEVEL;
+    protected static final float LOAD_FACTOR = Parameters.LOAD_FACTOR;       // hashtable parameter
+    protected static final Distributor DISTRIBUTOR = new Distributor(TOTAL_LEVEL); // only one instance
+
+    protected HashMap<String, Type> nameTable;    // from key to item
+    protected ArrayList<Type> itemTable[];        // array of lists of items, for items on different level
+       
+    protected int capacity;         // defined in different bags
+    protected int mass;             // current sum of occupied level
+    protected int levelIndex;       // index to get next level, kept in individual objects
+    protected int currentLevel;     // current take out level
+    protected int currentCounter;   // maximum number of items to be taken out at current level
+    
+    
+    // ---------- constructor ---------- //
+    
+    // called from subclasses
+    protected Bag() {
+        capacity = capacity();
+        levelIndex = capacity % TOTAL_LEVEL; // so that different bags start at different point
+        currentLevel = TOTAL_LEVEL - 1;
+        itemTable = new ArrayList[TOTAL_LEVEL];
+        nameTable = new HashMap<String, Type>((int) (capacity / LOAD_FACTOR), LOAD_FACTOR);
+    }
+    
+    // --- property methods --- //
+    
+    protected abstract int capacity();
+    
+    // the number of times for a decay factor to be fully applied
+    // it can be changed in run time by the user, so not a constant
+    protected abstract int forgetRate();
+    
+    // --- Bag property --- //
+    
+    public ArrayList<Type> getAllContents() {
+    	return (ArrayList<Type>) this.nameTable.values();
+    }
+    
+    // get the average priority of the bag --- can be removed???
+    public float averagePriority() {
+        if (nameTable.size() == 0)
+            return 0.01f;
+        float f = (float) mass / (nameTable.size() * TOTAL_LEVEL);
+        if (f > 1)
+            return 1.0f;
+        return f;
+    }
+    
+    // check if an item is in the bag
+    public boolean contains(Type it) {
+        return nameTable.containsValue(it);
+    }
+
+    public Type get(String key) {
+        return nameTable.get(key);
+    }
+    
+    // ---------- put/remove methods ---------- //
+    
+    // put a new Item into the Bag
+    public void putIn(Type newItem) {
+        String newKey = newItem.getKey();
+        Type oldItem = nameTable.put(newKey, newItem);
+        if (oldItem != null) {                  // merge duplications
+            outOfBase(oldItem);
+            newItem.merge(oldItem);
+        }
+        Type overflowItem = intoBase(newItem);  // put the (new or merged) item into itemTable
+        if (overflowItem != null) {             // remove overflow
+            String overflowKey = overflowItem.getKey();
+            nameTable.remove(overflowKey);
+        }
+    }
+    
+    // put an item back into the itemTable (it is already in the table)
+    public void putBack(Type oldItem) {
+        BudgetFunctions.forget(oldItem.getBudget(), forgetRate(), RELATIVE_THRESHOLD);
+        putIn(oldItem);
+    }
+    
+    // choose an item according to priority distribution
+    // and take it out of the itemTable
+    public Type takeOut() {     // default behavior: the Item will be putBack
+        if (mass == 0)                              // empty bag
+            return null;
+        if (emptyLevel(currentLevel) || (currentCounter == 0)) { // done with the current level
+            currentLevel = DISTRIBUTOR.pick(levelIndex);
+            levelIndex = DISTRIBUTOR.next(levelIndex);
+            while (emptyLevel(currentLevel)) {          // look for a non-empty level
+                currentLevel = DISTRIBUTOR.pick(levelIndex);
+                levelIndex = DISTRIBUTOR.next(levelIndex);
+            }
+            if (currentLevel < THRESHOLD)
+                currentCounter = 1;                             // for dormant levels, take one item
+            else
+                currentCounter = itemTable[currentLevel].size();     // for active levels, take all current items
+        }
+        Type selected = takeOutFirst(currentLevel); // take out the first item in the level
+        currentCounter--;
+        nameTable.remove(selected.getKey());    // 01-07-04
+        return selected;
+    }
+    
+    // pick an item by key, then remove it from the bag
+    public Type pickOut(String key) {
+        Type picked = nameTable.get(key);
+        if (picked != null) {
+            outOfBase(picked);
+            nameTable.remove(key);    // 01-07-04
+        }
+        return picked;
+    }
+    
+    // ---------- private methods ---------- //
+    
+    // check whether a level is empty
+    private boolean emptyLevel(int n) {
+        if (itemTable[n] == null)
+            return true;
+        else
+            return itemTable[n].isEmpty();
+    }
+    
+    // decide the in level according to priority
+    private int getLevel(Type item) {
+        float fl = item.getPriority() * TOTAL_LEVEL;
+        int level = (int) Math.ceil(fl) - 1;
+        return (level < 0) ? 0 : level;     // cannot be -1
+    }
+    
+    // insert an item into the itemTable, and return the overflow
+    private Type intoBase(Type newItem) {
+        Type oldItem = null;
+        int inLevel = getLevel(newItem);
+        if (nameTable.size() > capacity) {      // the bag is full
+            int outLevel = 0;
+            while (emptyLevel(outLevel))
+                outLevel++;
+            if (outLevel > inLevel) {           // ignore the item and exit
+                return newItem;
+            } else {                            // remove an old item in the lowest non-empty level
+                oldItem = takeOutFirst(outLevel);
+            }
+        }
+        if (itemTable[inLevel] == null)
+            itemTable[inLevel] = new ArrayList();               // first time insert
+        itemTable[inLevel].add(newItem);          // FIFO
+        mass += (inLevel + 1);                          // increase total mass
+        return oldItem;
+    }
+    
+    // take out the first or last Type in a level from the itemTable
+    private Type takeOutFirst(int level) {
+        Type selected = itemTable[level].get(0);
+        itemTable[level].remove(0);         // take the item out
+        mass -= (level + 1);                    // decrease total mass
+        return selected;
+    }
+    
+    // remove an item from itemTable, then adjust mass
+    protected void outOfBase(Type oldItem) {
+        int level = getLevel(oldItem);
+        itemTable[level].remove(oldItem);
+        mass -= (level + 1);                    // decrease total mass
+    }
+}
diff --git a/open-nars/com/googlecode/opennars/storage/ConceptBag.java b/open-nars/com/googlecode/opennars/storage/ConceptBag.java
new file mode 100644
index 0000000000000000000000000000000000000000..57698efb58d20fbe5999327840b71bbd93ebf234
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/storage/ConceptBag.java
@@ -0,0 +1,46 @@
+/*
+ * ConceptBag.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.storage;
+
+import java.util.HashMap;
+
+import com.googlecode.opennars.entity.Concept;
+import com.googlecode.opennars.main.Parameters;
+
+/**
+ * Contains Concepts.
+ */
+public class ConceptBag extends Bag<Concept> {
+    
+    protected int capacity() {
+        return Parameters.CONCEPT_BAG_SIZE;
+    }
+    
+    // this is for active concept only
+    protected int forgetRate() {
+        return Parameters.CONCEPT_DEFAULT_FORGETTING_CYCLE;
+    }
+
+	public HashMap<String, Concept> getNameTable() {
+		return this.nameTable;
+	}
+}
\ No newline at end of file
diff --git a/open-nars/com/googlecode/opennars/storage/Distributor.java b/open-nars/com/googlecode/opennars/storage/Distributor.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6af10337c601c7e8aa94c81d2e49bb9882e7e71
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/storage/Distributor.java
@@ -0,0 +1,76 @@
+/*
+ * Distributor.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.storage;
+
+/**
+ * A pseudo-random number generator, used in Bag.
+ */
+class Distributor {
+    /**
+     * Random sequence of valid numbers
+     */
+    private int order[];
+    /**
+     * Capacity of the array
+     */
+    private int capacity;
+    
+    /**
+     * For any number N < range, there is N+1 copies of it in the array.
+     * 
+     * @param range Range of valid numbers
+     */
+    public Distributor(int range) {
+        int index, rank, time;
+        capacity = (range * (range + 1)) / 2;
+        order = new int[capacity];
+        for (index = 0; index < capacity; index++)
+            order[index] = -1;
+        for (rank = range; rank > 0; rank--)
+            for (time = 0; time < rank; time++) {
+                index = (((int) (capacity / rank)) + index) % capacity;
+                while (order[index] >= 0)
+                    index = (index + 1) % capacity;
+                order[index] = rank - 1;
+            }
+    }
+    
+    /**
+     * Get the next number according to the given index
+     * 
+     * @param index The current index
+     * @return the random value
+     */
+    public int pick(int index)	{
+        return order[index];
+    }
+    
+    /**
+     * Advance the index
+     * 
+     * @param index The current index
+     * @return the next index
+     */
+    public int next(int index) {
+        return (index + 1) % capacity;
+    }
+}
\ No newline at end of file
diff --git a/open-nars/com/googlecode/opennars/storage/TaskBag.java b/open-nars/com/googlecode/opennars/storage/TaskBag.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4b5f4def43dca86741250b4f506728b0c679c6e
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/storage/TaskBag.java
@@ -0,0 +1,42 @@
+/*
+ * TaskBag.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.storage;
+
+import com.googlecode.opennars.entity.Task;
+import com.googlecode.opennars.main.*;
+
+/**
+ * New tasks that contain new Term.
+ */
+public class TaskBag extends Bag<Task> {
+    public static final int defaultForgetRate = Parameters.NEW_TASK_DEFAULT_FORGETTING_CYCLE;
+    
+    protected int capacity() {
+        return Parameters.TASK_BUFFER_SIZE;
+    }
+    
+    protected int forgetRate() {
+        return Parameters.TASK_DEFAULT_FORGETTING_CYCLE;
+    }
+
+}
+
diff --git a/open-nars/com/googlecode/opennars/storage/TaskLinkBag.java b/open-nars/com/googlecode/opennars/storage/TaskLinkBag.java
new file mode 100644
index 0000000000000000000000000000000000000000..051dc27a4b220ea6455af1e2d1dab0a832fac1bf
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/storage/TaskLinkBag.java
@@ -0,0 +1,40 @@
+/*
+ * TaskLinkBag.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.storage;
+
+import com.googlecode.opennars.entity.TaskLink;
+import com.googlecode.opennars.main.Parameters;
+
+/**
+ * TaskLinkBag contains links to tasks.
+ */
+public class TaskLinkBag extends Bag<TaskLink> {
+
+    protected int capacity() {
+        return Parameters.TASK_BAG_SIZE;
+    }
+    
+    protected int forgetRate() {
+        return Parameters.TASK_DEFAULT_FORGETTING_CYCLE;
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/storage/TermLinkBag.java b/open-nars/com/googlecode/opennars/storage/TermLinkBag.java
new file mode 100644
index 0000000000000000000000000000000000000000..743a44d1dfc653c50189d4800beb39249b6b8882
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/storage/TermLinkBag.java
@@ -0,0 +1,56 @@
+/*
+ * TermLinkBag.java
+ *
+ * Copyright (C) 2008  Pei Wang
+ *
+ * This file is part of Open-NARS.
+ *
+ * Open-NARS is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Open-NARS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.googlecode.opennars.storage;
+
+import com.googlecode.opennars.entity.*;
+import com.googlecode.opennars.main.Parameters;
+
+/**
+ * Contains CompositionLinks to relevant Terms.
+ */
+public class TermLinkBag extends Bag<TermLink> {
+
+    private static final int maxTakeOut = Parameters.MAX_TAKE_OUT_K_LINK;
+    
+    protected int capacity() {
+        return Parameters.BELIEF_BAG_SIZE;
+    }
+    
+    protected int forgetRate() {
+        return Parameters.BELIEF_DEFAULT_FORGETTING_CYCLE;
+    }
+    
+    // replace defualt to prevent repeated inference
+    public TermLink takeOut(TaskLink tLink) {
+        for (int i = 0; i < maxTakeOut; i++) {
+            TermLink bLink = takeOut();
+            if (bLink == null)
+                return null;
+            if (tLink.novel(bLink)) {
+                return bLink;
+            }
+            putBack(bLink);
+        }
+        return null;
+    }
+}
+
diff --git a/open-nars/com/googlecode/opennars/storage/package.html b/open-nars/com/googlecode/opennars/storage/package.html
new file mode 100644
index 0000000000000000000000000000000000000000..7e267931eef36c0e33f24628a0ee52fb7a433670
--- /dev/null
+++ b/open-nars/com/googlecode/opennars/storage/package.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<body bgcolor="white">
+
+Storage management
+
+<h2>Package Specification</h2>
+
+All items (Concept within Memory, TaskLinks and CompositionLinks within Concept) are put into Bags, which supports priority-based resources allocation.  Also, bag supports access by key (String).
+<p>
+A bag supports three major operations:
+<ul>
+<li>To take out an item by key.</li>
+<li>To take out an item probabilistically according to priority.</li>
+<li>To put an item into the bag.</li>
+</ul>
+All the operations take constant time to finish.
+<p>
+The "take out by priority" operation takes an item out probablistically, with the 
+probability proportional to the priority value.
+<p>
+The probability distribution is generated from a deterministic table.
+<p>
+All classes in package <tt>nars.storage</tt> extend <tt>Bag</tt>.
+<p>
+In NARS, the memory consists of a bag of concepts.  Each concept uniquely corresponds to a term, which uniquely corresponds to a String served as its name.  It is necessary to separate a term and the corresponding concept, because a concept may be deleted due to space competition, and a term is removed only when no other term is linked to it.  In the system, there may be multiple terms refer to the same concept, though the concept just refer to one of them.  NARS does not follow a "one term, one concept" policy and use a hash table in memory to maps names into terms, because the system needs to remove a concept without removing the term that naming it. 
+<p>
+Variable terms correspond to no concept, and their meaning is local to the "smallest" term that contains all occurences of the variable.
+<p>
+From name to term, call Term.nameToTerm(String).  From name to concept, call Concept.nameToConcept(String).   Both use the name as key to get the concept from the concept hashtable in memory. 
+<p>
+The main memory also contains buffers for new tasks. One buffer contains tasks to be processed immediately (to be finished in constant time), and the other, a bag, for the tasks to be processed later.
+
+</body>
+</html>
diff --git a/open-nars/lib/antlr-runtime-3.0.1.jar b/open-nars/lib/antlr-runtime-3.0.1.jar
new file mode 100644
index 0000000000000000000000000000000000000000..b2efb5b6669945c818a71989c49943b18ffcef49
Binary files /dev/null and b/open-nars/lib/antlr-runtime-3.0.1.jar differ
diff --git a/open-nars/lib/stringtemplate-3.0.jar b/open-nars/lib/stringtemplate-3.0.jar
new file mode 100644
index 0000000000000000000000000000000000000000..5efcffce509c7ce466fd6f5c0e5a56ed2ce75e21
Binary files /dev/null and b/open-nars/lib/stringtemplate-3.0.jar differ