Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle equals and allow typing texts in cells #91

Merged
merged 12 commits into from
Jul 23, 2020
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ executable(meson.project_name(),
'src/Services/Formula/AST/CellReference.vala',
'src/Services/Formula/AST/Expression.vala',
'src/Services/Formula/AST/NumberExpression.vala',
'src/Services/Formula/AST/TextExpression.vala',
'src/Services/Formula/FormulaGrammar.vala',
'src/Services/Formula/FormulaParser.vala',
'src/Services/Parsing/Evaluator.vala',
Expand Down
7 changes: 6 additions & 1 deletion src/Models/Cell.vala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ public class Spreadsheet.Models.Cell : Object {
try {
var parser = new FormulaParser (new Lexer (new FormulaGrammar ()).tokenize (value));
var expression = parser.parse ();
display_content = ((double)expression.eval (page)).to_string ();

if (expression.expression_type == AST.Expression.ExpressionType.NUMBER) {
display_content = ((double)expression.eval (page)).to_string ();
} else {
display_content = (string)expression.eval (page);
}
} catch (ParserError err) {
debug ("Error: " + err.message);
display_content = "Error";
Expand Down
6 changes: 6 additions & 0 deletions src/Services/Formula/AST/Expression.vala
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
using Spreadsheet.Models;

public abstract class Spreadsheet.Services.Formula.AST.Expression : Object {
public enum ExpressionType {
NUMBER,
STRING
}

public ExpressionType expression_type { get; construct; default = ExpressionType.NUMBER; }
public abstract Value eval (Page sheet);
}
16 changes: 16 additions & 0 deletions src/Services/Formula/AST/TextExpression.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Spreadsheet.Models;

public class Spreadsheet.Services.Formula.AST.TextExpression : Expression {
public string text { get; construct; }

public TextExpression (string value) {
Object (
text: value,
expression_type: ExpressionType.STRING
);
}

public override Value eval (Page sheet) {
return text;
}
}
23 changes: 21 additions & 2 deletions src/Services/Formula/FormulaGrammar.vala
Original file line number Diff line number Diff line change
@@ -1,16 +1,34 @@
using Spreadsheet.Services.Parsing;

public class Spreadsheet.Services.Formula.FormulaGrammar : Grammar {
private string func_name_regex = "";

public FormulaGrammar () {
rules["root"] = root_rules ();
}

private string get_func_name_regex () {
if (func_name_regex != "") {
return func_name_regex;
}

for (int i = 0; i < App.functions.size; i++) {
func_name_regex += "%s|%s".printf (App.functions[i].name, App.functions[i].name.ascii_up ());

if (i + 1 != App.functions.size) {
func_name_regex += "|";
}
}
ryonakano marked this conversation as resolved.
Show resolved Hide resolved

return func_name_regex;
}

private Gee.ArrayList<Evaluator> root_rules () {
return new Gee.ArrayList<Evaluator>.wrap ({
new Evaluator (/[ \t]/, token ("[[ignore]]")),
new Evaluator (/[A-Z]+[0-9]+/, token ("cell-name")),
new Evaluator (/=/, token ("equal")),
new Evaluator (/[A-Za-z][\w]*/, token ("identifier")),
new Evaluator (new GLib.Regex (get_func_name_regex ()), token ("identifier")),
new Evaluator (/\(/, token ("left-parenthese")),
new Evaluator (/\)/, token ("right-parenthese")),
new Evaluator (/,/, token ("comma")),
Expand All @@ -21,7 +39,8 @@ public class Spreadsheet.Services.Formula.FormulaGrammar : Grammar {
new Evaluator (/-/, token ("dash")),
new Evaluator (/\//, token ("slash")),
new Evaluator (/%/, token ("percent")),
new Evaluator (/\^/, token ("carat"))
new Evaluator (/\^/, token ("carat")),
new Evaluator (/.*/, token ("text"))
});
}
}
32 changes: 23 additions & 9 deletions src/Services/Formula/FormulaParser.vala
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,25 @@ public class Spreadsheet.Services.Formula.FormulaParser : Parsing.Parser {
private Expression parse_primary_expression () throws ParserError {
if (current.kind == "equal") {
accept ("equal");
return parse_expression ();
} else if (current.kind == "identifier") {
return parse_call_expression ();

if (current.kind == "identifier") {
return parse_call_expression ();
} else if (current.kind == "number") {
return parse_number ();
} else if (accept ("left-parenthese")) {
var res = parse_expression ();
expect ("right-parenthese");
return res;
} else if (current.kind == "cell-name") {
return parse_cell_name ();
} else {
// Parse as a plain text
return parse_text ();
}
} else if (current.kind == "number") {
return parse_number ();
} else if (accept ("left-parenthese")) {
var res = parse_expression ();
expect ("right-parenthese");
return res;
} else if (current.kind == "cell-name") {
return parse_cell_name ();
} else if (current.kind == "text") {
return parse_text ();
} else {
unexpected ();
return new NumberExpression (0.0);
Expand Down Expand Up @@ -138,6 +146,12 @@ public class Spreadsheet.Services.Formula.FormulaParser : Parsing.Parser {
return res;
}

private TextExpression parse_text () throws ParserError {
TextExpression res = new TextExpression (current.lexeme);
expect ("text");
return res;
}

private CellReference parse_cell_name () throws ParserError {
var cell = new CellReference () { cell_name = current.lexeme };
expect ("cell-name");
Expand Down