[gnome-calculator/60-split-out-a-backend-library] gcalc: added parenthesis (group) term support
- From: Daniel Espinosa Ortiz <despinosa src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calculator/60-split-out-a-backend-library] gcalc: added parenthesis (group) term support
- Date: Fri, 4 Jan 2019 20:16:12 +0000 (UTC)
commit 9ce1cc5e629deb2924c50d605de32a95d30818d0
Author: Daniel Espinosa Ortiz <esodan gmail com>
Date: Fri Jan 4 12:08:37 2019 -0600
gcalc: added parenthesis (group) term support
gcalc/gcalc-expression-container.vala | 17 +++++++++++
gcalc/gcalc-expression.vala | 1 +
gcalc/gcalc-gexpression.vala | 5 ++++
gcalc/gcalc-ggroup.vala | 54 +++++++++++++++++++++++++++++++++++
gcalc/gcalc-group.vala | 30 +++++++++++++++++++
gcalc/gcalc-parser.vala | 52 +++++++++++++++++++++++++++++----
gcalc/meson.build | 2 ++
tests/gcalc-parsing.vala | 54 +++++++++++++++++++++++++++++++++++
8 files changed, 209 insertions(+), 6 deletions(-)
---
diff --git a/gcalc/gcalc-expression-container.vala b/gcalc/gcalc-expression-container.vala
index fb0623d5..a948639e 100644
--- a/gcalc/gcalc-expression-container.vala
+++ b/gcalc/gcalc-expression-container.vala
@@ -19,6 +19,23 @@
* Daniel Espinosa <esodan gmail com>
*/
public class GCalc.ExpressionContainer : Gee.ArrayList<Expression>, GLib.ListModel {
+ public weak Expression parent { get; set; }
+ public new void add (Expression exp) {
+ (this as Gee.ArrayList<Expression>).add (exp);
+ exp.parent = parent;
+ }
+ public new Expression remove_at (int index) {
+ var r = (this as Gee.ArrayList<Expression>).remove_at (index);
+ if (r != null) {
+ r.parent = null;
+ }
+ return r;
+ }
+ public new Expression remove (Expression exp) {
+ var i = (this as Gee.ArrayList<Expression>).index_of (exp);
+ return remove_at (i);
+ }
+ // GLib.ListModel
public Object? get_item (uint position) {
return (this as Gee.ArrayList<Expression>).@get ((int) position) as Object;
}
diff --git a/gcalc/gcalc-expression.vala b/gcalc/gcalc-expression.vala
index 4e86b3fb..6b83c5d5 100644
--- a/gcalc/gcalc-expression.vala
+++ b/gcalc/gcalc-expression.vala
@@ -19,6 +19,7 @@
* Daniel Espinosa <esodan gmail com>
*/
public interface GCalc.Expression : Object {
+ public abstract weak Expression parent { get; set; }
public abstract ExpressionContainer expressions { get; }
public abstract string to_string ();
public abstract Result solve ();
diff --git a/gcalc/gcalc-gexpression.vala b/gcalc/gcalc-gexpression.vala
index aac356d4..8238e9bf 100644
--- a/gcalc/gcalc-gexpression.vala
+++ b/gcalc/gcalc-gexpression.vala
@@ -20,6 +20,11 @@
*/
public class GCalc.GExpression : Object, Expression {
ExpressionContainer exps = new ExpressionContainer ();
+ construct {
+ exps.parent = this;
+ }
+ // Expression
+ public weak Expression parent { get; set; }
public ExpressionContainer expressions { get { return exps; } }
public new virtual string to_string () {
return "";
diff --git a/gcalc/gcalc-ggroup.vala b/gcalc/gcalc-ggroup.vala
new file mode 100644
index 00000000..b9e7b074
--- /dev/null
+++ b/gcalc/gcalc-ggroup.vala
@@ -0,0 +1,54 @@
+/* gcalc-ggroup.vala
+ *
+ * Copyright (C) 2018 Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Daniel Espinosa <esodan gmail com>
+ */
+public class GCalc.GGroup : GExpression, Group {
+ public Group.Level level { get; set; }
+ public bool closed { get; set; }
+ public override string to_string () {
+ string s = "";
+ switch (level) {
+ case ONE:
+ s = "(";
+ break;
+ case TWO:
+ s = "[";
+ break;
+ case THREE:
+ s = "{";
+ break;
+ }
+ foreach (Expression e in expressions) {
+ s += e.to_string ();
+ }
+ switch (level) {
+ case ONE:
+ s += ")";
+ break;
+ case TWO:
+ s += "]";
+ break;
+ case THREE:
+ s += "}";
+ break;
+ }
+ return s;
+ }
+}
+
diff --git a/gcalc/gcalc-group.vala b/gcalc/gcalc-group.vala
new file mode 100644
index 00000000..c56c98b8
--- /dev/null
+++ b/gcalc/gcalc-group.vala
@@ -0,0 +1,30 @@
+/* gcalc-group.vala
+ *
+ * Copyright (C) 2018 Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Daniel Espinosa <esodan gmail com>
+ */
+public interface GCalc.Group : Object, Expression {
+ public abstract Level level { get; set; }
+ public abstract bool closed { get; set; }
+ public enum Level {
+ ONE,
+ TWO,
+ THREE
+ }
+}
+
diff --git a/gcalc/gcalc-parser.vala b/gcalc/gcalc-parser.vala
index f64575c8..8d23e6a0 100644
--- a/gcalc/gcalc-parser.vala
+++ b/gcalc/gcalc-parser.vala
@@ -178,6 +178,12 @@ public class GCalc.Parser : Object {
current_parent.expressions.add (cexp);
expected.clear ();
current = cexp;
+ } else if (current is Term && current_parent is Polynomial && top_parent is Group) {
+ current.expressions.add (cexp);
+ top_parent = current_parent;
+ current_parent = current;
+ current = cexp;
+ expected.clear ();
}
break;
case Vala.TokenType.PERCENT:
@@ -221,7 +227,21 @@ public class GCalc.Parser : Object {
}
break;
case Vala.TokenType.OPEN_PARENS:
- if (current is Function) {
+ if (current == null) {
+ var exp = new GPolynomial ();
+ eq.expressions.add (exp);
+ var t = new GTerm ();
+ exp.expressions.add (t);
+ var g = new GGroup ();
+ t.expressions.add (g);
+ var exp2 = new GPolynomial ();
+ var t2 = new GTerm ();
+ exp2.expressions.add (t2);
+ g.expressions.add (exp2);
+ current = t2;
+ current_parent = exp2;
+ top_parent = g;
+ } else if (current is Function) {
var fexp = new GPolynomial ();
current = fexp;
expected.clear ();
@@ -232,6 +252,30 @@ public class GCalc.Parser : Object {
}
break;
case Vala.TokenType.CLOSE_PARENS:
+ if (current == null) {
+ throw new ParserError.INVALID_TOKEN_ERROR ("Found an unexpected expression while closing
parenthesis");
+ }
+ bool foundp = false;
+ var par = current;
+ while (par != null) {
+ if (par is Group) {
+ foundp = true;
+ ((Group) par).closed = true;
+ break;
+ }
+ par = par.parent;
+ }
+ if (foundp) {
+ current = par.parent; // Term
+ current_parent = current.parent;
+ top_parent = current_parent.parent;
+ }
+ break;
+ // braces
+ case Vala.TokenType.CLOSE_BRACE:
+ case Vala.TokenType.CLOSE_BRACKET:
+ case Vala.TokenType.OPEN_BRACE:
+ case Vala.TokenType.OPEN_BRACKET:
break;
case Vala.TokenType.STRING_LITERAL:
message ("Found string literal");
@@ -266,13 +310,9 @@ public class GCalc.Parser : Object {
case Vala.TokenType.OP_SHIFT_LEFT:
// Carret?
case Vala.TokenType.CARRET:
- // braces
- case Vala.TokenType.CLOSE_BRACE:
- case Vala.TokenType.CLOSE_BRACKET:
+ // templates and regex
case Vala.TokenType.CLOSE_REGEX_LITERAL:
case Vala.TokenType.CLOSE_TEMPLATE:
- case Vala.TokenType.OPEN_BRACE:
- case Vala.TokenType.OPEN_BRACKET:
case Vala.TokenType.OPEN_REGEX_LITERAL:
case Vala.TokenType.OPEN_TEMPLATE:
//
diff --git a/gcalc/meson.build b/gcalc/meson.build
index 2b0936c2..42101824 100644
--- a/gcalc/meson.build
+++ b/gcalc/meson.build
@@ -60,6 +60,8 @@ sources = files([
'gcalc-gplus.vala',
'gcalc-gpolynomial.vala',
'gcalc-gresult.vala',
+ 'gcalc-group.vala',
+ 'gcalc-ggroup.vala',
'gcalc-gsolver.vala',
'gcalc-gterm.vala',
'gcalc-gvariable.vala',
diff --git a/tests/gcalc-parsing.vala b/tests/gcalc-parsing.vala
index 515a05ec..6ab031e1 100644
--- a/tests/gcalc-parsing.vala
+++ b/tests/gcalc-parsing.vala
@@ -509,6 +509,60 @@ class Tests {
Constant c = new GConstant.@double (-1.0) as Constant;
assert ("-1" in c.to_string ());
});
+ Test.add_func ("/gcalc/parser/term/parenthesis",
+ ()=>{
+ try {
+ var parser = new Parser ();
+ var eqman = new GMathEquationManager ();
+ parser.parse ("(1)", eqman);
+ assert (eqman.equations.get_n_items () == 1);
+ var eq = eqman.equations.get_item (0) as MathEquation;
+ assert (eq != null);
+ assert (eq.expressions.get_n_items () == 1);
+ var p = eq.expressions.get_item (0) as Polynomial;
+ assert (p != null);
+ assert (p.expressions.get_n_items () == 1);
+ var t = p.expressions.get_item (0) as Term;
+ assert (t != null);
+ assert (t.expressions.get_n_items () == 1);
+ var g = t.expressions.get_item (0) as Group;
+ assert (g != null);
+ assert (g.closed);
+ assert (g.expressions.get_n_items () == 1);
+ var p1 = g.expressions.get_item (0) as Polynomial;
+ assert (p1 != null);
+ assert (p1.expressions.get_n_items () == 1);
+ var t1 = p1.expressions.get_item (0) as Term;
+ assert (t1 != null);
+ assert (t1.expressions.get_n_items () == 1);
+ var c = t1.expressions.get_item (0) as Constant;
+ assert (c != null);
+ } catch (GLib.Error error) {
+ warning ("Error: %s", error.message);
+ }
+ });
+ Test.add_func ("/gcalc/parser/term/parenthesis/errors",
+ ()=>{
+ var parser = new Parser ();
+ var eqman1 = new GMathEquationManager ();
+ try {
+ parser.parse ("(", eqman1);
+ } catch (GLib.Error error) {
+ message ("Correctly catched grouping error: %s", error.message);
+ }
+ var eqman2 = new GMathEquationManager ();
+ try {
+ parser.parse ("1)", eqman2);
+ } catch (GLib.Error error) {
+ message ("Correctly catched grouping error: %s", error.message);
+ }
+ var eqman3 = new GMathEquationManager ();
+ try {
+ parser.parse ("(1))", eqman3);
+ } catch (GLib.Error error) {
+ message ("Correctly catched grouping error: %s", error.message);
+ }
+ });
return Test.run ();
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]