├── .gitignore ├── COPYRIGHT ├── LICENSE ├── README.md ├── build.xml ├── cleanup.sh ├── data └── inputs-train │ ├── flex │ └── input0.lex │ ├── grep │ └── tests.txt │ ├── python │ ├── input0.py │ ├── input10.py │ ├── input11.py │ ├── input13.py │ ├── input14.py │ ├── input15.py │ ├── input16.py │ ├── input17.py │ ├── input18.py │ ├── input19.py │ ├── input2.py │ ├── input3.py │ ├── input4.py │ ├── input5.py │ ├── input6.py │ ├── input7.py │ ├── input8.py │ └── input9.py │ ├── python_wrapped │ ├── input0.py │ ├── input1.py │ ├── input10.py │ ├── input11.py │ ├── input12.py │ ├── input13.py │ ├── input14.py │ ├── input15.py │ ├── input16.py │ ├── input17.py │ ├── input18.py │ ├── input19.py │ ├── input2.py │ ├── input20.py │ ├── input3.py │ ├── input4.py │ ├── input5.py │ ├── input6.py │ ├── input7.py │ ├── input8.py │ └── input9.py │ ├── sed │ ├── input0.sed │ ├── input1.sed │ └── input2.sed │ └── xml │ ├── input0.xml │ ├── input1.xml │ ├── input2.xml │ ├── input3.xml │ ├── input4.xml │ ├── input5.xml │ └── input6.xml ├── setup.sh ├── setup_osx.sh ├── src └── glade │ ├── constants │ ├── Files.java │ └── program │ │ ├── FlexData.java │ │ ├── GrepData.java │ │ ├── PythonData.java │ │ ├── PythonWrappedData.java │ │ ├── SedData.java │ │ └── XmlData.java │ ├── grammar │ ├── GrammarSerializer.java │ ├── GrammarUtils.java │ ├── ParseTreeUtils.java │ ├── fuzz │ │ └── GrammarFuzzer.java │ └── synthesize │ │ ├── GrammarSynthesis.java │ │ ├── GrammarTransformer.java │ │ ├── MergesSynthesis.java │ │ └── RegexSynthesis.java │ ├── main │ ├── GrammarDataUtils.java │ ├── Main.java │ ├── ProgramDataUtils.java │ └── Settings.java │ └── util │ ├── CharacterUtils.java │ ├── Log.java │ ├── OracleUtils.java │ ├── ShellUtils.java │ └── Utils.java └── test └── main └── Test.java /.gitignore: -------------------------------------------------------------------------------- 1 | prog-query 2 | glade.jar 3 | data/prog 4 | data/grammars 5 | log.txt 6 | *.class 7 | classes -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright 2015-2016 Stanford University 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. -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GLADE 2 | ===== 3 | 4 | GLADE is a tool for automatically synthesizing program input grammars, i.e., a context-free grammar encoding the language of valid inputs for a target program. GLADE requires two inputs: (i) an query oracle that responds whether a given input is valid for the target program, and (ii) a set of examples of valid inputs, known as seed inputs. From these inputs, GLADE produces a grammar that can be sampled to produce new program inputs. 5 | 6 | For a detailed introduction to GLADE, see: 7 | 8 | - [**Synthesizing Program Input Grammars**](http://arxiv.org/abs/1608.01723) 9 | 10 | **Note:** GLADE is no longer actively developed. Consider using this unofficial fork of GLADE: https://github.com/kuhy/glade 11 | 12 | Table of Contents 13 | ===== 14 | 0. Prerequisites 15 | 1. Downloading and Building GLADE 16 | 2. Running GLADE 17 | 3. Using GLADE as a Library 18 | 5. Notes 19 | 6. Contact 20 | 21 | Prerequisites 22 | ===== 23 | 24 | GLADE has been tested on Ubuntu 64-bit 16.04.1 and on Mac OS X 10.9.5, but should work on typical Linux installations. GLADE requires Java 1.7 or above, and building GLADE requires Apache Ant. The build process has specifically been tested on OpenJDK version 1.8.0_91 and Apache Ant version 1.9.7. The example programs that come with GLADE should be self contained, except flex requires GNU M4, which on Ubuntu can be installed using 25 | 26 | $ sudo apt-get install m4 27 | 28 | GLADE can be built without GNU M4, but running the flex example will fail (the remaining programs should run without issue). 29 | 30 | Downloading and Building GLADE 31 | ===== 32 | 33 | The GLADE source code is available on GitHub under the Apache Software License version 2.0 at https://github.com/obastani/glade. To check out the GLADE source code repository, run: 34 | 35 | $ git clone https://github.com/obastani/glade.git 36 | 37 | To build GLADE, run: 38 | 39 | $ cd glade 40 | $ ant 41 | 42 | Doing so should produce a jar file named `glade.jar`. 43 | 44 | The GLADE code is currently set up to synthesize grammars for the following programs: GNU sed, GNU grep, flex, xml, and the standard Python interpreter. To set up the example programs that come with GLADE on Ubuntu, run: 45 | 46 | $ ./setup.sh 47 | 48 | This command should work for typical Linux distributions. If setting up GLADE on Mac OS X, instead run 49 | 50 | $ ./setup_osx.sh 51 | 52 | To test that the build script and the setup script ran as expected, run: 53 | 54 | $ java -jar glade.jar -mode test -verbose 55 | 56 | Additionally, to run the tests for a specific program provided with GLADE, run: 57 | 58 | $ java -jar glade.jar -mode test -program -verbose 59 | 60 | The available values of `` are `sed`, `grep`, `flex`, `xml`, `python`, and `python-wrapped`. The last option synthesizes a grammar specifically for the Python parser, by wrapping the input (say, ``) in an `if False` block: 61 | 62 | $ if False: 63 | $ 64 | 65 | Logging information is printed to `log.txt`. Additional options are `-log `, which prints logging information to the file with the given filename, and `-verbose`, which prints logging information to `stdout`. For example, running: 66 | 67 | $ java -jar glade.jar -mode test -log out.txt 68 | 69 | runs the tests for all provided programs, and prints logging information both to `out.txt` (but not to `stdout`). 70 | 71 | To uninstall GLADE, run: 72 | 73 | $ ant clean 74 | 75 | To uninstall the example programs that come with GLADE, run: 76 | 77 | $ ./cleanup.sh 78 | 79 | Running GLADE 80 | ===== 81 | 82 | To synthesize a grammar for an example program using GLADE, run: 83 | 84 | $ java -jar glade.jar -mode learn -program 85 | 86 | The `-log` and `-verbose` options work as for running tests. For example, running: 87 | 88 | $ java -jar glade.jar -mode learn -program sed -log out_learn.txt -verbose 89 | 90 | synthesizes a grammar for GNU sed, and prints logging information to `out_learn.txt` and to `stdout`. 91 | 92 | The seed inputs given to GLADE as examples for each of these programs are stored in `data/inputs-train//`. Learned grammars are stored (in serialized form, not human readable) in the folder `data/grammars//`. A grammar is generated for each seed input, as well as a grammar `all.gram` learned from all seed inputs. 93 | 94 | Once a grammar has been synthesized for a program (in particular, a file `data/grammars//all.gram` has been generated), it can be used to randomly generate new inputs by running: 95 | 96 | $ java -jar glade.jar -mode fuzz -program -fuzzer 97 | 98 | The two fuzzers `` available are `grammar` (the grammar-based fuzzer), which only generates inputs in the synthesized grammar, and `combined` (the combined fuzzer), which generates a combination of inputs in the synthesized grammar and purposely invalid inputs. GLADE prints 10 sample inputs to the log as well as the overall pass rate (i.e., the fraction of the 10 sample inputs that are valid). For example, running: 99 | 100 | $ java -jar glade.jar -mode fuzz -program sed -fuzzer grammar -log out_fuzz.txt -verbose 101 | 102 | runs the grammar-based fuzzer on the grammar learned for GNU sed, and prints logging information to `out_fuzz.txt` and `stdout`. 103 | 104 | Using GLADE as a Library 105 | ===== 106 | 107 | We have provided a simple Java program that uses GLADE to synthesize a grammar and then generate random samples. The program is located at `test/main/Test.java`. To compile this test program, run: 108 | 109 | $ javac -classpath test:glade.jar test/main/Test.java 110 | 111 | To run the compiled test program, run: 112 | 113 | $ java -classpath test:glade.jar main.Test 114 | 115 | To clean the test, run: 116 | 117 | $ rm test/main/Test.class 118 | 119 | The test program uses GLADE to synthesize a grammar encoding a matching parentheses language, with three kinds of parentheses: `()`, `[]`, and `{}`. Then, it uses the synthesized grammar to generate 10 random samples. Finally, it computes and prints the pass rate, which is the fraction of samples that are contained in the true matching parentheses language. The pass rate should be 1.0. 120 | 121 | There are two key inputs to GLADE's grammar synthesis algorithm: 122 | 123 | **Query oracle:** The query oracle is an instance of a class implementing the interface `glade.util.OracleUtils.DiscriminativeOracle`, which specifies a single method 124 | 125 | $ boolean query(String query) 126 | 127 | This method should return true if the string `query` is contained in the target language, and false otherwise. Our test program uses the following oracle: 128 | 129 | $ DiscriminativeOracle oracle = new TestOracle(); 130 | 131 | The implementation of `TestOracle` is in `test/main/Test.java` (lines 31-56). 132 | 133 | **Examples:** The examples are a list of strings contained in the target language. 134 | 135 | $ List examples = Arrays.asList(new String[]{"{([][])([][])}{[()()][()()]}"}); 136 | 137 | Then, the following code calls the grammar synthesis algorithm: 138 | 139 | $ Grammar grammar = GrammarSynthesis.getGrammarMultiple(examples, oracle); 140 | 141 | Now, we can use GLADE to generate samples from `grammar`. The following code creates an `Iterable` that returns random samples from `grammar`: 142 | 143 | $ Iterable samples = new GrammarMutationSampler(grammar, sampleParams, maxLen, numMut, new Random()); 144 | 145 | The parameter `maxLen` (set to 1000 in the test program) bounds the maximum length of a sample. The parameter `numMut` (set to 20 in the test program) is the number of random mutations made to obtain a random sample. The parameter `sampleParams` are the probabilities of expanding different terms in the grammar; the defaults used in the test program should work well for most applications. 146 | 147 | Notes 148 | ===== 149 | 150 | - Flex, sed, grep, and xml inputs are primarily obtained from the respective distributions. 151 | - Python inputs are obtained from https://wiki.python.org/moin/SimplePrograms. 152 | 153 | Contact 154 | ===== 155 | 156 | For questions, feel free to contact `obastani@cs.stanford.edu`. 157 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2015-2016 Stanford University 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 | rm -rf prog-query 18 | -------------------------------------------------------------------------------- /data/inputs-train/flex/input0.lex: -------------------------------------------------------------------------------- 1 | DIGIT [0-9] 2 | 3 | %% 4 | 5 | xyz{DIGIT} { 6 | abc 7 | } 8 | 9 | (abc)xyz[abc] { 10 | xyz 11 | } 12 | 13 | %% 14 | 15 | abc 16 | 17 | -------------------------------------------------------------------------------- /data/inputs-train/grep/tests.txt: -------------------------------------------------------------------------------- 1 | ab 2 | ab[cde]fg 3 | ab\(cde\)fg 4 | ab\xcd 5 | -------------------------------------------------------------------------------- /data/inputs-train/python/input0.py: -------------------------------------------------------------------------------- 1 | print 'Hello, world!' 2 | -------------------------------------------------------------------------------- /data/inputs-train/python/input10.py: -------------------------------------------------------------------------------- 1 | REFRAIN = ''' 2 | %d bottles of beer on the wall, 3 | %d bottles of beer, 4 | take one down, pass it around, 5 | %d bottles of beer on the wall! 6 | ''' 7 | bottles_of_beer = 99 8 | while bottles_of_beer > 1: 9 | print REFRAIN % (bottles_of_beer, bottles_of_beer, 10 | bottles_of_beer - 1) 11 | bottles_of_beer -= 1 12 | -------------------------------------------------------------------------------- /data/inputs-train/python/input11.py: -------------------------------------------------------------------------------- 1 | class BankAccount(object): 2 | def __init__(self, initial_balance=0): 3 | self.balance = initial_balance 4 | def deposit(self, amount): 5 | self.balance += amount 6 | def withdraw(self, amount): 7 | self.balance -= amount 8 | def overdrawn(self): 9 | return self.balance < 0 10 | my_account = BankAccount(15) 11 | my_account.withdraw(5) 12 | print my_account.balance 13 | -------------------------------------------------------------------------------- /data/inputs-train/python/input13.py: -------------------------------------------------------------------------------- 1 | def median(pool): 2 | '''Statistical median to demonstrate doctest. 3 | >>> median([2, 9, 9, 7, 9, 2, 4, 5, 8]) 4 | 7 5 | ''' 6 | copy = sorted(pool) 7 | size = len(copy) 8 | if size % 2 == 1: 9 | return copy[(size - 1) / 2] 10 | else: 11 | return (copy[size/2 - 1] + copy[size/2]) / 2 12 | if __name__ == '__main__': 13 | import doctest 14 | doctest.testmod() 15 | -------------------------------------------------------------------------------- /data/inputs-train/python/input14.py: -------------------------------------------------------------------------------- 1 | from itertools import groupby 2 | lines = ''' 3 | This is the 4 | first paragraph. 5 | 6 | This is the second. 7 | '''.splitlines() 8 | # Use itertools.groupby and bool to return groups of 9 | # consecutive lines that either have content or don't. 10 | for has_chars, frags in groupby(lines, bool): 11 | if has_chars: 12 | print ' '.join(frags) 13 | # PRINTS: 14 | # This is the first paragraph. 15 | # This is the second. 16 | -------------------------------------------------------------------------------- /data/inputs-train/python/input15.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | # write stocks data as comma-separated values 4 | writer = csv.writer(open('stocks.csv', 'wb', buffering=0)) 5 | writer.writerows([ 6 | ('GOOG', 'Google, Inc.', 505.24, 0.47, 0.09), 7 | ('YHOO', 'Yahoo! Inc.', 27.38, 0.33, 1.22), 8 | ('CNET', 'CNET Networks, Inc.', 8.62, -0.13, -1.49) 9 | ]) 10 | 11 | # read stocks data, print status messages 12 | stocks = csv.reader(open('stocks.csv', 'rb')) 13 | status_labels = {-1: 'down', 0: 'unchanged', 1: 'up'} 14 | for ticker, name, price, change, pct in stocks: 15 | status = status_labels[cmp(float(change), 0.0)] 16 | print '%s is %s (%s%%)' % (name, status, pct) 17 | -------------------------------------------------------------------------------- /data/inputs-train/python/input16.py: -------------------------------------------------------------------------------- 1 | BOARD_SIZE = 8 2 | 3 | def under_attack(col, queens): 4 | left = right = col 5 | 6 | for r, c in reversed(queens): 7 | left, right = left - 1, right + 1 8 | 9 | if c in (left, col, right): 10 | return True 11 | return False 12 | 13 | def solve(n): 14 | if n == 0: 15 | return [[]] 16 | 17 | smaller_solutions = solve(n - 1) 18 | 19 | return [solution+[(n,i+1)] 20 | for i in xrange(BOARD_SIZE) 21 | for solution in smaller_solutions 22 | if not under_attack(i+1, solution)] 23 | for answer in solve(BOARD_SIZE): 24 | print answer 25 | -------------------------------------------------------------------------------- /data/inputs-train/python/input17.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | 3 | def iter_primes(): 4 | # an iterator of all numbers between 2 and +infinity 5 | numbers = itertools.count(2) 6 | 7 | # generate primes forever 8 | while True: 9 | # get the first number from the iterator (always a prime) 10 | prime = numbers.next() 11 | yield prime 12 | 13 | # this code iteratively builds up a chain of 14 | # filters...slightly tricky, but ponder it a bit 15 | numbers = itertools.ifilter(prime.__rmod__, numbers) 16 | 17 | for p in iter_primes(): 18 | if p > 1000: 19 | break 20 | print p 21 | -------------------------------------------------------------------------------- /data/inputs-train/python/input18.py: -------------------------------------------------------------------------------- 1 | dinner_recipe = ''' 2 | 3 | 4 | 5 | 6 | 7 |
amtunititem
24slicesbaguette
2+tbspolive oil
1cuptomatoes
1jarpesto
''' 8 | 9 | # In Python 2.5 or from http://effbot.org/zone/element-index.htm 10 | import xml.etree.ElementTree as etree 11 | tree = etree.fromstring(dinner_recipe) 12 | 13 | # For invalid HTML use http://effbot.org/zone/element-soup.htm 14 | # import ElementSoup, StringIO 15 | # tree = ElementSoup.parse(StringIO.StringIO(dinner_recipe)) 16 | 17 | pantry = set(['olive oil', 'pesto']) 18 | for ingredient in tree.getiterator('tr'): 19 | amt, unit, item = ingredient 20 | if item.tag == "td" and item.text not in pantry: 21 | print "%s: %s %s" % (item.text, amt.text, unit.text) 22 | -------------------------------------------------------------------------------- /data/inputs-train/python/input19.py: -------------------------------------------------------------------------------- 1 | BOARD_SIZE = 8 2 | 3 | class BailOut(Exception): 4 | pass 5 | 6 | def validate(queens): 7 | left = right = col = queens[-1] 8 | for r in reversed(queens[:-1]): 9 | left, right = left-1, right+1 10 | if r in (left, col, right): 11 | raise BailOut 12 | 13 | def add_queen(queens): 14 | for i in range(BOARD_SIZE): 15 | test_queens = queens + [i] 16 | try: 17 | validate(test_queens) 18 | if len(test_queens) == BOARD_SIZE: 19 | return test_queens 20 | else: 21 | return add_queen(test_queens) 22 | except BailOut: 23 | pass 24 | raise BailOut 25 | 26 | queens = add_queen([]) 27 | print queens 28 | print "\n".join(". "*q + "Q " + ". "*(BOARD_SIZE-q-1) for q in queens) 29 | -------------------------------------------------------------------------------- /data/inputs-train/python/input2.py: -------------------------------------------------------------------------------- 1 | friends = ['john', 'pat', 'gary', 'michael'] 2 | for i, name in enumerate(friends): 3 | print "iteration {iteration} is {name}".format(iteration=i, name=name) 4 | -------------------------------------------------------------------------------- /data/inputs-train/python/input3.py: -------------------------------------------------------------------------------- 1 | parents, babies = (1, 1) 2 | while babies < 100: 3 | print 'This generation has {0} babies'.format(babies) 4 | parents, babies = (babies, parents + babies) 5 | -------------------------------------------------------------------------------- /data/inputs-train/python/input4.py: -------------------------------------------------------------------------------- 1 | def greet(name): 2 | print 'Hello', name 3 | greet('Jack') 4 | greet('Jill') 5 | greet('Bob') 6 | -------------------------------------------------------------------------------- /data/inputs-train/python/input5.py: -------------------------------------------------------------------------------- 1 | import re 2 | for test_string in ['555-1212', 'ILL-EGAL']: 3 | if re.match(r'^\d{3}-\d{4}$', test_string): 4 | print test_string, 'is a valid US local phone number' 5 | else: 6 | print test_string, 'rejected' 7 | -------------------------------------------------------------------------------- /data/inputs-train/python/input6.py: -------------------------------------------------------------------------------- 1 | prices = {'apple': 0.40, 'banana': 0.50} 2 | my_purchase = { 3 | 'apple': 1, 4 | 'banana': 6} 5 | grocery_bill = sum(prices[fruit] * my_purchase[fruit] 6 | for fruit in my_purchase) 7 | print 'I owe the grocer $%.2f' % grocery_bill 8 | -------------------------------------------------------------------------------- /data/inputs-train/python/input7.py: -------------------------------------------------------------------------------- 1 | # This program adds up integers in the command line 2 | import sys 3 | try: 4 | total = sum(int(arg) for arg in sys.argv[1:]) 5 | print 'sum =', total 6 | except ValueError: 7 | print 'Please supply integer arguments' 8 | -------------------------------------------------------------------------------- /data/inputs-train/python/input8.py: -------------------------------------------------------------------------------- 1 | # indent your Python code to put into an email 2 | import glob 3 | # glob supports Unix style pathname extensions 4 | python_files = glob.glob('*.py') 5 | for file_name in sorted(python_files): 6 | print ' ------' + file_name 7 | 8 | with open(file_name) as f: 9 | for line in f: 10 | print ' ' + line.rstrip() 11 | 12 | print 13 | -------------------------------------------------------------------------------- /data/inputs-train/python/input9.py: -------------------------------------------------------------------------------- 1 | from time import localtime 2 | 3 | activities = {8: 'Sleeping', 4 | 9: 'Commuting', 5 | 17: 'Working', 6 | 18: 'Commuting', 7 | 20: 'Eating', 8 | 22: 'Resting' } 9 | 10 | time_now = localtime() 11 | hour = time_now.tm_hour 12 | 13 | for activity_time in sorted(activities.keys()): 14 | if hour < activity_time: 15 | print activities[activity_time] 16 | break 17 | else: 18 | print 'Unknown, AFK or sleeping!' 19 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input0.py: -------------------------------------------------------------------------------- 1 | print 'Hello, world!' 2 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input1.py: -------------------------------------------------------------------------------- 1 | name = raw_input('What is your name?\n') 2 | print 'Hi, %s.' % name 3 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input10.py: -------------------------------------------------------------------------------- 1 | REFRAIN = ''' 2 | %d bottles of beer on the wall, 3 | %d bottles of beer, 4 | take one down, pass it around, 5 | %d bottles of beer on the wall! 6 | ''' 7 | bottles_of_beer = 99 8 | while bottles_of_beer > 1: 9 | print REFRAIN % (bottles_of_beer, bottles_of_beer, 10 | bottles_of_beer - 1) 11 | bottles_of_beer -= 1 12 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input11.py: -------------------------------------------------------------------------------- 1 | class BankAccount(object): 2 | def __init__(self, initial_balance=0): 3 | self.balance = initial_balance 4 | def deposit(self, amount): 5 | self.balance += amount 6 | def withdraw(self, amount): 7 | self.balance -= amount 8 | def overdrawn(self): 9 | return self.balance < 0 10 | my_account = BankAccount(15) 11 | my_account.withdraw(5) 12 | print my_account.balance 13 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input12.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | def median(pool): 3 | copy = sorted(pool) 4 | size = len(copy) 5 | if size % 2 == 1: 6 | return copy[(size - 1) / 2] 7 | else: 8 | return (copy[size/2 - 1] + copy[size/2]) / 2 9 | class TestMedian(unittest.TestCase): 10 | def testMedian(self): 11 | self.failUnlessEqual(median([2, 9, 9, 7, 9, 2, 4, 5, 8]), 7) 12 | if __name__ == '__main__': 13 | unittest.main() 14 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input13.py: -------------------------------------------------------------------------------- 1 | def median(pool): 2 | '''Statistical median to demonstrate doctest. 3 | >>> median([2, 9, 9, 7, 9, 2, 4, 5, 8]) 4 | 7 5 | ''' 6 | copy = sorted(pool) 7 | size = len(copy) 8 | if size % 2 == 1: 9 | return copy[(size - 1) / 2] 10 | else: 11 | return (copy[size/2 - 1] + copy[size/2]) / 2 12 | if __name__ == '__main__': 13 | import doctest 14 | doctest.testmod() 15 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input14.py: -------------------------------------------------------------------------------- 1 | from itertools import groupby 2 | lines = ''' 3 | This is the 4 | first paragraph. 5 | 6 | This is the second. 7 | '''.splitlines() 8 | # Use itertools.groupby and bool to return groups of 9 | # consecutive lines that either have content or don't. 10 | for has_chars, frags in groupby(lines, bool): 11 | if has_chars: 12 | print ' '.join(frags) 13 | # PRINTS: 14 | # This is the first paragraph. 15 | # This is the second. 16 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input15.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | # write stocks data as comma-separated values 4 | writer = csv.writer(open('stocks.csv', 'wb', buffering=0)) 5 | writer.writerows([ 6 | ('GOOG', 'Google, Inc.', 505.24, 0.47, 0.09), 7 | ('YHOO', 'Yahoo! Inc.', 27.38, 0.33, 1.22), 8 | ('CNET', 'CNET Networks, Inc.', 8.62, -0.13, -1.49) 9 | ]) 10 | 11 | # read stocks data, print status messages 12 | stocks = csv.reader(open('stocks.csv', 'rb')) 13 | status_labels = {-1: 'down', 0: 'unchanged', 1: 'up'} 14 | for ticker, name, price, change, pct in stocks: 15 | status = status_labels[cmp(float(change), 0.0)] 16 | print '%s is %s (%s%%)' % (name, status, pct) 17 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input16.py: -------------------------------------------------------------------------------- 1 | BOARD_SIZE = 8 2 | 3 | def under_attack(col, queens): 4 | left = right = col 5 | 6 | for r, c in reversed(queens): 7 | left, right = left - 1, right + 1 8 | 9 | if c in (left, col, right): 10 | return True 11 | return False 12 | 13 | def solve(n): 14 | if n == 0: 15 | return [[]] 16 | 17 | smaller_solutions = solve(n - 1) 18 | 19 | return [solution+[(n,i+1)] 20 | for i in xrange(BOARD_SIZE) 21 | for solution in smaller_solutions 22 | if not under_attack(i+1, solution)] 23 | for answer in solve(BOARD_SIZE): 24 | print answer 25 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input17.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | 3 | def iter_primes(): 4 | # an iterator of all numbers between 2 and +infinity 5 | numbers = itertools.count(2) 6 | 7 | # generate primes forever 8 | while True: 9 | # get the first number from the iterator (always a prime) 10 | prime = numbers.next() 11 | yield prime 12 | 13 | # this code iteratively builds up a chain of 14 | # filters...slightly tricky, but ponder it a bit 15 | numbers = itertools.ifilter(prime.__rmod__, numbers) 16 | 17 | for p in iter_primes(): 18 | if p > 1000: 19 | break 20 | print p 21 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input18.py: -------------------------------------------------------------------------------- 1 | dinner_recipe = ''' 2 | 3 | 4 | 5 | 6 | 7 |
amtunititem
24slicesbaguette
2+tbspolive oil
1cuptomatoes
1jarpesto
''' 8 | 9 | # In Python 2.5 or from http://effbot.org/zone/element-index.htm 10 | import xml.etree.ElementTree as etree 11 | tree = etree.fromstring(dinner_recipe) 12 | 13 | # For invalid HTML use http://effbot.org/zone/element-soup.htm 14 | # import ElementSoup, StringIO 15 | # tree = ElementSoup.parse(StringIO.StringIO(dinner_recipe)) 16 | 17 | pantry = set(['olive oil', 'pesto']) 18 | for ingredient in tree.getiterator('tr'): 19 | amt, unit, item = ingredient 20 | if item.tag == "td" and item.text not in pantry: 21 | print "%s: %s %s" % (item.text, amt.text, unit.text) 22 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input19.py: -------------------------------------------------------------------------------- 1 | BOARD_SIZE = 8 2 | 3 | class BailOut(Exception): 4 | pass 5 | 6 | def validate(queens): 7 | left = right = col = queens[-1] 8 | for r in reversed(queens[:-1]): 9 | left, right = left-1, right+1 10 | if r in (left, col, right): 11 | raise BailOut 12 | 13 | def add_queen(queens): 14 | for i in range(BOARD_SIZE): 15 | test_queens = queens + [i] 16 | try: 17 | validate(test_queens) 18 | if len(test_queens) == BOARD_SIZE: 19 | return test_queens 20 | else: 21 | return add_queen(test_queens) 22 | except BailOut: 23 | pass 24 | raise BailOut 25 | 26 | queens = add_queen([]) 27 | print queens 28 | print "\n".join(". "*q + "Q " + ". "*(BOARD_SIZE-q-1) for q in queens) 29 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input2.py: -------------------------------------------------------------------------------- 1 | friends = ['john', 'pat', 'gary', 'michael'] 2 | for i, name in enumerate(friends): 3 | print "iteration {iteration} is {name}".format(iteration=i, name=name) 4 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input20.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | guesses_made = 0 4 | 5 | name = raw_input('Hello! What is your name?\n') 6 | 7 | number = random.randint(1, 20) 8 | print 'Well, {0}, I am thinking of a number between 1 and 20.'.format(name) 9 | 10 | while guesses_made < 6: 11 | 12 | guess = int(raw_input('Take a guess: ')) 13 | 14 | guesses_made += 1 15 | 16 | if guess < number: 17 | print 'Your guess is too low.' 18 | 19 | if guess > number: 20 | print 'Your guess is too high.' 21 | 22 | if guess == number: 23 | break 24 | 25 | if guess == number: 26 | print 'Good job, {0}! You guessed my number in {1} guesses!'.format(name, guesses_made) 27 | else: 28 | print 'Nope. The number I was thinking of was {0}'.format(number) 29 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input3.py: -------------------------------------------------------------------------------- 1 | parents, babies = (1, 1) 2 | while babies < 100: 3 | print 'This generation has {0} babies'.format(babies) 4 | parents, babies = (babies, parents + babies) 5 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input4.py: -------------------------------------------------------------------------------- 1 | def greet(name): 2 | print 'Hello', name 3 | greet('Jack') 4 | greet('Jill') 5 | greet('Bob') 6 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input5.py: -------------------------------------------------------------------------------- 1 | import re 2 | for test_string in ['555-1212', 'ILL-EGAL']: 3 | if re.match(r'^\d{3}-\d{4}$', test_string): 4 | print test_string, 'is a valid US local phone number' 5 | else: 6 | print test_string, 'rejected' 7 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input6.py: -------------------------------------------------------------------------------- 1 | prices = {'apple': 0.40, 'banana': 0.50} 2 | my_purchase = { 3 | 'apple': 1, 4 | 'banana': 6} 5 | grocery_bill = sum(prices[fruit] * my_purchase[fruit] 6 | for fruit in my_purchase) 7 | print 'I owe the grocer $%.2f' % grocery_bill 8 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input7.py: -------------------------------------------------------------------------------- 1 | # This program adds up integers in the command line 2 | import sys 3 | try: 4 | total = sum(int(arg) for arg in sys.argv[1:]) 5 | print 'sum =', total 6 | except ValueError: 7 | print 'Please supply integer arguments' 8 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input8.py: -------------------------------------------------------------------------------- 1 | # indent your Python code to put into an email 2 | import glob 3 | # glob supports Unix style pathname extensions 4 | python_files = glob.glob('*.py') 5 | for file_name in sorted(python_files): 6 | print ' ------' + file_name 7 | 8 | with open(file_name) as f: 9 | for line in f: 10 | print ' ' + line.rstrip() 11 | 12 | print 13 | -------------------------------------------------------------------------------- /data/inputs-train/python_wrapped/input9.py: -------------------------------------------------------------------------------- 1 | from time import localtime 2 | 3 | activities = {8: 'Sleeping', 4 | 9: 'Commuting', 5 | 17: 'Working', 6 | 18: 'Commuting', 7 | 20: 'Eating', 8 | 22: 'Resting' } 9 | 10 | time_now = localtime() 11 | hour = time_now.tm_hour 12 | 13 | for activity_time in sorted(activities.keys()): 14 | if hour < activity_time: 15 | print activities[activity_time] 16 | break 17 | else: 18 | print 'Unknown, AFK or sleeping!' 19 | -------------------------------------------------------------------------------- /data/inputs-train/sed/input0.sed: -------------------------------------------------------------------------------- 1 | s/abcd/bc/p 2 | -------------------------------------------------------------------------------- /data/inputs-train/sed/input1.sed: -------------------------------------------------------------------------------- 1 | s/a[bc]d/bc/p 2 | -------------------------------------------------------------------------------- /data/inputs-train/sed/input2.sed: -------------------------------------------------------------------------------- 1 | s/a\(bc\)d/ab\1cd/p 2 | -------------------------------------------------------------------------------- /data/inputs-train/xml/input0.xml: -------------------------------------------------------------------------------- 1 | xyxyxyxyxy 2 | -------------------------------------------------------------------------------- /data/inputs-train/xml/input1.xml: -------------------------------------------------------------------------------- 1 | xyxy 2 | -------------------------------------------------------------------------------- /data/inputs-train/xml/input2.xml: -------------------------------------------------------------------------------- 1 | xyxy 2 | -------------------------------------------------------------------------------- /data/inputs-train/xml/input3.xml: -------------------------------------------------------------------------------- 1 | xyxy 2 | -------------------------------------------------------------------------------- /data/inputs-train/xml/input4.xml: -------------------------------------------------------------------------------- 1 | xyxy 2 | -------------------------------------------------------------------------------- /data/inputs-train/xml/input5.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /data/inputs-train/xml/input6.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2015-2016 Stanford University 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 up folders 18 | DIR="$(pwd)" 19 | mkdir prog-query 20 | cd prog-query 21 | 22 | # sed 23 | mkdir sed 24 | cd sed 25 | curl ftp://ftp.gnu.org/gnu/sed/sed-4.2.2.tar.gz > sed-4.2.2.tar.gz 26 | tar xf sed-4.2.2.tar.gz 27 | cd sed-4.2.2 28 | ./configure 29 | make 30 | cd $DIR/prog-query 31 | 32 | # grep 33 | mkdir grep 34 | cd grep 35 | curl ftp://ftp.gnu.org/gnu/grep/grep-2.23.tar.xz > grep-2.23.tar.xz 36 | tar xf grep-2.23.tar.xz 37 | cd grep-2.23 38 | ./configure 39 | make 40 | cd $DIR/prog-query 41 | 42 | # flex 43 | mkdir flex 44 | cd flex 45 | # curl doesn't work here 46 | wget https://sourceforge.net/projects/flex/files/flex-2.6.0.tar.gz 47 | tar xf flex-2.6.0.tar.gz 48 | cd flex-2.6.0 49 | ./configure 50 | make 51 | cd $DIR/prog-query 52 | 53 | # xml 54 | mkdir xml 55 | cd xml 56 | curl ftp://xmlsoft.org/libxml2/libxml2-2.9.2.tar.gz > libxml2-2.9.2.tar.gz 57 | tar xf libxml2-2.9.2.tar.gz 58 | cd libxml2-2.9.2 59 | ./configure 60 | make 61 | cd $DIR/prog-query 62 | 63 | # python 64 | mkdir python 65 | cd python 66 | curl https://www.python.org/ftp/python/2.7.10/Python-2.7.10.tgz > Python-2.7.10.tgz 67 | tar xf Python-2.7.10.tgz 68 | cd Python-2.7.10 69 | ./configure 70 | make 71 | cd $DIR/prog-query 72 | 73 | # end in root directory 74 | cd $DIR 75 | -------------------------------------------------------------------------------- /setup_osx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2015-2016 Stanford University 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 up folders 18 | DIR="$(pwd)" 19 | mkdir prog-query 20 | cd prog-query 21 | 22 | # sed 23 | mkdir sed 24 | cd sed 25 | curl ftp://ftp.gnu.org/gnu/sed/sed-4.2.2.tar.gz > sed-4.2.2.tar.gz 26 | tar xf sed-4.2.2.tar.gz 27 | cd sed-4.2.2 28 | ./configure 29 | make 30 | cd $DIR/prog-query 31 | 32 | # grep 33 | mkdir grep 34 | cd grep 35 | curl ftp://ftp.gnu.org/gnu/grep/grep-2.23.tar.xz > grep-2.23.tar.xz 36 | tar xf grep-2.23.tar.xz 37 | cd grep-2.23 38 | ./configure 39 | make 40 | cd $DIR/prog-query 41 | 42 | # flex 43 | mkdir flex 44 | cd flex 45 | # curl doesn't work here 46 | wget https://sourceforge.net/projects/flex/files/flex-2.6.0.tar.gz 47 | tar xf flex-2.6.0.tar.gz 48 | cd flex-2.6.0 49 | ./configure 50 | make 51 | cd $DIR/prog-query 52 | 53 | # xml 54 | mkdir xml 55 | cd xml 56 | curl ftp://xmlsoft.org/libxml2/libxml2-2.9.2.tar.gz > libxml2-2.9.2.tar.gz 57 | tar xf libxml2-2.9.2.tar.gz 58 | cd libxml2-2.9.2 59 | ./configure 60 | make 61 | cd $DIR/prog-query 62 | 63 | # python 64 | mkdir python 65 | cd python 66 | curl https://www.python.org/ftp/python/2.7.10/Python-2.7.10.tgz > Python-2.7.10.tgz 67 | tar xf Python-2.7.10.tgz 68 | cd Python-2.7.10 69 | ./configure 70 | make 71 | # hack for Mac OS X 72 | mv python python_ 73 | mv python.exe python 74 | # end hack 75 | cd $DIR/prog-query 76 | 77 | # end in root directory 78 | cd $DIR 79 | -------------------------------------------------------------------------------- /src/glade/constants/Files.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.constants; 16 | 17 | import glade.main.ProgramDataUtils.FileParameters; 18 | 19 | public class Files { 20 | public static final String QUERY_PROG = "prog-query"; 21 | 22 | public static final String FILENAME = "seed"; 23 | public static final String AUX_FILENAME = "aux_seed"; 24 | public static final long TIMEOUT = 400; 25 | 26 | public static final String EXAMPLE_TRAIN_PATH = "data/inputs-train"; 27 | public static final String GRAMMAR_PATH = "data/grammars"; 28 | 29 | public static final FileParameters FILE_PARAMETERS = new FileParameters(QUERY_PROG, FILENAME, AUX_FILENAME, TIMEOUT, EXAMPLE_TRAIN_PATH); 30 | } 31 | -------------------------------------------------------------------------------- /src/glade/constants/program/FlexData.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.constants.program; 16 | 17 | import glade.constants.Files; 18 | import glade.main.ProgramDataUtils.MultiFileProgramExamples; 19 | import glade.main.ProgramDataUtils.ProgramData; 20 | import glade.main.ProgramDataUtils.ProgramExamples; 21 | import glade.main.ProgramDataUtils.ShellProgramData; 22 | import glade.util.OracleUtils.IdentityWrapper; 23 | 24 | public class FlexData { 25 | public static final String FLEX_EXE = "flex/flex-2.6.0/src/flex"; 26 | public static final boolean FLEX_IS_ERROR = true; 27 | 28 | public static final String FLEX_EXTENSION = ".lex"; 29 | public static final String FLEX_EMPTY = "%%\n%%"; 30 | 31 | public static final String FLEX_NAME = "flex"; 32 | public static final ProgramData FLEX_DATA = new ShellProgramData(Files.FILE_PARAMETERS, FLEX_EXE, FLEX_IS_ERROR); 33 | public static final ProgramExamples FLEX_EXAMPLES = new MultiFileProgramExamples(Files.FILE_PARAMETERS, FLEX_NAME, FLEX_EXTENSION, FLEX_EMPTY, new IdentityWrapper()); 34 | } 35 | -------------------------------------------------------------------------------- /src/glade/constants/program/GrepData.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.constants.program; 16 | 17 | import glade.constants.Files; 18 | import glade.main.ProgramDataUtils.ProgramData; 19 | import glade.main.ProgramDataUtils.ProgramExamples; 20 | import glade.main.ProgramDataUtils.ShellProgramData; 21 | import glade.main.ProgramDataUtils.SingleFileProgramExamples; 22 | import glade.util.OracleUtils.IdentityWrapper; 23 | import glade.util.ShellUtils.CommandFactory; 24 | 25 | public class GrepData { 26 | public static final String GREP_EXE = "grep/grep-2.23/src/grep"; 27 | public static final boolean GREP_IS_ERROR = true; 28 | 29 | public static final String GREP_EXAMPLE_FILENAME = "tests.txt"; 30 | public static final String GREP_ALL_EXAMPLE_FILENAME = "tests_all.txt"; 31 | public static final String GREP_EMPTY = ""; 32 | 33 | public static final String GREP_NAME = "grep"; 34 | public static final ProgramData GREP_DATA = new ShellProgramData(Files.FILE_PARAMETERS, new GrepCommandFactory(), GREP_EXE, GREP_IS_ERROR); 35 | public static final ProgramExamples GREP_EXAMPLES = new SingleFileProgramExamples(Files.FILE_PARAMETERS, GREP_NAME, GREP_EXAMPLE_FILENAME, GREP_EMPTY, new IdentityWrapper()); 36 | 37 | public static class GrepCommandFactory implements CommandFactory { 38 | @Override 39 | public String getCommand(String filename, String auxFilename, String exePath) { 40 | return exePath + " -f " + filename + " " + auxFilename; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/glade/constants/program/PythonData.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.constants.program; 16 | 17 | import glade.constants.Files; 18 | import glade.main.ProgramDataUtils.MultiFileProgramExamples; 19 | import glade.main.ProgramDataUtils.ProgramData; 20 | import glade.main.ProgramDataUtils.ProgramExamples; 21 | import glade.main.ProgramDataUtils.ShellProgramData; 22 | import glade.util.OracleUtils.IdentityWrapper; 23 | 24 | public class PythonData { 25 | public static final String PYTHON_EXE = "python/Python-2.7.10/python"; 26 | public static final boolean PYTHON_IS_ERROR = true; 27 | 28 | public static final String PYTHON_EXTENSION = ".py"; 29 | public static final String PYTHON_EMPTY = ""; 30 | 31 | public static final String PYTHON_NAME = "python"; 32 | public static final ProgramData PYTHON_DATA = new ShellProgramData(Files.FILE_PARAMETERS, PYTHON_EXE, PYTHON_IS_ERROR); 33 | 34 | public static final ProgramExamples PYTHON_EXAMPLES = new MultiFileProgramExamples(Files.FILE_PARAMETERS, PYTHON_NAME, PYTHON_EXTENSION, PYTHON_EMPTY, new IdentityWrapper()); 35 | } 36 | -------------------------------------------------------------------------------- /src/glade/constants/program/PythonWrappedData.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.constants.program; 16 | 17 | import glade.constants.Files; 18 | import glade.main.ProgramDataUtils.MultiFileProgramExamples; 19 | import glade.main.ProgramDataUtils.ProgramData; 20 | import glade.main.ProgramDataUtils.ProgramExamples; 21 | import glade.main.ProgramDataUtils.WrappedProgramData; 22 | import glade.util.OracleUtils.IdentityWrapper; 23 | import glade.util.OracleUtils.Wrapper; 24 | 25 | public class PythonWrappedData { 26 | public static final String PYTHON_WRAPPED_NAME = "python_wrapped"; 27 | public static final String PYTHON_WRAPPED_EMPTY = "pass"; 28 | public static final ProgramData PYTHON_WRAPPED_DATA = new WrappedProgramData(PythonData.PYTHON_DATA, new PythonWrapper()); 29 | 30 | public static final ProgramExamples PYTHON_EXAMPLES = new MultiFileProgramExamples(Files.FILE_PARAMETERS, PYTHON_WRAPPED_NAME, PythonData.PYTHON_EXTENSION, PYTHON_WRAPPED_EMPTY, new IdentityWrapper()); 31 | 32 | public static class PythonWrapper implements Wrapper { 33 | @Override 34 | public String wrap(String input) { 35 | StringBuilder sb = new StringBuilder(); 36 | 37 | // header 38 | sb.append("if False:\n"); 39 | 40 | // query 41 | boolean isEmpty = true; 42 | for(String line : input.split("\n")) { 43 | sb.append(" ").append(line).append("\n"); 44 | isEmpty = false; 45 | } 46 | 47 | // pass if needed 48 | if(isEmpty) { 49 | sb.append(" pass"); 50 | } 51 | 52 | return sb.toString(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/glade/constants/program/SedData.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.constants.program; 16 | 17 | import glade.constants.Files; 18 | import glade.main.ProgramDataUtils.MultiFileProgramExamples; 19 | import glade.main.ProgramDataUtils.ProgramData; 20 | import glade.main.ProgramDataUtils.ProgramExamples; 21 | import glade.main.ProgramDataUtils.ShellProgramData; 22 | import glade.util.OracleUtils.IdentityWrapper; 23 | import glade.util.ShellUtils.CommandFactory; 24 | 25 | 26 | public class SedData { 27 | public static final String SED_EXE = "sed/sed-4.2.2/sed/sed"; 28 | public static final boolean SED_IS_ERROR = true; 29 | 30 | public static final String SED_EXTENSION = ".sed"; 31 | public static final String SED_EMPTY = ""; 32 | 33 | public static final String SED_NAME = "sed"; 34 | public static final ProgramData SED_DATA = new ShellProgramData(Files.FILE_PARAMETERS, new SedCommandFactory(), SED_EXE, SED_IS_ERROR); 35 | public static final ProgramExamples SED_EXAMPLES = new MultiFileProgramExamples(Files.FILE_PARAMETERS, SED_NAME, SED_EXTENSION, SED_EMPTY, new IdentityWrapper()); 36 | 37 | public static class SedCommandFactory implements CommandFactory { 38 | @Override 39 | public String getCommand(String filename, String auxFilename, String exePath) { 40 | return exePath + " -f " + filename + " " + auxFilename; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/glade/constants/program/XmlData.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.constants.program; 16 | 17 | import glade.constants.Files; 18 | import glade.main.ProgramDataUtils.MultiFileProgramExamples; 19 | import glade.main.ProgramDataUtils.ProgramData; 20 | import glade.main.ProgramDataUtils.ProgramExamples; 21 | import glade.main.ProgramDataUtils.ShellProgramData; 22 | import glade.util.OracleUtils.IdentityWrapper; 23 | 24 | public class XmlData { 25 | public static final String XML_EXE = "xml/libxml2-2.9.2/xmllint"; 26 | public static final boolean XML_IS_ERROR = true; 27 | public static final String XML_HEADER = ""; 28 | public static final String XML_EXTENSION = ".xml"; 29 | public static final String XML_EMPTY = ""; 30 | 31 | public static final String XML_NAME = "xml"; 32 | public static final ProgramData XML_DATA = new ShellProgramData(Files.FILE_PARAMETERS, XML_EXE, XML_IS_ERROR); 33 | public static final ProgramExamples XML_EXAMPLES = new MultiFileProgramExamples(Files.FILE_PARAMETERS, XML_NAME, XML_EXTENSION, XML_EMPTY, new IdentityWrapper()); 34 | 35 | public static final String XML_EXAMPLE = "seed.xml"; 36 | } 37 | -------------------------------------------------------------------------------- /src/glade/grammar/GrammarSerializer.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.grammar; 16 | 17 | import glade.grammar.GrammarUtils.AlternationNode; 18 | import glade.grammar.GrammarUtils.ConstantNode; 19 | import glade.grammar.GrammarUtils.Context; 20 | import glade.grammar.GrammarUtils.Grammar; 21 | import glade.grammar.GrammarUtils.MultiAlternationNode; 22 | import glade.grammar.GrammarUtils.MultiConstantNode; 23 | import glade.grammar.GrammarUtils.Node; 24 | import glade.grammar.GrammarUtils.NodeData; 25 | import glade.grammar.GrammarUtils.NodeMerges; 26 | import glade.grammar.GrammarUtils.RepetitionNode; 27 | import glade.util.Utils; 28 | 29 | import java.io.DataInputStream; 30 | import java.io.DataOutputStream; 31 | import java.io.IOException; 32 | import java.util.ArrayList; 33 | import java.util.List; 34 | import java.util.Map; 35 | import java.util.Set; 36 | 37 | public class GrammarSerializer { 38 | public static void serialize(String string, DataOutputStream dos) throws IOException { 39 | if(string == null) { 40 | dos.writeInt(-1); 41 | } else { 42 | dos.writeInt(string.length()); 43 | for(int i=0; i nodes = GrammarUtils.getAllNodes(grammar.node); 81 | Map nodeIds = Utils.getInverse(nodes); 82 | dos.writeInt(nodes.size()); // 0 83 | for(Node node : nodes) { 84 | dos.writeInt(nodeIds.get(node)); // 1 85 | serialize(node.getData(), dos); // 2 86 | if(node instanceof ConstantNode) { 87 | dos.writeInt(0); // 3/1 88 | } else if(node instanceof AlternationNode) { 89 | AlternationNode altNode = (AlternationNode)node; 90 | dos.writeInt(1); // 3/1 91 | dos.writeInt(nodeIds.get(altNode.first)); // 3/2 92 | dos.writeInt(nodeIds.get(altNode.second)); // 3/3 93 | } else if(node instanceof MultiAlternationNode) { 94 | MultiAlternationNode maltNode = (MultiAlternationNode)node; 95 | dos.writeInt(2); // 3/1 96 | dos.writeInt(maltNode.getChildren().size()); // 3/2 97 | for(Node child : maltNode.getChildren()) { 98 | dos.writeInt(nodeIds.get(child)); // 3/3 99 | } 100 | } else if(node instanceof RepetitionNode) { 101 | RepetitionNode repNode = (RepetitionNode)node; 102 | dos.writeInt(3); // 3/1 103 | dos.writeInt(nodeIds.get(repNode.start)); // 3/2 104 | dos.writeInt(nodeIds.get(repNode.rep)); // 3/3 105 | dos.writeInt(nodeIds.get(repNode.end)); // 3/4 106 | } else if(node instanceof MultiConstantNode) { 107 | MultiConstantNode mconstNode = (MultiConstantNode)node; 108 | dos.writeInt(4); // 3/1 109 | dos.writeInt(mconstNode.characterOptions.size()); // 3/2 110 | for(int i=0; i characterOption = mconstNode.characterOptions.get(i); 112 | dos.writeInt(characterOption.size()); // 3/3 113 | for(char c : characterOption) { 114 | dos.writeChar(c); // 3/4 115 | } 116 | Set characterChecks = mconstNode.characterChecks.get(i); 117 | dos.writeInt(characterChecks.size()); // 3/5 118 | for(char c : characterChecks) { 119 | dos.writeChar(c); // 3/6 120 | } 121 | } 122 | } else { 123 | throw new RuntimeException("Unrecognized node type: " + node.getClass().getName()); 124 | } 125 | } 126 | dos.writeInt(grammar.merges.keySet().size()); // 4 127 | for(Node first : grammar.merges.keySet()) { 128 | dos.writeInt(grammar.merges.get(first).size()); // 5 129 | for(Node second : grammar.merges.get(first)) { 130 | dos.writeInt(nodeIds.get(first)); // 6 131 | dos.writeInt(nodeIds.get(second)); // 7 132 | } 133 | } 134 | } 135 | 136 | private static interface NodeSerialization { 137 | public abstract NodeData getData(); 138 | } 139 | 140 | private static class ConstantNodeSerialization implements NodeSerialization { 141 | private final NodeData data; 142 | private ConstantNodeSerialization(NodeData data) { 143 | this.data = data; 144 | } 145 | public NodeData getData() { 146 | return this.data; 147 | } 148 | } 149 | 150 | private static class MultiConstantNodeSerialization implements NodeSerialization { 151 | private final NodeData data; 152 | private final List> characterOptions; 153 | private final List> characterChecks; 154 | private MultiConstantNodeSerialization(NodeData data, List> characterOptions, List> characterChecks) { 155 | this.data = data; 156 | this.characterOptions = characterOptions; 157 | this.characterChecks = characterChecks; 158 | } 159 | public NodeData getData() { 160 | return this.data; 161 | } 162 | } 163 | 164 | private static class AlternationNodeSerialization implements NodeSerialization { 165 | private final NodeData data; 166 | private final int first; 167 | private final int second; 168 | private AlternationNodeSerialization(NodeData data, int first, int second) { 169 | this.data = data; 170 | this.first = first; 171 | this.second = second; 172 | } 173 | public NodeData getData() { 174 | return this.data; 175 | } 176 | } 177 | 178 | private static class MultiAlternationNodeSerialization implements NodeSerialization { 179 | private final NodeData data; 180 | private final List children; 181 | private MultiAlternationNodeSerialization(NodeData data, List children) { 182 | this.data = data; 183 | this.children = children; 184 | } 185 | public NodeData getData() { 186 | return this.data; 187 | } 188 | } 189 | 190 | private static class RepetitionNodeSerialization implements NodeSerialization { 191 | private final NodeData data; 192 | private final int start; 193 | private final int rep; 194 | private final int end; 195 | private RepetitionNodeSerialization(NodeData data, int start, int rep, int end) { 196 | this.data = data; 197 | this.start = start; 198 | this.rep = rep; 199 | this.end = end; 200 | } 201 | public NodeData getData() { 202 | return this.data; 203 | } 204 | } 205 | 206 | private static class NodeDeserializer { 207 | private final List nodeSerializations; 208 | private final List nodes; 209 | private NodeDeserializer(List nodeSerializations) { 210 | this.nodeSerializations = nodeSerializations; 211 | this.nodes = new ArrayList(); 212 | for(int i=0; i children = new ArrayList(); 227 | for(int childIndex : maltNodeSerialization.children) { 228 | children.add(this.deserialize(childIndex)); 229 | } 230 | this.nodes.set(index, new MultiAlternationNode(maltNodeSerialization.getData(), children)); 231 | } else if(nodeSerialization instanceof RepetitionNodeSerialization) { 232 | RepetitionNodeSerialization repNodeSerialization = (RepetitionNodeSerialization)nodeSerialization; 233 | this.nodes.set(index, new RepetitionNode(repNodeSerialization.getData(), this.deserialize(repNodeSerialization.start), this.deserialize(repNodeSerialization.rep), this.deserialize(repNodeSerialization.end))); 234 | } else if(nodeSerialization instanceof MultiConstantNodeSerialization) { 235 | MultiConstantNodeSerialization mconstNodeSerialization = (MultiConstantNodeSerialization)nodeSerialization; 236 | return new MultiConstantNode(mconstNodeSerialization.getData(), mconstNodeSerialization.characterOptions, mconstNodeSerialization.characterChecks); 237 | } else { 238 | throw new RuntimeException("Unrecognized node type: " + nodeSerialization.getClass().getName()); 239 | } 240 | } 241 | return this.nodes.get(index); 242 | } 243 | private List deserialize() { 244 | for(int i=0; i nodeSerializations = new ArrayList(numNodes); 254 | for(int i=0; i children = new ArrayList(); 270 | for(int j=0; j> characterOptions = new ArrayList>(); 282 | List> characterChecks = new ArrayList>(); 283 | for(int j=0; j characterOption = new ArrayList(); 286 | for(int k=0; k characterCheck = new ArrayList(); 292 | int numCharacterCheck = dis.readInt(); // 3/5 293 | for(int k=0; k nodes = new NodeDeserializer(nodeSerializations).deserialize(); 305 | NodeMerges merges = new NodeMerges(); 306 | int numMerges = dis.readInt(); // 4 307 | for(int i=0; i getChildren(); 67 | public abstract NodeData getData(); 68 | } 69 | 70 | public static class ConstantNode implements Node { 71 | private final NodeData data; 72 | public ConstantNode(NodeData data) { 73 | this.data = data; 74 | } 75 | public List getChildren() { 76 | return new ArrayList(); 77 | } 78 | public NodeData getData() { 79 | return this.data; 80 | } 81 | public String toString() { 82 | return this.data.example; 83 | } 84 | } 85 | 86 | public static class MultiConstantNode implements Node { 87 | private final NodeData data; 88 | public final List> characterOptions = new ArrayList>(); 89 | public final List> characterChecks = new ArrayList>(); 90 | public MultiConstantNode(NodeData data, List> characterOptions, List> characterChecks) { 91 | this.data = data; 92 | if(characterOptions.size() != characterChecks.size()) { 93 | throw new RuntimeException("Invalid characters!"); 94 | } 95 | for(List characters : characterOptions) { 96 | this.characterOptions.add(new LinkedHashSet(characters)); 97 | } 98 | for(Listcharacters : characterChecks) { 99 | this.characterChecks.add(new LinkedHashSet(characters)); 100 | } 101 | } 102 | public List getChildren() { 103 | return new ArrayList(); 104 | } 105 | public NodeData getData() { 106 | return this.data; 107 | } 108 | public String toString() { 109 | StringBuilder sb = new StringBuilder(); 110 | for(Set characterOption : this.characterOptions) { 111 | sb.append("("); 112 | for(char character : characterOption) { 113 | sb.append(character).append("+"); 114 | } 115 | sb.replace(sb.length()-1, sb.length(), ")"); 116 | } 117 | return sb.toString(); 118 | } 119 | } 120 | 121 | public static class AlternationNode implements Node { 122 | private final NodeData data; 123 | public final Node first; 124 | public final Node second; 125 | public AlternationNode(NodeData data, Node first, Node second) { 126 | this.data = data; 127 | this.first = first; 128 | this.second = second; 129 | } 130 | public List getChildren() { 131 | List children = new ArrayList(); 132 | children.add(this.first); 133 | children.add(this.second); 134 | return children; 135 | } 136 | public NodeData getData() { 137 | return this.data; 138 | } 139 | public String toString() { 140 | return "(" + this.first.toString() + ")+(" + this.second.toString(); 141 | } 142 | } 143 | 144 | public static class MultiAlternationNode implements Node { 145 | private final NodeData data; 146 | private final List children = new ArrayList(); 147 | public MultiAlternationNode(NodeData data, List children) { 148 | this.data = data; 149 | this.children.addAll(children); 150 | } 151 | public List getChildren() { 152 | List newChildren = new ArrayList(); 153 | newChildren.addAll(this.children); 154 | return newChildren; 155 | } 156 | public NodeData getData() { 157 | return this.data; 158 | } 159 | public String toString() { 160 | StringBuilder sb = new StringBuilder(); 161 | for(Node child : this.children) { 162 | sb.append("(").append(child.toString()).append(")+"); 163 | } 164 | return sb.substring(0, sb.length()-1); 165 | } 166 | } 167 | 168 | public static class RepetitionNode implements Node { 169 | private final NodeData data; 170 | public final Node start; 171 | public final Node rep; 172 | public final Node end; 173 | public RepetitionNode(NodeData data, Node start, Node rep, Node end) { 174 | this.data = data; 175 | this.start = start; 176 | this.rep = rep; 177 | this.end = end; 178 | } 179 | public List getChildren() { 180 | List children = new ArrayList(); 181 | children.add(this.start); 182 | children.add(this.rep); 183 | children.add(this.end); 184 | return children; 185 | } 186 | public NodeData getData() { 187 | return this.data; 188 | } 189 | public String toString() { 190 | return this.start.toString() + "(" + this.rep.toString() + ")*" + this.end.toString(); 191 | } 192 | } 193 | 194 | public static class NodeMerges { 195 | private final MultivalueMap merges = new MultivalueMap(); 196 | public void add(Node first, Node second) { 197 | this.merges.add(first, second); 198 | this.merges.add(second, first); 199 | } 200 | public void addAll(NodeMerges other) { 201 | for(Node first : other.keySet()) { 202 | for(Node second : other.get(first)) { 203 | this.add(first, second); 204 | } 205 | } 206 | } 207 | public Set get(Node node) { 208 | return this.merges.get(node); 209 | } 210 | public Set keySet() { 211 | return this.merges.keySet(); 212 | } 213 | public boolean contains(Node first, Node second) { 214 | return this.merges.get(first).contains(second); 215 | } 216 | } 217 | 218 | private static void getAllNodesHelper(Node root, List nodes) { 219 | nodes.add(root); 220 | for(Node child : root.getChildren()) { 221 | getAllNodesHelper(child, nodes); 222 | } 223 | } 224 | 225 | public static List getAllNodes(Node root) { 226 | List nodes = new ArrayList(); 227 | getAllNodesHelper(root, nodes); 228 | return nodes; 229 | } 230 | 231 | private static void getDescendantsHelper(Node node, List descendants) { 232 | descendants.add(node); 233 | for(Node child : node.getChildren()) { 234 | getDescendantsHelper(child, descendants); 235 | } 236 | } 237 | 238 | public static List getDescendants(Node node) { 239 | List descendants = new ArrayList(); 240 | getDescendantsHelper(node, descendants); 241 | return descendants; 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /src/glade/grammar/ParseTreeUtils.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.grammar; 16 | 17 | import glade.grammar.GrammarUtils.MultiAlternationNode; 18 | import glade.grammar.GrammarUtils.MultiConstantNode; 19 | import glade.grammar.GrammarUtils.Node; 20 | import glade.grammar.GrammarUtils.RepetitionNode; 21 | import glade.util.Utils; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | public class ParseTreeUtils { 27 | public static interface ParseTreeNode { 28 | public abstract String getExample(); 29 | public abstract Node getNode(); 30 | public abstract List getChildren(); 31 | } 32 | 33 | public static class ParseTreeRepetitionNode implements ParseTreeNode { 34 | private final RepetitionNode node; 35 | private final String example; 36 | 37 | public final ParseTreeNode start; 38 | public final List rep; 39 | public final ParseTreeNode end; 40 | 41 | public ParseTreeRepetitionNode(RepetitionNode node, ParseTreeNode start, List rep, ParseTreeNode end) { 42 | this.node = node; 43 | this.start = start; 44 | this.rep = rep; 45 | this.end = end; 46 | StringBuilder sb = new StringBuilder(); 47 | sb.append(start.getExample()); 48 | for(ParseTreeNode repNode : rep) { 49 | sb.append(repNode.getExample()); 50 | } 51 | sb.append(end.getExample()); 52 | this.example = sb.toString(); 53 | } 54 | 55 | @Override 56 | public Node getNode() { 57 | return this.node; 58 | } 59 | 60 | @Override 61 | public String getExample() { 62 | return this.example; 63 | } 64 | 65 | @Override 66 | public List getChildren() { 67 | List children = new ArrayList(); 68 | children.add(this.start); 69 | children.addAll(this.rep); 70 | children.add(this.end); 71 | return children; 72 | } 73 | 74 | @Override 75 | public String toString() { 76 | return this.example; 77 | } 78 | } 79 | 80 | public static class ParseTreeMultiAlternationNode implements ParseTreeNode { 81 | private final MultiAlternationNode node; 82 | private final String example; 83 | 84 | public final ParseTreeNode choice; 85 | 86 | public ParseTreeMultiAlternationNode(MultiAlternationNode node, ParseTreeNode choice) { 87 | this.node = node; 88 | this.example = choice.getExample(); 89 | this.choice = choice; 90 | } 91 | 92 | @Override 93 | public Node getNode() { 94 | return this.node; 95 | } 96 | 97 | @Override 98 | public String getExample() { 99 | return this.example; 100 | } 101 | 102 | @Override 103 | public List getChildren() { 104 | return Utils.getList(this.choice); 105 | } 106 | 107 | @Override 108 | public String toString() { 109 | return this.example; 110 | } 111 | } 112 | 113 | public static class ParseTreeMultiConstantNode implements ParseTreeNode { 114 | private final MultiConstantNode node; 115 | private final String example; 116 | 117 | public ParseTreeMultiConstantNode(MultiConstantNode node, String example) { 118 | this.node = node; 119 | this.example = example; 120 | } 121 | 122 | @Override 123 | public Node getNode() { 124 | return this.node; 125 | } 126 | 127 | @Override 128 | public String getExample() { 129 | return this.example; 130 | } 131 | 132 | @Override 133 | public List getChildren() { 134 | return new ArrayList(); 135 | } 136 | 137 | @Override 138 | public String toString() { 139 | return this.example; 140 | } 141 | } 142 | 143 | public static class ParseTreeMergeNode implements ParseTreeNode { 144 | private final Node node; 145 | private final String example; 146 | 147 | public final ParseTreeNode merge; 148 | 149 | public ParseTreeMergeNode(Node node, ParseTreeNode merge) { 150 | this.node = node; 151 | this.merge = merge; 152 | this.example = merge.getExample(); 153 | } 154 | 155 | @Override 156 | public Node getNode() { 157 | return this.node; 158 | } 159 | 160 | @Override 161 | public String getExample() { 162 | return this.example; 163 | } 164 | 165 | @Override 166 | public List getChildren() { 167 | return Utils.getList(this.merge); 168 | } 169 | 170 | @Override 171 | public String toString() { 172 | return this.example; 173 | } 174 | } 175 | 176 | public static List getParseTreeAlt(MultiAlternationNode node) { 177 | List parseTreeNodes = new ArrayList(); 178 | for(Node child : node.getChildren()) { 179 | parseTreeNodes.add(new ParseTreeMultiAlternationNode(node, getParseTreeRepConst(child))); 180 | } 181 | return parseTreeNodes; 182 | } 183 | 184 | public static ParseTreeNode getParseTreeRepConst(Node node) { 185 | if(node instanceof RepetitionNode) { 186 | RepetitionNode repNode = (RepetitionNode)node; 187 | ParseTreeNode start = getParseTreeRepConst(repNode.start); 188 | ParseTreeNode end = getParseTreeRepConst(repNode.end); 189 | if(repNode.rep instanceof MultiAlternationNode) { 190 | return new ParseTreeRepetitionNode(repNode, start, getParseTreeAlt((MultiAlternationNode)repNode.rep), end); 191 | } else { 192 | return new ParseTreeRepetitionNode(repNode, start, Utils.getList(getParseTreeRepConst(repNode.rep)), end); 193 | } 194 | } else if(node instanceof MultiConstantNode) { 195 | return new ParseTreeMultiConstantNode((MultiConstantNode)node, node.getData().example); 196 | } else { 197 | throw new RuntimeException("Invalid node type: " + node.getClass().getName()); 198 | } 199 | } 200 | 201 | public static ParseTreeNode getParseTree(Node node) { 202 | return getParseTreeRepConst(node); 203 | } 204 | 205 | private static void getDescendantsHelper(ParseTreeNode node, List descendants) { 206 | descendants.add(node); 207 | for(ParseTreeNode child : node.getChildren()) { 208 | getDescendantsHelper(child, descendants); 209 | } 210 | } 211 | 212 | public static List getDescendants(ParseTreeNode node) { 213 | List descendants = new ArrayList(); 214 | getDescendantsHelper(node, descendants); 215 | return descendants; 216 | } 217 | 218 | private static void getDescendantsByTypeHelper(ParseTreeNode node, List[] descendants) { 219 | if(node instanceof ParseTreeMultiConstantNode) { 220 | descendants[0].add(node); 221 | } else { 222 | descendants[1].add(node); 223 | } 224 | for(ParseTreeNode child : node.getChildren()) { 225 | getDescendantsByTypeHelper(child, descendants); 226 | } 227 | } 228 | 229 | public static List[] getDescendantsByType(ParseTreeNode node) { 230 | @SuppressWarnings("unchecked") 231 | List[] descendants = new List[2]; 232 | for(int i=0; i<2; i++) { 233 | descendants[i] = new ArrayList(); 234 | } 235 | getDescendantsByTypeHelper(node, descendants); 236 | return descendants; 237 | } 238 | 239 | public static ParseTreeNode getSubstitute(ParseTreeNode node, ParseTreeNode cur, ParseTreeNode sub) { 240 | if(node == cur) { 241 | return sub; 242 | } else if(node instanceof ParseTreeRepetitionNode) { 243 | ParseTreeRepetitionNode repNode = (ParseTreeRepetitionNode)node; 244 | ParseTreeNode newStart = getSubstitute(repNode.start, cur, sub); 245 | List newRep = new ArrayList(); 246 | for(ParseTreeNode rep : repNode.rep) { 247 | newRep.add(getSubstitute(rep, cur, sub)); 248 | } 249 | ParseTreeNode newEnd = getSubstitute(repNode.end, cur, sub); 250 | return new ParseTreeRepetitionNode(repNode.node, newStart, newRep, newEnd); 251 | } else if(node instanceof ParseTreeMultiAlternationNode) { 252 | ParseTreeNode newChoice = getSubstitute(((ParseTreeMultiAlternationNode)node).choice, cur, sub); 253 | return new ParseTreeMultiAlternationNode(((ParseTreeMultiAlternationNode)node).node, newChoice); 254 | } else if(node instanceof ParseTreeMultiConstantNode) { 255 | return node; 256 | } else { 257 | throw new RuntimeException("Unrecognized node type: " + node.getClass().getName()); 258 | } 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /src/glade/grammar/fuzz/GrammarFuzzer.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.grammar.fuzz; 16 | 17 | import glade.grammar.GrammarUtils; 18 | import glade.grammar.GrammarUtils.Grammar; 19 | import glade.grammar.GrammarUtils.MultiAlternationNode; 20 | import glade.grammar.GrammarUtils.MultiConstantNode; 21 | import glade.grammar.GrammarUtils.Node; 22 | import glade.grammar.GrammarUtils.NodeMerges; 23 | import glade.grammar.GrammarUtils.RepetitionNode; 24 | import glade.grammar.ParseTreeUtils; 25 | import glade.grammar.ParseTreeUtils.ParseTreeMultiConstantNode; 26 | import glade.grammar.ParseTreeUtils.ParseTreeNode; 27 | import glade.grammar.ParseTreeUtils.ParseTreeRepetitionNode; 28 | 29 | import java.util.ArrayList; 30 | import java.util.HashMap; 31 | import java.util.Iterator; 32 | import java.util.List; 33 | import java.util.Map; 34 | import java.util.Random; 35 | import java.util.Set; 36 | 37 | public class GrammarFuzzer { 38 | public static class SampleParameters { 39 | private final double[] pRepetition; 40 | private final double pRecursion; 41 | private final double pAllCharacters; 42 | private final int boxSize; 43 | public SampleParameters(double[] pRepetition, double pRecursion, double pAllCharacters, int boxSize) { 44 | this.pRepetition = pRepetition; 45 | this.pRecursion = pRecursion; 46 | this.pAllCharacters = pAllCharacters; 47 | this.boxSize = boxSize; 48 | } 49 | public boolean randRecursion(Random random) { 50 | return this.pRecursion >= random.nextDouble(); 51 | } 52 | public boolean randAllCharacters(Random random) { 53 | return this.pAllCharacters >= random.nextDouble(); 54 | } 55 | public int randRepetition(Random random) { 56 | double sample = random.nextDouble(); 57 | double sum = 0.0; 58 | for(int i=0; i= sample) { 61 | return i; 62 | } 63 | } 64 | return this.pRepetition.length; 65 | } 66 | public int randAlternation(Random random) { 67 | return random.nextInt(3); 68 | } 69 | public int randMultiAlternation(Random random, int numChoices) { 70 | return random.nextInt(numChoices); 71 | } 72 | public int getBoxSize() { 73 | return this.boxSize; 74 | } 75 | } 76 | 77 | public static class IntBox { 78 | private int value; 79 | public IntBox(int value) { 80 | this.value = value; 81 | } 82 | public void decrement() { 83 | this.value--; 84 | } 85 | public int value() { 86 | return this.value; 87 | } 88 | } 89 | 90 | private static ParseTreeNode sampleHelper(Node grammar, NodeMerges recursiveNodes, SampleParameters parameters, Random random, Map backup, IntBox length) { 91 | if(length.value() == 0) { 92 | return backup.get(grammar); 93 | } 94 | length.decrement(); 95 | if(!recursiveNodes.get(grammar).isEmpty() && parameters.randRecursion(random)) { 96 | int choice = parameters.randMultiAlternation(random, recursiveNodes.get(grammar).size()); 97 | return sampleHelper(new ArrayList(recursiveNodes.get(grammar)).get(choice), recursiveNodes, parameters, random, backup, length); 98 | } else if(grammar instanceof MultiAlternationNode) { 99 | MultiAlternationNode node = (MultiAlternationNode)grammar; 100 | int choice = parameters.randMultiAlternation(random, node.getChildren().size()); 101 | return sampleHelper(node.getChildren().get(choice), recursiveNodes, parameters, random, backup, length); 102 | } else if(grammar instanceof RepetitionNode) { 103 | ParseTreeNode start = sampleHelper(((RepetitionNode)grammar).start, recursiveNodes, parameters, random, backup, length); 104 | List rep = new ArrayList(); 105 | int reps = parameters.randRepetition(random); 106 | for(int i=0; i characterOption : useAllCharacters ? mconstNode.characterOptions : mconstNode.characterChecks) { 116 | List characterOptionList = new ArrayList(characterOption); 117 | int choice = parameters.randMultiAlternation(random, characterOptionList.size()); 118 | sb.append(characterOptionList.get(choice)); 119 | } 120 | return new ParseTreeMultiConstantNode(mconstNode, sb.toString()); 121 | } else { 122 | throw new RuntimeException("Invalid node type: " + grammar.getClass().getName()); 123 | } 124 | } 125 | 126 | private static void getBackup(ParseTreeNode node, Map backup) { 127 | backup.put(node.getNode(), node); 128 | for(ParseTreeNode child : node.getChildren()) { 129 | getBackup(child, backup); 130 | } 131 | } 132 | 133 | public static ParseTreeNode sample(Node program, Grammar grammar, SampleParameters parameters, Random random) { 134 | Map backup = new HashMap(); 135 | if(grammar.node instanceof MultiAlternationNode) { 136 | for(ParseTreeNode parseTree : ParseTreeUtils.getParseTreeAlt((MultiAlternationNode)grammar.node)) { 137 | getBackup(parseTree, backup); 138 | } 139 | } else { 140 | getBackup(ParseTreeUtils.getParseTree(grammar.node), backup); 141 | } 142 | for(Node node : grammar.merges.keySet()) { 143 | if(!backup.containsKey(node)) { 144 | throw new RuntimeException("Invalid node: " + node); 145 | } 146 | for(Node merge : grammar.merges.get(node)) { 147 | if(!backup.containsKey(merge)) { 148 | throw new RuntimeException("Invalid node: " + node); 149 | } 150 | } 151 | } 152 | for(Node descendant : GrammarUtils.getDescendants(program)) { 153 | if(!backup.containsKey(descendant)) { 154 | throw new RuntimeException("Invalid node: " + descendant); 155 | } 156 | } 157 | return sampleHelper(program, grammar.merges, parameters, random, backup, new IntBox(parameters.getBoxSize())); 158 | } 159 | 160 | public static class GrammarSampler implements Iterator, Iterable { 161 | private final Grammar grammar; 162 | private final SampleParameters parameters; 163 | private final Random random; 164 | 165 | public GrammarSampler(Grammar grammar, SampleParameters parameters, Random random) { 166 | this.grammar = grammar; 167 | this.parameters = parameters; 168 | this.random = random; 169 | } 170 | 171 | @Override 172 | public boolean hasNext() { 173 | return true; 174 | } 175 | 176 | @Override 177 | public String next() { 178 | return GrammarFuzzer.sample(this.grammar.node, this.grammar, this.parameters, this.random).getExample(); 179 | } 180 | 181 | @Override 182 | public Iterator iterator() { 183 | return this; 184 | } 185 | 186 | @Override 187 | public void remove() { 188 | throw new RuntimeException("Remove not supported!"); 189 | } 190 | } 191 | 192 | public static class GrammarMutationSampler implements Iterator, Iterable { 193 | private final Grammar grammar; 194 | private final SampleParameters parameters; 195 | private final int maxLength; 196 | private final int numMutations; 197 | private final Random random; 198 | 199 | public GrammarMutationSampler(Grammar grammar, SampleParameters parameters, int maxLength, int numMutations, Random random) { 200 | this.grammar = grammar; 201 | this.parameters = parameters; 202 | this.maxLength = maxLength; 203 | this.numMutations = numMutations; 204 | this.random = random; 205 | } 206 | 207 | private ParseTreeNode sampleHelper(ParseTreeNode seed) { 208 | List[] descendants = ParseTreeUtils.getDescendantsByType(seed); 209 | int isMultiConstant = descendants[1].isEmpty() || (!descendants[0].isEmpty() && this.random.nextBoolean()) ? 0 : 1; 210 | int choice = this.random.nextInt(descendants[isMultiConstant].size()); 211 | ParseTreeNode cur = descendants[isMultiConstant].get(choice); 212 | ParseTreeNode sub = GrammarFuzzer.sample(cur.getNode(), this.grammar, this.parameters, this.random); 213 | ParseTreeNode result = ParseTreeUtils.getSubstitute(seed, cur, sub); 214 | return result; 215 | } 216 | 217 | private ParseTreeNode sample(ParseTreeNode seed) { 218 | while(true) { 219 | ParseTreeNode result = sampleHelper(seed); 220 | if(result.getExample().length() <= this.maxLength) { 221 | return result; 222 | } 223 | } 224 | } 225 | 226 | public String sampleOne(Node node) { 227 | ParseTreeNode cur = ParseTreeUtils.getParseTree(node); 228 | int choice = this.random.nextInt(this.numMutations); 229 | for(int i=0; i children = maltNode.getChildren(); 246 | int choice = this.random.nextInt(children.size()); 247 | return this.sampleOne(children.get(choice)); 248 | } else { 249 | return this.sampleOne(node); 250 | } 251 | } 252 | 253 | @Override 254 | public Iterator iterator() { 255 | return this; 256 | } 257 | 258 | @Override 259 | public void remove() { 260 | throw new RuntimeException("Remove not supported!"); 261 | } 262 | } 263 | 264 | public static class CombinedMutationSampler implements Iterator, Iterable { 265 | private final Iterator sampler; 266 | private final int numMutations; 267 | private final Random random; 268 | 269 | public CombinedMutationSampler(Iterable sampler, int numMutations, Random random) { 270 | this.sampler = sampler.iterator(); 271 | this.numMutations = numMutations; 272 | this.random = random; 273 | } 274 | 275 | @Override 276 | public boolean hasNext() { 277 | return this.sampler.hasNext(); 278 | } 279 | 280 | @Override 281 | public String next() { 282 | String sample = this.sampler.next(); 283 | if(sample == null) { 284 | return null; 285 | } 286 | return this.random.nextBoolean() ? sample : nextStringMutant(sample, this.random.nextInt(this.numMutations), this.random); 287 | } 288 | 289 | @Override 290 | public Iterator iterator() { 291 | return this; 292 | } 293 | 294 | @Override 295 | public void remove() { 296 | throw new RuntimeException("Remove not supported!"); 297 | } 298 | } 299 | 300 | private static char nextChar(Random random) { 301 | return (char)random.nextInt(128); 302 | } 303 | 304 | // performs a single edit to the string 305 | private static String nextStringMutant(String string, Random random) { 306 | if(string.length() == 0) { return "" + nextChar(random); } 307 | int randIndex = random.nextInt(string.length()); 308 | boolean randOp = random.nextBoolean(); // false -> delete, true -> insert 309 | String head = string.substring(0, randIndex); 310 | String tail = string.substring(randIndex); 311 | if(randOp) { 312 | return head + nextChar(random) + tail; 313 | } else { 314 | return head + (tail.length() == 0 ? "" : tail.substring(1)); 315 | } 316 | } 317 | 318 | private static String nextStringMutant(String string, int numMutantions, Random random) { 319 | for(int i=0; i roots, DiscriminativeOracle oracle) { 53 | long time = System.currentTimeMillis(); 54 | Grammar grammar = new Grammar(new MultiAlternationNode(new NodeData(null, new Context()), roots), MergesSynthesis.getMergesMultiple(roots, oracle)); 55 | Log.info("MULTIPLE MERGE TIME: " + ((System.currentTimeMillis() - time)/1000.0) + " seconds"); 56 | return grammar; 57 | } 58 | 59 | public static Grammar getGrammarMultiple(List examples, DiscriminativeOracle oracle) { 60 | List roots = new ArrayList(); 61 | for(String example : examples) { 62 | roots.add(getNode(example, oracle)); 63 | } 64 | return getGrammarMultipleFromRoots(roots, oracle); 65 | } 66 | 67 | public static Grammar getRegularGrammarMultipleFromRoots(List roots, DiscriminativeOracle oracle) { 68 | long time = System.currentTimeMillis(); 69 | Grammar grammar = new Grammar(new MultiAlternationNode(new NodeData(null, new Context()), roots), new NodeMerges()); 70 | Log.info("MULTIPLE MERGE TIME: " + ((System.currentTimeMillis() - time)/1000.0) + " seconds"); 71 | return grammar; 72 | } 73 | 74 | public static Grammar getRegularGrammarMultiple(List examples, DiscriminativeOracle oracle) { 75 | List roots = new ArrayList(); 76 | for(String example : examples) { 77 | roots.add(getNode(example, oracle)); 78 | } 79 | return getRegularGrammarMultipleFromRoots(roots, oracle); 80 | } 81 | 82 | public static boolean getCheck(DiscriminativeOracle oracle, Context context, Iterable examples) { 83 | for(String example : examples) { 84 | if(!oracle.query(context.pre + example + context.post) || (context.useExtra() && !oracle.query(context.extraPre + example + context.extraPost))) { 85 | return false; 86 | } 87 | } 88 | return true; 89 | } 90 | 91 | public static Maybe> getMultiAlternationRepetitionConstantChildren(Node node, boolean isParentRep) { 92 | if(!isParentRep) { 93 | return new Maybe>(); 94 | } 95 | if(!(node instanceof MultiAlternationNode)) { 96 | return new Maybe>(); 97 | } 98 | List constantChildren = new ArrayList(); 99 | for(Node child : node.getChildren()) { 100 | if(child instanceof RepetitionNode) { 101 | RepetitionNode repChild = (RepetitionNode)child; 102 | if(!(repChild.start instanceof ConstantNode) && !(repChild.start instanceof MultiConstantNode)) { 103 | return new Maybe>(); 104 | } 105 | if(!(repChild.rep instanceof ConstantNode) && !(repChild.rep instanceof MultiConstantNode)) { 106 | return new Maybe>(); 107 | } 108 | if(!(repChild.end instanceof ConstantNode) && !(repChild.end instanceof MultiConstantNode)) { 109 | return new Maybe>(); 110 | } 111 | if(!repChild.start.getData().example.equals("") || !repChild.end.getData().example.equals("")) { 112 | return new Maybe>(); 113 | } 114 | constantChildren.add(repChild.rep); 115 | } else if(child instanceof ConstantNode) { 116 | constantChildren.add((ConstantNode)child); 117 | } else if(child instanceof MultiConstantNode) { 118 | constantChildren.add((MultiConstantNode)child); 119 | } else { 120 | return new Maybe>(); 121 | } 122 | } 123 | return new Maybe>(constantChildren); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/glade/grammar/synthesize/GrammarTransformer.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.grammar.synthesize; 16 | 17 | import glade.grammar.GrammarUtils.AlternationNode; 18 | import glade.grammar.GrammarUtils.ConstantNode; 19 | import glade.grammar.GrammarUtils.Context; 20 | import glade.grammar.GrammarUtils.MultiAlternationNode; 21 | import glade.grammar.GrammarUtils.MultiConstantNode; 22 | import glade.grammar.GrammarUtils.Node; 23 | import glade.grammar.GrammarUtils.RepetitionNode; 24 | import glade.util.CharacterUtils; 25 | import glade.util.Log; 26 | import glade.util.CharacterUtils.CharacterGeneralization; 27 | import glade.util.OracleUtils.DiscriminativeOracle; 28 | import glade.util.Utils.Maybe; 29 | import glade.util.Utils.MultivalueMap; 30 | 31 | import java.util.ArrayList; 32 | import java.util.HashSet; 33 | import java.util.List; 34 | import java.util.Set; 35 | 36 | public class GrammarTransformer { 37 | public static Node getTransform(Node node, DiscriminativeOracle oracle) { 38 | Node transformFlatten = getTransform(node, new FlattenTransformer()); 39 | return getTransform(transformFlatten, new ConstantTransformer(oracle, getMultiAlternationRepetitionConstantNodes(transformFlatten))); 40 | } 41 | 42 | private static interface NodeTransformer { 43 | public abstract Node transformConstant(ConstantNode node); 44 | public abstract Node transformMultiConstant(MultiConstantNode node); 45 | public abstract Node transformAlternation(AlternationNode node, Node newFirst, Node newSecond); 46 | public abstract Node transformRepetition(RepetitionNode node, Node newStart, Node newRep, Node newEnd); 47 | public abstract Node transformMultiAlternation(MultiAlternationNode node, List newChildren); 48 | } 49 | 50 | private static Node getTransform(Node node, NodeTransformer transformer) { 51 | if(node instanceof ConstantNode) { 52 | return transformer.transformConstant((ConstantNode)node); 53 | } else if(node instanceof MultiConstantNode) { 54 | return transformer.transformMultiConstant((MultiConstantNode)node); 55 | } else if(node instanceof AlternationNode) { 56 | AlternationNode altNode = (AlternationNode)node; 57 | Node newFirst = getTransform(altNode.first, transformer); 58 | Node newSecond = getTransform(altNode.second, transformer); 59 | return transformer.transformAlternation(altNode, newFirst, newSecond); 60 | } else if(node instanceof MultiAlternationNode) { 61 | List newChildren = new ArrayList(); 62 | for(Node child : node.getChildren()) { 63 | newChildren.add(getTransform(child, transformer)); 64 | } 65 | return transformer.transformMultiAlternation((MultiAlternationNode)node, newChildren); 66 | } else if(node instanceof RepetitionNode) { 67 | RepetitionNode repNode = (RepetitionNode)node; 68 | Node newStart = getTransform(repNode.start, transformer); 69 | Node newRep = getTransform(repNode.rep, transformer); 70 | Node newEnd = getTransform(repNode.end, transformer); 71 | return transformer.transformRepetition(repNode, newStart, newRep, newEnd); 72 | } else { 73 | throw new RuntimeException("Invalid node type: " + node.getClass().getName()); 74 | } 75 | } 76 | 77 | private static MultiConstantNode generalizeConstant(ConstantNode node, DiscriminativeOracle oracle) { 78 | String example = node.getData().example; 79 | Context context = node.getData().context; 80 | if(example.length() != 0) { 81 | Log.info("GENERALIZING CONST: " + example + " ## " + context.pre + " ## " + context.post); 82 | } 83 | List> characterOptions = new ArrayList>(); 84 | List> characterChecks = new ArrayList>(); 85 | for(int i=0; i characterOption = new ArrayList(); 87 | List characterCheck = new ArrayList(); 88 | char curC = example.charAt(i); 89 | Context curContext = new Context(context, example.substring(0, i), example.substring(i+1), example.substring(0, i), example.substring(i+1)); 90 | characterOption.add(curC); 91 | characterCheck.add(curC); 92 | for(CharacterGeneralization generalization : CharacterUtils.getGeneralizations()) { 93 | if(generalization.triggers.contains(curC)) { 94 | List checks = new ArrayList(); 95 | for(char c : generalization.checks) { 96 | if(curC != c) { 97 | checks.add("" + c); 98 | } 99 | } 100 | if(GrammarSynthesis.getCheck(oracle, curContext, checks)) { 101 | for(char c : generalization.characters) { 102 | if(curC != c) { 103 | characterOption.add(c); 104 | } 105 | } 106 | for(char c : generalization.checks) { 107 | if(curC != c) { 108 | characterCheck.add(c); 109 | } 110 | } 111 | } 112 | } 113 | } 114 | characterOptions.add(characterOption); 115 | characterChecks.add(characterCheck); 116 | } 117 | return new MultiConstantNode(node.getData(), characterOptions, characterChecks); 118 | } 119 | 120 | private static boolean isContained(String example, MultiConstantNode mconstNode) { 121 | if(example.length() != mconstNode.characterOptions.size()) { 122 | return false; 123 | } 124 | for(int i=0; i mconstNodes) { 133 | for(MultiConstantNode mconstNode : mconstNodes) { 134 | if(isContained(example, mconstNode)) { 135 | return true; 136 | } 137 | } 138 | return false; 139 | } 140 | 141 | private static MultiAlternationNode generalizeMultiAlternationConstant(MultiAlternationNode node, MultivalueMap multiAlternationNodeConstantChildren, DiscriminativeOracle oracle) { 142 | List curConsts = new ArrayList(); 143 | Log.info("GENERALIZING MULTI ALT: " + node.getData().example); 144 | for(Node child : multiAlternationNodeConstantChildren.get(node)) { 145 | if(!isContained(child.getData().example, curConsts)) { 146 | curConsts.add(generalizeConstant((ConstantNode)child, oracle)); 147 | } 148 | } 149 | return new MultiAlternationNode(node.getData(), new ArrayList(curConsts)); 150 | } 151 | 152 | private static class ConstantTransformer implements NodeTransformer { 153 | private final DiscriminativeOracle oracle; 154 | private final MultivalueMap multiAlternationNodeConstantChildren; 155 | private final Set ignoredConstants = new HashSet();; 156 | private ConstantTransformer(DiscriminativeOracle oracle, MultivalueMap multiAlternationNodeConstantChildren) { 157 | this.oracle = oracle; 158 | this.multiAlternationNodeConstantChildren = multiAlternationNodeConstantChildren; 159 | for(MultiAlternationNode maltNode : multiAlternationNodeConstantChildren.keySet()) { 160 | this.ignoredConstants.addAll(multiAlternationNodeConstantChildren.get(maltNode)); 161 | } 162 | } 163 | public Node transformConstant(ConstantNode node) { 164 | return this.ignoredConstants.contains(node) ? node : generalizeConstant(node, this.oracle); 165 | } 166 | public Node transformMultiConstant(MultiConstantNode node) { 167 | throw new RuntimeException("Invalid node: " + node); 168 | } 169 | public Node transformAlternation(AlternationNode node, Node newFirst, Node newSecond) { 170 | return new AlternationNode(node.getData(), newFirst, newSecond); 171 | } 172 | public Node transformMultiAlternation(MultiAlternationNode node, List newChildren) { 173 | return this.multiAlternationNodeConstantChildren.containsKey(node) ? generalizeMultiAlternationConstant(node, this.multiAlternationNodeConstantChildren, this.oracle) : new MultiAlternationNode(node.getData(), newChildren); 174 | } 175 | public Node transformRepetition(RepetitionNode node, Node newStart, Node newRep, Node newEnd) { 176 | return new RepetitionNode(node.getData(), newStart, newRep, newEnd); 177 | } 178 | } 179 | 180 | private static class FlattenTransformer implements NodeTransformer { 181 | public Node transformConstant(ConstantNode node) { 182 | return node; 183 | } 184 | public Node transformMultiConstant(MultiConstantNode node) { 185 | return node; 186 | } 187 | public Node transformAlternation(AlternationNode node, Node newFirst, Node newSecond) { 188 | List newChildren = new ArrayList(); 189 | if(newFirst instanceof MultiAlternationNode) { 190 | newChildren.addAll(((MultiAlternationNode)newFirst).getChildren()); 191 | } else { 192 | newChildren.add(newFirst); 193 | } 194 | if(newSecond instanceof MultiAlternationNode) { 195 | newChildren.addAll(((MultiAlternationNode)newSecond).getChildren()); 196 | } else { 197 | newChildren.add(newSecond); 198 | } 199 | return new MultiAlternationNode(node.getData(), newChildren); 200 | } 201 | public Node transformMultiAlternation(MultiAlternationNode node, List newChildren) { 202 | throw new RuntimeException("Invalid node: " + node); 203 | } 204 | public Node transformRepetition(RepetitionNode node, Node newStart, Node newRep, Node newEnd) { 205 | return new RepetitionNode(node.getData(), newStart, newRep, newEnd); 206 | } 207 | } 208 | 209 | private static void getMultiAlternationRepetitionConstantNodesHelper(Node node, MultivalueMap result, boolean isParentRep) { 210 | Maybe> constantChildren = GrammarSynthesis.getMultiAlternationRepetitionConstantChildren(node, isParentRep); 211 | if(constantChildren.hasT()) { 212 | for(Node child : constantChildren.getT()) { 213 | result.add((MultiAlternationNode)node, (ConstantNode)child); 214 | } 215 | } else if(node instanceof RepetitionNode) { 216 | RepetitionNode repNode = (RepetitionNode)node; 217 | getMultiAlternationRepetitionConstantNodesHelper(repNode.start, result, false); 218 | getMultiAlternationRepetitionConstantNodesHelper(repNode.rep, result, true); 219 | getMultiAlternationRepetitionConstantNodesHelper(repNode.end, result, false); 220 | } else { 221 | for(Node child : node.getChildren()) { 222 | getMultiAlternationRepetitionConstantNodesHelper(child, result, false); 223 | } 224 | } 225 | } 226 | 227 | private static MultivalueMap getMultiAlternationRepetitionConstantNodes(Node root) { 228 | MultivalueMap result = new MultivalueMap(); 229 | getMultiAlternationRepetitionConstantNodesHelper(root, result, false); 230 | return result; 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /src/glade/grammar/synthesize/MergesSynthesis.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.grammar.synthesize; 16 | 17 | import glade.grammar.GrammarUtils; 18 | import glade.grammar.GrammarUtils.AlternationNode; 19 | import glade.grammar.GrammarUtils.ConstantNode; 20 | import glade.grammar.GrammarUtils.MultiAlternationNode; 21 | import glade.grammar.GrammarUtils.MultiConstantNode; 22 | import glade.grammar.GrammarUtils.Node; 23 | import glade.grammar.GrammarUtils.NodeMerges; 24 | import glade.grammar.GrammarUtils.RepetitionNode; 25 | import glade.util.Log; 26 | import glade.util.OracleUtils.DiscriminativeOracle; 27 | import glade.util.Utils.MultivalueMap; 28 | 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | import java.util.Set; 32 | 33 | public class MergesSynthesis { 34 | public static NodeMerges getMergesMultiple(List roots, DiscriminativeOracle oracle) { 35 | NodeMerges merges = new NodeMerges(); 36 | NodeMerges processed = new NodeMerges(); 37 | for(Node first : roots) { 38 | for(Node second : roots) { 39 | if(processed.contains(first, second)) { 40 | continue; 41 | } 42 | processed.add(first, second); 43 | merges.addAll(getMergesSingle(first, second, oracle)); 44 | } 45 | } 46 | return merges; 47 | } 48 | 49 | public static NodeMerges getMergesSingle(Node firstRoot, Node secondRoot, DiscriminativeOracle oracle) { 50 | NodeMerges merges = new NodeMerges(); 51 | NodeMerges processedMerges = new NodeMerges(); 52 | MultivalueMap pairFirst = getAllExamples(firstRoot); 53 | MultivalueMap pairSecond = getAllExamples(secondRoot); 54 | for(Node first : GrammarUtils.getAllNodes(firstRoot)) { 55 | for(Node second : GrammarUtils.getAllNodes(secondRoot)) { 56 | if(processedMerges.contains(first, second)) { 57 | continue; 58 | } 59 | processedMerges.add(first, second); 60 | getMergesHelper(first, second, pairFirst, pairSecond, oracle, merges); 61 | } 62 | } 63 | return merges; 64 | } 65 | 66 | private static void getMergesHelper(Node first, Node second, MultivalueMap firstExampleMap, MultivalueMap secondExampleMap, DiscriminativeOracle oracle, NodeMerges merges) { 67 | if(first.equals(second)) { 68 | return; 69 | } 70 | if(!(first instanceof RepetitionNode) || !(second instanceof RepetitionNode)) { 71 | return; 72 | } 73 | Node firstRep = ((RepetitionNode)first).rep; 74 | Node secondRep = ((RepetitionNode)second).rep; 75 | if(firstRep instanceof ConstantNode || firstRep instanceof MultiConstantNode || secondRep instanceof ConstantNode || secondRep instanceof MultiConstantNode) { 76 | return; 77 | } 78 | if(isMultiAlternationRepetitionConstant(firstRep, true) || isMultiAlternationRepetitionConstant(secondRep, true)) { 79 | return; 80 | } 81 | List firstExamplesSimple = new ArrayList(); 82 | List secondExamplesSimple = new ArrayList(); 83 | firstExamplesSimple.add(secondRep.getData().example + secondRep.getData().example); 84 | secondExamplesSimple.add(firstRep.getData().example + firstRep.getData().example); 85 | if(!GrammarSynthesis.getCheck(oracle, firstRep.getData().context, firstExamplesSimple) || !GrammarSynthesis.getCheck(oracle, secondRep.getData().context, secondExamplesSimple)) { 86 | return; 87 | } 88 | List firstExamples = new ArrayList(); 89 | for(String example : secondExampleMap.get(secondRep)) { 90 | firstExamples.add(example + example); 91 | } 92 | List secondExamples = new ArrayList(); 93 | for(String example : firstExampleMap.get(firstRep)) { 94 | secondExamples.add(example + example); 95 | } 96 | if((isStructuredExample(firstRep) && isStructuredExample(secondRep)) 97 | || (GrammarSynthesis.getCheck(oracle, firstRep.getData().context, firstExamples) && GrammarSynthesis.getCheck(oracle, secondRep.getData().context, secondExamples))) { 98 | Log.info("MERGE NODE FIRST:\n" + firstRep.getData().context.pre + " ## " + firstRep.getData().example + " ## " + firstRep.getData().context.post); 99 | Log.info("MERGE NODE SECOND:\n" + secondRep.getData().context.pre + " ## " + secondRep.getData().example + " ## " + secondRep.getData().context.post); 100 | merges.add(firstRep, secondRep); 101 | } 102 | } 103 | 104 | private static void getAllExamplesHelper(Node node, MultivalueMap examples) { 105 | for(Node child : node.getChildren()) { 106 | getAllExamplesHelper(child, examples); 107 | } 108 | if(node instanceof RepetitionNode) { 109 | RepetitionNode repNode = (RepetitionNode)node; 110 | for(String example : examples.get(repNode.start)) { 111 | examples.add(repNode, example + repNode.rep.getData().example + repNode.end.getData().example); 112 | } 113 | for(String example : examples.get(repNode.rep)) { 114 | examples.add(repNode, repNode.start.getData().example + example + repNode.end.getData().example); 115 | } 116 | for(String example : examples.get(repNode.end)) { 117 | examples.add(repNode, repNode.start.getData().example + repNode.rep.getData().example + example); 118 | } 119 | } else if(node instanceof MultiConstantNode) { 120 | MultiConstantNode mconstNode = (MultiConstantNode)node; 121 | String example = mconstNode.getData().example; 122 | for(int i=0; i getAllExamples(Node root) { 153 | MultivalueMap allExamples = new MultivalueMap(); 154 | getAllExamplesHelper(root, allExamples); 155 | return allExamples; 156 | } 157 | 158 | 159 | private static boolean isMultiAlternationRepetitionConstant(Node node, boolean isParentRep) { 160 | return GrammarSynthesis.getMultiAlternationRepetitionConstantChildren(node, isParentRep).hasT(); 161 | } 162 | 163 | private static boolean isStructuredExample(Node node) { 164 | for(Node descendant : GrammarUtils.getDescendants(node)) { 165 | if(!(descendant instanceof MultiConstantNode)) { 166 | continue; 167 | } 168 | MultiConstantNode mconstNode = (MultiConstantNode)descendant; 169 | for(Set checks : mconstNode.characterChecks) { 170 | if(checks.size() == 1) { 171 | return true; 172 | } 173 | } 174 | } 175 | return false; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/glade/grammar/synthesize/RegexSynthesis.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.grammar.synthesize; 16 | 17 | import glade.grammar.GrammarUtils.AlternationNode; 18 | import glade.grammar.GrammarUtils.ConstantNode; 19 | import glade.grammar.GrammarUtils.Context; 20 | import glade.grammar.GrammarUtils.Node; 21 | import glade.grammar.GrammarUtils.NodeData; 22 | import glade.grammar.GrammarUtils.RepetitionNode; 23 | import glade.util.Log; 24 | import glade.util.OracleUtils.DiscriminativeOracle; 25 | import glade.util.Utils.Maybe; 26 | 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | 30 | public class RegexSynthesis { 31 | public static Node getNode(String example, DiscriminativeOracle oracle) { 32 | return getNode(new NodeData(example, new Context()), oracle, new NodeType[]{NodeType.REPETITION, NodeType.ALTERNATION}, true); 33 | } 34 | 35 | private static List getAlternationChecks(String first, String second) { 36 | List checks = new ArrayList(); 37 | checks.add(second + first + second + first); 38 | checks.add(first + second + first + second); 39 | checks.add(second + first); 40 | checks.add(second + second); 41 | checks.add(first + first); 42 | checks.add(second); 43 | checks.add(first); 44 | checks.add(""); 45 | return checks; 46 | } 47 | 48 | private static List getRepetitionChecks(String start, String rep, String end) { 49 | List checks = new ArrayList(); 50 | checks.add(start + rep + rep + end); 51 | checks.add(start + end); 52 | return checks; 53 | } 54 | 55 | private static class AlternationPartialNode { 56 | private final NodeData first; 57 | private final NodeData second; 58 | private AlternationPartialNode(NodeData first, NodeData second) { 59 | this.first = first; 60 | this.second = second; 61 | } 62 | } 63 | 64 | private static class RepetitionPartialNode { 65 | private final NodeData start; 66 | private final NodeData rep; 67 | private final NodeData end; 68 | private RepetitionPartialNode(NodeData start, NodeData rep, NodeData end) { 69 | this.start = start; 70 | this.rep = rep; 71 | this.end = end; 72 | } 73 | } 74 | 75 | private static Maybe getAlternationPartialNode(NodeData cur, DiscriminativeOracle oracle) { 76 | for(int i=1; i<=cur.example.length()-1; i++) { 77 | String first = cur.example.substring(0, i); 78 | String second = cur.example.substring(i); 79 | if(GrammarSynthesis.getCheck(oracle, cur.context, getAlternationChecks(first, second))) { 80 | NodeData firstData = new NodeData(first, new Context(cur.context, "", second, "", "")); 81 | NodeData secondData = new NodeData(second, new Context(cur.context, first, "", "", "")); 82 | Log.info("FOUND ALT: " + first + " ## " + second); 83 | return new Maybe(new AlternationPartialNode(firstData, secondData)); 84 | } 85 | } 86 | return new Maybe(); 87 | } 88 | 89 | private static Maybe getRepetitionPartialNode(NodeData cur, DiscriminativeOracle oracle, boolean isWholeStringRepeatable) { 90 | for(int init=0; init<=cur.example.length()-1; init++) { 91 | for(int len=cur.example.length()-init; len>=1; len--) { 92 | if(len == cur.example.length() && !isWholeStringRepeatable) { 93 | continue; 94 | } 95 | String start = cur.example.substring(0, init); 96 | String rep = cur.example.substring(init, init+len); 97 | String end = cur.example.substring(init+len); 98 | if(GrammarSynthesis.getCheck(oracle, cur.context, getRepetitionChecks(start, rep, end))) { 99 | NodeData startData = new NodeData(start, new Context(cur.context, "", rep+end, "", end)); 100 | NodeData repData = new NodeData(rep, new Context(cur.context, start, end, start, end)); 101 | NodeData endData = new NodeData(end, new Context(cur.context, start+rep, "", start, "")); 102 | Log.info("FOUND REP: " + rep + " ## " + start + " ## " + end); 103 | return new Maybe(new RepetitionPartialNode(startData, repData, endData)); 104 | } 105 | } 106 | } 107 | return new Maybe(); 108 | } 109 | 110 | private static Maybe getConstantNode(NodeData cur, DiscriminativeOracle oracle) { 111 | return new Maybe(new ConstantNode(cur)); 112 | } 113 | 114 | private static Maybe getAlternationNode(NodeData cur, DiscriminativeOracle oracle) { 115 | Maybe maybe = getAlternationPartialNode(cur, oracle); 116 | if(!maybe.hasT()) { 117 | return new Maybe(); 118 | } 119 | Node first = getNode(maybe.getT().first, oracle, new NodeType[]{NodeType.REPETITION}, true); 120 | Node second = getNode(maybe.getT().second, oracle, new NodeType[]{NodeType.ALTERNATION, NodeType.REPETITION}, true); 121 | return new Maybe(new AlternationNode(cur, first, second)); 122 | } 123 | 124 | private static Maybe getRepetitionNode(NodeData cur, DiscriminativeOracle oracle, boolean isWholeStringRepeatable) { 125 | Maybe maybe = getRepetitionPartialNode(cur, oracle, isWholeStringRepeatable); 126 | if(!maybe.hasT()) { 127 | return new Maybe(); 128 | } 129 | Node start = getNode(maybe.getT().start, oracle, new NodeType[]{}, true); 130 | Node rep = getNode(maybe.getT().rep, oracle, new NodeType[]{NodeType.ALTERNATION, NodeType.REPETITION}, false); 131 | Node end = getNode(maybe.getT().end, oracle, new NodeType[]{NodeType.REPETITION}, true); 132 | return new Maybe(new RepetitionNode(cur, start, rep, end)); 133 | } 134 | 135 | private static enum NodeType { 136 | REPETITION, ALTERNATION; 137 | } 138 | 139 | private static Node getNode(NodeData cur, DiscriminativeOracle oracle, NodeType[] types, boolean isWholeStringRepeatable) { 140 | for(NodeType type : types) { 141 | switch(type) { 142 | case REPETITION: 143 | Maybe nodeRep = getRepetitionNode(cur, oracle, isWholeStringRepeatable); 144 | if(nodeRep.hasT()) { 145 | return nodeRep.getT(); 146 | } 147 | break; 148 | case ALTERNATION: 149 | Maybe nodeAlt = getAlternationNode(cur, oracle); 150 | if(nodeAlt.hasT()) { 151 | return nodeAlt.getT(); 152 | } 153 | break; 154 | } 155 | } 156 | return getConstantNode(cur, oracle).getT(); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/glade/main/GrammarDataUtils.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.main; 16 | 17 | import glade.grammar.GrammarSerializer; 18 | import glade.grammar.GrammarUtils.Grammar; 19 | import glade.grammar.GrammarUtils.Node; 20 | import glade.grammar.synthesize.GrammarSynthesis; 21 | import glade.main.ProgramDataUtils.ProgramData; 22 | import glade.main.ProgramDataUtils.ProgramExamples; 23 | 24 | import java.io.DataInputStream; 25 | import java.io.DataOutputStream; 26 | import java.io.File; 27 | import java.io.FileInputStream; 28 | import java.io.FileOutputStream; 29 | import java.io.IOException; 30 | import java.util.ArrayList; 31 | import java.util.List; 32 | 33 | public class GrammarDataUtils { 34 | public static void clearGrammarDirectory(String grammarPath, String name) { 35 | File dir = new File(grammarPath + File.separator + name); 36 | if(dir.exists()) { 37 | for(File file : dir.listFiles()) { 38 | file.delete(); 39 | } 40 | } 41 | } 42 | 43 | private static String getGrammarFilename(String grammarPath, String name, int index) { 44 | return grammarPath + File.separator + name + File.separator + "example" + index + ".gram"; 45 | } 46 | 47 | private static String getAllGrammarFilename(String grammarPath, String name) { 48 | return grammarPath + File.separator + name + File.separator + "all.gram"; 49 | } 50 | 51 | public static void saveGrammar(String filename, Grammar grammar) { 52 | try { 53 | File file = new File(filename); 54 | File parent = file.getParentFile(); 55 | if(parent != null) { 56 | parent.mkdirs(); 57 | } 58 | DataOutputStream dos = new DataOutputStream(new FileOutputStream(filename)); 59 | GrammarSerializer.serialize(grammar, dos); 60 | } catch(IOException e) { 61 | throw new RuntimeException("Error opening file during grammar save: " + filename, e); 62 | } catch(RuntimeException e) { 63 | throw new RuntimeException(e.getMessage() + "\nError serializing grammar: " + filename, e); 64 | } 65 | } 66 | 67 | public static Grammar loadGrammar(String filename) { 68 | try { 69 | DataInputStream dis = new DataInputStream(new FileInputStream(filename)); 70 | return GrammarSerializer.deserializeNodeWithMerges(dis); 71 | } catch(IOException e) { 72 | throw new RuntimeException("Error opening grammar file during grammar load: " + filename, e); 73 | } catch(RuntimeException e) { 74 | throw new RuntimeException(e.getMessage() + "\nError deserializing grammar: " + filename, e); 75 | } 76 | } 77 | 78 | public static void saveGrammar(String grammarPath, String name, int index, Grammar grammar) { 79 | saveGrammar(getGrammarFilename(grammarPath, name, index), grammar); 80 | } 81 | 82 | public static void saveAllGrammar(String grammarPath, String name, Grammar grammar) { 83 | saveGrammar(getAllGrammarFilename(grammarPath, name), grammar); 84 | } 85 | 86 | public static Grammar loadGrammar(String grammarPath, String name, int index) { 87 | return loadGrammar(getGrammarFilename(grammarPath, name, index)); 88 | } 89 | 90 | public static Grammar loadAllGrammar(String grammarPath, String name) { 91 | return loadGrammar(getAllGrammarFilename(grammarPath, name)); 92 | } 93 | 94 | public static void learnGrammar(String grammarPath, String name, ProgramData data, ProgramExamples examples, int index) { 95 | String example = examples.getTrainExamples().get(index); 96 | Grammar grammar = GrammarSynthesis.getGrammarSingle(example, ProgramDataUtils.getQueryOracle(data)); 97 | saveGrammar(grammarPath, name, index, grammar); 98 | } 99 | 100 | public static void mergeGrammar(String grammarPath, String name, ProgramData data, ProgramExamples examples) { 101 | List roots = new ArrayList(); 102 | for(int i=0; i samples = fuzz.fuzzer.getSamples(program, grammar, fuzz, random); 96 | int pass = 0; 97 | int count = 0; 98 | for(String sample : samples) { 99 | Log.info("SAMPLE:"); 100 | Log.info(sample); 101 | if(ProgramDataUtils.getQueryOracle(program.data).query(sample)) { 102 | Log.info("PASS\n"); 103 | pass++; 104 | } else { 105 | Log.info("FAIL\n"); 106 | } 107 | count++; 108 | if(count >= fuzz.numIters) { 109 | break; 110 | } 111 | } 112 | Log.info("PASS RATE: " + (float)pass/fuzz.numIters); 113 | } 114 | 115 | public static void usage() { 116 | System.out.println("usage: java -jar glade.jar -mode [learn|fuzz|test] [-program [sed|grep|flex|xml|python|python-wrapped]] [-fuzzer [grammar|combined]] [-log ] [-verbose]"); 117 | System.out.println("note: -program option required if mode=learn or mode=fuzz"); 118 | System.out.println("note: -fuzzer option required if mode=fuzz"); 119 | System.out.println("note: -log defaults to log.txt"); 120 | System.exit(0); 121 | } 122 | 123 | private static Program getProgram(String programName) { 124 | if(programName == null) { usage(); } 125 | if(programName.equals("sed")) { 126 | return Program.SED; 127 | } else if(programName.equals("grep")) { 128 | return Program.GREP; 129 | } else if(programName.equals("flex")) { 130 | return Program.FLEX; 131 | } else if(programName.equals("xml")) { 132 | return Program.XML; 133 | } else if(programName.equals("python")) { 134 | return Program.PYTHON; 135 | } else if(programName.equals("python-wrapped")) { 136 | return Program.PYTHON_WRAPPED; 137 | } else { 138 | usage(); 139 | return null; 140 | } 141 | } 142 | 143 | private static Fuzzer getFuzzer(String fuzzerName) { 144 | if(fuzzerName == null) { usage(); } 145 | if(fuzzerName.equals("grammar")) { 146 | return Fuzzer.GRAMMAR; 147 | } else if(fuzzerName.equals("combined")) { 148 | return Fuzzer.COMBINED; 149 | } else { 150 | usage(); 151 | return null; 152 | } 153 | } 154 | 155 | public static void run(String[] args) { 156 | String mode = null; 157 | String programName = null; 158 | String fuzzerName = null; 159 | String logName = null; 160 | boolean verbose = false; 161 | 162 | int i = 0; 163 | while(i < args.length) { 164 | if(args[i].equals("-mode")) { 165 | if(mode != null) { usage(); } 166 | i++; 167 | mode = args[i]; 168 | } else if(args[i].equals("-program")) { 169 | if(programName != null) { usage(); } 170 | i++; 171 | programName = args[i]; 172 | } else if(args[i].equals("-fuzzer")) { 173 | if(fuzzerName != null) { usage(); } 174 | i++; 175 | fuzzerName = args[i]; 176 | } else if(args[i].equals("-log")) { 177 | if(logName != null) { usage(); } 178 | i++; 179 | logName = args[i]; 180 | } else if(args[i].equals("-verbose")) { 181 | verbose = true; 182 | } else { 183 | usage(); 184 | } 185 | 186 | i++; 187 | } 188 | 189 | try { 190 | if(mode == null) { usage(); } 191 | 192 | if(logName == null) { 193 | logName = "log.txt"; 194 | } 195 | Log.init(logName, verbose); 196 | 197 | if(mode.equals("test")) { 198 | int pass = 0; 199 | int fail = 0; 200 | List programs = new ArrayList(); 201 | if(programName == null) { 202 | programs.addAll(Arrays.asList(new Program[]{Program.SED, Program.GREP, Program.FLEX, Program.XML, Program.PYTHON, Program.PYTHON_WRAPPED})); 203 | } else { 204 | programs.add(getProgram(programName)); 205 | } 206 | List passedPrograms = new ArrayList(); 207 | List failedPrograms = new ArrayList(); 208 | for(Program program : programs) { 209 | IntPair curResults = runTest(program.getSettings()); 210 | (curResults.fail == 0 ? passedPrograms : failedPrograms).add(program.getSettings().name); 211 | pass += curResults.pass; 212 | fail += curResults.fail; 213 | } 214 | int total = pass + fail; 215 | Log.info("PASSED: " + pass + "/" + total); 216 | Log.info("FAILED: " + fail + "/" + total); 217 | Log.info("PROGRAMS PASSED:"); 218 | for(String passedProgram : passedPrograms) { 219 | Log.info(passedProgram); 220 | } 221 | Log.info("PROGRAMS FAILED:"); 222 | for(String failedProgram : failedPrograms) { 223 | Log.info(failedProgram); 224 | } 225 | } else if(mode.equals("learn")) { 226 | GrammarSettings grammarSettings = getDefaultGrammarSettings(); 227 | Program program = getProgram(programName); 228 | long time = System.currentTimeMillis(); 229 | runLearn(program.getSettings(), grammarSettings); 230 | Log.info("TOTAL TIME: " + ((System.currentTimeMillis() - time)/1000.0) + " seconds"); 231 | } else if(mode.equals("fuzz")) { 232 | Random random = new Random(); 233 | GrammarSettings grammarSettings = getDefaultGrammarSettings(); 234 | Program program = getProgram(programName); 235 | Fuzzer fuzzer = getFuzzer(fuzzerName); 236 | FuzzSettings fuzzerSettings = getDefaultFuzzSettings(random, fuzzer); 237 | runFuzz(program.getSettings(), grammarSettings, fuzzerSettings, random); 238 | } else { 239 | usage(); 240 | } 241 | } catch(Exception e) { 242 | Log.err(e); 243 | } 244 | } 245 | 246 | public static void main(String[] args) { 247 | run(args); 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /src/glade/main/ProgramDataUtils.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.main; 16 | 17 | import glade.util.OracleUtils.DiscriminativeOracle; 18 | import glade.util.OracleUtils.Oracle; 19 | import glade.util.OracleUtils.WrappedOracle; 20 | import glade.util.OracleUtils.Wrapper; 21 | import glade.util.ShellUtils.CommandFactory; 22 | import glade.util.ShellUtils.ExecuteDiscriminativeOracle; 23 | import glade.util.ShellUtils.ShellOracle; 24 | import glade.util.ShellUtils.SimpleCommandFactory; 25 | import glade.util.Utils; 26 | 27 | import java.io.BufferedReader; 28 | import java.io.File; 29 | import java.io.FileReader; 30 | import java.io.IOException; 31 | import java.util.ArrayList; 32 | import java.util.List; 33 | 34 | public class ProgramDataUtils { 35 | public static class FileParameters { 36 | public final String queryProg; 37 | public final String filename; 38 | public final String auxFilename; 39 | public final long timeout; 40 | public final String exampleTrainPath; 41 | public FileParameters(String queryProg, String filename, String auxFilename, long timeout, String exampleTrainPath) { 42 | this.queryProg = queryProg; 43 | this.filename = filename; 44 | this.auxFilename = auxFilename; 45 | this.timeout = timeout; 46 | this.exampleTrainPath = exampleTrainPath; 47 | } 48 | } 49 | 50 | public static interface ProgramData { 51 | public abstract Oracle getOracle(); 52 | } 53 | 54 | public static DiscriminativeOracle getQueryOracle(ProgramData data) { 55 | return new ExecuteDiscriminativeOracle(data.getOracle()); 56 | } 57 | 58 | public static interface ProgramExamples { 59 | public abstract List getTrainExamples(); 60 | public abstract List getEmptyExamples(); 61 | } 62 | 63 | public static class ShellProgramData implements ProgramData { 64 | private final FileParameters file; 65 | private final CommandFactory factory; 66 | private final String exePath; 67 | private final boolean isError; 68 | 69 | public ShellProgramData(FileParameters file, CommandFactory factory, String exePath, boolean isError) { 70 | this.file = file; 71 | this.factory = factory; 72 | this.exePath = exePath; 73 | this.isError = isError; 74 | } 75 | 76 | public ShellProgramData(FileParameters file, String exePath, boolean isError) { 77 | this(file, new SimpleCommandFactory(), exePath, isError); 78 | } 79 | 80 | @Override 81 | public Oracle getOracle() { 82 | return new ShellOracle(this.file.filename, this.file.auxFilename, this.factory.getCommand(this.file.filename, this.file.auxFilename, this.file.queryProg + File.separator + this.exePath), this.isError, this.file.timeout); 83 | } 84 | } 85 | 86 | public static class WrappedProgramData implements ProgramData { 87 | private final ProgramData data; 88 | private final Wrapper wrapper; 89 | 90 | public WrappedProgramData(ProgramData data, Wrapper wrapper) { 91 | this.data = data; 92 | this.wrapper = wrapper; 93 | } 94 | 95 | @Override 96 | public Oracle getOracle() { 97 | return new WrappedOracle(this.data.getOracle(), this.wrapper); 98 | } 99 | } 100 | 101 | public static class SingleFileProgramExamples implements ProgramExamples { 102 | private final FileParameters file; 103 | private final String name; 104 | private final String filename; 105 | private final String emptyExample; 106 | private final Wrapper exampleProcessor; 107 | 108 | public SingleFileProgramExamples(FileParameters file, String name, String filename, String emptyExample, Wrapper exampleProcessor) { 109 | this.file = file; 110 | this.name = name; 111 | this.filename = filename; 112 | this.emptyExample = emptyExample; 113 | this.exampleProcessor = exampleProcessor; 114 | } 115 | 116 | private List getExamples(String path) { 117 | try { 118 | List examples = new ArrayList(); 119 | BufferedReader br = new BufferedReader(new FileReader(path + File.separator + this.name + File.separator + this.filename)); 120 | String line; 121 | while((line = br.readLine()) != null) { 122 | examples.add(this.exampleProcessor.wrap(line)); 123 | } 124 | br.close(); 125 | return examples; 126 | } catch(IOException e) { 127 | throw new RuntimeException("Error reading examples!", e); 128 | } 129 | } 130 | 131 | @Override 132 | public List getTrainExamples() { 133 | return this.getExamples(this.file.exampleTrainPath); 134 | } 135 | 136 | @Override 137 | public List getEmptyExamples() { 138 | return Utils.getList(this.emptyExample); 139 | } 140 | } 141 | 142 | public static class MultiFileProgramExamples implements ProgramExamples { 143 | private final FileParameters file; 144 | private final String name; 145 | private final String extension; 146 | private final String emptyExample; 147 | private final Wrapper exampleProcessor; 148 | 149 | public MultiFileProgramExamples(FileParameters file, String name, String extension, String emptyExample, Wrapper exampleProcessor) { 150 | this.name = name; 151 | this.extension = extension; 152 | this.emptyExample = emptyExample; 153 | this.exampleProcessor = exampleProcessor; 154 | this.file = file; 155 | } 156 | 157 | private List getExamples(String path) { 158 | List examples = new ArrayList(); 159 | for(File file : new File(path, this.name).listFiles()) { 160 | if(!file.getName().endsWith(this.extension)) { 161 | continue; 162 | } 163 | try { 164 | StringBuilder sb = new StringBuilder(); 165 | BufferedReader br = new BufferedReader(new FileReader(file)); 166 | String line; 167 | while((line = br.readLine()) != null) { 168 | sb.append(line).append("\n"); 169 | } 170 | br.close(); 171 | examples.add(this.exampleProcessor.wrap(sb.toString())); 172 | } catch(IOException e) { 173 | throw new RuntimeException("Error reading examples!", e); 174 | } 175 | } 176 | return examples; 177 | } 178 | 179 | @Override 180 | public List getTrainExamples() { 181 | return this.getExamples(this.file.exampleTrainPath); 182 | } 183 | 184 | @Override 185 | public List getEmptyExamples() { 186 | return Utils.getList(this.emptyExample); 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/glade/main/Settings.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.main; 16 | 17 | import glade.constants.program.FlexData; 18 | import glade.constants.program.GrepData; 19 | import glade.constants.program.PythonData; 20 | import glade.constants.program.PythonWrappedData; 21 | import glade.constants.program.SedData; 22 | import glade.constants.program.XmlData; 23 | import glade.grammar.fuzz.GrammarFuzzer.CombinedMutationSampler; 24 | import glade.grammar.fuzz.GrammarFuzzer.GrammarMutationSampler; 25 | import glade.grammar.fuzz.GrammarFuzzer.GrammarSampler; 26 | import glade.grammar.fuzz.GrammarFuzzer.SampleParameters; 27 | import glade.main.ProgramDataUtils.ProgramData; 28 | import glade.main.ProgramDataUtils.ProgramExamples; 29 | 30 | import java.util.ArrayList; 31 | import java.util.Random; 32 | 33 | public class Settings { 34 | public static class GrammarSettings { 35 | public final String grammarPath; 36 | public GrammarSettings(String grammarPath) { 37 | this.grammarPath = grammarPath; 38 | } 39 | } 40 | 41 | public static class ProgramSettings { 42 | public final ProgramData data; 43 | public final ProgramExamples examples; 44 | public final String name; 45 | public ProgramSettings(ProgramData data, ProgramExamples examples, String name) { 46 | this.data = data; 47 | this.examples = examples; 48 | this.name = name; 49 | } 50 | } 51 | 52 | public static class FuzzSettings { 53 | public final int numMutations; 54 | public final int numIters; 55 | public final int maxLength; 56 | public final SampleParameters sample; 57 | public final Fuzzer fuzzer; 58 | public FuzzSettings(int numMutations, int numIters, int maxLength, SampleParameters sample, Fuzzer fuzzer) { 59 | this.numMutations = numMutations; 60 | this.numIters = numIters; 61 | this.maxLength = maxLength; 62 | this.sample = sample; 63 | this.fuzzer = fuzzer; 64 | } 65 | } 66 | 67 | public static enum Program { 68 | XML, GREP, SED, FLEX, PYTHON, PYTHON_WRAPPED; 69 | public ProgramSettings getSettings() { 70 | switch(this) { 71 | case XML: 72 | return new ProgramSettings(XmlData.XML_DATA, XmlData.XML_EXAMPLES, XmlData.XML_NAME); 73 | case PYTHON: 74 | return new ProgramSettings(PythonData.PYTHON_DATA, PythonData.PYTHON_EXAMPLES, PythonData.PYTHON_NAME); 75 | case PYTHON_WRAPPED: 76 | return new ProgramSettings(PythonWrappedData.PYTHON_WRAPPED_DATA, PythonWrappedData.PYTHON_EXAMPLES, PythonWrappedData.PYTHON_WRAPPED_NAME); 77 | case GREP: 78 | return new ProgramSettings(GrepData.GREP_DATA, GrepData.GREP_EXAMPLES, GrepData.GREP_NAME); 79 | case SED: 80 | return new ProgramSettings(SedData.SED_DATA, SedData.SED_EXAMPLES, SedData.SED_NAME); 81 | case FLEX: 82 | return new ProgramSettings(FlexData.FLEX_DATA, FlexData.FLEX_EXAMPLES, FlexData.FLEX_NAME); 83 | default: 84 | throw new RuntimeException("Invalid settings!"); 85 | } 86 | } 87 | } 88 | 89 | public static enum Fuzzer { 90 | NONE, EMPTY, TEST, TRAIN, NAIVE, GRAMMAR, GRAMMAR_NO_SEED, COMBINED; 91 | public Iterable getSamples(ProgramSettings program, GrammarSettings grammar, FuzzSettings fuzz, Random random) { 92 | switch(this) { 93 | case NONE: 94 | return new ArrayList(); 95 | case EMPTY: 96 | return program.examples.getEmptyExamples(); 97 | case TRAIN: 98 | return program.examples.getTrainExamples(); 99 | case GRAMMAR: 100 | return new GrammarMutationSampler(GrammarDataUtils.loadAllGrammar(grammar.grammarPath, program.name), fuzz.sample, fuzz.maxLength, fuzz.numMutations, random); 101 | case GRAMMAR_NO_SEED: 102 | return new GrammarSampler(GrammarDataUtils.loadAllGrammar(grammar.grammarPath, program.name), fuzz.sample, random); 103 | case COMBINED: 104 | Iterable grammarMutationSampler = new GrammarMutationSampler(GrammarDataUtils.loadAllGrammar(grammar.grammarPath, program.name), fuzz.sample, fuzz.maxLength, fuzz.numMutations, random); 105 | return new CombinedMutationSampler(grammarMutationSampler, fuzz.numMutations, random); 106 | default: 107 | throw new RuntimeException("Invalid settings!"); 108 | } 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/glade/util/CharacterUtils.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.util; 16 | 17 | import java.util.ArrayList; 18 | import java.util.Collection; 19 | import java.util.HashSet; 20 | import java.util.List; 21 | import java.util.Set; 22 | 23 | public class CharacterUtils { 24 | public static boolean isNewlineOrTabCharacter(char c) { 25 | return c == '\n' || c == '\t'; 26 | } 27 | 28 | public static boolean isNumeric(char c) { 29 | return c >= '0' && c <= '9'; 30 | } 31 | 32 | public static boolean isAlphaUpperCase(char c) { 33 | return c >= 'A' && c <= 'Z'; 34 | } 35 | 36 | public static boolean isAlphaLowerCase(char c) { 37 | return c >= 'a' && c <= 'z'; 38 | } 39 | 40 | public static boolean isAlpha(char c) { 41 | return isAlphaUpperCase(c) || isAlphaLowerCase(c); 42 | } 43 | 44 | public static boolean isAlphaNumeric(char c) { 45 | return isAlpha(c) || isNumeric(c); 46 | } 47 | 48 | public static boolean isNonAlphaNumeric(char c) { 49 | return !isNumeric(c) && !isAlphaUpperCase(c) && !isAlphaLowerCase(c); 50 | } 51 | 52 | public static boolean isSingleQuote(char c) { 53 | return c == 39; 54 | } 55 | 56 | public static boolean isDoubleQuote(char c) { 57 | return c == 34; 58 | } 59 | 60 | public static class CharacterGeneralization { 61 | public final Set triggers; 62 | public final List characters; 63 | public final List checks; 64 | public CharacterGeneralization(Collection triggers, Collection characters, Collection checks) { 65 | this.triggers = new HashSet(triggers); 66 | this.characters = new ArrayList(characters); 67 | this.checks = new ArrayList(checks); 68 | } 69 | } 70 | 71 | private static final List allCharacters = new ArrayList(); 72 | private static final List numericCharacters = new ArrayList(); 73 | private static final List alphaUpperCaseCharacters = new ArrayList(); 74 | private static final List alphaLowerCaseCharacters = new ArrayList(); 75 | private static final List nonAlphaNumericCharacters = new ArrayList(); 76 | private static final List numericChecks = new ArrayList(); 77 | private static final List alphaUpperCaseChecks = new ArrayList(); 78 | private static final List alphaLowerCaseChecks = new ArrayList(); 79 | private static final List generalizations = new ArrayList(); 80 | static { 81 | for(char c=0; c<128; c++) { 82 | allCharacters.add(c); 83 | if(isNumeric(c)) { 84 | numericCharacters.add(c); 85 | } else if(isAlphaUpperCase(c)) { 86 | alphaUpperCaseCharacters.add(c); 87 | } else if(isAlphaLowerCase(c)) { 88 | alphaLowerCaseCharacters.add(c); 89 | } else { 90 | nonAlphaNumericCharacters.add(c); 91 | } 92 | } 93 | numericChecks.add('0'); 94 | numericChecks.add('1'); 95 | numericChecks.add('9'); 96 | alphaUpperCaseChecks.add('E'); 97 | alphaUpperCaseChecks.add('Q'); 98 | alphaLowerCaseChecks.add('e'); 99 | alphaLowerCaseChecks.add('q'); 100 | for(char c : nonAlphaNumericCharacters) { 101 | List curC = Utils.getList(c); 102 | generalizations.add(new CharacterGeneralization(numericCharacters, curC, curC)); 103 | generalizations.add(new CharacterGeneralization(alphaLowerCaseCharacters, curC, curC)); 104 | generalizations.add(new CharacterGeneralization(alphaUpperCaseCharacters, curC, curC)); 105 | } 106 | generalizations.add(new CharacterGeneralization(numericCharacters, numericCharacters, numericChecks)); 107 | generalizations.add(new CharacterGeneralization(numericCharacters, alphaUpperCaseCharacters, alphaUpperCaseChecks)); 108 | generalizations.add(new CharacterGeneralization(numericCharacters, alphaLowerCaseCharacters, alphaLowerCaseChecks)); 109 | generalizations.add(new CharacterGeneralization(alphaUpperCaseCharacters, numericCharacters, numericChecks)); 110 | generalizations.add(new CharacterGeneralization(alphaUpperCaseCharacters, alphaUpperCaseCharacters, alphaUpperCaseChecks)); 111 | generalizations.add(new CharacterGeneralization(alphaUpperCaseCharacters, alphaLowerCaseCharacters, alphaLowerCaseChecks)); 112 | generalizations.add(new CharacterGeneralization(alphaLowerCaseCharacters, numericCharacters, numericChecks)); 113 | generalizations.add(new CharacterGeneralization(alphaLowerCaseCharacters, alphaUpperCaseCharacters, alphaUpperCaseChecks)); 114 | generalizations.add(new CharacterGeneralization(alphaLowerCaseCharacters, alphaLowerCaseCharacters, alphaLowerCaseChecks)); 115 | } 116 | 117 | public static List getAllCharacters() { 118 | return allCharacters; 119 | } 120 | 121 | public static List getNumericCharacters() { 122 | return numericCharacters; 123 | } 124 | 125 | public static List getAlphaUpperCaseCharacters() { 126 | return alphaUpperCaseCharacters; 127 | } 128 | 129 | public static List getAlphaLowerCaseCharacters() { 130 | return alphaLowerCaseCharacters; 131 | } 132 | 133 | public static List getNonAlphaNumericCharacters() { 134 | return nonAlphaNumericCharacters; 135 | } 136 | 137 | public static List getNumericChecks() { 138 | return numericChecks; 139 | } 140 | 141 | public static List getAlphaUpperCaseChecks() { 142 | return alphaUpperCaseChecks; 143 | } 144 | 145 | public static List getAlphaLowerCaseChecks() { 146 | return alphaLowerCaseChecks; 147 | } 148 | 149 | public static List getGeneralizations() { 150 | return generalizations; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/glade/util/Log.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.util; 16 | 17 | import java.io.File; 18 | import java.io.FileOutputStream; 19 | import java.io.IOException; 20 | import java.io.PrintWriter; 21 | 22 | public class Log { 23 | private static String logName = null; 24 | private static boolean verboseValue = false; 25 | 26 | public static void init(String log, boolean verbose) { 27 | logName = log; 28 | verboseValue = verbose; 29 | new File(logName).delete(); 30 | } 31 | 32 | public static void info(String s) { 33 | if(logName == null) { 34 | return; 35 | } 36 | if(verboseValue) { 37 | System.out.println(s); 38 | } 39 | try { 40 | PrintWriter pw = new PrintWriter(new FileOutputStream(logName, true)); 41 | pw.println(s); 42 | pw.close(); 43 | } catch(IOException e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | 48 | public static void err(Exception e) { 49 | if(verboseValue) { 50 | e.printStackTrace(); 51 | } else { 52 | System.err.println(e.getMessage()); 53 | } 54 | try { 55 | PrintWriter pw = new PrintWriter(new FileOutputStream(logName, true)); 56 | e.printStackTrace(pw); 57 | pw.close(); 58 | } catch(IOException ep) { 59 | ep.printStackTrace(); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/glade/util/OracleUtils.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.util; 16 | 17 | public class OracleUtils { 18 | public interface Oracle { 19 | public String execute(String query); 20 | } 21 | 22 | public interface DiscriminativeOracle { 23 | public abstract boolean query(String query); 24 | } 25 | 26 | public static interface Wrapper { 27 | public abstract String wrap(String input); 28 | } 29 | 30 | public static class IdentityWrapper implements Wrapper { 31 | @Override 32 | public String wrap(String input) { 33 | return input; 34 | } 35 | } 36 | 37 | public static class WrappedOracle implements Oracle { 38 | private final Oracle oracle; 39 | private final Wrapper wrapper; 40 | 41 | public WrappedOracle(Oracle oracle, Wrapper wrapper) { 42 | this.oracle = oracle; 43 | this.wrapper = wrapper; 44 | } 45 | 46 | @Override 47 | public String execute(String query) { 48 | return this.oracle.execute(this.wrapper.wrap(query)); 49 | } 50 | } 51 | 52 | public static class WrappedDiscriminativeOracle implements DiscriminativeOracle { 53 | private final DiscriminativeOracle oracle; 54 | private final Wrapper wrapper; 55 | 56 | public WrappedDiscriminativeOracle(DiscriminativeOracle oracle, Wrapper wrapper) { 57 | this.oracle = oracle; 58 | this.wrapper = wrapper; 59 | } 60 | 61 | @Override 62 | public boolean query(String query) { 63 | return this.oracle.query(this.wrapper.wrap(query)); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/glade/util/ShellUtils.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.util; 16 | 17 | import glade.util.OracleUtils.DiscriminativeOracle; 18 | import glade.util.OracleUtils.Oracle; 19 | 20 | import java.io.BufferedReader; 21 | import java.io.File; 22 | import java.io.FileWriter; 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.io.InputStreamReader; 26 | import java.util.concurrent.Callable; 27 | import java.util.concurrent.ExecutorService; 28 | import java.util.concurrent.Executors; 29 | import java.util.concurrent.Future; 30 | import java.util.concurrent.TimeUnit; 31 | 32 | public class ShellUtils { 33 | public static void delete(String filename) { 34 | new File(filename).delete(); 35 | } 36 | 37 | public static void write(String query, File file) { 38 | file.delete(); 39 | try { 40 | FileWriter fw = new FileWriter(file); 41 | fw.write(query); 42 | fw.close(); 43 | } catch(IOException e) { 44 | throw new RuntimeException("Error writing seed file!", e); 45 | } 46 | } 47 | 48 | public static void write(String query, String filename) { 49 | write(query, new File(filename)); 50 | } 51 | 52 | public static String read(InputStream input) { 53 | try { 54 | StringBuilder result = new StringBuilder(); 55 | BufferedReader br = new BufferedReader(new InputStreamReader(input)); 56 | String line; 57 | while((line = br.readLine()) != null) { 58 | result.append(line).append("\n"); 59 | } 60 | br.close(); 61 | return result.toString(); 62 | } catch (IOException e) { 63 | throw new RuntimeException("Error reading program output stream!", e); 64 | } 65 | } 66 | 67 | private static Process executeNoWait(String command) { 68 | try { 69 | String[] shellCommand = {"/bin/sh", "-c", command}; 70 | return Runtime.getRuntime().exec(shellCommand); 71 | } catch(Exception e) { 72 | throw new RuntimeException("Error executing command: " + command, e); 73 | } 74 | } 75 | 76 | public static String executeForStream(final String command, final boolean isError, long timeoutMillis) { 77 | final Process process = executeNoWait(command); 78 | Callable exec = new Callable() { 79 | public String call() { 80 | String result = read(isError ? process.getErrorStream() : process.getInputStream()); 81 | try { 82 | process.waitFor(); 83 | } catch (InterruptedException e) { 84 | throw new RuntimeException("Error executing command: " + command, e); 85 | } 86 | return result; 87 | } 88 | }; 89 | if(timeoutMillis == -1) { 90 | try { 91 | return exec.call(); 92 | } catch (Exception e) { 93 | throw new RuntimeException("Error executing command: " + command, e); 94 | } 95 | } else { 96 | final ExecutorService executor = Executors.newSingleThreadExecutor(); 97 | final Future future = executor.submit(exec); 98 | executor.shutdown(); 99 | String result; 100 | try { 101 | result = future.get(timeoutMillis, TimeUnit.MILLISECONDS); 102 | } catch(Exception e) { 103 | process.destroy(); 104 | result = "Timeout!"; 105 | } 106 | if(!executor.isTerminated()) { 107 | executor.shutdownNow(); 108 | } 109 | return result; 110 | } 111 | } 112 | 113 | public static interface CommandFactory { 114 | public abstract String getCommand(String filename, String auxFilename, String exePath); 115 | } 116 | 117 | public static class SimpleCommandFactory implements CommandFactory { 118 | @Override 119 | public String getCommand(String filename, String auxFilename, String exePath) { 120 | return exePath + " " + filename; 121 | } 122 | } 123 | 124 | public static class ShellOracle implements Oracle { 125 | private final String command; 126 | private final String filename; 127 | private final String auxFilename; 128 | private final boolean isError; 129 | private final long timeoutMillis; 130 | 131 | public ShellOracle(String filename, String auxFilename, String command, boolean isError, long timeoutMillis) { 132 | this.filename = filename; 133 | this.auxFilename = auxFilename; 134 | this.command = command; 135 | this.isError = isError; 136 | this.timeoutMillis = timeoutMillis; 137 | } 138 | 139 | @Override 140 | public String execute(String query) { 141 | write("", this.auxFilename); 142 | write(query, this.filename); 143 | String result = ShellUtils.executeForStream(this.command, this.isError, this.timeoutMillis); 144 | delete(this.auxFilename); 145 | delete(this.filename); 146 | return result; 147 | } 148 | } 149 | 150 | public static class ExecuteDiscriminativeOracle implements DiscriminativeOracle { 151 | private final Oracle oracle; 152 | 153 | public ExecuteDiscriminativeOracle(Oracle oracle) { 154 | this.oracle = oracle; 155 | } 156 | 157 | @Override 158 | public boolean query(String query) { 159 | return this.oracle.execute(query).matches("\\s*"); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/glade/util/Utils.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 glade.util; 16 | 17 | import java.util.ArrayList; 18 | import java.util.HashMap; 19 | import java.util.HashSet; 20 | import java.util.List; 21 | import java.util.Map; 22 | import java.util.Set; 23 | 24 | public class Utils { 25 | public static Map getInverse(List list) { 26 | Map inverse = new HashMap(); 27 | for(int i=0; i List getList(T ... ts) { 35 | List tlist = new ArrayList(); 36 | for(T t : ts) { 37 | tlist.add(t); 38 | } 39 | return tlist; 40 | } 41 | 42 | public static class MultivalueMap extends HashMap> { 43 | private static final long serialVersionUID = -6390444829513305915L; 44 | 45 | public void add(K k, V v) { 46 | ensure(k).add(v); 47 | } 48 | 49 | public Set ensure(K k) { 50 | Set vSet = super.get(k); 51 | if(vSet == null) { 52 | super.put(k, vSet = new HashSet()); 53 | } 54 | return vSet; 55 | } 56 | 57 | @Override 58 | public Set get(Object k) { 59 | Set vSet = super.get(k); 60 | return vSet == null ? new HashSet() : vSet; 61 | } 62 | } 63 | 64 | public static class Maybe { 65 | private T t; 66 | public Maybe(T t) { 67 | this.t = t; 68 | } 69 | public Maybe() { 70 | this.t = null; 71 | } 72 | public T getT() { 73 | if(this.t != null) { 74 | return t; 75 | } 76 | throw new RuntimeException("Invalid access!"); 77 | } 78 | public boolean hasT() { 79 | return this.t != null; 80 | } 81 | public T getTOr(T t) { 82 | return this.hasT() ? this.getT() : t; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /test/main/Test.java: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Stanford University 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 main; 16 | 17 | import glade.grammar.fuzz.GrammarFuzzer.GrammarMutationSampler; 18 | import glade.grammar.fuzz.GrammarFuzzer.SampleParameters; 19 | import glade.grammar.GrammarUtils.Grammar; 20 | import glade.grammar.synthesize.GrammarSynthesis; 21 | import glade.util.Log; 22 | import glade.util.OracleUtils.DiscriminativeOracle; 23 | 24 | import java.util.Arrays; 25 | import java.util.List; 26 | import java.util.Random; 27 | import java.util.Stack; 28 | 29 | public class Test { 30 | // encodes language of matching parentheses over \Sigma = { '(', ')', '[', ']', '{', '}' } 31 | public static class TestOracle implements DiscriminativeOracle { 32 | // returns true if query is a string of matching parentheses 33 | public boolean query(String query) { 34 | Stack stack = new Stack(); 35 | for(int i=0; i getTrainExamples() { 58 | return Arrays.asList(new String[]{"{([][])([][])}{[()()][()()]}"}); 59 | } 60 | 61 | public static SampleParameters getSampleParameters() { 62 | return new SampleParameters(new double[]{0.2, 0.2, 0.2, 0.4}, // (multinomial) distribution of repetitions 63 | 0.8, // probability of using recursive production 64 | 0.1, // probability of a uniformly random character (vs. a special character) 65 | 100); // max number of steps before timing out 66 | } 67 | 68 | 69 | public static void main(String[] args) { 70 | // number of samples to print 71 | int numSamples = 10; 72 | 73 | // log settings 74 | String logName = "log.txt"; 75 | boolean verbose = true; 76 | 77 | // seed for random number generator 78 | int seed = 0; 79 | 80 | // fuzzer settings 81 | int maxLen = 1000; // max length of a sample 82 | int numMut = 20; // number of mutations to seed input 83 | SampleParameters sampleParams = getSampleParameters(); // sampling parameters 84 | 85 | // enable logging 86 | Log.init(logName, verbose); 87 | 88 | // input: query oracle 89 | DiscriminativeOracle oracle = new TestOracle(); 90 | 91 | // input: (positive) training examples 92 | List examples = getTrainExamples(); 93 | 94 | // learn grammar 95 | Grammar grammar = GrammarSynthesis.getGrammarMultiple(examples, oracle); 96 | 97 | // fuzz using grammar 98 | Iterable samples = new GrammarMutationSampler(grammar, sampleParams, maxLen, numMut, new Random(seed)); 99 | 100 | int pass = 0; 101 | int count = 0; 102 | for(String sample : samples) { 103 | Log.info("SAMPLE: " + sample); 104 | if(oracle.query(sample)) { 105 | Log.info("PASS"); 106 | pass++; 107 | } else { 108 | Log.info("FAIL"); 109 | } 110 | Log.info(""); 111 | count++; 112 | if(count >= numSamples) { 113 | break; 114 | } 115 | } 116 | Log.info("PASS RATE: " + (float)pass/numSamples); 117 | } 118 | } --------------------------------------------------------------------------------