├── .idea
├── ant.xml
└── libraries
│ ├── Maven__junit_junit_4_10.xml
│ ├── Maven__javax_servlet_jstl_1_2.xml
│ ├── Maven__org_jsoup_jsoup_1_7_2.xml
│ ├── Maven__org_json_json_20090211.xml
│ ├── Maven__joda_time_joda_time_2_1.xml
│ ├── Maven__org_joda_joda_money_0_6.xml
│ ├── Maven__com_google_guava_guava_14_0_1.xml
│ ├── Maven__org_jscience_jscience_4_3_1.xml
│ ├── Maven__com_google_code_gson_gson_2_2_2.xml
│ ├── Maven__javax_servlet_servlet_api_2_5.xml
│ ├── Maven__org_mockito_mockito_all_1_9_0.xml
│ ├── Maven__org_hamcrest_hamcrest_core_1_1.xml
│ ├── Maven__org_javolution_javolution_5_2_3.xml
│ ├── Maven__com_google_gwt_gwt_user_2_5_0_rc1.xml
│ ├── Maven__org_functionaljava_functionaljava_3_1.xml
│ ├── Maven__com_googlecode_objectify_objectify_4_0b1.xml
│ ├── Maven__javax_validation_validation_api_1_0_0_GA.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_core_2_0_6.xml
│ ├── Maven__javax_validation_validation_api_sources_1_0_0_GA.xml
│ ├── Maven__com_google_appengine_appengine_api_labs_1_7_2.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_databind_2_0_6.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_annotations_2_0_6.xml
│ └── Maven__org_apache_geronimo_specs_geronimo_jpa_3_0_spec_1_1_1.xml
├── src
├── main
│ ├── webapp
│ │ ├── images
│ │ │ ├── mind-blown.jpg
│ │ │ └── homework-cartoon.gif
│ │ ├── WEB-INF
│ │ │ ├── appengine-generated
│ │ │ │ └── local_db.bin
│ │ │ ├── datastore-indexes.xml
│ │ │ ├── logging.properties
│ │ │ ├── appengine-web.xml
│ │ │ └── web.xml
│ │ ├── noie.html
│ │ ├── js
│ │ │ ├── jquery.cookie.js
│ │ │ ├── rangy-selectionsaverestore.js
│ │ │ └── rangy-serializer.js
│ │ └── css
│ │ │ ├── highlighting.css
│ │ │ └── metal
│ │ │ └── style.css
│ └── java
│ │ └── com
│ │ └── lastcalc
│ │ ├── bootstrap
│ │ └── Bootstrap.java
│ │ ├── db
│ │ ├── DAO.java
│ │ ├── Question.java
│ │ ├── User.java
│ │ ├── Worksheet.java
│ │ └── Line.java
│ │ ├── parsers
│ │ ├── math
│ │ │ ├── ImplicitMultiply.java
│ │ │ ├── Radix.java
│ │ │ ├── BitwiseOp.java
│ │ │ ├── RadixConverter.java
│ │ │ ├── GCDLCMParser.java
│ │ │ ├── FactorialParser.java
│ │ │ ├── IsPrimeParser.java
│ │ │ └── PrimesUnderParser.java
│ │ ├── collections
│ │ │ ├── AppendList.java
│ │ │ ├── FoldLeft.java
│ │ │ ├── ApplyTo.java
│ │ │ ├── Filter.java
│ │ │ └── GetFromListOrMap.java
│ │ ├── NoopParser.java
│ │ ├── ParserContext.java
│ │ ├── TrailingEqualsStripper.java
│ │ ├── currency
│ │ │ ├── CurrencyReverser.java
│ │ │ └── Currencies.java
│ │ ├── bool
│ │ │ ├── BoolFunctionsParser.java
│ │ │ ├── BoolParser.java
│ │ │ ├── EqualityParser.java
│ │ │ ├── NotParser.java
│ │ │ └── IfThenElseParser.java
│ │ ├── ToLowerCase.java
│ │ ├── Interpret.java
│ │ ├── amounts
│ │ │ ├── UnitStripper.java
│ │ │ ├── AmountParser.java
│ │ │ └── AmountConverterParser.java
│ │ ├── UDPApplier.java
│ │ ├── strings
│ │ │ └── StringAppender.java
│ │ ├── web
│ │ │ ├── GetFromElement.java
│ │ │ ├── HttpRetriever.java
│ │ │ └── Select.java
│ │ ├── RewriteParser.java
│ │ └── meta
│ │ │ └── ImportParser.java
│ │ ├── servlets
│ │ ├── UserServlet.java
│ │ ├── HelpServlet.java
│ │ └── StatelessServlet.java
│ │ ├── engines
│ │ ├── ParseEngine.java
│ │ ├── ParserSet.java
│ │ ├── FixedOrderParserPickerFactory.java
│ │ ├── CombinedParserPickerFactory.java
│ │ ├── RecentFirstParserPickerFactory.java
│ │ ├── ParseStep.java
│ │ ├── BacktrackingParseEngine.java
│ │ ├── ParserPickerFactory.java
│ │ └── KeywordParserPickerFactory.java
│ │ ├── cache
│ │ ├── ElementWrapper.java
│ │ ├── DocumentWrapper.java
│ │ └── ObjectCache.java
│ │ ├── Misc.java
│ │ └── Tokenizer.java
└── test
│ └── java
│ └── com
│ └── lastcalc
│ ├── TokenizerTest.java
│ ├── parsers
│ ├── currency
│ │ └── CurrenciesTest.java
│ ├── amounts
│ │ └── UnitParserTest.java
│ ├── PreParserTest.java
│ ├── math
│ │ ├── FactorialParserTest.java
│ │ ├── PrimesUnderTest.java
│ │ ├── GCDLCMTest.java
│ │ └── IsPrimeTest.java
│ ├── bool
│ │ └── IfThenElseParserTest.java
│ ├── collections
│ │ └── CollectionsTest.java
│ └── UserDefinedParserParserTest.java
│ ├── ParsersTest.java
│ ├── engines
│ └── CombinedParserPickerFactoryTest.java
│ └── servlets
│ └── WorksheetServletTest.java
├── .settings
├── com.google.gdt.eclipse.core.prefs
└── com.google.appengine.eclipse.core.prefs
├── .gitignore
├── .travis.yml
├── README.markdown
├── .project
└── .classpath
/.idea/ant.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/main/webapp/images/mind-blown.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanity/LastCalc/HEAD/src/main/webapp/images/mind-blown.jpg
--------------------------------------------------------------------------------
/src/main/webapp/images/homework-cartoon.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanity/LastCalc/HEAD/src/main/webapp/images/homework-cartoon.gif
--------------------------------------------------------------------------------
/.settings/com.google.gdt.eclipse.core.prefs:
--------------------------------------------------------------------------------
1 | #Fri Dec 09 10:46:02 CST 2011
2 | eclipse.preferences.version=1
3 | warSrcDir=war
4 | warSrcDirIsOutput=true
5 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/appengine-generated/local_db.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sanity/LastCalc/HEAD/src/main/webapp/WEB-INF/appengine-generated/local_db.bin
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 | war/WEB-INF/appengine-generated
3 | war/WEB-INF/classes
4 | test-output/
5 | annotations/
6 | .idea/
7 | .settings/
8 | target/
9 | *.iml
10 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | after_success:sudo: false
2 | language: java
3 | notifications:
4 | email:
5 | - ian.clarke@gmail.com
6 | - oliverlee010@gmail.com
7 | after_success:
8 | - mvn clean cobertura:cobertura coveralls:report
9 |
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | SourceCode for [LastCalc.com](http://lastcalc.com/).
2 |
3 | Please see [the wiki](https://github.com/sanity/LastCalc/wiki) for further information about how LastCalc works internally, and a guide to contributing to LastCalc.
4 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/datastore-indexes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__junit_junit_4_10.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/logging.properties:
--------------------------------------------------------------------------------
1 | # A default java.util.logging configuration.
2 | # (All App Engine logging is through java.util.logging by default).
3 | #
4 | # To use this configuration, copy it into your application's WEB-INF
5 | # folder and add the following to your appengine-web.xml:
6 | #
7 | #
8 | #
9 | #
10 | #
11 |
12 | # Set the default logging level for all loggers to WARNING
13 | .level = WARNING
14 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_servlet_jstl_1_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.settings/com.google.appengine.eclipse.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | filesCopiedToWebInfLib=appengine-api-labs.jar|appengine-endpoints.jar|appengine-jsr107cache-1.7.1.jar|jsr107cache-1.1.jar|appengine-api-1.0-sdk-1.7.1.jar|datanucleus-appengine-1.0.10.final.jar|datanucleus-core-1.1.5.jar|datanucleus-jpa-1.1.5.jar|geronimo-jpa_3.0_spec-1.1.1.jar|geronimo-jta_1.1_spec-1.1.1.jar|jdo2-api-2.3-eb.jar
3 | gaeDeployDialogSettings=
4 | gaeHrdEnabled=true
5 | gaeIsEclipseDefaultInstPath=false
6 | googleCloudSqlEnabled=false
7 | localDevMySqlEnabled=true
8 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_jsoup_jsoup_1_7_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_json_json_20090211.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__joda_time_joda_time_2_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_joda_joda_money_0_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_guava_guava_14_0_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_jscience_jscience_4_3_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_code_gson_gson_2_2_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_servlet_servlet_api_2_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_mockito_mockito_all_1_9_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_javolution_javolution_5_2_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_gwt_gwt_user_2_5_0_rc1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | lastcalc
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.m2e.core.maven2Builder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.m2e.core.maven2Nature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_functionaljava_functionaljava_3_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_googlecode_objectify_objectify_4_0b1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_validation_validation_api_1_0_0_GA.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_0_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_validation_validation_api_sources_1_0_0_GA.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/webapp/noie.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | LastCalc: Your browser is not supported :-(
4 |
5 |
6 |
7 | Your browser is not yet supported
8 | Due to your web browser's incomplete support for modern web standards, we're afraid
9 | that LastCalc will not yet work with it. We hope to sort out these issues soon,
10 | but in the meantime we recommend that you use
11 | Google Chrome .
12 |
13 | LastCalc is also compatible with Firefox and
14 | Safari .
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_appengine_appengine_api_labs_1_7_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/appengine-web.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | lastcalc-upr
4 | 1
5 |
6 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | true
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_0_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_0_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_geronimo_specs_geronimo_jpa_3_0_spec_1_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/bootstrap/Bootstrap.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.bootstrap;
17 |
18 | public class Bootstrap {
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/TokenizerTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc;
17 |
18 |
19 | public class TokenizerTest {
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/db/DAO.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.db;
17 |
18 | import com.googlecode.objectify.*;
19 |
20 | public class DAO {
21 |
22 | static {
23 | ObjectifyService.register(Worksheet.class);
24 | }
25 |
26 | public static Objectify begin() {
27 | return ObjectifyService.ofy();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/parsers/currency/CurrenciesTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.currency;
17 |
18 | import org.junit.Test;
19 |
20 | public class CurrenciesTest {
21 |
22 | @Test
23 | public void test() {
24 | Currencies.updateExchangeRates();
25 |
26 | System.out.println(Currencies.currenciesByCode);
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/parsers/amounts/UnitParserTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.amounts;
17 |
18 | import java.util.Set;
19 |
20 | import org.junit.Test;
21 |
22 | public class UnitParserTest {
23 |
24 | @Test
25 | public void test() {
26 | final Set parsers = UnitParser.getParsers();
27 | System.out.println(parsers);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/ParsersTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc;
17 |
18 | import org.junit.Test;
19 |
20 | public class ParsersTest {
21 |
22 | @Test
23 | public void testTokenize() {
24 | final String test1 = "one=15+(3/7.8)*12,533 + average of [1, 2...[3]]";
25 | final TokenList test1t = Tokenizer.tokenize(test1);
26 | for (final Object o : test1t) {
27 | System.out.println(o);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/db/Question.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.db;
17 |
18 | import com.googlecode.objectify.annotation.Entity;
19 | import com.googlecode.objectify.annotation.Unindex;
20 |
21 | import javax.persistence.Id;
22 |
23 | @Entity
24 | public class Question {
25 | @Id
26 | public long id;
27 |
28 | public int position;
29 |
30 | public String worksheet;
31 |
32 | @Unindex
33 | public String question;
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/math/ImplicitMultiply.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.parsers.math;
2 |
3 | import com.lastcalc.TokenList;
4 | import com.lastcalc.parsers.Parser;
5 |
6 | /**
7 | * Created by ian on 5/31/15.
8 | */
9 | public class ImplicitMultiply extends Parser {
10 | private static TokenList template = TokenList.createD(org.jscience.mathematics.number.Number.class, org.jscience.mathematics.number.Number.class);
11 |
12 | @Override
13 | public TokenList getTemplate() {
14 | return template;
15 | }
16 |
17 | @Override
18 | public int hashCode() {
19 | return "ImplicitMultiply".hashCode();
20 | }
21 |
22 | @Override
23 | public ParseResult parse(TokenList tokens, int templatePos) {
24 | Number number1 = (Number) tokens.get(templatePos);
25 | Number number2 = (Number) tokens.get(templatePos + 1);
26 |
27 | TokenList.CompositeTokenList newTokens = tokens.replaceWithTokens(templatePos, templatePos + 2, number1, "*", number2);
28 | // Add a score bias so that "twenty five" is parsed as "20+5" and not "20*5"
29 | return ParseResult.success(newTokens, 1);
30 | }
31 |
32 | @Override
33 | public boolean equals(Object obj) {
34 | return obj instanceof ImplicitMultiply;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/db/User.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.db;
17 |
18 | import com.googlecode.objectify.annotation.Cache;
19 | import com.googlecode.objectify.annotation.Unindex;
20 |
21 | import javax.persistence.Id;
22 |
23 | @Cache
24 | public class User {
25 | public static final String passwordSalt = "5pDTVGeciETDWwy";
26 |
27 | @Id
28 | public long id;
29 |
30 | public String cookieId;
31 |
32 | public String username;
33 |
34 | public String email;
35 |
36 | @Unindex
37 | public String saltedPasswordHash;
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/collections/AppendList.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.parsers.collections;
2 |
3 | import com.google.appengine.labs.repackaged.com.google.common.collect.Lists;
4 | import com.lastcalc.TokenList;
5 | import com.lastcalc.parsers.Parser;
6 | import com.lastcalc.parsers.ParserContext;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * Created by ian on 6/2/15.
12 | */
13 | public class AppendList extends Parser {
14 | private static TokenList template = TokenList.createD(List.class, Lists.newArrayList("append", "+"), List.class);
15 |
16 | @Override
17 | public TokenList getTemplate() {
18 | return template;
19 | }
20 |
21 | @Override
22 | public int hashCode() {
23 | return "AppendList".hashCode();
24 | }
25 |
26 | @Override
27 | public ParseResult parse(final TokenList tokens, final int templatePos, final ParserContext context) {
28 | List list1 = (List) tokens.get(templatePos);
29 | List list2 = (List) tokens.get(templatePos+2);
30 | List newList = Lists.newArrayList();
31 | newList.addAll(list1);
32 | newList.addAll(list2);
33 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos+3, newList));
34 | }
35 |
36 | @Override
37 | public boolean equals(Object obj) {
38 | return false;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | MainPage
9 | com.lastcalc.servlets.MainPageServlet
10 |
11 |
12 | Worksheet
13 | com.lastcalc.servlets.WorksheetServlet
14 |
15 |
16 | Stateless
17 | com.lastcalc.servlets.StatelessServlet
18 |
19 |
20 | Help
21 | com.lastcalc.servlets.HelpServlet
22 |
23 |
24 | MainPage
25 | /*
26 |
27 |
28 | Worksheet
29 | /ws
30 |
31 |
32 | Stateless
33 | /sl
34 |
35 |
36 | Help
37 | /help
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/servlets/UserServlet.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.servlets;
17 |
18 | import javax.servlet.http.HttpServlet;
19 |
20 | public class UserServlet extends HttpServlet {
21 | private static final long serialVersionUID = 8713053995956225568L;
22 |
23 | @Override
24 | protected void doPost(final javax.servlet.http.HttpServletRequest req,
25 | final javax.servlet.http.HttpServletResponse resp) throws javax.servlet.ServletException,
26 | java.io.IOException {
27 | }
28 |
29 | public static class UserServletRequest {
30 | public String username, saltedPasswordHash;
31 |
32 | public RegisterRequest register;
33 | }
34 |
35 | public static class RegisterRequest {
36 | public String email;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/NoopParser.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers;
17 |
18 | import com.lastcalc.TokenList;
19 |
20 | public class NoopParser extends Parser {
21 | private static final long serialVersionUID = 7600767637692555261L;
22 | public static final NoopParser singleton = new NoopParser();
23 |
24 | @Override
25 | public TokenList getTemplate() {
26 | return null;
27 | }
28 |
29 | @Override
30 | public ParseResult parse(final TokenList tokens, final int templatePos) {
31 | return ParseResult.success(tokens);
32 | }
33 |
34 | @Override
35 | public int hashCode() {
36 | return "NoopParser".hashCode();
37 | }
38 |
39 | @Override
40 | public boolean equals(final Object obj) {
41 | return obj instanceof NoopParser;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/ParserContext.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers;
17 |
18 | import com.lastcalc.engines.ParseEngine;
19 |
20 | public class ParserContext implements Cloneable {
21 | public final ParseEngine parseEngine;
22 |
23 | public int importDepth = 0;
24 |
25 | public long timeout;
26 |
27 | public ParserContext(final ParseEngine parseEngine, final long timeout, final int importDepth) {
28 | this(parseEngine, timeout);
29 | this.importDepth = importDepth;
30 | }
31 |
32 | public ParserContext(final ParseEngine parseEngine, final long timeout) {
33 | this.parseEngine = parseEngine;
34 | this.timeout = timeout;
35 | }
36 |
37 | @Override
38 | public Object clone() throws CloneNotSupportedException {
39 | return super.clone();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/engines/ParseEngine.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.engines;
17 |
18 | import java.util.LinkedList;
19 |
20 | import com.lastcalc.TokenList;
21 | import com.lastcalc.parsers.ParserContext;
22 |
23 |
24 | public abstract class ParseEngine {
25 |
26 | public TokenList parseAndGetLastStep(final TokenList input,
27 | final ParserContext context,
28 | final TokenList... alternateInputs) {
29 | final LinkedList parse = parse(input, context, alternateInputs);
30 | if (parse.isEmpty())
31 | throw new RuntimeException("Parse resulted in no ParseSteps");
32 | return parse.getLast().result.output;
33 | }
34 |
35 | public abstract LinkedList parse(final TokenList input,
36 | ParserContext context,
37 | TokenList... alternateInputs);
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/servlets/HelpServlet.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.servlets;
17 |
18 | import java.io.IOException;
19 |
20 | import javax.servlet.ServletException;
21 | import javax.servlet.http.*;
22 |
23 | import com.lastcalc.lessons.Help;
24 |
25 | public class HelpServlet extends HttpServlet {
26 | private static final long serialVersionUID = -7706942563225877578L;
27 |
28 | @Override
29 | public void init() throws javax.servlet.ServletException {
30 | // Force static initialization
31 | Help.lessons.size();
32 | };
33 |
34 | @Override
35 | protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException,
36 | IOException {
37 | resp.setContentType("text/html; charset=UTF-8");
38 | resp.setCharacterEncoding("UTF-8");
39 | resp.getWriter().append(Help.getHelpDoc().toString());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/engines/ParserSet.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.engines;
2 |
3 | import java.util.*;
4 |
5 | import com.lastcalc.parsers.*;
6 | import com.lastcalc.parsers.UserDefinedParserParser.UserDefinedParser;
7 |
8 | /**
9 | * A set for parsers where the UserDefinedParser that shortens the token
10 | * list most comes first. For use in ParserPickerFactories.
11 | *
12 | * @author Ian Clarke
13 | *
14 | */
15 | public class ParserSet extends TreeSet {
16 | private static final long serialVersionUID = -6285593762627218550L;
17 |
18 | public ParserSet() {
19 | super(new Comparator() {
20 |
21 | @Override
22 | public int compare(final Parser o1, final Parser o2) {
23 | if (o1 instanceof UserDefinedParser && !(o2 instanceof UserDefinedParser))
24 | return -1;
25 | else if (o2 instanceof UserDefinedParser && !(o1 instanceof UserDefinedParser))
26 | return 1;
27 | else if (o1 instanceof UserDefinedParser && o2 instanceof UserDefinedParser) {
28 | final UserDefinedParser udp1 = (UserDefinedParser) o1;
29 | final UserDefinedParser udp2 = (UserDefinedParser) o2;
30 | final int sizeRed1 = udp1.after.size() - udp1.getTemplate().size();
31 | final int sizeRed2 = udp2.after.size() - udp2.getTemplate().size();
32 | return compareInts(sizeRed1, sizeRed2, compareInts(o1.hashCode(), o2.hashCode(), 0));
33 | }
34 | else
35 | return compareInts(o1.hashCode(), o2.hashCode(), 0);
36 | }
37 |
38 | });
39 | }
40 |
41 | private static int compareInts(final int a, final int b, final int otherwise) {
42 | if (ab) return 1;
44 | else return otherwise;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/parsers/PreParserTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers;
17 |
18 | import junit.framework.Assert;
19 |
20 | import org.junit.Test;
21 |
22 | import com.lastcalc.*;
23 |
24 | public class PreParserTest {
25 | @Test
26 | public void findObjectTest() {
27 | final TokenList tl = Tokenizer.tokenize("i wish (i was) a tea pot");
28 | Assert.assertEquals(tl.indexOf("wish"), PreParser.findEdgeOrObjectForwards(tl, tl.indexOf("i"), "wish"));
29 | Assert.assertEquals(tl.size() - 1, PreParser.findEdgeOrObjectForwards(tl, tl.indexOf("i"), "i"));
30 | Assert.assertEquals(0, PreParser.findEdgeOrObjectBackwards(tl, tl.indexOf("pot"), "i"));
31 | Assert.assertEquals(tl.indexOf("(") + 1, PreParser.findEdgeOrObjectBackwards(tl, tl.indexOf("was"), null));
32 | Assert.assertEquals(tl.size() - 1, PreParser.findEdgeOrObjectForwards(tl, tl.indexOf("wish"), null));
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/parsers/math/FactorialParserTest.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.parsers.math;
2 |
3 | import junit.framework.Assert;
4 |
5 | import org.jscience.mathematics.number.LargeInteger;
6 | import org.junit.Test;
7 |
8 | import com.lastcalc.SequentialParser;
9 | import com.lastcalc.TokenList;
10 | import com.lastcalc.parsers.Parser;
11 | import com.lastcalc.parsers.Parser.ParseResult;
12 |
13 | public class FactorialParserTest {
14 |
15 | @Test
16 | public void successfulParseTest(){
17 |
18 | final FactorialParser fp = new FactorialParser();
19 | ParseResult pr=fp.parse(TokenList.createD("blah","factorial",LargeInteger.valueOf(3),"blah"),1);
20 | Assert.assertTrue("Ensure parse was succcesful", pr.isSuccess());
21 | Assert.assertEquals("Ensure parse result is what it's supposed to be",TokenList.createD("blah",LargeInteger.valueOf(6),"blah"), pr.output);
22 | }
23 |
24 |
25 | @Test
26 | public void tooBigOrSmallTest(){
27 |
28 | final FactorialParser fp = new FactorialParser();
29 | ParseResult pr=fp.parse(TokenList.createD("blah","factorial",LargeInteger.valueOf(-1),"blah"),1);
30 | Assert.assertFalse("Ensure parse failed b/c it's a negative num", pr.isSuccess());
31 |
32 | ParseResult pr2=fp.parse(TokenList.createD("blah","factorial",LargeInteger.valueOf(20),"blah"),1);
33 | Assert.assertFalse("Ensure parse failed b/c it's a too big", pr2.isSuccess());
34 |
35 | }
36 |
37 | public void hookedUpProperly(){
38 |
39 | final SequentialParser sp=SequentialParser.create();
40 |
41 | TokenList pr=sp.parseNext(TokenList.createD("6","!"));
42 |
43 | Assert.assertEquals(1,pr.size());
44 | Assert.assertEquals(LargeInteger.valueOf(720), pr.get(0));
45 |
46 | }
47 |
48 |
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/TrailingEqualsStripper.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers;
17 |
18 | import com.lastcalc.TokenList;
19 |
20 | public class TrailingEqualsStripper extends Parser {
21 | private static final TokenList template = TokenList.createD("=");
22 | private static final long serialVersionUID = 2340131974673871340L;
23 |
24 | @Override
25 | public TokenList getTemplate() {
26 | return template;
27 | }
28 |
29 | @Override
30 | public int hashCode() {
31 | return "TrailingEqualsStripper".hashCode();
32 | }
33 |
34 | @Override
35 | public ParseResult parse(final TokenList tokens, final int templatePos) {
36 | if (templatePos == tokens.size()-1)
37 | return ParseResult.success(tokens.subList(0, tokens.size() - 1));
38 | else
39 | return ParseResult.fail();
40 | }
41 |
42 | @Override
43 | public boolean equals(final Object obj) {
44 | return obj instanceof TrailingEqualsStripper;
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/parsers/bool/IfThenElseParserTest.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.parsers.bool;
2 |
3 | import com.lastcalc.TokenList;
4 | import com.lastcalc.parsers.Parser;
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 |
8 | /**
9 | * Created by ian on 6/3/15.
10 | */
11 | public class IfThenElseParserTest {
12 | @Test
13 | public void ifThenElseTrueTest() {
14 | IfThenElseParser ifThenElseParser = new IfThenElseParser();
15 | TokenList trueTL = TokenList.createD("(", "if", Boolean.TRUE, "then", 1, "else", 0, ")");
16 | Parser.ParseResult trueResult = ifThenElseParser.parse(trueTL, 1);
17 | Assert.assertTrue(trueResult.isSuccess());
18 | Assert.assertEquals(TokenList.createD("(", 1, ")"), trueResult.output);
19 |
20 | TokenList falseTL = TokenList.createD("(", "if", Boolean.FALSE, "then", 1, "else", 0, ")");
21 | Parser.ParseResult falseResult = ifThenElseParser.parse(falseTL, 1);
22 | Assert.assertTrue(falseResult.isSuccess());
23 | Assert.assertEquals(TokenList.createD("(", 0, ")"), falseResult.output);
24 | }
25 |
26 | @Test
27 | public void ifThenTest() {
28 | IfThenElseParser ifThenElseParser = new IfThenElseParser();
29 | TokenList trueTL = TokenList.createD("(", "if", Boolean.TRUE, "then", 1, ")");
30 | Parser.ParseResult trueResult = ifThenElseParser.parse(trueTL, 1);
31 | Assert.assertTrue(trueResult.isSuccess());
32 | Assert.assertEquals(TokenList.createD("(", 1, ")"), trueResult.output);
33 |
34 | TokenList falseTL = TokenList.createD("(", "if", Boolean.FALSE, "then", 1, ")");
35 | Parser.ParseResult falseResult = ifThenElseParser.parse(falseTL, 1);
36 | Assert.assertFalse(falseResult.isSuccess());
37 | }
38 | }
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/parsers/math/PrimesUnderTest.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.parsers.math;
2 |
3 | import com.google.appengine.labs.repackaged.com.google.common.collect.Lists;
4 | import com.lastcalc.TokenList;
5 | import com.lastcalc.parsers.Parser;
6 | import junit.framework.Assert;
7 | import org.jscience.mathematics.number.LargeInteger;
8 | import org.junit.Test;
9 |
10 | import java.util.ArrayList;
11 |
12 | /**
13 | * ****************************************************************************
14 | * LastCalc - The last calculator you'll ever need
15 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
16 | *
17 | * This program is free software: you can redistribute it and/or modify it
18 | * under the terms of the GNU Affero General Public License as published
19 | * by the Free Software Foundation, either version 3 of the License, or
20 | * (at your option) any later version.
21 | *
22 | * This program is distributed in the hope that it will be useful, but
23 | * WITHOUT ANY WARRANTY; without even the implied warranty of
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
25 | * PURPOSE. See the GNU Affero General Public License for more
26 | * details.
27 | * ****************************************************************************
28 | */
29 | public class PrimesUnderTest {
30 |
31 |
32 |
33 | @Test
34 | public void primesUnderTest(){
35 |
36 | final PrimesUnderParser pup = new PrimesUnderParser();
37 | Parser.ParseResult pr=pup.parse(TokenList.createD("blah", "primesunder", LargeInteger.valueOf(3), "blah"),1);
38 | Assert.assertTrue("Ensure parse was successful: ", pr.isSuccess());
39 | Assert.assertEquals("Ensure parse result is what it's supposed to be: ",TokenList.createD("blah", Lists.newArrayList(2,3),"blah"), pr.output);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/currency/CurrencyReverser.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.currency;
17 |
18 | import org.jscience.economics.money.Currency;
19 |
20 | import com.lastcalc.TokenList;
21 | import com.lastcalc.parsers.Parser;
22 |
23 | public class CurrencyReverser extends Parser {
24 |
25 | public static TokenList template = TokenList.createD(Currency.class, Number.class);
26 |
27 | @Override
28 | public ParseResult parse(final TokenList tokens, final int templatePos) {
29 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(),
30 | tokens.get(templatePos + 1), tokens.get(templatePos)), -1);
31 | }
32 |
33 | @Override
34 | public TokenList getTemplate() {
35 | return template;
36 | }
37 |
38 | @Override
39 | public int hashCode() {
40 | return "CurrencyReverser".hashCode();
41 | }
42 |
43 | @Override
44 | public String toString() {
45 | return "";
46 | }
47 |
48 | @Override
49 | public boolean equals(final Object obj) {
50 | return obj instanceof CurrencyReverser;
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/bool/BoolFunctionsParser.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.bool;
17 |
18 | import com.google.common.collect.Lists;
19 |
20 | import com.lastcalc.TokenList;
21 | import com.lastcalc.parsers.Parser;
22 |
23 | public class BoolFunctionsParser extends Parser {
24 | private static final long serialVersionUID = -7820633700412274072L;
25 | private static TokenList template = TokenList.createD(Lists.newArrayList("not", "!"),
26 | Boolean.class);
27 |
28 | @Override
29 | public ParseResult parse(final TokenList tokens, final int templatePos) {
30 | final boolean a = (Boolean) tokens.get(templatePos + 1);
31 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), !a));
32 | }
33 |
34 | @Override
35 | public TokenList getTemplate() {
36 | return template;
37 | }
38 |
39 | @Override
40 | public int hashCode() {
41 | return "BoolFunctionsParser".hashCode();
42 | }
43 |
44 | @Override
45 | public boolean equals(final Object obj) {
46 | return obj instanceof BoolFunctionsParser;
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/bool/BoolParser.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.bool;
17 |
18 | import com.google.common.collect.Lists;
19 |
20 | import com.lastcalc.TokenList;
21 | import com.lastcalc.parsers.Parser;
22 |
23 |
24 | public class BoolParser extends Parser {
25 | private static final long serialVersionUID = -7666856639055196045L;
26 | private static TokenList template = TokenList.createD(Lists.newArrayList("true", "yes", "false", "no"));
27 |
28 |
29 | @Override
30 | public TokenList getTemplate() {
31 | return template;
32 | }
33 |
34 | @Override
35 | public ParseResult parse(final TokenList tokens, final int templatePos) {
36 | final boolean result = (tokens.get(templatePos).equals("true") || tokens.get(templatePos).equals("yes"));
37 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), result));
38 | }
39 |
40 | @Override
41 | public int hashCode() {
42 | return "BoolParser".hashCode();
43 | }
44 |
45 | @Override
46 | public boolean equals(final Object obj) {
47 | return obj instanceof BoolParser;
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/math/Radix.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.math;
17 |
18 | import java.io.Serializable;
19 |
20 |
21 | public class Radix implements Serializable {
22 | private static final long serialVersionUID = 6793205833102927654L;
23 | public final long integer;
24 | public final int radix;
25 |
26 | public static Radix parse(final String value) {
27 | if (value.startsWith("0x"))
28 | return new Radix(Long.parseLong(value.substring(2), 16), 16);
29 | else if (value.startsWith("0b"))
30 | return new Radix(Long.parseLong(value.substring(2), 2), 2);
31 | else if (value.startsWith("0o"))
32 | return new Radix(Long.parseLong(value.substring(2), 8), 8);
33 | else
34 | return null;
35 | }
36 |
37 | public Radix(final long integer, final int radix) {
38 | this.integer = integer;
39 | this.radix = radix;
40 | }
41 |
42 | @Override
43 | public String toString() {
44 | String prefix;
45 | if (radix == 2) {
46 | prefix = "0b";
47 | } else if (radix == 8) {
48 | prefix = "0o";
49 | } else {
50 | prefix = "0x";
51 | }
52 | return prefix + Long.toString(integer, radix);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/ToLowerCase.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers;
17 |
18 | import com.lastcalc.TokenList;
19 |
20 | public class ToLowerCase extends Parser {
21 | private static final long serialVersionUID = 4507416694168613210L;
22 |
23 | private static TokenList template = TokenList.createD(String.class);
24 |
25 | @Override
26 | public TokenList getTemplate() {
27 | return template;
28 | }
29 |
30 | @Override
31 | public String toString() {
32 | return "";
33 | }
34 |
35 | @Override
36 | public ParseResult parse(final TokenList tokens, final int templatePos) {
37 | final String orig = (String) tokens.get(templatePos);
38 | final String lowerCase = orig.toLowerCase();
39 | if (!lowerCase.equals(orig))
40 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), lowerCase),
41 | 0.5);
42 | else
43 | return ParseResult.fail();
44 | }
45 |
46 | @Override
47 | public int hashCode() {
48 | return "ToLowerCase".hashCode();
49 | }
50 |
51 | @Override
52 | public boolean equals(final Object obj) {
53 | return obj instanceof ToLowerCase;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/math/BitwiseOp.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.parsers.math;
2 |
3 | import com.google.common.collect.Lists;
4 |
5 | import org.jscience.mathematics.number.LargeInteger;
6 |
7 | import com.lastcalc.TokenList;
8 | import com.lastcalc.parsers.Parser;
9 |
10 | public class BitwiseOp extends Parser {
11 | private static final long serialVersionUID = -694604478564851560L;
12 | private final TokenList template = TokenList.createD(Lists.newArrayList(LargeInteger.class, Radix.class),
13 | Lists.newArrayList("xor", "and", "or"), Lists.newArrayList(LargeInteger.class, Radix.class));
14 |
15 | @Override
16 | public TokenList getTemplate() {
17 | return template;
18 | }
19 |
20 | @Override
21 | public ParseResult parse(final TokenList tokens, final int templatePos) {
22 | final Object ar = tokens.get(templatePos);
23 | final long a = ar instanceof LargeInteger ? ((LargeInteger) ar).longValue() : ((Radix) ar).integer;
24 | final String op = (String) tokens.get(templatePos + 1);
25 | final Object br = tokens.get(templatePos + 2);
26 | final long b = br instanceof LargeInteger ? ((LargeInteger) br).longValue() : ((Radix) br).integer;
27 | int radix = 10;
28 | if (ar instanceof Radix && br instanceof Radix && ((Radix) ar).radix == ((Radix) br).radix) {
29 | radix = ((Radix) ar).radix;
30 | }
31 | long result;
32 | if (op.equals("xor")) {
33 | result = a ^ b;
34 | } else if (op.equals("and")) {
35 | result = a & b;
36 | } else if (op.equals("or")) {
37 | result = a | b;
38 | } else
39 | return ParseResult.fail();
40 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(),
41 | radix == 10 ? LargeInteger.valueOf(result) : new Radix(result, radix)));
42 | }
43 |
44 | @Override
45 | public int hashCode() {
46 | return "BitwiseOp".hashCode();
47 | }
48 |
49 | @Override
50 | public boolean equals(final Object obj) {
51 | return obj instanceof BitwiseOp;
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/Interpret.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers;
17 |
18 | import com.lastcalc.*;
19 | import com.lastcalc.Tokenizer.QuotedString;
20 |
21 | public class Interpret extends Parser {
22 | private static final long serialVersionUID = 4507416694168613210L;
23 |
24 | private static TokenList template = TokenList.createD("interpret", Tokenizer.QuotedString.class);
25 |
26 | @Override
27 | public TokenList getTemplate() {
28 | return template;
29 | }
30 |
31 | @Override
32 | public String toString() {
33 | return "";
34 | }
35 |
36 | @Override
37 | public ParseResult parse(final TokenList tokens, final int templatePos) {
38 | final Tokenizer.QuotedString string = (QuotedString) tokens.get(templatePos + 1);
39 | final TokenList ret = Tokenizer.tokenize(string.value);
40 | return ParseResult.success(tokens.replaceWithTokenList(templatePos, templatePos + template.size(), ret),
41 | -ret.size());
42 | }
43 |
44 | @Override
45 | public int hashCode() {
46 | return "ToLowerCase".hashCode();
47 | }
48 |
49 | @Override
50 | public boolean equals(final Object obj) {
51 | return obj instanceof Interpret;
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/amounts/UnitStripper.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.amounts;
17 |
18 | import javax.measure.unit.Unit;
19 |
20 | import org.jscience.physics.amount.Amount;
21 |
22 | import com.lastcalc.TokenList;
23 | import com.lastcalc.parsers.Parser;
24 |
25 |
26 | public class UnitStripper extends Parser {
27 | private static final long serialVersionUID = 5689741343269900107L;
28 | private static final TokenList template = TokenList.createD(Amount.class);
29 |
30 | @Override
31 | public TokenList getTemplate() {
32 | return template;
33 | }
34 |
35 | @Override
36 | public ParseResult parse(final TokenList tokens, final int templatePos) {
37 | final Amount> amount = (Amount>) tokens.get(templatePos);
38 | if (amount.getUnit().equals(Unit.ONE))
39 | return ParseResult.fail();
40 | return ParseResult.success(
41 | tokens.replaceWithTokens(templatePos, templatePos + template.size(),
42 | Amount.valueOf(amount.getEstimatedValue(), Unit.ONE)), 2);
43 | }
44 |
45 | @Override
46 | public int hashCode() {
47 | return "UnitStripper".hashCode();
48 | }
49 |
50 | @Override
51 | public boolean equals(final Object obj) {
52 | return obj instanceof UnitStripper;
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/bool/EqualityParser.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.bool;
17 |
18 | import com.google.common.collect.Lists;
19 |
20 | import com.lastcalc.TokenList;
21 | import com.lastcalc.parsers.Parser;
22 |
23 | public class EqualityParser extends Parser {
24 | private static final long serialVersionUID = -2750832188085003939L;
25 | private static TokenList template = TokenList.createD(Object.class, Lists.newArrayList("==", "!="), Object.class);
26 |
27 | @Override
28 | public ParseResult parse(final TokenList tokens, final int templatePos) {
29 | final Object a = tokens.get(templatePos);
30 | final String op = (String) tokens.get(templatePos + 1);
31 | final Object b = tokens.get(templatePos + 2);
32 | final boolean result = op.equals("==") ? a.equals(b) : !a.equals(b);
33 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), result));
34 | }
35 |
36 | @Override
37 | public TokenList getTemplate() {
38 | return template;
39 | }
40 |
41 | @Override
42 | public int hashCode() {
43 | return "EqualityParser".hashCode();
44 | }
45 |
46 | @Override
47 | public boolean equals(final Object obj) {
48 | return obj instanceof EqualityParser;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/db/Worksheet.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.db;
17 |
18 | import com.google.common.collect.Lists;
19 | import com.googlecode.objectify.annotation.Cache;
20 | import com.googlecode.objectify.annotation.Entity;
21 | import com.googlecode.objectify.annotation.Id;
22 | import com.googlecode.objectify.annotation.Serialize;
23 | import com.lastcalc.Misc;
24 | import com.lastcalc.parsers.Parser;
25 |
26 | import javax.persistence.PrePersist;
27 | import java.util.ArrayList;
28 | import java.util.Collection;
29 | import java.util.Date;
30 |
31 | @Cache
32 | @Entity
33 | public class Worksheet {
34 |
35 | public Worksheet() {
36 | id = Misc.randomString(7);
37 | readOnlyId = Misc.randomString(8);
38 | qaPairs = Lists.newArrayList();
39 | created = new Date();
40 | }
41 |
42 | @Id
43 | public String id;
44 |
45 | public String parentId;
46 |
47 | public String readOnlyId;
48 |
49 | public String description;
50 |
51 | public boolean used;
52 |
53 | @Serialize
54 | public ArrayList qaPairs;
55 |
56 | @Serialize
57 | public Collection definedParsers;
58 |
59 | public Date created, lastModified;
60 |
61 | @PrePersist
62 | private void prePersist() {
63 | lastModified = new Date();
64 | used = qaPairs.size() > 0;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/webapp/js/jquery.cookie.js:
--------------------------------------------------------------------------------
1 | /**
2 | * jQuery Cookie plugin
3 | *
4 | * Copyright (c) 2010 Klaus Hartl (stilbuero.de)
5 | * Dual licensed under the MIT and GPL licenses:
6 | * http://www.opensource.org/licenses/mit-license.php
7 | * http://www.gnu.org/licenses/gpl.html
8 | *
9 | */
10 | (function($) {
11 | $.cookie = function(key, value, options) {
12 |
13 | // key and at least value given, set cookie...
14 | if (arguments.length > 1 && (!/Object/.test(Object.prototype.toString.call(value)) || value === null || value === undefined)) {
15 | options = $.extend({}, options);
16 |
17 | if (value === null || value === undefined) {
18 | options.expires = -1;
19 | }
20 |
21 | if (typeof options.expires === 'number') {
22 | var days = options.expires, t = options.expires = new Date();
23 | t.setDate(t.getDate() + days);
24 | }
25 |
26 | value = String(value);
27 |
28 | return (document.cookie = [
29 | encodeURIComponent(key), '=', options.raw ? value : encodeURIComponent(value),
30 | options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
31 | options.path ? '; path=' + options.path : '',
32 | options.domain ? '; domain=' + options.domain : '',
33 | options.secure ? '; secure' : ''
34 | ].join(''));
35 | }
36 |
37 | // key and possibly options given, get cookie...
38 | options = value || {};
39 | var decode = options.raw ? function(s) { return s; } : decodeURIComponent;
40 |
41 | var pairs = document.cookie.split('; ');
42 | for (var i = 0, pair; pair = pairs[i] && pairs[i].split('='); i++) {
43 | if (decode(pair[0]) === key) return decode(pair[1] || ''); // IE saves cookies with empty string as "c; ", e.g. without "=" as opposed to EOMB, thus pair[1] may be undefined
44 | }
45 | return null;
46 | };
47 | })(jQuery);
48 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/cache/ElementWrapper.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.cache;
17 |
18 | import java.io.*;
19 |
20 | import org.jsoup.Jsoup;
21 | import org.jsoup.nodes.Element;
22 |
23 | // Turns out Document has a crappy hashCode() implementation,
24 | // this makes it more efficient
25 | public class ElementWrapper implements Serializable {
26 | public Element el;
27 |
28 | String asString;
29 |
30 | private int hashCode;
31 |
32 | public ElementWrapper(final Element el) {
33 | this.el = el;
34 | asString = el.toString();
35 | hashCode = asString.hashCode();
36 |
37 | }
38 |
39 | @Override
40 | public int hashCode() {
41 | return hashCode;
42 | }
43 |
44 | @Override
45 | public String toString() {
46 | if (asString.length() < 60)
47 | return asString;
48 | else
49 | return "<" + el.tagName() + " - too big (" + asString.length() + " chars)>";
50 | }
51 |
52 | private void writeObject(final ObjectOutputStream out) throws IOException {
53 | out.writeInt(hashCode);
54 | out.writeObject(asString);
55 | }
56 |
57 | private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
58 | hashCode = in.readInt();
59 | asString = (String) in.readObject();
60 | el = Jsoup.parseBodyFragment(asString).body();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/engines/CombinedParserPickerFactoryTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.engines;
17 |
18 | import com.google.common.collect.Lists;
19 |
20 | import org.junit.*;
21 |
22 | import com.lastcalc.TokenList;
23 | import com.lastcalc.parsers.*;
24 |
25 |
26 | public class CombinedParserPickerFactoryTest {
27 |
28 | @Test
29 | public void test() {
30 | final Parser p1 = new RewriteParser(Lists.newArrayList("1", "1"), "one");
31 | final Parser p2 = new RewriteParser(Lists.newArrayList("2", "2"), "two");
32 | final Parser p3 = new RewriteParser(Lists.newArrayList("3", "3"), "three");
33 | final Parser p4 = new RewriteParser(Lists.newArrayList("4", "4"), "four");
34 |
35 | final FixedOrderParserPickerFactory f1 = new FixedOrderParserPickerFactory(p1, p2);
36 | final FixedOrderParserPickerFactory f2 = new FixedOrderParserPickerFactory(p3, p4);
37 | final CombinedParserPickerFactory f = new CombinedParserPickerFactory(f1, f2);
38 |
39 | final BacktrackingParseEngine pe = new BacktrackingParseEngine(f);
40 |
41 | final ParserContext context = new ParserContext(pe, Long.MAX_VALUE);
42 | final TokenList result = pe.parseAndGetLastStep(new TokenList.SimpleTokenList("1", "1", "2", "2", "3", "3",
43 | "4", "4"),
44 | context);
45 |
46 | Assert.assertEquals(TokenList.createD("one", "two", "three", "four"), result);
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/bool/NotParser.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.bool;
17 |
18 | import com.google.common.collect.Lists;
19 |
20 | import com.lastcalc.TokenList;
21 | import com.lastcalc.parsers.Parser;
22 |
23 | public class NotParser extends Parser {
24 | private static final long serialVersionUID = -7820633700412274072L;
25 | private static TokenList template = TokenList.createD(Boolean.class, Lists.newArrayList("and", "or", "xor"),
26 | Boolean.class);
27 |
28 | @Override
29 | public ParseResult parse(final TokenList tokens, final int templatePos) {
30 | final boolean a = (Boolean) tokens.get(templatePos);
31 | final boolean b = (Boolean) tokens.get(templatePos + 2);
32 | final String function = (String) tokens.get(templatePos + 1);
33 | boolean ret;
34 | if (function.equals("and")) {
35 | ret = a && b;
36 | } else if (function.equals("or")) {
37 | ret = a || b;
38 | } else {
39 | ret = a != b;
40 | }
41 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), ret));
42 | }
43 |
44 | @Override
45 | public TokenList getTemplate() {
46 | return template;
47 | }
48 |
49 | @Override
50 | public int hashCode() {
51 | return "BoolFunctionsParser".hashCode();
52 | }
53 |
54 | @Override
55 | public boolean equals(final Object obj) {
56 | return obj instanceof NotParser;
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/Misc.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc;
17 |
18 | import com.google.common.base.Joiner;
19 | import com.google.gson.Gson;
20 | import com.google.gson.GsonBuilder;
21 |
22 | import java.text.NumberFormat;
23 | import java.util.Random;
24 |
25 | public class Misc {
26 | public static Random rand = new Random();
27 |
28 | private static final String randStrChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"
29 | + "0123456789";
30 |
31 | public static String toString(final Iterable o) {
32 | final StringBuilder sb = new StringBuilder();
33 | for (final Object io : o) {
34 | sb.append(io.getClass().getSimpleName() + " " + io + ", ");
35 | }
36 | return sb.toString();
37 | }
38 |
39 | public static String randomString(final int digits) {
40 | final StringBuilder sb = new StringBuilder(digits);
41 | for (int x = 0; x < digits; x++) {
42 | sb.append(randStrChars.charAt(rand.nextInt(randStrChars.length())));
43 | }
44 | return sb.toString();
45 | }
46 |
47 | public static final Gson gson = new GsonBuilder().create();
48 |
49 | public static NumberFormat numberFormat;
50 | static {
51 | numberFormat = NumberFormat.getInstance();
52 | numberFormat.setGroupingUsed(false);
53 | numberFormat.setParseIntegerOnly(false);
54 | numberFormat.setMaximumFractionDigits(20);
55 | }
56 |
57 | public static final Joiner joiner = Joiner.on(' ');
58 | }
59 |
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/parsers/collections/CollectionsTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.collections;
17 |
18 | import java.util.LinkedList;
19 |
20 | import junit.framework.Assert;
21 |
22 | import com.google.common.collect.Lists;
23 |
24 | import com.lastcalc.*;
25 | import com.lastcalc.engines.*;
26 | import com.lastcalc.parsers.*;
27 |
28 |
29 | public class CollectionsTest {
30 |
31 | // @Test
32 | public void getFromMapTest() {
33 | final PreParser bp = new PreParser();
34 | final TokenList origTokens = Tokenizer.tokenize("get b from {a:A, b:B}");
35 | final LinkedList parsers = Lists.newLinkedList();
36 | com.lastcalc.parsers.Parser.getAll(parsers);
37 | final LinkedList priorityParsers = Lists.newLinkedList();
38 | priorityParsers.add(new PreParser());
39 | priorityParsers.add(new UserDefinedParserParser());
40 | final FixedOrderParserPickerFactory priorityPPF = new FixedOrderParserPickerFactory(priorityParsers);
41 | final RecentFirstParserPickerFactory catchAllPPF = new RecentFirstParserPickerFactory(parsers);
42 | final ParseEngine st = new BacktrackingParseEngine(new CombinedParserPickerFactory(priorityPPF, catchAllPPF));
43 | final ParserContext context = new ParserContext(st, Long.MAX_VALUE);
44 | final TokenList result = st.parseAndGetLastStep(origTokens, context);
45 | Assert.assertEquals(1, result.size());
46 | Assert.assertEquals("B", result.get(0));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/cache/DocumentWrapper.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.cache;
17 |
18 | import java.io.*;
19 |
20 | import org.jsoup.Jsoup;
21 | import org.jsoup.nodes.Document;
22 |
23 | // Turns out Document has a crappy hashCode() implementation,
24 | // this makes it more efficient
25 | public class DocumentWrapper implements Serializable {
26 | private static final long serialVersionUID = -4508748891178262750L;
27 |
28 | public Document doc;
29 |
30 | String asString;
31 |
32 | private int hashCode;
33 |
34 | private String title;
35 |
36 | public DocumentWrapper(final Document doc) {
37 | this.doc = doc;
38 | asString = doc.toString();
39 | hashCode = asString.hashCode();
40 | title = doc.head().select("title").text();
41 |
42 | }
43 |
44 | @Override
45 | public int hashCode() {
46 | return hashCode;
47 | }
48 |
49 | public String title() {
50 | return title;
51 | }
52 |
53 | @Override
54 | public String toString() {
55 | return asString;
56 | }
57 |
58 | private void writeObject(final ObjectOutputStream out) throws IOException {
59 | out.writeInt(hashCode);
60 | out.writeObject(title);
61 | out.writeObject(asString);
62 | }
63 |
64 | private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
65 | hashCode = in.readInt();
66 | title = (String) in.readObject();
67 | asString = (String) in.readObject();
68 | doc = Jsoup.parse(asString);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/amounts/AmountParser.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.amounts;
17 |
18 | import javax.measure.unit.Unit;
19 |
20 | import org.jscience.physics.amount.Amount;
21 |
22 | import com.lastcalc.TokenList;
23 | import com.lastcalc.parsers.Parser;
24 |
25 |
26 | public class AmountParser extends Parser {
27 | private static final long serialVersionUID = 9120544485351922021L;
28 | private static final TokenList template = TokenList.createD(Number.class, Unit.class);
29 |
30 | @Override
31 | public ParseResult parse(final TokenList tokens, final int templatePos) {
32 | final Number number = (Number) tokens.get(templatePos);
33 | final Unit> unit = (Unit>) tokens.get(templatePos + 1);
34 | if (number.longValue() == number.doubleValue())
35 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(),
36 | Amount.valueOf(number.longValue(), unit)));
37 | else
38 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(),
39 | Amount.valueOf(number.doubleValue(), unit)));
40 | }
41 |
42 | @Override
43 | public TokenList getTemplate() {
44 | return template;
45 | }
46 |
47 | @Override
48 | public int hashCode() {
49 | return "AmountParser".hashCode();
50 | }
51 |
52 | @Override
53 | public String toString() {
54 | return "";
55 | }
56 |
57 | @Override
58 | public boolean equals(final Object obj) {
59 | return obj instanceof AmountParser;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/UDPApplier.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers;
17 |
18 | import com.lastcalc.TokenList;
19 | import com.lastcalc.parsers.UserDefinedParserParser.UserDefinedParser;
20 |
21 | public class UDPApplier extends Parser {
22 | private static final long serialVersionUID = -5412238263419670848L;
23 | private static TokenList template = TokenList.createD("apply", UserDefinedParser.class, "to");
24 |
25 | @Override
26 | public TokenList getTemplate() {
27 | return template;
28 | }
29 |
30 | @Override
31 | public ParseResult parse(final TokenList tokens, final int templatePos, final ParserContext context) {
32 | final UserDefinedParser function = (UserDefinedParser) tokens.get(templatePos + 1);
33 | if (2 + templatePos + function.getTemplate().size() > tokens.size())
34 | return ParseResult.fail();
35 | final TokenList input = tokens.subList(templatePos + 3, templatePos + 3 + function.getTemplate().size());
36 | if (function.matchTemplate(input) != 0)
37 | return ParseResult.fail();
38 | final ParseResult parse = function.parse(input, 0, context);
39 | if (parse.isSuccess())
40 | return ParseResult.success(tokens.replaceWithTokenList(templatePos, templatePos + 3
41 | + function.getTemplate().size(), parse.output));
42 | else
43 | return ParseResult.fail();
44 | }
45 |
46 | @Override
47 | public int hashCode() {
48 | return "UDPApplier".hashCode();
49 | }
50 |
51 | @Override
52 | public boolean equals(final Object obj) {
53 | return obj instanceof UDPApplier;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/strings/StringAppender.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.strings;
17 |
18 | import com.lastcalc.*;
19 | import com.lastcalc.Tokenizer.QuotedString;
20 | import com.lastcalc.parsers.Parser;
21 |
22 | public class StringAppender extends Parser {
23 | private static final long serialVersionUID = -7820633700412274072L;
24 | private static TokenList template = TokenList.createD(Object.class, "+", Object.class);
25 |
26 | @Override
27 | public ParseResult parse(final TokenList tokens, final int templatePos) {
28 | final Object o1 = tokens.get(templatePos);
29 | final Object o2 = tokens.get(templatePos + 2);
30 | QuotedString ret;
31 | if ((o1 instanceof QuotedString) && (o2 instanceof QuotedString)) {
32 | ret = new QuotedString(((QuotedString) o1).value + ((QuotedString) o2).value);
33 | } else if (o1 instanceof QuotedString) {
34 | ret = new QuotedString(((QuotedString) o1).value + o2.toString());
35 | } else if (o2 instanceof QuotedString) {
36 | ret = new QuotedString(o1.toString() + ((QuotedString) o2).value);
37 | } else
38 | return ParseResult.fail();
39 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), ret));
40 | }
41 |
42 | @Override
43 | public TokenList getTemplate() {
44 | return template;
45 | }
46 |
47 | @Override
48 | public int hashCode() {
49 | return "StringAppender".hashCode();
50 | }
51 |
52 | @Override
53 | public boolean equals(final Object obj) {
54 | return obj instanceof StringAppender;
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/engines/FixedOrderParserPickerFactory.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.engines;
17 |
18 | import java.util.*;
19 |
20 | import com.google.common.collect.Lists;
21 |
22 | import com.lastcalc.parsers.*;
23 |
24 |
25 | public class FixedOrderParserPickerFactory extends ParserPickerFactory {
26 | private static final long serialVersionUID = -2346529366052255216L;
27 | private final LinkedList parsers;
28 |
29 | public FixedOrderParserPickerFactory(final Parser... parsers) {
30 | this.parsers = Lists.newLinkedList(Lists.newArrayList(parsers));
31 | }
32 |
33 | public FixedOrderParserPickerFactory(final LinkedList parsers) {
34 | this.parsers = parsers;
35 | }
36 |
37 | @Override
38 | public void addParser(final Parser parser) {
39 | parsers.add(parser);
40 | }
41 |
42 | @Override
43 | public ParserPicker getPicker(final Map prevAttemptPos) {
44 | return new FixedOrderParserPicker(prevAttemptPos, parsers);
45 | }
46 |
47 | @Override
48 | public void teach(final Iterable step) {
49 | // Noop
50 | }
51 |
52 | public static class FixedOrderParserPicker extends ParserPicker {
53 |
54 | private final Iterable parsers;
55 |
56 | public FixedOrderParserPicker(final Map prevAttemptPos, final Iterable parsers) {
57 | super(prevAttemptPos);
58 | this.parsers = parsers;
59 | }
60 |
61 | @Override
62 | public ParseStep pickNext(final ParserContext context, final ParseStep previous) {
63 | final ParseStep next = getNext(context, parsers, previous);
64 | return next;
65 | }
66 |
67 | }
68 |
69 | public List getParsers() {
70 | return parsers;
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/db/Line.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.db;
17 |
18 | import com.googlecode.objectify.annotation.Unindex;
19 | import com.lastcalc.TokenList;
20 |
21 | import java.io.IOException;
22 | import java.io.ObjectInputStream;
23 | import java.io.ObjectOutputStream;
24 | import java.io.Serializable;
25 |
26 | public class Line implements Serializable {
27 | private static final long serialVersionUID = 8234981855606438804L;
28 |
29 | public Line(final String question, final TokenList answer)
30 | throws IOException {
31 | this.question = question;
32 | this.answer = answer;
33 | }
34 |
35 | public Line(final int lineNum, final String question, final TokenList answer)
36 | throws IOException {
37 | this.lineNum=lineNum;
38 | this.question = question;
39 | this.answer = answer;
40 | }
41 |
42 | public int lineNum;
43 |
44 | @Unindex
45 | public String question;
46 |
47 | @Unindex
48 | public TokenList answer;
49 |
50 | // We serialize manually to ensure that TokenLists are serialized
51 | // efficiently
52 | private void writeObject(final ObjectOutputStream out) throws IOException {
53 | out.writeObject(question);
54 | out.writeInt(answer.size());
55 | for (final Object o : answer) {
56 | out.writeObject(o);
57 | }
58 | }
59 |
60 | private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
61 | question = (String) in.readObject();
62 | final Object[] answer = new Object[in.readInt()];
63 | for (int x = 0; x < answer.length; x++) {
64 | answer[x] = in.readObject();
65 | }
66 | this.answer = TokenList.createD(answer);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/bool/IfThenElseParser.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.bool;
17 |
18 | import com.lastcalc.TokenList;
19 | import com.lastcalc.parsers.Parser;
20 | import com.lastcalc.parsers.ParserContext;
21 | import com.lastcalc.parsers.PreParser;
22 |
23 | public class IfThenElseParser extends Parser {
24 | private static final long serialVersionUID = -7731508022221902181L;
25 |
26 | private static TokenList template = TokenList.createD("if", Boolean.class, "then");
27 |
28 | @Override
29 | public TokenList getTemplate() {
30 | return template;
31 | }
32 |
33 | @Override
34 | public ParseResult parse(final TokenList tokens, final int templatePos, final ParserContext context) {
35 | final boolean condition = (Boolean) tokens.get(templatePos + 1);
36 | final int endPos = PreParser.findEdgeOrObjectForwards(tokens, templatePos + 2, null) + 1;
37 | final int elsePos = PreParser.findEdgeOrObjectForwards(tokens, templatePos + 2, "else");
38 | TokenList ret;
39 | if (!tokens.get(elsePos).equals("else")) {
40 | if (condition) {
41 | ret = new TokenList.SubTokenList(tokens, templatePos + 3, endPos);
42 | } else {
43 | return ParseResult.fail();
44 | }
45 | } else {
46 | if (condition) {
47 | ret = new TokenList.SubTokenList(tokens, templatePos + 3, elsePos);
48 | } else {
49 | ret = new TokenList.SubTokenList(tokens, elsePos + 1, endPos);
50 | }
51 | }
52 | return ParseResult.success(tokens.replaceWithTokenList(templatePos, endPos, ret));
53 | }
54 |
55 | @Override
56 | public int hashCode() {
57 | return "IfThenElseParser".hashCode();
58 | }
59 |
60 | @Override
61 | public boolean equals(final Object obj) {
62 | return obj instanceof IfThenElseParser;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/servlets/WorksheetServletTest.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.servlets;
2 |
3 |
4 | import com.lastcalc.TokenList;
5 | import com.lastcalc.db.Worksheet;
6 | import org.jscience.mathematics.number.Number;
7 | import org.junit.Assert;
8 | import org.junit.Test;
9 |
10 |
11 | import java.io.IOException;
12 | import java.util.HashMap;
13 |
14 | /*******************************************************************************
15 | * LastCalc - The last calculator you'll ever need
16 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
17 | *
18 | * This program is free software: you can redistribute it and/or modify it
19 | * under the terms of the GNU Affero General Public License as published
20 | * by the Free Software Foundation, either version 3 of the License, or
21 | * (at your option) any later version.
22 | *
23 | * This program is distributed in the hope that it will be useful, but
24 | * WITHOUT ANY WARRANTY; without even the implied warranty of
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
26 | * PURPOSE. See the GNU Affero General Public License for more
27 | * details.
28 | ******************************************************************************/
29 | public class WorksheetServletTest {
30 |
31 |
32 | @Test
33 | public void testFunctionCreation() throws IOException {
34 |
35 | final Worksheet worksheet=new Worksheet();
36 |
37 | {
38 | WorksheetServlet.WorksheetRequest worksheetRequest=new WorksheetServlet.WorksheetRequest();
39 |
40 | worksheetRequest.questions=new HashMap();
41 | worksheetRequest.questions.put(1,"double X = X*2");
42 |
43 |
44 | WorksheetServlet.getWorksheetResponse(worksheet, worksheetRequest, "");
45 |
46 | }
47 |
48 | {
49 | WorksheetServlet.WorksheetRequest worksheetRequest=new WorksheetServlet.WorksheetRequest();
50 |
51 | worksheetRequest.questions=new HashMap();
52 | worksheetRequest.questions.put(2,"double 5");
53 | WorksheetServlet.getWorksheetResponse(worksheet, worksheetRequest, "");
54 | }
55 |
56 |
57 | final TokenList result=worksheet.qaPairs.get(1).answer;
58 |
59 |
60 | Assert.assertEquals(1, result.size());
61 |
62 | Assert.assertTrue("Assert that " + result.get(0).getClass() + " is a Number", result.get(0) instanceof org.jscience.mathematics.number.Number);
63 | double value = ((Number) result.get(0)).doubleValue();
64 | Assert.assertEquals(10.0, value,0.01);
65 |
66 | System.out.println("worksheet servlet test finished");
67 |
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/collections/FoldLeft.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.collections;
17 |
18 | import java.util.List;
19 |
20 | import com.lastcalc.TokenList;
21 | import com.lastcalc.parsers.*;
22 | import com.lastcalc.parsers.UserDefinedParserParser.UserDefinedParser;
23 |
24 | public class FoldLeft extends Parser {
25 | private static final long serialVersionUID = 9178891850811247754L;
26 | private static TokenList template = TokenList.createD("fold", UserDefinedParser.class, "over", List.class, "with",
27 | Object.class);
28 |
29 | @Override
30 | public ParseResult parse(final TokenList tokens, final int templatePos, final ParserContext context) {
31 | Object ret = tokens.get(templatePos + 5);
32 | final UserDefinedParser udp = (UserDefinedParser) tokens.get(templatePos + 1);
33 | final Object datastructure = tokens.get(templatePos + 3);
34 | if (datastructure instanceof List) {
35 | if (udp.getTemplate().size() != 2)
36 | return ParseResult.fail();
37 | final List list = (List) datastructure;
38 | for (final Object o : list) {
39 | TokenList r = udp.parse(TokenList.createD(ret, o), 0).output;
40 | r = context.parseEngine.parseAndGetLastStep(r, context);
41 | if (r.size() != 1)
42 | return ParseResult.fail();
43 | else {
44 | ret = r.get(0);
45 | }
46 | }
47 | } else
48 | return ParseResult.fail();
49 | return ParseResult.success(tokens.replaceWithTokenList(templatePos, templatePos + template.size(),
50 | TokenList.createD(ret)));
51 | }
52 |
53 | @Override
54 | public TokenList getTemplate() {
55 | return template;
56 | }
57 |
58 | @Override
59 | public int hashCode() {
60 | return "FoldLeft".hashCode();
61 | }
62 |
63 | @Override
64 | public boolean equals(final Object obj) {
65 | return obj instanceof FoldLeft;
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/math/RadixConverter.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.math;
17 |
18 | import com.google.common.collect.Lists;
19 |
20 | import org.jscience.mathematics.number.LargeInteger;
21 |
22 | import com.lastcalc.TokenList;
23 | import com.lastcalc.parsers.Parser;
24 |
25 |
26 | public class RadixConverter extends Parser {
27 | private static final long serialVersionUID = 9120544485351922021L;
28 | private static final TokenList template = TokenList.createD(Lists.newArrayList(LargeInteger.class, Radix.class),
29 | Lists.newArrayList("to", "as", "in"),
30 | Lists.newArrayList("bin", "binary", "hex", "hexadecimal", "oct", "octal", "dec", "decimal"));
31 |
32 | @Override
33 | public ParseResult parse(final TokenList tokens, final int templatePos) {
34 | final Object num = tokens.get(templatePos);
35 | final long li = num instanceof LargeInteger ?((LargeInteger) tokens.get(templatePos)).longValue(): ((Radix) num).integer;
36 |
37 | final String convertTo = (String) tokens.get(templatePos + 2);
38 | Object result;
39 | if (convertTo.startsWith("bin")) {
40 | result = new Radix(li, 2);
41 | } else if (convertTo.startsWith("hex")) {
42 | result = new Radix(li, 16);
43 | } else if (convertTo.startsWith("oct")) {
44 | result = new Radix(li, 8);
45 | } else {
46 | result = LargeInteger.valueOf(li);
47 | }
48 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), result));
49 | }
50 |
51 | @Override
52 | public TokenList getTemplate() {
53 | return template;
54 | }
55 |
56 | @Override
57 | public int hashCode() {
58 | return "RadixConverter".hashCode();
59 | }
60 |
61 | @Override
62 | public String toString() {
63 | return "";
64 | }
65 |
66 | @Override
67 | public boolean equals(final Object obj) {
68 | return obj instanceof RadixConverter;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/parsers/math/GCDLCMTest.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.parsers.math;
2 |
3 | import com.lastcalc.TokenList;
4 | import com.lastcalc.parsers.Parser;
5 | import junit.framework.Assert;
6 | import org.jscience.mathematics.number.LargeInteger;
7 | import org.junit.Test;
8 |
9 | /**
10 | * ****************************************************************************
11 | * LastCalc - The last calculator you'll ever need
12 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
13 | *
14 | * This program is free software: you can redistribute it and/or modify it
15 | * under the terms of the GNU Affero General Public License as published
16 | * by the Free Software Foundation, either version 3 of the License, or
17 | * (at your option) any later version.
18 | *
19 | * This program is distributed in the hope that it will be useful, but
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
22 | * PURPOSE. See the GNU Affero General Public License for more
23 | * details.
24 | * ****************************************************************************
25 | */
26 | public class GCDLCMTest {
27 |
28 |
29 | @Test
30 | public void gcdlcmTest(){
31 |
32 | final GCDLCMParser gcdParser = new GCDLCMParser();
33 | Parser.ParseResult pr=gcdParser.parse(TokenList.createD("blah", "gcd", LargeInteger.valueOf(3), LargeInteger.valueOf(4), "blah"),1);
34 | Assert.assertTrue("Ensure parse was successful: ", pr.isSuccess());
35 | Assert.assertEquals("Ensure parse result is what it's supposed to be: ",TokenList.createD("blah", 1,"blah"), pr.output);
36 |
37 | pr=gcdParser.parse(TokenList.createD("blah", "gcd", LargeInteger.valueOf(100), LargeInteger.valueOf(90), "blah"),1);
38 | Assert.assertTrue("Ensure parse was successful: ", pr.isSuccess());
39 | Assert.assertEquals("Ensure parse result is what it's supposed to be: ",TokenList.createD("blah", 10,"blah"), pr.output);
40 |
41 | pr=gcdParser.parse(TokenList.createD("blah", "lcm", LargeInteger.valueOf(3), LargeInteger.valueOf(4), "blah"),1);
42 | Assert.assertTrue("Ensure parse was successful: ", pr.isSuccess());
43 | Assert.assertEquals("Ensure parse result is what it's supposed to be: ",TokenList.createD("blah", 12,"blah"), pr.output);
44 |
45 | pr=gcdParser.parse(TokenList.createD("blah", "lcm", LargeInteger.valueOf(100), LargeInteger.valueOf(90), "blah"),1);
46 | Assert.assertTrue("Ensure parse was successful: ", pr.isSuccess());
47 | Assert.assertEquals("Ensure parse result is what it's supposed to be: ",TokenList.createD("blah", 900,"blah"), pr.output);
48 |
49 |
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/web/GetFromElement.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.web;
17 |
18 | import java.util.Map;
19 |
20 | import com.google.common.collect.*;
21 |
22 | import org.jsoup.nodes.Attribute;
23 |
24 | import com.lastcalc.*;
25 | import com.lastcalc.cache.ElementWrapper;
26 | import com.lastcalc.parsers.Parser;
27 |
28 |
29 | public class GetFromElement extends Parser {
30 |
31 | private static TokenList template = TokenList.createD("get", Lists.newArrayList("text", "attributes", "tag"),
32 | "from", ElementWrapper.class);
33 |
34 | /**
35 | *
36 | */
37 | private static final long serialVersionUID = 5755928813441453688L;
38 |
39 | @Override
40 | public ParseResult parse(final TokenList tokens, final int templatePos) {
41 | final String what = (String) tokens.get(templatePos + 1);
42 | final ElementWrapper ew = (ElementWrapper) tokens.get(templatePos + 3);
43 | Object ret;
44 | if (what.equals("text")) {
45 | ret = new Tokenizer.QuotedString(ew.el.text());
46 | } else if (what.equals("attributes")) {
47 | final Map attributes = Maps.newLinkedHashMap();
48 | for (final Attribute x : ew.el.attributes()) {
49 | // TODO: Verify that these are single values when tokenized
50 | attributes.put(new Tokenizer.QuotedString(x.getKey()), new Tokenizer.QuotedString(x.getValue()));
51 | }
52 | ret = TokenList.createD(attributes);
53 | } else if (what.equals("tag")) {
54 | ret = TokenList.createD(ew.el.tagName());
55 | } else
56 | return ParseResult.fail();
57 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), ret));
58 | }
59 |
60 | @Override
61 | public TokenList getTemplate() {
62 | return template;
63 | }
64 |
65 | @Override
66 | public int hashCode() {
67 | return "GetFromElement".hashCode();
68 | }
69 |
70 | @Override
71 | public boolean equals(final Object obj) {
72 | return obj instanceof GetFromElement;
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/RewriteParser.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers;
17 |
18 | import java.util.ArrayList;
19 |
20 | import com.lastcalc.TokenList;
21 |
22 |
23 | public class RewriteParser extends Parser {
24 |
25 | private static final long serialVersionUID = 7536991519287899564L;
26 | private final TokenList template;
27 | private final TokenList to;
28 |
29 | public RewriteParser(final Object from, final Object to) {
30 | if (from instanceof ArrayList) {
31 | template = TokenList.create((ArrayList) from);
32 | } else {
33 | template = TokenList.createD(from);
34 | }
35 | if (to instanceof ArrayList) {
36 | this.to = TokenList.create((ArrayList) to);
37 | } else {
38 | this.to = TokenList.createD(to);
39 | }
40 | }
41 |
42 | @Override
43 | public TokenList getTemplate() {
44 | return template;
45 | }
46 |
47 | @Override
48 | public ParseResult parse(final TokenList tokens, final int templatePos) {
49 | return ParseResult.success(tokens.replaceWithTokenList(templatePos, templatePos + template.size(), to));
50 | }
51 |
52 | @Override
53 | public int hashCode() {
54 | final int prime = 31;
55 | int result = 1;
56 | result = prime * result + ((template == null) ? 0 : template.hashCode());
57 | result = prime * result + ((to == null) ? 0 : to.hashCode());
58 | return result;
59 | }
60 |
61 | @Override
62 | public boolean equals(final Object obj) {
63 | if (this == obj)
64 | return true;
65 | if (obj == null)
66 | return false;
67 | if (!(obj instanceof RewriteParser))
68 | return false;
69 | final RewriteParser other = (RewriteParser) obj;
70 | if (template == null) {
71 | if (other.template != null)
72 | return false;
73 | } else if (!template.equals(other.template))
74 | return false;
75 | if (to == null) {
76 | if (other.to != null)
77 | return false;
78 | } else if (!to.equals(other.to))
79 | return false;
80 | return true;
81 | }
82 |
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/collections/ApplyTo.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.collections;
17 |
18 | import java.util.*;
19 |
20 | import com.google.common.collect.*;
21 |
22 | import com.lastcalc.TokenList;
23 | import com.lastcalc.parsers.*;
24 | import com.lastcalc.parsers.UserDefinedParserParser.UserDefinedParser;
25 |
26 | public class ApplyTo extends Parser {
27 | private static final long serialVersionUID = 9178891850811247754L;
28 | private static TokenList template = TokenList.createD("apply", UserDefinedParser.class, "to",
29 | Lists.newArrayList(List.class, Map.class));
30 |
31 | @Override
32 | public ParseResult parse(final TokenList tokens, final int templatePos, final ParserContext context) {
33 | final UserDefinedParser udp = (UserDefinedParser) tokens.get(templatePos + 1);
34 | final Object datastructure = tokens.get(templatePos + 3);
35 | List ret;
36 | if (datastructure instanceof List) {
37 | if (udp.variables.size() != 1 || udp.getTemplate().size() != 1)
38 | return ParseResult.fail();
39 | final List list = (List) datastructure;
40 | ret = Lists.newArrayListWithCapacity(list.size() * 4);
41 | ret.add("[");
42 | for (final Object o : list) {
43 | final TokenList r = context.parseEngine.parseAndGetLastStep(udp.parse(TokenList.createD(o), 0).output,
44 | context);
45 | Iterables.addAll(ret, r);
46 | ret.add(",");
47 | }
48 | ret.set(ret.size() - 1, "]"); // Overwrite last comma
49 | } else
50 | return ParseResult.fail();
51 | return ParseResult.success(tokens.replaceWithTokenList(templatePos, templatePos + template.size(),
52 | TokenList.create(ret)));
53 | }
54 |
55 | @Override
56 | public TokenList getTemplate() {
57 | return template;
58 | }
59 |
60 | @Override
61 | public int hashCode() {
62 | return "ApplyToList".hashCode();
63 | }
64 |
65 | @Override
66 | public boolean equals(final Object obj) {
67 | return obj instanceof ApplyTo;
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/amounts/AmountConverterParser.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.amounts;
17 |
18 | import javax.measure.converter.ConversionException;
19 | import javax.measure.unit.Unit;
20 |
21 | import com.google.common.collect.Lists;
22 |
23 | import org.jscience.mathematics.number.FloatingPoint;
24 | import org.jscience.physics.amount.Amount;
25 |
26 | import com.lastcalc.TokenList;
27 | import com.lastcalc.parsers.Parser;
28 |
29 |
30 | public class AmountConverterParser extends Parser {
31 | private static final long serialVersionUID = -2549484003198615095L;
32 | private static final TokenList template = TokenList.createD(Amount.class,
33 | Lists.newArrayList("in", "to", "as"),
34 | Object.class);
35 |
36 | @Override
37 | public TokenList getTemplate() {
38 | return template;
39 | }
40 |
41 | @Override
42 | public ParseResult parse(final TokenList tokens, final int templatePos) {
43 | final Amount> amount = (Amount>) tokens.get(templatePos);
44 | if (tokens.get(templatePos + 2) instanceof Unit) {
45 | final Unit> unit = (Unit>) tokens.get(templatePos + 2);
46 | try {
47 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(),
48 | amount.to(unit)));
49 | } catch (final ConversionException e) {
50 | // return ParseResult.error("Cannot convert " + amount.getUnit() +
51 | // " to " + unit);
52 | return ParseResult.fail();
53 | }
54 | } else if (tokens.get(templatePos + 2).equals("number"))
55 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(),
56 | FloatingPoint.valueOf(amount.getEstimatedValue())));
57 | else
58 | return ParseResult.fail();
59 | }
60 |
61 | @Override
62 | public String toString() {
63 | return "";
64 | }
65 |
66 | @Override
67 | public int hashCode() {
68 | return "AmountConverterParser".hashCode();
69 | }
70 |
71 | @Override
72 | public boolean equals(final Object obj) {
73 | return obj instanceof AmountConverterParser;
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/engines/CombinedParserPickerFactory.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.engines;
17 |
18 | import java.util.*;
19 |
20 | import com.google.common.collect.*;
21 |
22 | import com.lastcalc.parsers.*;
23 |
24 |
25 | public class CombinedParserPickerFactory extends ParserPickerFactory {
26 | private static final long serialVersionUID = -9047872184877535738L;
27 | private final Iterable factories;
28 |
29 | public CombinedParserPickerFactory(final ParserPickerFactory... factories) {
30 | this(Lists.newArrayList(factories));
31 | }
32 |
33 | public CombinedParserPickerFactory(final Iterable factories) {
34 | this.factories = factories;
35 | }
36 |
37 | @Override
38 | public ParserPicker getPicker(final Map prevAttemptPos) {
39 | return new CombinedParserPicker(prevAttemptPos, factories);
40 | }
41 |
42 | @Override
43 | public void teach(final Iterable step) {
44 | for (final ParserPickerFactory ppf : factories) {
45 | ppf.teach(step);
46 | }
47 | }
48 |
49 | public static class CombinedParserPicker extends ParserPicker {
50 | private final Iterable ppfs;
51 |
52 | public CombinedParserPicker(final Map prevAttemptPos, final Iterable ppfs) {
53 | super(prevAttemptPos);
54 | this.ppfs = ppfs;
55 | }
56 |
57 | @Override
58 | public ParseStep pickNext(final ParserContext context, final ParseStep previous) {
59 | for (final ParserPickerFactory ppf : ppfs) {
60 | final ParseStep ps = ppf.getPicker(prevAttemptPos).pickNext(context, previous);
61 | if (ps != null)
62 | return ps;
63 | }
64 | return null;
65 | }
66 |
67 | }
68 |
69 | @Override
70 | public Collection getParsers() {
71 | final Set parsers = Sets.newHashSet();
72 | for (final ParserPickerFactory ppf : factories) {
73 | parsers.addAll(ppf.getParsers());
74 | }
75 | return parsers;
76 | }
77 |
78 | @Override
79 | public void addParser(final Parser parser) {
80 | throw new UnsupportedOperationException();
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/math/GCDLCMParser.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.parsers.math;
2 |
3 | import com.google.common.collect.Lists;
4 | import com.lastcalc.TokenList;
5 | import com.lastcalc.parsers.Parser;
6 | import org.jscience.mathematics.number.LargeInteger;
7 |
8 | /**
9 | * ****************************************************************************
10 | * LastCalc - The last calculator you'll ever need
11 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
12 | *
13 | * This program is free software: you can redistribute it and/or modify it
14 | * under the terms of the GNU Affero General Public License as published
15 | * by the Free Software Foundation, either version 3 of the License, or
16 | * (at your option) any later version.
17 | *
18 | * This program is distributed in the hope that it will be useful, but
19 | * WITHOUT ANY WARRANTY; without even the implied warranty of
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
21 | * PURPOSE. See the GNU Affero General Public License for more
22 | * details.
23 | * ****************************************************************************
24 | */
25 | public class GCDLCMParser extends Parser{
26 |
27 |
28 | private static TokenList template = TokenList.createD(Lists. newArrayList("gcd", "lcm"),Number.class, Number.class);
29 |
30 | @Override
31 | public TokenList getTemplate() {
32 | return template;
33 | }
34 |
35 |
36 | @Override
37 | public Parser.ParseResult parse(final TokenList tokens, final int templatePos) {
38 |
39 | final String op = (String) tokens.get(templatePos);
40 | final Integer input1 = ((LargeInteger)tokens.get(templatePos + 1)).intValue();
41 | final Integer input2 = ((LargeInteger)tokens.get(templatePos + 2)).intValue();
42 |
43 |
44 | if(op.equals("gcd")){
45 |
46 | Integer result=gcd_iter(input1,input2);
47 |
48 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), result));
49 | }
50 | else if(op.equals("lcm")){
51 |
52 | Integer result=lcm(input1,input2);
53 |
54 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), result));
55 | }
56 | else{
57 | return Parser.ParseResult.fail();
58 | }
59 | }
60 |
61 | private Integer gcd_iter(Integer u, Integer v) {
62 | Integer t;
63 | while (v!=0) {
64 | t = u;
65 | u = v;
66 | v = t % v;
67 | }
68 | return u < 0 ? -u : u; /* abs(u) */
69 | }
70 |
71 | private Integer lcm(Integer a, Integer b)
72 | {
73 | return a * (b / gcd_iter(a, b));
74 | }
75 |
76 | @Override
77 | public int hashCode() {
78 | return 0;
79 | }
80 |
81 | @Override
82 | public boolean equals(Object obj) {
83 | return false;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/collections/Filter.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.collections;
17 |
18 | import java.util.List;
19 |
20 | import com.google.common.collect.Lists;
21 |
22 | import com.lastcalc.TokenList;
23 | import com.lastcalc.parsers.*;
24 | import com.lastcalc.parsers.UserDefinedParserParser.UserDefinedParser;
25 |
26 | public class Filter extends Parser {
27 | private static final long serialVersionUID = 9178891850811247754L;
28 | private static TokenList template = TokenList.createD("filter", Lists.newArrayList(List.class), "with",
29 | UserDefinedParser.class);
30 |
31 | @Override
32 | public ParseResult parse(final TokenList tokens, final int templatePos, final ParserContext context) {
33 | final UserDefinedParser udp = (UserDefinedParser) tokens.get(templatePos + 3);
34 | final Object datastructure = tokens.get(templatePos + 1);
35 | List ret;
36 | if (datastructure instanceof List) {
37 | if (udp.variables.size() != 1 || udp.getTemplate().size() != 1)
38 | return ParseResult.fail();
39 | final List list = (List) datastructure;
40 | ret = Lists.newArrayListWithCapacity(list.size() * 4);
41 | ret.add("[");
42 | for (final Object o : list) {
43 | final TokenList result = context.parseEngine.parseAndGetLastStep(
44 | udp.parse(TokenList.createD(o), 0).output, context);
45 | if (result.size() != 1 || !(result.get(0) instanceof Boolean))
46 | return ParseResult.fail();
47 | if (result.get(0).equals(true)) {
48 | ret.add(o);
49 | ret.add(",");
50 | }
51 | }
52 | ret.set(ret.size() - 1, "]"); // Overwrite last comma
53 | } else
54 | return ParseResult.fail();
55 | return ParseResult.success(tokens.replaceWithTokenList(templatePos, templatePos + template.size(),
56 | TokenList.create(ret)));
57 | }
58 |
59 | @Override
60 | public TokenList getTemplate() {
61 | return template;
62 | }
63 |
64 | @Override
65 | public int hashCode() {
66 | return "Filter".hashCode();
67 | }
68 |
69 | @Override
70 | public boolean equals(final Object obj) {
71 | return obj instanceof Filter;
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/collections/GetFromListOrMap.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.collections;
17 |
18 | import java.util.*;
19 |
20 | import com.google.common.collect.Lists;
21 |
22 | import org.jscience.mathematics.number.LargeInteger;
23 |
24 | import com.lastcalc.TokenList;
25 | import com.lastcalc.parsers.Parser;
26 |
27 |
28 | public class GetFromListOrMap extends Parser {
29 |
30 | private static TokenList template = TokenList.createD("get", Object.class, "from",
31 | Lists.newArrayList(Map.class, List.class));
32 |
33 | /**
34 | *
35 | */
36 | private static final long serialVersionUID = 5755928813441453688L;
37 |
38 | @Override
39 | public ParseResult parse(final TokenList tokens, final int templatePos) {
40 | final Object toGet = tokens.get(templatePos + 1);
41 | if (tokens.get(templatePos + 3) instanceof Map) {
42 | final Map map = (Map) tokens.get(templatePos + 3);
43 | final Object got = map.get(toGet);
44 | if (got != null)
45 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), got));
46 | else
47 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), false));
48 | } else if (tokens.get(templatePos + 3) instanceof List) {
49 | final List list = (List) tokens.get(templatePos + 3);
50 | if (toGet instanceof LargeInteger) {
51 | final int ix = ((LargeInteger) toGet).intValue();
52 | if (ix < 0 || ix >= list.size())
53 | return ParseResult.fail();
54 | else
55 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(),
56 | list.get(ix)));
57 | } else
58 | return ParseResult.fail();
59 | } else
60 | return ParseResult.fail();
61 | }
62 |
63 | @Override
64 | public TokenList getTemplate() {
65 | return template;
66 | }
67 |
68 | @Override
69 | public int hashCode() {
70 | return "GetFromListOrMap".hashCode();
71 | }
72 |
73 | @Override
74 | public boolean equals(final Object obj) {
75 | return obj instanceof GetFromListOrMap;
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/web/HttpRetriever.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.web;
17 |
18 | import java.io.IOException;
19 | import java.net.*;
20 |
21 | import org.jsoup.Jsoup;
22 |
23 | import com.lastcalc.*;
24 | import com.lastcalc.Tokenizer.QuotedString;
25 | import com.lastcalc.cache.*;
26 | import com.lastcalc.parsers.*;
27 |
28 | public class HttpRetriever extends Parser {
29 | private static final long serialVersionUID = 429169446256736079L;
30 | private static TokenList template = TokenList.createD("retrieve", QuotedString.class);
31 |
32 | @Override
33 | public TokenList getTemplate() {
34 | return template;
35 | }
36 |
37 | @Override
38 | public ParseResult parse(final TokenList tokens, final int templatePos, final ParserContext context) {
39 | URL url;
40 | try {
41 | url = new URL(((QuotedString) tokens.get(templatePos + 1)).value);
42 | } catch (final MalformedURLException e) {
43 | return ParseResult.fail();
44 | }
45 |
46 | final Object cached = ObjectCache.getSlow(1000l * 60l * 60l * 24l, url);
47 |
48 | if (cached != null)
49 | return ParseResult
50 | .success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), cached));
51 |
52 | URLConnection connection;
53 | try {
54 | connection = url.openConnection();
55 | } catch (final IOException e) {
56 | return ParseResult.fail();
57 | }
58 | final String contentType = connection.getContentType();
59 | if (contentType.toLowerCase().contains("text/html")) {
60 | DocumentWrapper doc;
61 | try {
62 | doc = new DocumentWrapper(Jsoup.parse(connection.getInputStream(), "UTF-8", "/"));
63 | } catch (final IOException e) {
64 | return ParseResult.fail();
65 | }
66 | ObjectCache.put(1000l * 60l * 60l * 24l, doc, url);
67 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), doc));
68 | }
69 | return ParseResult.fail();
70 |
71 | }
72 |
73 | @Override
74 | public int hashCode() {
75 | return "HttpRetriever".hashCode();
76 | }
77 |
78 | @Override
79 | public boolean equals(final Object obj) {
80 | return obj instanceof HttpRetriever;
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/main/webapp/js/rangy-selectionsaverestore.js:
--------------------------------------------------------------------------------
1 | /*
2 | Selection save and restore module for Rangy.
3 | Saves and restores user selections using marker invisible elements in the DOM.
4 |
5 | Part of Rangy, a cross-browser JavaScript range and selection library
6 | http://code.google.com/p/rangy/
7 |
8 | Depends on Rangy core.
9 |
10 | Copyright 2011, Tim Down
11 | Licensed under the MIT license.
12 | Version: 1.2.2
13 | Build date: 13 November 2011
14 | */
15 | rangy.createModule("SaveRestore",function(h,m){function n(a,g){var e="selectionBoundary_"+ +new Date+"_"+(""+Math.random()).slice(2),c,f=p.getDocument(a.startContainer),d=a.cloneRange();d.collapse(g);c=f.createElement("span");c.id=e;c.style.lineHeight="0";c.style.display="none";c.className="rangySelectionBoundary";c.appendChild(f.createTextNode(q));d.insertNode(c);d.detach();return c}function o(a,g,e,c){if(a=(a||document).getElementById(e)){g[c?"setStartBefore":"setEndBefore"](a);a.parentNode.removeChild(a)}else m.warn("Marker element has been removed. Cannot restore selection.")}
16 | function r(a,g){return g.compareBoundaryPoints(a.START_TO_START,a)}function k(a,g){var e=(a||document).getElementById(g);e&&e.parentNode.removeChild(e)}h.requireModules(["DomUtil","DomRange","WrappedRange"]);var p=h.dom,q="\ufeff";h.saveSelection=function(a){a=a||window;var g=a.document;if(h.isSelectionValid(a)){var e=h.getSelection(a),c=e.getAllRanges(),f=[],d,j;c.sort(r);for(var b=0,i=c.length;b=0;--b){d=c[b];if(d.collapsed)d.collapseBefore((g||document).getElementById(f[b].markerId));else{d.setEndBefore((g||document).getElementById(f[b].endMarkerId));d.setStartAfter((g||document).getElementById(f[b].startMarkerId))}}e.setRanges(c);return{win:a,doc:g,rangeInfos:f,restored:false}}else m.warn("Cannot save selection. This usually happens when the selection is collapsed and the selection document has lost focus.")};
18 | h.restoreSelection=function(a,g){if(!a.restored){for(var e=a.rangeInfos,c=h.getSelection(a.win),f=[],d=e.length,j=d-1,b,i;j>=0;--j){b=e[j];i=h.createRange(a.doc);if(b.collapsed)if(b=(a.doc||document).getElementById(b.markerId)){b.style.display="inline";var l=b.previousSibling;if(l&&l.nodeType==3){b.parentNode.removeChild(b);i.collapseToPoint(l,l.length)}else{i.collapseBefore(b);b.parentNode.removeChild(b)}}else m.warn("Marker element has been removed. Cannot restore selection.");else{o(a.doc,i,b.startMarkerId,
19 | true);o(a.doc,i,b.endMarkerId,false)}d==1&&i.normalizeBoundaries();f[j]=i}if(d==1&&g&&h.features.selectionHasExtend&&e[0].backwards){c.removeAllRanges();c.addRange(f[0],true)}else c.setRanges(f);a.restored=true}};h.removeMarkerElement=k;h.removeMarkers=function(a){for(var g=a.rangeInfos,e=0,c=g.length,f;e newArrayList("factorial"),LargeInteger.class);
38 |
39 | //private static TokenList template=TokenList.createD(LargeInteger.class,Lists. newArrayList("!"));
40 |
41 | @Override
42 | public TokenList getTemplate() {
43 | return template;
44 | }
45 |
46 | @SuppressWarnings("rawtypes")
47 | @Override
48 | public ParseResult parse(final TokenList tokens, final int templatePos) {
49 |
50 | final String op = (String) tokens.get(templatePos);
51 | final LargeInteger input = (LargeInteger) tokens.get(templatePos + 1);
52 | Number result = null;
53 |
54 | if(op.equals("factorial")){
55 | //System.out.println("INput is: "+input);
56 |
57 | if(input.isLessThan(LargeInteger.valueOf(20)) && input.isGreaterThan(LargeInteger.ZERO)){
58 | result = LargeInteger.valueOf(factorial(input.longValue()));
59 |
60 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos+template.size(), result));
61 | }
62 |
63 |
64 | }
65 | return ParseResult.fail();
66 | }
67 |
68 | protected long factorial(long input){
69 | long fact = 1;
70 | for (long x = input; x > 1; x--){
71 | fact *= x;
72 | }
73 | return fact;
74 | }
75 |
76 | @Override
77 | public String toString() {
78 | return "";
79 | }
80 |
81 | @Override
82 | public int hashCode() {
83 | return "FactorialParser".hashCode();
84 | }
85 |
86 | @Override
87 | public boolean equals(final Object obj) {
88 | return false;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/web/Select.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.web;
17 |
18 | import java.util.List;
19 |
20 | import com.google.common.collect.Lists;
21 |
22 | import org.jsoup.nodes.Element;
23 | import org.jsoup.select.Elements;
24 |
25 | import com.lastcalc.*;
26 | import com.lastcalc.Tokenizer.QuotedString;
27 | import com.lastcalc.cache.*;
28 | import com.lastcalc.parsers.*;
29 |
30 | public class Select extends Parser {
31 |
32 | private static final TokenList template = TokenList.createD("select", QuotedString.class, "from",
33 | Lists. newArrayList(DocumentWrapper.class, ElementWrapper.class));
34 |
35 | @Override
36 | public TokenList getTemplate() {
37 | return template;
38 | }
39 |
40 | @Override
41 | public ParseResult parse(final TokenList tokens, final int templatePos, final ParserContext context) {
42 | final String selectStatement = ((QuotedString) tokens.get(templatePos + 1)).value;
43 | final Object docOrElement = tokens.get(templatePos + 3);
44 | final Object cached = ObjectCache.getFast(Long.MAX_VALUE, "select", selectStatement, docOrElement);
45 | if (cached != null)
46 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos+template.size(), cached));
47 | Element el;
48 | if (docOrElement instanceof DocumentWrapper) {
49 | el = ((DocumentWrapper) docOrElement).doc;
50 | } else {
51 | el = ((ElementWrapper) docOrElement).el;
52 | }
53 | final Elements elements = el.select(selectStatement);
54 |
55 | if (elements.size() == 1)
56 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos+template.size(), new ElementWrapper(elements.first())));
57 | else {
58 | final List elementList = Lists.newArrayListWithCapacity(elements.size());
59 | for (final Element e : elements) {
60 | elementList.add(new ElementWrapper(e));
61 | }
62 | return ParseResult
63 | .success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), elementList));
64 | }
65 | }
66 |
67 | @Override
68 | public int hashCode() {
69 | return "Select".hashCode();
70 | }
71 |
72 | @Override
73 | public boolean equals(final Object obj) {
74 | return obj instanceof Select;
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/engines/RecentFirstParserPickerFactory.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.engines;
17 |
18 | import java.util.*;
19 | import java.util.concurrent.locks.ReentrantReadWriteLock;
20 |
21 | import com.google.common.collect.*;
22 |
23 | import com.lastcalc.parsers.*;
24 |
25 |
26 | public class RecentFirstParserPickerFactory extends ParserPickerFactory {
27 |
28 | ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
29 |
30 | private static final long serialVersionUID = -5521465155099741906L;
31 |
32 | LinkedList parsers = new LinkedList();
33 |
34 | private final int maxParsers;
35 |
36 | public RecentFirstParserPickerFactory(final Iterable parsers) {
37 | this(parsers, Integer.MAX_VALUE);
38 | }
39 |
40 | public RecentFirstParserPickerFactory(final Iterable parsers, final int maxParsers) {
41 | this.maxParsers = maxParsers;
42 | Iterables.addAll(this.parsers, parsers);
43 | while (this.parsers.size() > maxParsers) {
44 | this.parsers.removeLast();
45 | }
46 | }
47 |
48 | @Override
49 | public void addParser(final Parser parser) {
50 | parsers.add(parser);
51 | }
52 |
53 | @Override
54 | public void teach(final Iterable steps) {
55 | final ArrayList reversed = Lists.newArrayList(steps);
56 | Collections.reverse(reversed);
57 | rwl.writeLock().lock();
58 | for (final ParseStep ps : reversed) {
59 | // TODO: This is slow, probably need to use a better
60 | // datastructure for parsers, perhaps LinkedHashMap
61 | // or something
62 | parsers.remove(ps.parser);
63 | parsers.addFirst(ps.parser);
64 | }
65 | while (parsers.size() > maxParsers) {
66 | parsers.removeLast();
67 | }
68 | rwl.writeLock().unlock();
69 | }
70 |
71 |
72 | @Override
73 | public ParserPicker getPicker(final Map prevAttemptPos) {
74 | return new ParserPicker(prevAttemptPos) {
75 |
76 | @Override
77 | public ParseStep pickNext(final ParserContext context, final ParseStep previous) {
78 | // matchTemplate
79 | rwl.readLock().lock();
80 | final ParseStep nextParseStep = getNext(context, parsers, previous);
81 | rwl.readLock().unlock();
82 | return nextParseStep;
83 | }
84 | };
85 | }
86 |
87 | @Override
88 | public List getParsers() {
89 | return parsers;
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/parsers/math/IsPrimeTest.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.parsers.math;
2 |
3 | import com.lastcalc.TokenList;
4 | import com.lastcalc.parsers.Parser;
5 | import junit.framework.Assert;
6 | import org.jscience.mathematics.number.LargeInteger;
7 | import org.junit.Test;
8 |
9 | import java.util.ArrayList;
10 |
11 | /**
12 | * ****************************************************************************
13 | * LastCalc - The last calculator you'll ever need
14 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
15 | *
16 | * This program is free software: you can redistribute it and/or modify it
17 | * under the terms of the GNU Affero General Public License as published
18 | * by the Free Software Foundation, either version 3 of the License, or
19 | * (at your option) any later version.
20 | *
21 | * This program is distributed in the hope that it will be useful, but
22 | * WITHOUT ANY WARRANTY; without even the implied warranty of
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
24 | * PURPOSE. See the GNU Affero General Public License for more
25 | * details.
26 | * ****************************************************************************
27 | */
28 | public class IsPrimeTest {
29 |
30 |
31 |
32 | @Test
33 | public void isPrimeTest(){
34 |
35 | final IsPrimeParser ist = new IsPrimeParser();
36 | Parser.ParseResult pr=ist.parse(TokenList.createD("blah", "isprime", LargeInteger.valueOf(3), "blah"),1);
37 | Assert.assertTrue("Ensure parse was successful: ", pr.isSuccess());
38 | Assert.assertEquals("Ensure parse result is what it's supposed to be: ",TokenList.createD("blah", true,"blah"), pr.output);
39 |
40 | pr=ist.parse(TokenList.createD("blah", "isprime", LargeInteger.valueOf(5), "blah"),1);
41 | Assert.assertTrue("Ensure parse was successful: ", pr.isSuccess());
42 | Assert.assertEquals("Ensure parse result is what it's supposed to be: ",TokenList.createD("blah", true,"blah"), pr.output);
43 |
44 |
45 | pr=ist.parse(TokenList.createD("blah", "isprime", LargeInteger.valueOf(10), "blah"),1);
46 | Assert.assertTrue("Ensure parse was successful: ", pr.isSuccess());
47 | Assert.assertEquals("Ensure parse result is what it's supposed to be: ",TokenList.createD("blah", false,"blah"), pr.output);
48 |
49 | pr=ist.parse(TokenList.createD("blah", "isprime", LargeInteger.valueOf(29), "blah"),1);
50 | Assert.assertTrue("Ensure parse was successful: ", pr.isSuccess());
51 | Assert.assertEquals("Ensure parse result is what it's supposed to be: ",TokenList.createD("blah", true,"blah"), pr.output);
52 |
53 | pr=ist.parse(TokenList.createD("blah", "isprime", LargeInteger.valueOf(100), "blah"),1);
54 | Assert.assertTrue("Ensure parse was successful: ", pr.isSuccess());
55 | Assert.assertEquals("Ensure parse result is what it's supposed to be: ",TokenList.createD("blah", false,"blah"), pr.output);
56 |
57 | pr=ist.parse(TokenList.createD("blah", "isprime", LargeInteger.valueOf(7919 ), "blah"),1);
58 | Assert.assertTrue("Ensure parse was successful: ", pr.isSuccess());
59 | Assert.assertEquals("Ensure parse result is what it's supposed to be: ",TokenList.createD("blah", true,"blah"), pr.output);
60 |
61 |
62 |
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/test/java/com/lastcalc/parsers/UserDefinedParserParserTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers;
17 |
18 | import java.util.*;
19 |
20 | import junit.framework.Assert;
21 |
22 | import com.google.common.collect.*;
23 |
24 | import org.junit.Test;
25 |
26 | public class UserDefinedParserParserTest {
27 |
28 | @Test
29 | public void bindMapTest() throws Exception {
30 | final PreParser.MapWithTail mwt = new PreParser.MapWithTail(Maps.newLinkedHashMap(), "tailvar");
31 | mwt.map.put("key1", "value1var");
32 | mwt.map.put("key2var", "value2var");
33 | final Set variables = Sets.newHashSet("value1var", "key2var", "value2var", "tailvar");
34 | final LinkedHashMap bindMap = Maps.newLinkedHashMap();
35 | bindMap.put("key1", "value1");
36 | bindMap.put("key2", "value2");
37 | bindMap.put("key3", "value3");
38 | final Map bound = Maps.newHashMap();
39 | UserDefinedParserParser.bind(mwt, bindMap, variables, bound);
40 | Assert.assertEquals(variables.size(), bound.size());
41 | Assert.assertEquals("value1", bound.get("value1var"));
42 | Assert.assertEquals("key2", bound.get("key2var"));
43 | Assert.assertEquals("value2", bound.get("value2var"));
44 | Assert.assertTrue(bound.get("tailvar") instanceof Map);
45 | final Map tailMap = (Map) bound.get("tailvar");
46 | Assert.assertEquals(1, tailMap.size());
47 | Assert.assertEquals("value3", tailMap.get("key3"));
48 |
49 | // TODO: Test with just map, rather than MapWithTail
50 | }
51 |
52 | @Test
53 | public void bindListTest() throws Exception {
54 | final PreParser.ListWithTail lwt = new PreParser.ListWithTail(Lists. newArrayList("var1", "var2",
55 | "var3"), "tailvar");
56 | final List bindList = Lists. newArrayList("val1", "val2", "val3", "val4");
57 | final Set variables = Sets.newHashSet("var1", "var2", "var3", "tailvar");
58 | final LinkedHashMap bindMap = Maps.newLinkedHashMap();
59 | final Map bound = Maps.newHashMap();
60 | UserDefinedParserParser.bind(lwt, bindList, variables, bound);
61 | Assert.assertEquals(variables.size(), bound.size());
62 | Assert.assertEquals("val1", bound.get("var1"));
63 | Assert.assertEquals("val2", bound.get("var2"));
64 | Assert.assertEquals("val3", bound.get("var3"));
65 | Assert.assertTrue(bound.get("tailvar") instanceof List);
66 | final List tailList = (List) bound.get("tailvar");
67 | Assert.assertEquals(1, tailList.size());
68 | Assert.assertEquals("val4", tailList.get(0));
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/engines/ParseStep.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.engines;
17 |
18 | import com.lastcalc.TokenList;
19 | import com.lastcalc.parsers.*;
20 | import com.lastcalc.parsers.Parser.ParseResult;
21 | import com.lastcalc.parsers.UserDefinedParserParser.UserDefinedParser;
22 |
23 | public class ParseStep implements Comparable {
24 | public final TokenList input;
25 |
26 | public final ParseResult result;
27 |
28 | public final Parser parser;
29 |
30 | public final ParseStep previous;
31 |
32 | public final int depth;
33 |
34 | public final double scoreBias;
35 |
36 | public ParseStep(final TokenList input, final Parser parser, final ParseResult result, final ParseStep previous,
37 | final double score) {
38 | this.input = input;
39 | this.parser = parser;
40 | scoreBias = (previous == null ? 0 : previous.scoreBias) + score;
41 | this.result = result;
42 | this.previous = previous;
43 | if (previous != null) {
44 | depth = previous.depth + 1;
45 | } else {
46 | depth = 0;
47 | }
48 | }
49 |
50 | @Override
51 | public String toString() {
52 | return getScore() + "\t" + parser.getClass().getSimpleName() + "\t" + input + "\t" + result.output;
53 | }
54 |
55 | @Override
56 | public int compareTo(final ParseStep other) {
57 | if (getScore() < other.getScore())
58 | return -1;
59 | else if (getScore() > other.getScore())
60 | return 1;
61 | else if (hashCode() < other.hashCode())
62 | return -1;
63 | else if (hashCode() > other.hashCode())
64 | return 1;
65 | else
66 | return 0;
67 | }
68 |
69 | private double cachedScore = Double.MAX_VALUE;
70 |
71 | private double getScore() {
72 | if (cachedScore == Double.MAX_VALUE) {
73 | cachedScore = scoreBias + getScore(result.output) - (0.0001 * depth);
74 | }
75 | return cachedScore;
76 | }
77 |
78 | public static double getScore(final Object token) {
79 | double score = 0;
80 | if (token instanceof TokenList) {
81 | for (final Object t : ((TokenList) token)) {
82 | if (t instanceof String) {
83 | score++;
84 | } else if (t instanceof Number) {
85 | score += 0.8;
86 | } else {
87 | score += 0.5;
88 | }
89 | }
90 | }
91 | return score;
92 | }
93 |
94 | public boolean isMinimal() {
95 | if (result.output.size() == 1 && !(result.output.get(0) instanceof String)) {
96 | if (result.output.get(0) instanceof UserDefinedParser) {
97 | final UserDefinedParser udp = (UserDefinedParser) result.output.get(0);
98 | // Handle a common case
99 | if (udp.getTemplate().indexOf("if") != -1)
100 | return false;
101 | else
102 | return true;
103 | } else
104 | return true;
105 | } else
106 | return false;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/math/IsPrimeParser.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.parsers.math;
2 |
3 | import com.google.common.collect.Lists;
4 | import com.lastcalc.TokenList;
5 | import com.lastcalc.parsers.Parser;
6 | import org.jscience.mathematics.number.LargeInteger;
7 |
8 |
9 | /**
10 | * ****************************************************************************
11 | * LastCalc - The last calculator you'll ever need
12 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
13 | *
14 | * This program is free software: you can redistribute it and/or modify it
15 | * under the terms of the GNU Affero General Public License as published
16 | * by the Free Software Foundation, either version 3 of the License, or
17 | * (at your option) any later version.
18 | *
19 | * This program is distributed in the hope that it will be useful, but
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
22 | * PURPOSE. See the GNU Affero General Public License for more
23 | * details.
24 | * ****************************************************************************
25 | */
26 | public class IsPrimeParser extends Parser {
27 |
28 | private static TokenList template = TokenList.createD(Lists. newArrayList("isprime"),Number.class);
29 |
30 | @Override
31 | public TokenList getTemplate() {
32 | return template;
33 | }
34 |
35 |
36 | @Override
37 | public ParseResult parse(final TokenList tokens, final int templatePos) {
38 |
39 | final String op = (String) tokens.get(templatePos);
40 | final Integer input = ((LargeInteger)tokens.get(templatePos + 1)).intValue();
41 |
42 |
43 | if(op.equals("isprime")){
44 |
45 | //first, we check if the number is greater than the last element of the primeslist.
46 |
47 | //if yes, then we expand the primeslist to be big enough until the last element
48 | // of the primeslist is the largest prime that is still less than the input number. if the input number is prime
49 | // then return true else false
50 |
51 |
52 | //if the input number is less than the last element of the primeslist, then we see if it is in the primeslist
53 |
54 | //if it's there then it's prime, if not the false.
55 |
56 |
57 | //run the sqrt n primality test algorithm
58 |
59 | final Integer inputSqrRoot=(int)Math.sqrt((double)input);
60 |
61 | if(input ==1){
62 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), false));
63 | }
64 | else if(input==2 || input==3){
65 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), true));
66 | }
67 |
68 | for(int i=2;i<=inputSqrRoot;i++){
69 | if(input%i==0){
70 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), false));
71 | }
72 | }
73 |
74 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), true));
75 |
76 | }
77 | else{
78 | return ParseResult.fail();
79 | }
80 | }
81 |
82 | @Override
83 | public int hashCode() {
84 | return 0;
85 | }
86 |
87 | @Override
88 | public boolean equals(Object obj) {
89 | return false;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/engines/BacktrackingParseEngine.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.engines;
17 |
18 | import java.util.*;
19 |
20 | import com.google.common.collect.*;
21 |
22 | import com.lastcalc.TokenList;
23 | import com.lastcalc.engines.ParserPickerFactory.ParserPicker;
24 | import com.lastcalc.parsers.*;
25 | import com.lastcalc.parsers.Parser.ParseResult;
26 |
27 |
28 | public class BacktrackingParseEngine extends ParseEngine {
29 |
30 | private final ParserPickerFactory ppf;
31 |
32 | public BacktrackingParseEngine(final ParserPickerFactory ppf) {
33 | this.ppf = ppf;
34 |
35 | }
36 |
37 | private int lastParseStepCount = 0;
38 |
39 | private boolean dumpSteps = false;
40 |
41 | public void setDumpSteps(final boolean dumpSteps) {
42 | this.dumpSteps = dumpSteps;
43 | }
44 |
45 | @Override
46 | public LinkedList parse(final TokenList input,
47 | final ParserContext context,
48 | final TokenList... alternateInputs) {
49 | lastParseStepCount = 0;
50 | final TreeSet candidates = Sets. newTreeSet();
51 | final ParserPicker picker = ppf.getPicker();
52 | candidates.add(new ParseStep(input, NoopParser.singleton, ParseResult.success(input), null, 0));
53 | for (final TokenList alternateTL : alternateInputs) {
54 | candidates.add(new ParseStep(alternateTL, NoopParser.singleton, ParseResult.success(alternateTL), null, 0));
55 | }
56 | final long startTime = System.currentTimeMillis();
57 | ParserContext subContext;
58 | try {
59 | subContext = (ParserContext) context.clone();
60 | } catch (final CloneNotSupportedException e) {
61 | throw new RuntimeException(e);
62 | }
63 | subContext.timeout = context.timeout / 5;
64 | final Set exhausted = Sets.newHashSet();
65 | outer: while (System.currentTimeMillis() - startTime < context.timeout && !candidates.first().isMinimal()) {
66 | for (final ParseStep candidateStep : candidates) {
67 | if (exhausted.contains(candidateStep)) {
68 | continue;
69 | }
70 | final ParseStep nextStep = picker.pickNext(subContext, candidateStep);
71 | if (nextStep != null && nextStep.result.isSuccess()) {
72 | lastParseStepCount++;
73 | if (dumpSteps) {
74 | System.out.println(lastParseStepCount + "\t" + nextStep);
75 | }
76 | candidates.add(nextStep);
77 | continue outer;
78 | } else {
79 | exhausted.add(candidateStep);
80 | }
81 | }
82 | break outer;
83 | }
84 | final LinkedList steps = Lists.newLinkedList();
85 | ParseStep bestStep = candidates.first();
86 |
87 | bestStep.isMinimal();
88 |
89 | while (bestStep != null) {
90 | steps.addFirst(bestStep);
91 | bestStep = bestStep.previous;
92 | }
93 |
94 | return steps;
95 | }
96 |
97 | public int getLastParseStepCount() {
98 | return lastParseStepCount;
99 | }
100 | }
101 |
102 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/currency/Currencies.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.parsers.currency;
17 |
18 | import java.io.InputStreamReader;
19 | import java.net.URL;
20 | import java.util.*;
21 | import java.util.Map.Entry;
22 | import java.util.logging.Logger;
23 |
24 | import com.google.common.collect.*;
25 |
26 | import org.jscience.economics.money.Currency;
27 |
28 | import com.lastcalc.*;
29 | import com.lastcalc.parsers.Parser;
30 | import com.lastcalc.parsers.amounts.UnitParser;
31 |
32 | public class Currencies {
33 | private static final Logger log = Logger.getLogger(Currencies.class.getName());
34 |
35 | public static long lastExchangeRateUpdateAttempt = 0;
36 |
37 | public static volatile Map currenciesByCode;
38 |
39 | public static boolean shouldUpdate() {
40 | return System.currentTimeMillis() - lastExchangeRateUpdateAttempt > 60l * 60l * 1000l;
41 | }
42 |
43 | public static List getParsers() {
44 | if (currenciesByCode == null) {
45 | updateExchangeRates();
46 | }
47 | final LinkedList parsers = Lists.newLinkedList();
48 | if (currenciesByCode != null) {
49 | for (final Entry e : currenciesByCode.entrySet()) {
50 | parsers.add(new UnitParser(e.getValue(), TokenList.createD(e.getKey())));
51 | parsers.add(new UnitParser(e.getValue(), TokenList.createD(e.getKey().toLowerCase())));
52 | }
53 | parsers.add(new UnitParser(currenciesByCode.get("USD"), TokenList.createD("$")));
54 | parsers.add(new UnitParser(currenciesByCode.get("EUR"), TokenList.createD("�")));
55 | parsers.add(new UnitParser(currenciesByCode.get("JPY"), TokenList.createD("�")));
56 | parsers.add(new UnitParser(currenciesByCode.get("GBP"), TokenList.createD("�")));
57 |
58 | parsers.add(new CurrencyReverser());
59 | }
60 |
61 | return parsers;
62 | }
63 |
64 | public static void updateExchangeRates() {
65 | Currency.setReferenceCurrency(Currency.USD);
66 | try {
67 | final URL url = new URL("http://openexchangerates.org/api/latest.json?app_id=d1bd706a92774feca9c15d615ae85685");
68 | final Rates rates = Misc.gson.fromJson(new InputStreamReader(url.openStream()), Rates.class);
69 | if (!rates.base.equalsIgnoreCase("usd")) {
70 | log.warning("We assume base rate of USD, but it is " + rates.base);
71 | }
72 | final Map currencies = Maps.newHashMap();
73 | for (final Entry e : rates.rates.entrySet()) {
74 | final Currency currency = new Currency(e.getKey());
75 | currency.setExchangeRate(1.0 / e.getValue());
76 | currencies.put(e.getKey(), currency);
77 | }
78 |
79 | currenciesByCode = currencies;
80 | } catch (final Exception e) {
81 | log.warning("Couldn't update currency conversion rates " + e);
82 | e.printStackTrace();
83 | }
84 | lastExchangeRateUpdateAttempt = System.currentTimeMillis();
85 | }
86 |
87 | public static class Rates {
88 | public String base;
89 | public Map rates;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/math/PrimesUnderParser.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.parsers.math;
2 |
3 | import com.google.common.collect.Lists;
4 | import com.lastcalc.TokenList;
5 | import com.lastcalc.bootstrap.Bootstrap;
6 | import com.lastcalc.parsers.Parser;
7 | import org.jscience.mathematics.number.*;
8 | import org.jscience.mathematics.number.Number;
9 |
10 | import java.io.*;
11 | import java.util.ArrayList;
12 | import java.util.Iterator;
13 |
14 | /**
15 | * ****************************************************************************
16 | * LastCalc - The last calculator you'll ever need
17 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
18 | *
19 | * This program is free software: you can redistribute it and/or modify it
20 | * under the terms of the GNU Affero General Public License as published
21 | * by the Free Software Foundation, either version 3 of the License, or
22 | * (at your option) any later version.
23 | *
24 | * This program is distributed in the hope that it will be useful, but
25 | * WITHOUT ANY WARRANTY; without even the implied warranty of
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
27 | * PURPOSE. See the GNU Affero General Public License for more
28 | * details.
29 | * ****************************************************************************
30 | */
31 | public class PrimesUnderParser extends Parser {
32 |
33 | //all the primes under 1000. This parser doesnt work for numbers above 1000
34 | final private ArrayList allprimes=new ArrayList();
35 |
36 |
37 |
38 | private static TokenList template = TokenList.createD(Lists. newArrayList("primesunder"),Number.class);
39 |
40 | @Override
41 | public TokenList getTemplate() {
42 | return template;
43 | }
44 |
45 | public PrimesUnderParser(){//put the primes into the array list
46 |
47 | final BufferedReader br;
48 | final String [] primesString;
49 | try{
50 | br = new BufferedReader(new InputStreamReader(
51 | Bootstrap.class.getResourceAsStream("prime_numbers.txt")));
52 | //found in src/main/resources/com/lastcalc/bootstrap/prime_numbers.txt
53 |
54 | primesString = br.readLine().split(", ");
55 | }
56 | catch(Exception e){
57 | System.err.println("prime_numbers.txt input error");
58 | return;
59 | }
60 |
61 | for(int i=0;i allprimesiterator = allprimes.iterator();
77 |
78 | ArrayList resultList=new ArrayList();
79 |
80 | Integer i=allprimesiterator.next();
81 | while(allprimesiterator.hasNext() && i<=input){
82 | resultList.add(i);
83 | i=allprimesiterator.next();
84 | }
85 |
86 | return ParseResult.success(tokens.replaceWithTokens(templatePos, templatePos + template.size(), resultList));
87 | }
88 | return ParseResult.fail();
89 | }
90 |
91 |
92 | @Override
93 | public int hashCode() {
94 | return 0; //To change body of implemented methods use File | Settings | File Templates.
95 | }
96 |
97 | @Override
98 | public boolean equals(Object obj) {
99 | return false; //To change body of implemented methods use File | Settings | File Templates.
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/cache/ObjectCache.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * LastCalc - The last calculator you'll ever need
3 | * Copyright (C) 2011, 2012 Uprizer Labs LLC
4 | *
5 | * This program is free software: you can redistribute it and/or modify it
6 | * under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 | * PURPOSE. See the GNU Affero General Public License for more
14 | * details.
15 | ******************************************************************************/
16 | package com.lastcalc.cache;
17 |
18 | import java.io.Serializable;
19 | import java.util.*;
20 | import java.util.logging.Logger;
21 |
22 | import javax.cache.*;
23 |
24 | import com.google.common.collect.*;
25 |
26 | import com.google.appengine.api.memcache.jsr107cache.GCacheFactory;
27 |
28 | public class ObjectCache {
29 | private static final Logger log = Logger.getLogger(ObjectCache.class.getName());
30 |
31 | static Map softMap = new MapMaker().softValues().makeMap();
32 |
33 | public static T getFast(final long oldestAllowed, final Object... key) {
34 | return getFastWithHash(oldestAllowed, Arrays.hashCode(key));
35 | }
36 |
37 | @SuppressWarnings("unchecked")
38 | private static T getFastWithHash(final long oldestAllowed, final int hash) {
39 | final CachedObject co = softMap.get(hash);
40 | if (co == null)
41 | return null;
42 | if (System.currentTimeMillis() - oldestAllowed > co.cacheTime)
43 | return (T) co.object;
44 | else
45 | return null;
46 | }
47 |
48 | @SuppressWarnings("unchecked")
49 | public static T getSlow(final long oldestAllowed, final Object... key) {
50 | final int keyHash = Arrays.hashCode(key);
51 | final T o = getFastWithHash(oldestAllowed, keyHash);
52 | if (o != null) {
53 | log.info("Got from local RAM");
54 | return o;
55 | }
56 | else {
57 | CacheFactory cacheFactory;
58 | try {
59 | cacheFactory = CacheManager.getInstance().getCacheFactory();
60 | final Cache memcache = cacheFactory.createCache(Collections.emptyMap());
61 | final CachedObject co = (CachedObject) memcache.get(keyHash);
62 | if (co != null) {
63 | log.info("Got from memcache");
64 | return (T) co.object;
65 | }
66 | else
67 | return null;
68 | } catch (final CacheException e) {
69 | log.warning("Exception retrieving object from cache: " + e);
70 | return null;
71 | }
72 | }
73 | }
74 |
75 | @SuppressWarnings("unchecked")
76 | public static void put(final long expirationDelta, final Object value, final Object... key) {
77 | final int keyHash = Arrays.hashCode(key);
78 | final CachedObject co = new CachedObject(value);
79 | softMap.put(keyHash, co);
80 | CacheFactory cacheFactory;
81 | try {
82 | cacheFactory = CacheManager.getInstance().getCacheFactory();
83 | final Map props = Maps.newHashMap();
84 | props.put(GCacheFactory.EXPIRATION_DELTA, 3600);
85 | final Cache memcache = cacheFactory.createCache(props);
86 | memcache.put(keyHash, co);
87 | } catch (final CacheException e) {
88 | log.warning("Exception retrieving object from cache: " + e);
89 | }
90 | }
91 |
92 | public static class CachedObject implements Serializable {
93 | /**
94 | *
95 | */
96 | private static final long serialVersionUID = 2851269118906160513L;
97 |
98 | public final long cacheTime;
99 |
100 | public final Object object;
101 |
102 | public CachedObject(final Object object) {
103 | this.object = object;
104 | cacheTime = System.currentTimeMillis();
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/com/lastcalc/parsers/meta/ImportParser.java:
--------------------------------------------------------------------------------
1 | package com.lastcalc.parsers.meta;
2 |
3 | import java.io.*;
4 | import java.net.*;
5 | import java.util.Collection;
6 |
7 | import com.lastcalc.*;
8 | import com.lastcalc.Tokenizer.QuotedString;
9 | import com.lastcalc.cache.ObjectCache;
10 | import com.lastcalc.parsers.*;
11 |
12 | public class ImportParser extends Parser {
13 |
14 | private static TokenList template = TokenList.createD("import", QuotedString.class);
15 |
16 | @Override
17 | public TokenList getTemplate() {
18 | return template;
19 | }
20 | @Override
21 | public ParseResult parse(final TokenList tokens, final int templatePos, final ParserContext context) {
22 | if (context.importDepth > 5)
23 | return ParseResult.fail();
24 | URL url;
25 | try {
26 | url = new URL(((QuotedString) tokens.get(templatePos + 1)).value);
27 | } catch (final MalformedURLException e) {
28 | return ParseResult.fail();
29 | }
30 |
31 | CachedImport cached = ObjectCache.getSlow(1000l * 60l * 60l * 24l, url);
32 |
33 | if (cached == null ||
34 | (System.currentTimeMillis() > cached.expires && System.currentTimeMillis() - cached.currentAt > 60l*1000l)) {
35 | // More than a minute ago and after expires time, let's check to see
36 | // whether the original URL is updated
37 | try {
38 | final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
39 | connection.setRequestProperty("Accept", "text/plain");
40 | if (cached != null && cached.lastModifiedHeader != null) {
41 | connection.setRequestProperty("If-Modified-Since", cached.lastModifiedHeader);
42 | }
43 | if (cached != null && cached.eTag != null) {
44 | connection.setRequestProperty("If-None-Match", cached.eTag);
45 | }
46 | final int code = connection.getResponseCode();
47 | if (code == 304) {
48 | // It was cached, update
49 | cached.currentAt = System.currentTimeMillis();
50 | ObjectCache.put(1000l * 60l * 60l * 24l, cached, url);
51 | } else {
52 | final String contentType = connection.getContentType();
53 | if (contentType.toLowerCase().contains("text/plain")) {
54 | cached = new CachedImport();
55 | final BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
56 | final ParserContext pc = new ParserContext(context.parseEngine, context.timeout, context.importDepth + 1);
57 | final SequentialParser sp = SequentialParser.create(pc);
58 | while (true) {
59 | final String nextLine = br.readLine();
60 | if (nextLine == null) {
61 | break;
62 | }
63 | sp.parseNext(nextLine);
64 | }
65 |
66 | cached = new CachedImport();
67 |
68 | cached.userDefinedParsers = sp.getUserDefinedParsers().getParsers();
69 | cached.currentAt = System.currentTimeMillis();
70 | cached.lastModifiedHeader = connection.getHeaderField("Last-Modified");
71 | cached.eTag = connection.getHeaderField("ETag");
72 | cached.expires = connection.getHeaderFieldDate("Expires", 0);
73 | ObjectCache.put(1000l * 60l * 60l * 24l, cached, url);
74 |
75 | } else
76 | return ParseResult.fail();
77 | }
78 |
79 | } catch (final IOException e) {
80 | return ParseResult.fail();
81 | }
82 | }
83 |
84 | return ParseResult.success(tokens.replaceWithTokens(templatePos, template.size(), cached.userDefinedParsers));
85 | }
86 |
87 | @Override
88 | public int hashCode() {
89 | // TODO Auto-generated method stub
90 | return 0;
91 | }
92 |
93 | @Override
94 | public boolean equals(final Object obj) {
95 | // TODO Auto-generated method stub
96 | return false;
97 | }
98 |
99 | public static class CachedImport implements Serializable {
100 | private static final long serialVersionUID = -3304707639237443710L;
101 | public long currentAt, expires;
102 |
103 | public String eTag;
104 |
105 | public String lastModifiedHeader;
106 |
107 | public Collection userDefinedParsers;
108 | }
109 | }
110 |
111 |
--------------------------------------------------------------------------------
/src/main/webapp/css/highlighting.css:
--------------------------------------------------------------------------------
1 | .number {
2 | color: #229;
3 | }
4 |
5 | .quoted {
6 | color: #229999;
7 | }
8 |
9 | .recognized {
10 | color: #777777;
11 | }
12 |
13 | .variable {
14 | display: inline-block;
15 | outline: none;
16 | text-align: center;
17 | font-size: 14px;
18 | padding-top: 0px;
19 | padding-bottom: 2px;
20 | padding-left: 2px;
21 | padding-right: 2px;
22 | text-shadow: 0 1px 1px rgba(0, 0, 0, .3);
23 | -webkit-border-radius: .5em;
24 | -moz-border-radius: .5em;
25 | border-radius: .5em;
26 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
27 | -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
28 | box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
29 | }
30 |
31 | .black {
32 | color: #d7d7d7;
33 | border: solid 1px #333;
34 | background: #333;
35 | background: -webkit-gradient(linear, left top, left bottom, from(#666),
36 | to(#000) );
37 | background: -moz-linear-gradient(top, #666, #000);
38 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#666666',
39 | endColorstr='#000000' );
40 | }
41 |
42 | .gray {
43 | color: #e9e9e9;
44 | border: solid 1px #555;
45 | background: #6e6e6e;
46 | background: -webkit-gradient(linear, left top, left bottom, from(#888),
47 | to(#575757) );
48 | background: -moz-linear-gradient(top, #888, #575757);
49 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#888888',
50 | endColorstr='#575757' );
51 | }
52 |
53 | .white {
54 | color: #606060;
55 | border: solid 1px #b7b7b7;
56 | background: #fff;
57 | background: -webkit-gradient(linear, left top, left bottom, from(#fff),
58 | to(#ededed) );
59 | background: -moz-linear-gradient(top, #fff, #ededed);
60 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff',
61 | endColorstr='#ededed' );
62 | }
63 |
64 | .orange {
65 | color: #fef4e9;
66 | border: solid 1px #da7c0c;
67 | background: #f78d1d;
68 | background: -webkit-gradient(linear, left top, left bottom, from(#faa51a),
69 | to(#f47a20) );
70 | background: -moz-linear-gradient(top, #faa51a, #f47a20);
71 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#faa51a',
72 | endColorstr='#f47a20' );
73 | }
74 |
75 | .red {
76 | color: #faddde;
77 | border: solid 1px #980c10;
78 | background: #d81b21;
79 | background: -webkit-gradient(linear, left top, left bottom, from(#ed1c24),
80 | to(#aa1317) );
81 | background: -moz-linear-gradient(top, #ed1c24, #aa1317);
82 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ed1c24',
83 | endColorstr='#aa1317' );
84 | }
85 |
86 | .blue {
87 | color: #d9eef7;
88 | border: solid 1px #0076a3;
89 | background: #0095cd;
90 | background: -webkit-gradient(linear, left top, left bottom, from(#00adee),
91 | to(#0078a5) );
92 | background: -moz-linear-gradient(top, #00adee, #0078a5);
93 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00adee',
94 | endColorstr='#0078a5' );
95 | }
96 |
97 | .rosy {
98 | color: #fae7e9;
99 | border: solid 1px #b73948;
100 | background: #da5867;
101 | background: -webkit-gradient(linear, left top, left bottom, from(#f16c7c),
102 | to(#bf404f) );
103 | background: -moz-linear-gradient(top, #f16c7c, #bf404f);
104 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f16c7c',
105 | endColorstr='#bf404f' );
106 | }
107 |
108 | .green {
109 | color: #e8f0de;
110 | border: solid 1px #538312;
111 | background: #64991e;
112 | background: -webkit-gradient(linear, left top, left bottom, from(#7db72f),
113 | to(#4e7d0e) );
114 | background: -moz-linear-gradient(top, #7db72f, #4e7d0e);
115 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#7db72f',
116 | endColorstr='#4e7d0e' );
117 | }
118 |
119 | .pink {
120 | color: #feeef5;
121 | border: solid 1px #d2729e;
122 | background: #f895c2;
123 | background: -webkit-gradient(linear, left top, left bottom, from(#feb1d3),
124 | to(#f171ab) );
125 | background: -moz-linear-gradient(top, #feb1d3, #f171ab);
126 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#feb1d3',
127 | endColorstr='#f171ab' );
128 | }
129 |
--------------------------------------------------------------------------------
/src/main/webapp/js/rangy-serializer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Serializer module for Rangy.
3 | Serializes Ranges and Selections. An example use would be to store a user's selection on a particular page in a
4 | cookie or local storage and restore it on the user's next visit to the same page.
5 |
6 | Part of Rangy, a cross-browser JavaScript range and selection library
7 | http://code.google.com/p/rangy/
8 |
9 | Depends on Rangy core.
10 |
11 | Copyright 2011, Tim Down
12 | Licensed under the MIT license.
13 | Version: 1.2.2
14 | Build date: 13 November 2011
15 | */
16 | rangy.createModule("Serializer",function(g,n){function o(c,a){a=a||[];var b=c.nodeType,e=c.childNodes,d=e.length,f=[b,c.nodeName,d].join(":"),h="",k="";switch(b){case 3:h=c.nodeValue.replace(//g,">");break;case 8:h="