1
0
mirror of https://github.com/DanilaFe/abacus synced 2026-01-25 16:15:19 +00:00

Compare commits

..

13 Commits

Author SHA1 Message Date
192269ea9a Merge branch 'master' into variable-parsing 2017-08-29 18:11:30 -07:00
f134e5aa04 Merge pull request #5 from DanilaFe/dokka-setup
Add dokka plugin to generate documentation.
2017-08-29 18:09:36 -07:00
ece9f1ae04 Add dokka plugin to generate documentation. 2017-08-27 15:47:32 -07:00
553c7354c1 Account for the new string-only node structure.
The output has to be the same as the user-provided input, as the
tree isn't converted to numbers until evaluation.
2017-08-18 16:31:54 -07:00
50ede6460c Remove Abacus dependency from ShuntingYardParser. 2017-08-18 15:57:48 -07:00
beb583a231 Move number string parsing from the parser into the reducer. 2017-08-18 14:26:33 -07:00
e0ff229df4 Temporarily substitute 0 for variables. 2017-08-18 14:21:48 -07:00
1c751353f1 Lex and parse variables. 2017-08-18 14:21:14 -07:00
0a15043b63 Implement a variable TreeNode. 2017-08-18 14:20:49 -07:00
21e059c1ca Add a new TokenType for variables. 2017-08-18 14:20:37 -07:00
16faceb3cc Add comment to DocumentationType. 2017-08-16 15:38:02 -07:00
251da90d57 Fix problems with scaling on mobile phones. 2017-08-15 01:24:48 -07:00
a7536b198f Add a proper About page. 2017-08-15 01:02:16 -07:00
15 changed files with 79 additions and 28 deletions

View File

