├── .gitignore ├── .travis.yml ├── run.sh ├── clean.sh ├── make.sh ├── CONTRIBUTING.md ├── src └── com │ └── google │ └── codeu │ └── mathlang │ ├── testing │ ├── TestCriteria.java │ ├── TestListener.java │ ├── TestNoteFunction.java │ ├── TestPrintFunction.java │ ├── TestLetFunction.java │ ├── CallTable.java │ └── Tester.java │ ├── core │ ├── Variable.java │ ├── Function.java │ ├── tokens │ │ ├── Token.java │ │ ├── NumberToken.java │ │ ├── NameToken.java │ │ ├── StringToken.java │ │ └── SymbolToken.java │ └── State.java │ ├── functions │ ├── operations │ │ ├── Operation.java │ │ ├── AddOperation.java │ │ └── SubtractOperation.java │ ├── NoteFunction.java │ ├── PrintFunction.java │ └── LetFunction.java │ ├── parsing │ ├── TokenReader.java │ ├── StatementBuilder.java │ └── StatementReader.java │ ├── impl │ └── MyTokenReader.java │ └── Test.java ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | sudo: false 4 | 5 | jdk: 6 | - openjdk7 7 | - oraclejdk8 8 | 9 | os: 10 | - linux 11 | 12 | 13 | script: 14 | - ./clean.sh 15 | - ./build.sh 16 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2017 Google Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | java -classpath bin com.google.codeu.mathlang.Test 20 | -------------------------------------------------------------------------------- /clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2017 Google Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | if [ -d './bin' ] ; then 20 | rm -rf $(find './bin' -maxdepth 1 -mindepth 1) 21 | fi 22 | -------------------------------------------------------------------------------- /make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2017 Google Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | rm -rf bin 20 | mkdir -p bin 21 | javac -Xlint -classpath bin -d bin -sourcepath src $(find src -name *.java) 22 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution, 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/testing/TestCriteria.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.testing; 16 | 17 | // TEST CRITERIA 18 | // 19 | // This interface verifies a call table after a test has completed. 20 | public interface TestCriteria { 21 | 22 | // ON TEST END 23 | // 24 | // This method performs a final check on the call table, to verify that the 25 | // the call table is clean. If it is not clean, throw an exception, which will 26 | // cause the test to fail. 27 | void onTestEnd(CallTable calls) throws Exception; 28 | } 29 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/core/Variable.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.core; 16 | 17 | // VARIABLE 18 | // 19 | // This class writes the value of a variable. This is done to allow 20 | // a variable to be passed around by reference. 21 | public final class Variable { 22 | 23 | private double value = 0; 24 | 25 | // READ 26 | // 27 | // Read the value that this variable holds. 28 | public double read() { 29 | return value; 30 | } 31 | 32 | // WRITE 33 | // 34 | // Write a new value to the variable, replacing the previous value held by the variable. 35 | public void write(double value) { 36 | this.value = value; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/testing/TestListener.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.testing; 16 | 17 | // TEST LISTENER 18 | // 19 | // This interface defines the callbacks that |Tester| will use to communicate 20 | // events that happen while running through tests. 21 | public interface TestListener { 22 | 23 | // ON TEST START 24 | // 25 | // Called when a test first starts. 26 | void onTestStart(String testName); 27 | 28 | // ON PASS 29 | // 30 | // Called when a test completed successfully. 31 | void onPass(); 32 | 33 | // ON FAIL 34 | // 35 | // Called when a test fails to complete successfully. The exception 36 | // passed to the method is the original exception thrown during 37 | // execution. 38 | void onFail(Exception ex); 39 | } 40 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/core/Function.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.core; 16 | 17 | import com.google.codeu.mathlang.core.tokens.Token; 18 | 19 | // FUNCTION 20 | // 21 | // This interface is for a single functional unit of work defined by the 22 | // paramters passed to it as an array of tokens. Functions should avoid 23 | // carrying internal state. 24 | public interface Function { 25 | 26 | // RUN 27 | // 28 | // This method is called when the there is a statement ready for it. The first 29 | // token will always be the identifier of the function. The function should 30 | // ignore this token. If any other token does not meet the expectations of the 31 | // function, an exception should be thrown and execution will be stopped. 32 | void run(Token[] statement) throws Exception; 33 | } 34 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/core/tokens/Token.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.core.tokens; 16 | 17 | // TOKEN 18 | // 19 | // This is the common interface for all token types. A token is a 20 | // block of information parsed from the input. 21 | public interface Token { 22 | 23 | // TO STRING 24 | // 25 | // Require all tokens to supply a |toString| implementation so that 26 | // tokens can be printed when debugging. 27 | String toString(); 28 | 29 | // HASH CODE 30 | // 31 | // All tokens must implement hashCode to ensure that tokens can work 32 | // well with hash-based data structures. 33 | int hashCode(); 34 | 35 | // EQUALS 36 | // 37 | // Check for equality with other objects. All tokens must implement 38 | // this to make working with tokens easier. 39 | boolean equals(Object other); 40 | } 41 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/functions/operations/Operation.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.functions.operations; 16 | 17 | public interface Operation { 18 | 19 | // APPLY TO 20 | // 21 | // Apply the operation to the value x and return the result. 22 | double applyTo(double x); 23 | 24 | // TO STRING 25 | // 26 | // All operations must supply a |toString| implementation so 27 | // operations can be printed when debugging. 28 | String toString(); 29 | 30 | // HASH CODE 31 | // 32 | // All operations must implement hashCode to ensure that they can work 33 | // well with hash-based data structures. 34 | int hashCode(); 35 | 36 | // EQUALS 37 | // 38 | // Check for euality with other objects. All operations must implement 39 | // this to make working with them easier. 40 | boolean equals(Object other); 41 | } 42 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/parsing/TokenReader.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.parsing; 16 | 17 | import java.io.IOException; 18 | 19 | import com.google.codeu.mathlang.core.tokens.Token; 20 | 21 | // TOKEN READER 22 | // 23 | // Defines a stream of tokens. 24 | public interface TokenReader { 25 | 26 | // NEXT 27 | // 28 | // Get the next token in the stream. When the end of stream has been reached 29 | // |next| should return |null|. The only valid tokens that can be returned are: 30 | // - com.google.codeu.mathlang.core.tokens.StringToken 31 | // - com.google.codeu.mathlang.core.tokens.NameToken 32 | // - com.google.codeu.mathlang.core.tokens.SymbolToken 33 | // - com.google.codeu.mathlang.core.tokens.NumberToken 34 | // If there is ever a problem with the source data, |next| should throw an 35 | // IOException. 36 | Token next() throws IOException; 37 | } 38 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/core/tokens/NumberToken.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.core.tokens; 16 | 17 | // NUMBER TOKEN 18 | // 19 | // This class represents a floating-point numerical token. 20 | public final class NumberToken implements Token { 21 | 22 | public final double value; 23 | 24 | public NumberToken(double value) { 25 | this.value = value; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return String.format("NUMBER(%f)", value); 31 | } 32 | 33 | @Override 34 | public int hashCode() { 35 | return Double.hashCode(value); 36 | } 37 | 38 | @Override 39 | public boolean equals(Object other) { 40 | return other instanceof NumberToken && equals(this, (NumberToken) other); 41 | } 42 | 43 | private static boolean equals(NumberToken a, NumberToken b) { 44 | return a == b || (a != null && b != null && a.value == b.value); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/functions/operations/AddOperation.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.functions.operations; 16 | 17 | public final class AddOperation implements Operation { 18 | 19 | private final double amount; 20 | 21 | public AddOperation(double amount) { 22 | this.amount = amount; 23 | } 24 | 25 | @Override 26 | public double applyTo(double x) { 27 | return x + amount; 28 | } 29 | 30 | @Override 31 | public String toString() { return String.format("ADD(%f)", amount); } 32 | 33 | @Override 34 | public int hashCode() { return Double.hashCode(amount); } 35 | 36 | @Override 37 | public boolean equals(Object other) { 38 | return other instanceof AddOperation && equals(this, (AddOperation) other); 39 | } 40 | 41 | private static final boolean equals(AddOperation a, AddOperation b) { 42 | return a == b || (a != null && b != null && a.amount == b.amount); 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/core/tokens/NameToken.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.core.tokens; 16 | 17 | // NAME TOKEN 18 | // 19 | // This class represents a UTF-8 string that contains no whitespaces 20 | // and starts with an alphabetical character. 21 | public final class NameToken implements Token { 22 | 23 | public final String value; 24 | 25 | public NameToken(String value) { 26 | this.value = value; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return String.format("NAME(%s)", value); 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | return value.hashCode(); 37 | } 38 | 39 | @Override 40 | public boolean equals(Object other) { 41 | return other instanceof NameToken && equals(this, (NameToken) other); 42 | } 43 | 44 | private static boolean equals(NameToken a, NameToken b) { 45 | return a == b || (a != null && b!= null && a.value.equals(b.value)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/functions/operations/SubtractOperation.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.functions.operations; 16 | 17 | public final class SubtractOperation implements Operation { 18 | 19 | private final double amount; 20 | 21 | public SubtractOperation(double amount) { 22 | this.amount = amount; 23 | } 24 | 25 | @Override 26 | public double applyTo(double x) { 27 | return x - amount; 28 | } 29 | 30 | @Override 31 | public String toString() { return String.format("SUB(%f)", amount); } 32 | 33 | @Override 34 | public int hashCode() { return Double.hashCode(amount); } 35 | 36 | @Override 37 | public boolean equals(Object other) { 38 | return other instanceof SubtractOperation && equals(this, (SubtractOperation) other); 39 | } 40 | 41 | private static final boolean equals(SubtractOperation a, SubtractOperation b) { 42 | return a == b || (a != null && b != null && a.amount == b.amount); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/core/tokens/StringToken.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.core.tokens; 16 | 17 | // STRING TOKEN 18 | // 19 | // This class represents a UTF-8 string token. There are no restrictions 20 | // on what characters can be in it. 21 | public final class StringToken implements Token { 22 | 23 | public final String value; 24 | 25 | public StringToken(String value) { 26 | this.value = value; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return String.format("STRING(%s)", value); 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | return value.hashCode(); 37 | } 38 | 39 | @Override 40 | public boolean equals(Object other) { 41 | return other instanceof StringToken && equals(this, (StringToken) other); 42 | } 43 | 44 | private static boolean equals(StringToken a, StringToken b) { 45 | return a == b || (a != null && b != null && a.value.equals(b.value)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/testing/TestNoteFunction.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.testing; 16 | 17 | import java.util.Collection; 18 | 19 | import com.google.codeu.mathlang.functions.NoteFunction; 20 | import com.google.codeu.mathlang.testing.CallTable; 21 | 22 | // TEST NOTE FUNCTION 23 | // 24 | // Extend the Note Function and add entries to the call table 25 | // so that Note Function calls can be validated. 26 | public final class TestNoteFunction extends NoteFunction { 27 | 28 | private final CallTable table; 29 | 30 | public TestNoteFunction(CallTable table) { 31 | this.table = table; 32 | } 33 | 34 | @Override 35 | protected void onNoteBody(Collection segments) { 36 | // Add the call to the call table. 37 | final CallTable.Entry entry = table.newEntry(); 38 | entry.and("note"); 39 | for (final String segment : segments) { 40 | entry.and(segment); 41 | } 42 | 43 | super.onNoteBody(segments); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/core/tokens/SymbolToken.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.core.tokens; 16 | 17 | // SYMBOL TOKEN 18 | // 19 | // This class represents a single character token. The internal value is 20 | // limited to characters that have a special meaning to the parser. 21 | public final class SymbolToken implements Token { 22 | 23 | public final char value; 24 | 25 | public SymbolToken(char value) { 26 | this.value = value; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return String.format("SYMBOL(%c)", value); 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | return Character.hashCode(value); 37 | } 38 | 39 | @Override 40 | public boolean equals(Object other) { 41 | return other instanceof SymbolToken && equals(this, (SymbolToken) other); 42 | } 43 | 44 | private static boolean equals(SymbolToken a, SymbolToken b) { 45 | return a == b || (a != null && b != null && a.value == b.value); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/parsing/StatementBuilder.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.parsing; 16 | 17 | import java.util.ArrayList; 18 | import java.util.Collection; 19 | 20 | import com.google.codeu.mathlang.core.tokens.Token; 21 | 22 | // STATEMENT BUILDER 23 | // 24 | // The statement builder helps create a series of tokens. It supplies 25 | // an array of tokens when the series ends. 26 | final class StatementBuilder { 27 | 28 | private final Collection tokens = new ArrayList<>(); 29 | 30 | // APPEND 31 | // 32 | // Add the token to the end of the series. 33 | public void append(Token token) { 34 | tokens.add(token); 35 | } 36 | 37 | // BUILD 38 | // 39 | // Create an array from the series of tokens. 40 | public Token[] build() { 41 | final Token[] out = new Token[tokens.size()]; 42 | tokens.toArray(out); 43 | return out; 44 | } 45 | 46 | // RESET 47 | // 48 | // Reset the internal state of the builder. This should be called 49 | // before starting to append the tokens of a statement. 50 | public void reset() { 51 | tokens.clear(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/testing/TestPrintFunction.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.testing; 16 | 17 | import java.util.Collection; 18 | import java.util.Map; 19 | 20 | import com.google.codeu.mathlang.core.Variable; 21 | import com.google.codeu.mathlang.functions.PrintFunction; 22 | import com.google.codeu.mathlang.testing.CallTable; 23 | 24 | // TEST PRINT FUNCTION 25 | // 26 | // Extend the Print Function and add entries to the call table 27 | // so that Print Function calls can be validated. 28 | public final class TestPrintFunction extends PrintFunction { 29 | 30 | private final CallTable table; 31 | 32 | public TestPrintFunction(Map variables, CallTable table) { 33 | super(variables); 34 | this.table = table; 35 | } 36 | 37 | @Override 38 | protected void printLine(Collection segments) { 39 | // Add the call to the call table. 40 | final CallTable.Entry entry = table.newEntry(); 41 | entry.and("print"); 42 | for (final String segment : segments) { 43 | entry.and(segment); 44 | } 45 | 46 | super.printLine(segments); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/testing/TestLetFunction.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.testing; 16 | 17 | import java.util.Collection; 18 | import java.util.Map; 19 | 20 | import com.google.codeu.mathlang.core.Variable; 21 | import com.google.codeu.mathlang.functions.LetFunction; 22 | import com.google.codeu.mathlang.functions.operations.Operation; 23 | import com.google.codeu.mathlang.testing.CallTable; 24 | 25 | // TEST LET FUNCTION 26 | // 27 | // Extend the Let Function and add entries to the call table 28 | // so Let Function calls can be validated. 29 | public final class TestLetFunction extends LetFunction { 30 | 31 | private final CallTable table; 32 | 33 | public TestLetFunction(Map variables, CallTable table) { 34 | super(variables); 35 | this.table = table; 36 | } 37 | 38 | @Override 39 | protected double evaluate(Collection ops) { 40 | // Add the call to the call table. 41 | final CallTable.Entry entry = table.newEntry(); 42 | entry.and("let"); 43 | for (final Operation op : ops) { 44 | entry.and(op); 45 | } 46 | 47 | return super.evaluate(ops); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/impl/MyTokenReader.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.impl; 16 | 17 | import java.io.IOException; 18 | 19 | import com.google.codeu.mathlang.core.tokens.Token; 20 | import com.google.codeu.mathlang.parsing.TokenReader; 21 | 22 | // MY TOKEN READER 23 | // 24 | // This is YOUR implementation of the token reader interface. To know how 25 | // it should work, read src/com/google/codeu/mathlang/parsing/TokenReader.java. 26 | // You should not need to change any other files to get your token reader to 27 | // work with the test of the system. 28 | public final class MyTokenReader implements TokenReader { 29 | 30 | public MyTokenReader(String source) { 31 | // Your token reader will only be given a string for input. The string will 32 | // contain the whole source (0 or more lines). 33 | } 34 | 35 | @Override 36 | public Token next() throws IOException { 37 | // Most of your work will take place here. For every call to |next| you should 38 | // return a token until you reach the end. When there are no more tokens, you 39 | // should return |null| to signal the end of input. 40 | 41 | // If for any reason you detect an error in the input, you may throw an IOException 42 | // which will stop all execution. 43 | 44 | return null; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodeU Coding Assessment - Math Lang 2 | 3 | # Overview 4 | This project allows students to demonstrate their coding skills by implementing 5 | a component of a larger system. 6 | 7 | MathLang is a made-up math scripting language. Students are expected to 8 | implement `com.google.codeu.mathlang.impl.MyTokenReader`. The class has already 9 | been created and students only need to finish implementing its functionality. 10 | 11 | `MyTokenReader` is responsible for parsing the text input and converting it to 12 | a stream of tokens that the MathLang parser will use to build statements. 13 | Statements are then passed to the interpreter to be executed. Everything except 14 | for `MyTokenReader` has already been implemented. 15 | 16 | To further understand how `MyTokenReader` should behave, students can look at 17 | `com.google.codeu.mathlang.core.tokens.TokenReader`. `TokenReader` is the 18 | interface that `MyTokenReader` implements and contains in-code documentation 19 | for how each method should behave. 20 | 21 | # The Goal 22 | When students have finished their implementation of `MyTokenReader`, they should 23 | run the tests and see all tests pass. If any test fails, the student is not 24 | done. The tests provided are only for testing MathLang. There are no tests for 25 | `MyTokenReader`. Students are encouraged to write their own tests to ensure 26 | their implementation is working. 27 | 28 | Students should not use any third-party libraries to complete this assessment. 29 | The one exception is the use of a third-party test library to help test their 30 | implementation of `MyTokenReader`. 31 | 32 | When done, an evaluator should be able to run the student's project using the 33 | same build and run instructions provided here. This means that if a student 34 | uses a third-party test library, all dependencies must be included with the 35 | project and `build.sh` and `run.sh` must be updated. 36 | 37 | # Build Instructions 38 | These instructions are based on a Linux environment using BASH and JAVA 7. 39 | 40 | To clean, run `./clean.sh`. 41 | To build, run `./build.sh`. 42 | To run all tests, run `./run.sh`. -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/core/State.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.core; 16 | 17 | import java.util.HashMap; 18 | import java.util.Map; 19 | 20 | import com.google.codeu.mathlang.core.tokens.NameToken; 21 | import com.google.codeu.mathlang.core.tokens.Token; 22 | 23 | // STATE 24 | // 25 | // This class represents the execution environment for all functions. State 26 | // maintains a list of all functions and routes statements to the correct 27 | // function. 28 | public final class State { 29 | 30 | private final Map functions = new HashMap<>(); 31 | 32 | // DEFINE FUNCTION 33 | // 34 | // Assign a function to a keyword. This will overwrite any previous assigned 35 | // function with the same name. 36 | public void defineFunction(String name, Function function) { 37 | functions.put(name, function); 38 | } 39 | 40 | // RUN 41 | // 42 | // Find the correct function for the given statement and execute the 43 | // statement. 44 | public void run(Token[] statement) throws Exception { 45 | 46 | if (statement.length == 0) { 47 | // An empty statement should act like a No-op. 48 | return; 49 | } 50 | 51 | final Token head = statement[0]; 52 | 53 | if (!(head instanceof NameToken)) { 54 | throw new Exception(String.format("Expecting name token but found %s", head)); 55 | } 56 | 57 | final NameToken name = (NameToken) head; 58 | final Function function = functions.get(name.value); 59 | 60 | if (function == null) { 61 | throw new Exception(String.format("Unknown function \"%s\"", name.value)); 62 | } 63 | 64 | function.run(statement); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/functions/NoteFunction.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.functions; 16 | 17 | import java.util.ArrayList; 18 | import java.util.Collection; 19 | 20 | import com.google.codeu.mathlang.core.Function; 21 | import com.google.codeu.mathlang.core.tokens.StringToken; 22 | import com.google.codeu.mathlang.core.tokens.Token; 23 | 24 | // NOTE FUNCTION 25 | // 26 | // This class defines the note functionality of mathlang. A note is similar 27 | // to a comment in other programming languages. However, in Mathlang the only 28 | // text that can appear in a note are quoted strings. For example: 29 | // NOTE "this is a note"; 30 | // NOTE "this is the first half" "and this is this second"; 31 | // Note "this is the first half" 32 | // "and this is the second"; 33 | // 34 | // This class is not marked as final so that it can be overriden in our tests. 35 | public class NoteFunction implements Function { 36 | 37 | @Override 38 | public void run(Token[] statement) throws Exception { 39 | 40 | final Collection segments = new ArrayList<>(); 41 | 42 | for (int i = 1; i < statement.length; i++) { 43 | if (statement[i] instanceof StringToken) { 44 | final StringToken string = (StringToken) statement[i]; 45 | segments.add(string.value); 46 | } else { 47 | throw new Exception(String.format("NOTE should only contain string values but found %s", statement[i])); 48 | } 49 | } 50 | 51 | onNoteBody(segments); 52 | } 53 | 54 | // ON NOTE BODY 55 | // 56 | // This method does not need to do anything. It is exposed so NOTE 57 | // calls can be checked in our tests. 58 | protected void onNoteBody(Collection segments) { } 59 | } 60 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/parsing/StatementReader.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.parsing; 16 | 17 | import java.io.IOException; 18 | 19 | import com.google.codeu.mathlang.core.tokens.Token; 20 | import com.google.codeu.mathlang.core.tokens.SymbolToken; 21 | 22 | // STATEMENT READER 23 | // 24 | // The statement reader takes a token reader and creates a stream 25 | // of executable statements. 26 | public final class StatementReader { 27 | 28 | private static final Token END_OF_STATEMENT = new SymbolToken(';'); 29 | 30 | private final StatementBuilder builder = new StatementBuilder(); 31 | private final TokenReader reader; 32 | 33 | public StatementReader(TokenReader reader) { 34 | this.reader = reader; 35 | } 36 | 37 | // NEXT 38 | // 39 | // Get the next statement as an array of tokens. When the end of stream is 40 | // reached (there are no more statements) this method returns null. This 41 | // method will only return complete statements, if an end of stream is reached 42 | // before a complete statement is recognized, an IOException will be thrown. 43 | public Token[] next() throws IOException { 44 | builder.reset(); 45 | 46 | Token next = reader.next(); 47 | 48 | // If there is nothing when we start reading, assume that we made it to the 49 | // end of the stream safely. 50 | if (next == null) { 51 | return null; 52 | } 53 | 54 | while (next != null && !next.equals(END_OF_STATEMENT)) { 55 | builder.append(next); 56 | next = reader.next(); 57 | } 58 | 59 | // If next is null here it means that the last statement is incomplete. 60 | if (next == null) { 61 | throw new IOException("Reached end of stream while still reading statement."); 62 | } 63 | 64 | return builder.build(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/testing/CallTable.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.testing; 16 | 17 | import java.util.ArrayList; 18 | import java.util.Arrays; 19 | import java.util.Collection; 20 | import java.util.LinkedList; 21 | import java.util.List; 22 | import java.util.Queue; 23 | 24 | // CALL TABLE 25 | // 26 | // This class is used to verify that specific methods within a target class 27 | // have been called with the expected arguments in a specific order. For a given 28 | // target class, a subclass must be defined that overrides each method of the 29 | // target class with a method that writes to the call table. The call table 30 | // can then be checked to see if the expected calls were made. 31 | public final class CallTable { 32 | 33 | public interface Entry { 34 | Entry and(Object value); 35 | }; 36 | 37 | private final Queue> entries = new LinkedList<>(); 38 | 39 | // NEW ENTRY 40 | // 41 | // Create a new entry in the call table. This method returns an |Entry| which 42 | // holds information about the call. 43 | public Entry newEntry() { 44 | final List entry = new ArrayList<>(); 45 | entries.add(entry); 46 | 47 | return new Entry() { 48 | @Override 49 | public Entry and(Object value) { 50 | entry.add(value); 51 | return this; 52 | } 53 | }; 54 | } 55 | 56 | // ASSERT NEXT 57 | // 58 | // Check if the next call in the history matches what is given. If the entry 59 | // does not match exactly, throw an exception. 60 | public void assertNext(Object... expected) throws Exception { 61 | final Object[] actual = entries.size() > 0 ? 62 | entries.remove().toArray() : 63 | null; 64 | 65 | if (!Arrays.equals(actual, expected)) { 66 | throw new Exception(String.format( 67 | "Expected %s but got %s", Arrays.toString(expected), Arrays.toString(actual))); 68 | } 69 | } 70 | 71 | // ASSERT END 72 | // 73 | // Check that all calls have been consumed via calls to |assertNext|. If 74 | // any calls have not been consumed via |assertNext|, throw an exception. 75 | public void assertEnd() throws Exception { 76 | if (entries.size() > 0) { 77 | throw new Exception(String.format( 78 | "Expected all calls to have completed, but there are still %d unchecked calls.", 79 | entries.size())); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/functions/PrintFunction.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.functions; 16 | 17 | import java.io.IOException; 18 | import java.util.ArrayList; 19 | import java.util.Collection; 20 | import java.util.Map; 21 | 22 | import com.google.codeu.mathlang.core.Function; 23 | import com.google.codeu.mathlang.core.Variable; 24 | import com.google.codeu.mathlang.core.tokens.NameToken; 25 | import com.google.codeu.mathlang.core.tokens.NumberToken; 26 | import com.google.codeu.mathlang.core.tokens.StringToken; 27 | import com.google.codeu.mathlang.core.tokens.Token; 28 | 29 | // PRINT FUNCTION 30 | // 31 | // This function writes out the current value of a token. It can handle 32 | // strings, variables, and numbers. This class is not final so it can 33 | // be overridden in our tests. 34 | public class PrintFunction implements Function { 35 | 36 | // A map of variables that print will use to look up values. 37 | private final Map variables; 38 | 39 | public PrintFunction(Map variables) { 40 | this.variables = variables; 41 | } 42 | 43 | @Override 44 | public void run(Token[] statement) throws Exception { 45 | final Collection segments = new ArrayList<>(); 46 | 47 | for (int i = 1; i < statement.length; i++) { 48 | segments.add(toString(statement[i])); 49 | } 50 | 51 | printLine(segments); 52 | } 53 | 54 | private String toString(Token token) throws Exception { 55 | if (token instanceof NumberToken) { 56 | final NumberToken number = (NumberToken) token; 57 | return Double.toString(number.value); 58 | } 59 | 60 | if (token instanceof StringToken) { 61 | final StringToken string = (StringToken) token; 62 | return string.value; 63 | } 64 | 65 | if (token instanceof NameToken) { 66 | final NameToken name = (NameToken) token; 67 | final Variable v = variables.get(name.value); 68 | if (v == null) { 69 | throw new Exception(String.format("Attempting to read value of \"%s\" before assigning it a value.", name.value)); 70 | } else { 71 | return Double.toString(v.read()); 72 | } 73 | } 74 | 75 | throw new Exception(String.format("PRINT could not handle %s", token)); 76 | } 77 | 78 | // PRINT LINE 79 | // 80 | // This method is responsible for writing out a series of segments. This 81 | // implementation does not write to anythng. This method is exposed as 82 | // protected so that it can be overridden in our tests. 83 | protected void printLine(Collection segments) { } 84 | } 85 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/testing/Tester.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.testing; 16 | 17 | import java.io.IOException; 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | import com.google.codeu.mathlang.core.Function; 22 | import com.google.codeu.mathlang.core.State; 23 | import com.google.codeu.mathlang.core.tokens.Token; 24 | import com.google.codeu.mathlang.core.Variable; 25 | import com.google.codeu.mathlang.impl.MyTokenReader; 26 | import com.google.codeu.mathlang.parsing.StatementReader; 27 | import com.google.codeu.mathlang.parsing.TokenReader; 28 | import com.google.codeu.mathlang.testing.CallTable; 29 | import com.google.codeu.mathlang.testing.TestLetFunction; 30 | import com.google.codeu.mathlang.testing.TestNoteFunction; 31 | import com.google.codeu.mathlang.testing.TestPrintFunction; 32 | 33 | // TESTER 34 | // 35 | // This class sets up the environment and runs a test. The Tester 36 | // should isolate all failures so that one test does not affect another. 37 | // 38 | // When initializing a tester, a Test Listener must be provided so that 39 | // the tester can signal which tests pass and which tests fail. 40 | public final class Tester { 41 | 42 | private final TestListener listener; 43 | 44 | public Tester(TestListener listener) { 45 | this.listener = listener; 46 | } 47 | 48 | // TEST 49 | // 50 | // Given sample input and a test criteria, run the input through the 51 | // parser and interpeter. Once execution is complete, run the test 52 | // criteria to ensure that the execution met the expectations of the 53 | // test. 54 | public void test(String name, String input, TestCriteria criteria) { 55 | listener.onTestStart(name); 56 | try { 57 | runTest(input, criteria); 58 | listener.onPass(); 59 | } catch (Exception ex) { 60 | listener.onFail(ex); 61 | } 62 | } 63 | 64 | private static void runTest(String input, TestCriteria criteria) throws Exception { 65 | final CallTable callTable = new CallTable(); 66 | 67 | final Map variables = new HashMap<>(); 68 | final State state = new State(); 69 | state.defineFunction("let", new TestLetFunction(variables, callTable)); 70 | state.defineFunction("print", new TestPrintFunction(variables, callTable)); 71 | state.defineFunction("note", new TestNoteFunction(callTable)); 72 | 73 | final TokenReader tr = new MyTokenReader(input); 74 | final StatementReader sr = new StatementReader(tr); 75 | 76 | for (Token[] statement = sr.next(); statement != null; statement = sr.next()) { 77 | state.run(statement); 78 | } 79 | 80 | criteria.onTestEnd(callTable); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/functions/LetFunction.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang.functions; 16 | 17 | import java.util.ArrayList; 18 | import java.util.Collection; 19 | import java.util.Collections; 20 | import java.util.LinkedList; 21 | import java.util.Map; 22 | import java.util.Queue; 23 | 24 | import com.google.codeu.mathlang.core.Function; 25 | import com.google.codeu.mathlang.core.Variable; 26 | import com.google.codeu.mathlang.core.tokens.NameToken; 27 | import com.google.codeu.mathlang.core.tokens.NumberToken; 28 | import com.google.codeu.mathlang.core.tokens.SymbolToken; 29 | import com.google.codeu.mathlang.core.tokens.Token; 30 | import com.google.codeu.mathlang.functions.operations.AddOperation; 31 | import com.google.codeu.mathlang.functions.operations.Operation; 32 | import com.google.codeu.mathlang.functions.operations.SubtractOperation; 33 | 34 | // LET FUNCTION 35 | // 36 | // This function is used to assign values. It expects a syntax similar to the 37 | // following examples: 38 | // let x = 5; 39 | // let y = 3 + 5; 40 | // let z = x + y; 41 | // 42 | // This class is not marked as final so that functions can be overridden in 43 | // the tests. 44 | public class LetFunction implements Function { 45 | 46 | private static final Token EQUAL = new SymbolToken('='); 47 | private static final Token ADD = new SymbolToken('+'); 48 | private static final Token SUBTRACT = new SymbolToken('-'); 49 | private static final Token NEGATIVE = new SymbolToken('-'); 50 | 51 | private final Map variables; 52 | 53 | public LetFunction(Map variables) { 54 | this.variables = variables; 55 | } 56 | 57 | @Override 58 | public void run(Token[] statement) throws Exception { 59 | 60 | final Queue tokens = new LinkedList<>(); 61 | Collections.addAll(tokens, statement); 62 | 63 | tokens.remove(); // the first token is the command name 64 | 65 | if (!(tokens.peek() instanceof NameToken)) { 66 | throw new Exception(String.format("Expecting variable name but found %s", tokens.peek())); 67 | } 68 | 69 | final NameToken targetName = (NameToken) tokens.remove(); 70 | 71 | final Token assignment = tokens.remove(); 72 | if (!EQUAL.equals(assignment)) { 73 | throw new Exception(String.format("Expecting %s but found %s", EQUAL, assignment)); 74 | } 75 | 76 | final Collection operations = new ArrayList<>(); 77 | 78 | operations.add(new AddOperation(readValue(tokens))); 79 | 80 | while (tokens.size() > 0) { 81 | final Token op = tokens.remove(); 82 | if (ADD.equals(op)) { 83 | final double value = readValue(tokens); 84 | operations.add(new AddOperation(value)); 85 | } else if (SUBTRACT.equals(op)) { 86 | final double value = readValue(tokens); 87 | operations.add(new SubtractOperation(value)); 88 | } else { 89 | throw new Exception(String.format("Expecting symbol %s or %s but found %s", ADD, SUBTRACT, op)); 90 | } 91 | } 92 | 93 | final double finalValue = evaluate(operations); 94 | 95 | // Assign the value to the correct variable. If the variable does not exist, create it. 96 | // Do not create variables early, since it would then be readable before it is given a 97 | // value. 98 | if (variables.get(targetName.value) == null) { 99 | variables.put(targetName.value, new Variable()); 100 | } 101 | variables.get(targetName.value).write(finalValue); 102 | } 103 | 104 | // READ VALUE 105 | // 106 | // Read the next value from the top of the Queue. This method needs the queue 107 | // so that it can handle the presence of a negation. 108 | private double readValue(Queue tokens) throws Exception { 109 | double sign = 1.0; 110 | 111 | if (NEGATIVE.equals(tokens.peek())) { 112 | sign = -1.0; 113 | tokens.remove(); 114 | } 115 | 116 | final Token token = tokens.remove(); 117 | double value = 0.0; 118 | if (token instanceof NumberToken) { 119 | final NumberToken number = (NumberToken) token; 120 | value = number.value; 121 | } else if (token instanceof NameToken) { 122 | final NameToken name = (NameToken) token; 123 | final Variable variable = variables.get(name.value); 124 | if (variable == null) { 125 | throw new Exception(String.format( 126 | "Attempting to read value of \"%s\" before assigning value.", 127 | name.value)); 128 | } 129 | value = variable.read(); 130 | } else { 131 | throw new Exception(String.format("Cannot evaluate %s", token)); 132 | } 133 | 134 | return sign * value; 135 | } 136 | 137 | // EVALUATE 138 | // Evaluate a collection of operations, reducing them to a single floating-point 139 | // value. This method is exposed as protected so that it can be overridden 140 | // in our tests. 141 | protected double evaluate(Collection ops) { 142 | double runningValue = 0; 143 | 144 | for (final Operation op : ops) { 145 | runningValue = op.applyTo(runningValue); 146 | } 147 | 148 | return runningValue; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/com/google/codeu/mathlang/Test.java: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.codeu.mathlang; 16 | 17 | import com.google.codeu.mathlang.functions.operations.AddOperation; 18 | import com.google.codeu.mathlang.functions.operations.Operation; 19 | import com.google.codeu.mathlang.functions.operations.SubtractOperation; 20 | import com.google.codeu.mathlang.testing.CallTable; 21 | import com.google.codeu.mathlang.testing.TestCriteria; 22 | import com.google.codeu.mathlang.testing.TestListener; 23 | import com.google.codeu.mathlang.testing.Tester; 24 | 25 | final class Test { 26 | 27 | public static void main(String[] args) { 28 | 29 | final Tester tester = new Tester(new TestListener() { 30 | 31 | @Override 32 | public void onTestStart(String testName) { 33 | System.out.print("RUNNING: "); 34 | System.out.print(testName); 35 | System.out.println(":"); 36 | } 37 | 38 | @Override 39 | public void onPass() { 40 | System.out.println(" PASS"); 41 | } 42 | 43 | @Override 44 | public void onFail(Exception ex) { 45 | System.out.print(" FAIL ("); 46 | System.out.print(ex.toString()); 47 | System.out.println(")"); 48 | } 49 | }); 50 | 51 | tester.test( 52 | "One Comment On One Line", 53 | lines("note \"my comment\";"), 54 | new TestCriteria() { 55 | @Override 56 | public void onTestEnd(CallTable calls) throws Exception { 57 | calls.assertNext("note", "my comment"); 58 | calls.assertEnd(); 59 | } 60 | }); 61 | 62 | tester.test( 63 | "Two Comments One Line No Space", 64 | lines("note \"comment 1\"\"comment 2\";"), 65 | new TestCriteria() { 66 | @Override 67 | public void onTestEnd(CallTable calls) throws Exception { 68 | calls.assertNext("note", "comment 1", "comment 2"); 69 | calls.assertEnd(); 70 | } 71 | }); 72 | 73 | tester.test( 74 | "Two Comments One Line With Space", 75 | lines("note \"comment 1\" \"comment 2\";"), 76 | new TestCriteria() { 77 | @Override 78 | public void onTestEnd(CallTable calls) throws Exception { 79 | calls.assertNext("note", "comment 1", "comment 2"); 80 | calls.assertEnd(); 81 | } 82 | }); 83 | 84 | tester.test( 85 | "Two Comments Two Lines", 86 | lines("note \"comment 1\"", 87 | " \"comment 2\";"), 88 | new TestCriteria() { 89 | @Override 90 | public void onTestEnd(CallTable calls) throws Exception { 91 | calls.assertNext("note", "comment 1", "comment 2"); 92 | calls.assertEnd(); 93 | } 94 | }); 95 | 96 | tester.test( 97 | "Print One String", 98 | lines("print \"hello\";"), 99 | new TestCriteria() { 100 | @Override 101 | public void onTestEnd(CallTable calls) throws Exception { 102 | calls.assertNext("print", "hello"); 103 | calls.assertEnd(); 104 | } 105 | }); 106 | 107 | tester.test( 108 | "Print Two Strings", 109 | lines("print \"hello\" \"world\";"), 110 | new TestCriteria() { 111 | @Override 112 | public void onTestEnd(CallTable calls) throws Exception { 113 | calls.assertNext("print", "hello", "world"); 114 | calls.assertEnd(); 115 | } 116 | }); 117 | 118 | tester.test( 119 | "Print On Different Lines", 120 | lines("print \"hello\";", 121 | "print \"world\";"), 122 | new TestCriteria() { 123 | @Override 124 | public void onTestEnd(CallTable calls) throws Exception { 125 | calls.assertNext("print", "hello"); 126 | calls.assertNext("print", "world"); 127 | calls.assertEnd(); 128 | } 129 | }); 130 | 131 | tester.test( 132 | "Assign variable as constant", 133 | lines("let x = 5;"), 134 | new TestCriteria() { 135 | @Override 136 | public void onTestEnd(CallTable calls) throws Exception { 137 | calls.assertNext("let", new AddOperation(5)); 138 | calls.assertEnd(); 139 | } 140 | }); 141 | 142 | tester.test( 143 | "Adding two constant", 144 | lines("let x = 5 + 3;", 145 | "print x;"), 146 | new TestCriteria() { 147 | @Override 148 | public void onTestEnd(CallTable calls) throws Exception { 149 | calls.assertNext("let", new AddOperation(5), new AddOperation(3)); 150 | calls.assertNext("print", "8.0"); // use print to verify result 151 | calls.assertEnd(); 152 | } 153 | }); 154 | 155 | tester.test( 156 | "Subtract two constant", 157 | lines("let x = 5 - 3;", 158 | "print x;"), 159 | new TestCriteria() { 160 | @Override 161 | public void onTestEnd(CallTable calls) throws Exception { 162 | calls.assertNext("let", new AddOperation(5), new SubtractOperation(3)); 163 | calls.assertNext("print", "2.0"); // use print to verify result 164 | calls.assertEnd(); 165 | } 166 | }); 167 | 168 | tester.test( 169 | "Add two variables", 170 | lines("let x = 5;", 171 | "let y = 3;", 172 | "let z = x + y;", 173 | "print z;"), 174 | new TestCriteria() { 175 | @Override 176 | public void onTestEnd(CallTable calls) throws Exception { 177 | calls.assertNext("let", new AddOperation(5)); 178 | calls.assertNext("let", new AddOperation(3)); 179 | calls.assertNext("let", new AddOperation(5), new AddOperation(3)); 180 | calls.assertNext("print", "8.0"); // use print to verify result 181 | calls.assertEnd(); 182 | } 183 | }); 184 | 185 | tester.test( 186 | "Subtract two variables", 187 | lines("let x = 5;", 188 | "let y = 3;", 189 | "let z = x - y;", 190 | "print z;"), 191 | new TestCriteria() { 192 | @Override 193 | public void onTestEnd(CallTable calls) throws Exception { 194 | calls.assertNext("let", new AddOperation(5)); 195 | calls.assertNext("let", new AddOperation(3)); 196 | calls.assertNext("let", new AddOperation(5), new SubtractOperation(3)); 197 | calls.assertNext("print", "2.0"); // use print to verify result 198 | calls.assertEnd(); 199 | } 200 | }); 201 | 202 | tester.test( 203 | "Add negative constant to variable", 204 | lines("let x = 5;", 205 | "let y = x + -3;", 206 | "print y;"), 207 | new TestCriteria() { 208 | @Override 209 | public void onTestEnd(CallTable calls) throws Exception { 210 | calls.assertNext("let", new AddOperation(5)); 211 | calls.assertNext("let", new AddOperation(5), new AddOperation(-3)); 212 | calls.assertNext("print", "2.0"); // use print to verify result 213 | calls.assertEnd(); 214 | } 215 | }); 216 | 217 | tester.test( 218 | "Math with no spaces", 219 | lines("let x=5+3;", 220 | "print x;"), 221 | new TestCriteria() { 222 | @Override 223 | public void onTestEnd(CallTable calls) throws Exception { 224 | calls.assertNext("let", new AddOperation(5), new AddOperation(3)); 225 | calls.assertNext("print", "8.0"); // use print to verify result 226 | calls.assertEnd(); 227 | } 228 | }); 229 | } 230 | 231 | private static String lines(String... lines) { 232 | 233 | final StringBuilder builder = new StringBuilder(); 234 | 235 | for (final String line : lines) { 236 | builder.append(line).append("\n"); 237 | } 238 | 239 | // Remove the trailing new line before returning. 240 | return builder.substring(0, Math.max(0, builder.length() - 1)); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | --------------------------------------------------------------------------------