@@ -1,6 +1,22 @@
buildscript {
ext.kotlin_version = '1.1.3'
ext.dokka_version = '0.9.15'
repositories {
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
}
}
subprojects { subprojects {
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'org.jetbrains.dokka'
repositories { repositories {
mavenCentral() mavenCentral()

View File

@@ -1,7 +1,3 @@
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.1.3'
}
dependencies { dependencies {
compile 'com.moandjiezana.toml:toml4j:0.7.1' compile 'com.moandjiezana.toml:toml4j:0.7.1'
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'

View File

@@ -53,7 +53,7 @@ public class Abacus {
numberReducer = new NumberReducer(this); numberReducer = new NumberReducer(this);
this.configuration = new Configuration(configuration); this.configuration = new Configuration(configuration);
LexerTokenizer lexerTokenizer = new LexerTokenizer(); LexerTokenizer lexerTokenizer = new LexerTokenizer();
ShuntingYardParser shuntingYardParser = new ShuntingYardParser(this); ShuntingYardParser shuntingYardParser = new ShuntingYardParser();
treeBuilder = new TreeBuilder<>(lexerTokenizer, shuntingYardParser); treeBuilder = new TreeBuilder<>(lexerTokenizer, shuntingYardParser);
pluginManager.addListener(shuntingYardParser); pluginManager.addListener(shuntingYardParser);

View File

@@ -1,5 +1,9 @@
package org.nwapw.abacus.function; package org.nwapw.abacus.function;
/**
* Enum that holds the type of documentation that has been
* registered with Abacus.
*/
public enum DocumentationType { public enum DocumentationType {
FUNCTION FUNCTION

View File

@@ -34,6 +34,7 @@ public class LexerTokenizer implements Tokenizer<Match<TokenType>>, PluginListen
register(" ", TokenType.WHITESPACE); register(" ", TokenType.WHITESPACE);
register(",", TokenType.COMMA); register(",", TokenType.COMMA);
register("[0-9]*(\\.[0-9]+)?", TokenType.NUM); register("[0-9]*(\\.[0-9]+)?", TokenType.NUM);
register("[a-zA-Z]+", TokenType.VARIABLE);
register("\\(", TokenType.OPEN_PARENTH); register("\\(", TokenType.OPEN_PARENTH);
register("\\)", TokenType.CLOSE_PARENTH); register("\\)", TokenType.CLOSE_PARENTH);
}}; }};

View File

@@ -1,6 +1,5 @@
package org.nwapw.abacus.parsing; package org.nwapw.abacus.parsing;
import org.nwapw.abacus.Abacus;
import org.nwapw.abacus.function.Operator; import org.nwapw.abacus.function.Operator;
import org.nwapw.abacus.function.OperatorAssociativity; import org.nwapw.abacus.function.OperatorAssociativity;
import org.nwapw.abacus.function.OperatorType; import org.nwapw.abacus.function.OperatorType;
@@ -17,10 +16,6 @@ import java.util.*;
*/ */
public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListener { public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListener {
/**
* The Abacus instance used to create number instances.
*/
private Abacus abacus;
/** /**
* Map of operator precedences, loaded from the plugin operators. * Map of operator precedences, loaded from the plugin operators.
*/ */
@@ -35,12 +30,9 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
private Map<String, OperatorType> typeMap; private Map<String, OperatorType> typeMap;
/** /**
* Creates a new Shunting Yard parser with the given Abacus instance. * Creates a new Shunting Yard parser.
*
* @param abacus the abacus instance.
*/ */
public ShuntingYardParser(Abacus abacus) { public ShuntingYardParser() {
this.abacus = abacus;
precedenceMap = new HashMap<>(); precedenceMap = new HashMap<>();
associativityMap = new HashMap<>(); associativityMap = new HashMap<>();
typeMap = new HashMap<>(); typeMap = new HashMap<>();
@@ -61,7 +53,7 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
Match<TokenType> match = from.remove(0); Match<TokenType> match = from.remove(0);
previousType = matchType; previousType = matchType;
matchType = match.getType(); matchType = match.getType();
if (matchType == TokenType.NUM) { if (matchType == TokenType.NUM || matchType == TokenType.VARIABLE) {
output.add(match); output.add(match);
} else if (matchType == TokenType.FUNCTION) { } else if (matchType == TokenType.FUNCTION) {
output.add(new Match<>("", TokenType.INTERNAL_FUNCTION_END)); output.add(new Match<>("", TokenType.INTERNAL_FUNCTION_END));
@@ -143,7 +135,9 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe
else return new UnaryNode(operator, applyTo); else return new UnaryNode(operator, applyTo);
} }
} else if (matchType == TokenType.NUM) { } else if (matchType == TokenType.NUM) {
return new NumberNode(abacus.numberFromString(match.getContent())); return new NumberNode(match.getContent());
} else if (matchType == TokenType.VARIABLE) {
return new VariableNode(match.getContent());
} else if (matchType == TokenType.FUNCTION) { } else if (matchType == TokenType.FUNCTION) {
String functionName = match.getContent(); String functionName = match.getContent();
FunctionNode node = new FunctionNode(functionName); FunctionNode node = new FunctionNode(functionName);

View File

@@ -27,7 +27,9 @@ public class NumberReducer implements Reducer<NumberInterface> {
@Override @Override
public NumberInterface reduceNode(TreeNode node, Object... children) { public NumberInterface reduceNode(TreeNode node, Object... children) {
if (node instanceof NumberNode) { if (node instanceof NumberNode) {
return ((NumberNode) node).getNumber(); return abacus.numberFromString(((NumberNode) node).getNumber());
} else if(node instanceof VariableNode) {
return abacus.numberFromString("0");
} else if (node instanceof BinaryNode) { } else if (node instanceof BinaryNode) {
NumberInterface left = (NumberInterface) children[0]; NumberInterface left = (NumberInterface) children[0];
NumberInterface right = (NumberInterface) children[1]; NumberInterface right = (NumberInterface) children[1];

View File

@@ -7,7 +7,7 @@ package org.nwapw.abacus.tree;
public enum TokenType { public enum TokenType {
INTERNAL_FUNCTION_END(-1), INTERNAL_FUNCTION_END(-1),
ANY(0), WHITESPACE(1), COMMA(2), OP(3), NUM(4), FUNCTION(5), OPEN_PARENTH(6), CLOSE_PARENTH(7); ANY(0), WHITESPACE(1), COMMA(2), OP(3), NUM(4), VARIABLE(5), FUNCTION(6), OPEN_PARENTH(7), CLOSE_PARENTH(8);
/** /**
* The priority by which this token gets sorted. * The priority by which this token gets sorted.

View File

@@ -10,14 +10,14 @@ import org.nwapw.abacus.number.NumberInterface
* *
* @number the number value of this node. * @number the number value of this node.
*/ */
data class NumberNode(val number: NumberInterface) : TreeNode() { data class NumberNode(val number: String) : TreeNode() {
override fun <T : Any> reduce(reducer: Reducer<T>): T? { override fun <T : Any> reduce(reducer: Reducer<T>): T? {
return reducer.reduceNode(this) return reducer.reduceNode(this)
} }
override fun toString(): String { override fun toString(): String {
return number.toString() return number
} }
} }

View File

@@ -0,0 +1,21 @@
package org.nwapw.abacus.tree
/**
* A tree node that holds a placeholder variable.
*
* This node holds a variable string, and acts similarly to a number,
* with the key difference of not actually holding a value at runtime.
*
* @param variable the actual variable name that this node represents.
*/
data class VariableNode(val variable: String) : TreeNode() {
override fun <T : Any> reduce(reducer: Reducer<T>): T? {
return reducer.reduceNode(this)
}
override fun toString(): String {
return variable
}
}

View File

@@ -101,7 +101,7 @@ public class CalculationTests {
testOutput("2^50", "(2^50)", "112589990684262"); testOutput("2^50", "(2^50)", "112589990684262");
testOutput("7^(-sqrt2*17)", "(7^((sqrt(2)*17))`)", "4.81354609155297814551845300063563"); testOutput("7^(-sqrt2*17)", "(7^((sqrt(2)*17))`)", "4.81354609155297814551845300063563");
testEvalError("0^0", "(0^0)"); testEvalError("0^0", "(0^0)");
testEvalError("(-13)^.9999", "((13)`^0.9999)"); testEvalError("(-13)^.9999", "((13)`^.9999)");
} }
} }

View File

@@ -13,6 +13,8 @@
img { img {
margin: auto; margin: auto;
width: 100%;
max-width: 432px;
} }
div#buttons { div#buttons {

View File

@@ -5,6 +5,23 @@ title: About
permalink: /about/ permalink: /about/
--- ---
Welcome to the Abacus project website. ## So... what IS Abacus?
This website is currently under construction, please, check It's a calculator. Obviously. But what makes it better than
back later. what already exists? There's a few things. Abacus is:
* Programmable, and not in TI Basic.
* Precise. With the "precise" option, Abacus can keep up to 50 significant figures.
* Capable. Ever wonder what 2<sup>700</sup> is? How about 8!!? Abacus can tell you!
* Offline. While Wolfram Alpha can do powerful math, it needs internet connection!
* Built for the desktop. Why use buttons on the screen when there's buttons on the keyboard?
* Open source. Don't like something? Help is always welcome!
## Why was Abacus made?
The initial project was proposed for the [Northwest Advanced Programming Workshop](http://nwapw.org/about/).
You can read the project proposal on the main GitHub page, although the idea has
changed quite a bit, mostly in shifting from "fast" to "precise".
## What is Abacus made with?
Java and Kotlin. Java provides a good layer of abstraction and a great standard
library, while Kotlin allows for the reduction of boilerplate code and null
safety. Using JVM-based languages also allows Abacus to expose its entire
API to plugins, and load them at runtime.

View File

@@ -16,6 +16,7 @@ a {
color: $background-color; color: $background-color;
&.button { &.button {
display: inline-block;
background-color: $background-color; background-color: $background-color;
color: $clear-color; color: $clear-color;
padding: 10px; padding: 10px;

View File

@@ -1,6 +1,3 @@
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.1.3'
}
apply plugin: 'application' apply plugin: 'application'
dependencies { dependencies {