├── bb.edn ├── deps.edn ├── .gitignore ├── CHANGELOG.md ├── script └── changelog.clj ├── .circleci └── config.yml ├── test-resources └── commit-msg-grammar.txt ├── README.md ├── scratch.clj ├── src └── instaparse │ └── core.bb ├── test.clj └── LICENSE /bb.edn: -------------------------------------------------------------------------------- 1 | {:paths ["src"]} 2 | -------------------------------------------------------------------------------- /deps.edn: -------------------------------------------------------------------------------- 1 | {:paths ["src"]} 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cpcache 2 | .cache 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | [instaparse-bb](https://github.com/babashka/instaparse-bb): Use [instaparse](https://github.com/Engelberg/instaparse) from babashka 4 | 5 | ## 0.0.6 6 | 7 | - Bump pod, fixes failure handling ([@cap10morgan](https://github.com/cap10morgan)) 8 | 9 | ## 0.0.5 10 | 11 | - expose span function ([@cap10morgan](https://github.com/cap10morgan)) 12 | 13 | ## 0.0.4 14 | 15 | - added defparser macro 16 | - support regexes in grammar (by bumping pod to 0.0.4) 17 | 18 | ## 0.0.3 19 | 20 | - Upgrade pod to 0.0.3 ([@judepayne](https://github.com/judepayne)) 21 | - Expose new functions `parses` and `transform` ([@judepayne](https://github.com/judepayne)) 22 | -------------------------------------------------------------------------------- /script/changelog.clj: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bb 2 | 3 | (ns changelog 4 | (:require [clojure.string :as str])) 5 | 6 | (let [changelog (slurp "CHANGELOG.md") 7 | replaced (str/replace changelog 8 | #" #(\d+)" 9 | (fn [[_ issue after]] 10 | (format " [#%s](https://github.com/babashka/instaparse-bb/issues/%s)%s" 11 | issue issue (str after)))) 12 | replaced (str/replace replaced 13 | #"@([a-zA-Z0-9-_]+)([, \.)])" 14 | (fn [[_ name after]] 15 | (format "[@%s](https://github.com/%s)%s" 16 | name name after)))] 17 | (spit "CHANGELOG.md" replaced)) 18 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Use the latest 2.1 version of CircleCI pipeline process engine. 2 | # See: https://circleci.com/docs/2.0/configuration-reference 3 | # For a detailed guide to building and testing with clojure, read the docs: 4 | # https://circleci.com/docs/2.0/language-clojure/ for more details 5 | version: 2.1 6 | 7 | jobs: 8 | test: 9 | docker: 10 | # specify the version you desire here 11 | - image: circleci/clojure:lein-2.9.5 12 | 13 | working_directory: ~/repo 14 | 15 | environment: 16 | LEIN_ROOT: "true" 17 | # Customize the JVM maximum heap limit 18 | JVM_OPTS: -Xmx3200m 19 | 20 | # Add steps to the job 21 | # See: https://circleci.com/docs/2.0/configuration-reference/#steps 22 | steps: 23 | - checkout 24 | 25 | - run: 26 | name: Bootsrap 27 | command: | 28 | curl -sLO https://raw.githubusercontent.com/babashka/babashka/master/install 29 | chmod +x install 30 | sudo ./install 31 | 32 | - save_cache: 33 | paths: 34 | - ~/.m2 35 | key: v1-dependencies-{{ checksum "project.clj" }} 36 | 37 | # run tests! 38 | - run: 39 | name: Run tests 40 | command: bb test.clj 41 | 42 | workflows: 43 | sample: 44 | jobs: 45 | - test 46 | -------------------------------------------------------------------------------- /test-resources/commit-msg-grammar.txt: -------------------------------------------------------------------------------- 1 | = (HEADER FOOTER GIT-REPORT? *) 2 | / (HEADER BODY ( FOOTER)? GIT-REPORT? *) 3 | / (HEADER BODY GIT-REPORT? *) 4 | / (HEADER GIT-REPORT? *); 5 |
= TYPE (<'('>SCOPE<')'>)? <':'> SUBJECT; 6 | TYPE = 'feat' | 'fix' | 'refactor' | 'perf' | 'style' | 'test' | 'docs' | 'build' | 'ops' | 'chore'; 7 | SCOPE = #'[a-zA-Z0-9]+'; 8 | SUBJECT = TEXT ISSUE-REF? TEXT? !'.'; 9 | BODY = (!PRE-FOOTER PARAGRAPH) / (!PRE-FOOTER PARAGRAPH ( PARAGRAPH)*); 10 | PARAGRAPH = (ISSUE-REF / TEXT / (NEWLINE !NEWLINE))+; 11 | PRE-FOOTER = NEWLINE+ FOOTER; 12 | FOOTER = FOOTER-ELEMENT ( FOOTER-ELEMENT)*; 13 | FOOTER-ELEMENT = FOOTER-TOKEN <':'> FOOTER-VALUE; 14 | FOOTER-TOKEN = ('BREAKING CHANGE' (<'('>SCOPE<')'>)?) / #'[a-zA-Z\-^\#]+'; 15 | FOOTER-VALUE = (ISSUE-REF / TEXT)+; 16 | GIT-REPORT = ( / ) COMMENT*; 17 | COMMENT = <'#'> #'[^\n]*' ; 18 | ISSUE-REF = <'#'> ISSUE-ID; 19 | ISSUE-ID = #'([A-Z]+\-)?[0-9]+'; 20 | TEXT = #'[^\n\#]+'; 21 | SPACE = ' '; 22 | WHITESPACE = #'\s'; 23 | NEWLINE = <'\n'>; 24 | EMPTY-LINE = <'\n\n'>; 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # instaparse-bb 2 | 3 | A library that loads and wraps [pod-babashka-instaparse](https://github.com/babashka/pod-babashka-instaparse). 4 | 5 | This library can be safely included on your classpath alongside the regular 6 | [instaparse](https://github.com/Engelberg/instaparse) without causing issues for 7 | JVM Clojure, since it only has `.bb` files which do not conflict with `.clj` 8 | files. 9 | 10 | ## Installation 11 | 12 | Add this library to your `bb.edn` in the `:deps` map: 13 | 14 | ``` clojure 15 | io.github.babashka/instaparse-bb {:git/sha ""} 16 | ``` 17 | 18 | Replace `` with the latest SHA of this repo or use a tagged version. 19 | 20 | ## API 21 | 22 | Only a subset of instaparse is exposed. If you are missing functionality, please create an issue. 23 | 24 | ### instaparse.core 25 | 26 | - `parser` 27 | - `parse` 28 | - `parses` 29 | - `failure?` 30 | - `transform` 31 | - `defparser` 32 | 33 | ## Differences with instaparse 34 | 35 | none for currently exposed functionality 36 | 37 | ## Example 38 | 39 | ``` clojure 40 | (require '[instaparse.core :as insta]) 41 | 42 | (def as-and-bs 43 | (insta/parser 44 | "S = AB* 45 | AB = A B 46 | A = 'a'+ 47 | B = 'b'+")) 48 | 49 | (prn (insta/parse as-and-bs "aaaaabbbaaaabb")) 50 | 51 | (prn (as-and-bs "aaaaabbbaaaabb")) 52 | 53 | (def failure (insta/parse as-and-bs "xaaaaabbbaaaabb")) 54 | 55 | (prn failure) 56 | 57 | (prn :failure? (insta/failure? failure)) 58 | ``` 59 | 60 | ## License 61 | 62 | Copyright © 2023 Michiel Borkent 63 | 64 | Distributed under the EPL 1.0 license, same as Instaparse and Clojure. See LICENSE. 65 | -------------------------------------------------------------------------------- /scratch.clj: -------------------------------------------------------------------------------- 1 | (require '[instaparse.core :as insta]) 2 | 3 | (def grammar 4 | "A PEG grammar to validate and parse conventional commit messages." 5 | (str 6 | " = (HEADER FOOTER GIT-REPORT? *) 7 | / ( HEADER BODY ( FOOTER)? GIT-REPORT? *) 8 | 9 | / (HEADER BODY GIT-REPORT? *) 10 | / (HEADER GIT-REPORT? *);" 11 | "
= TYPE (<'('>SCOPE<')'>)? <':'> SUBJECT;" 12 | "TYPE = 'feat' | 'fix' | 'refactor' | 'perf' | 'style' | 'test' | 'docs' | 'build' | 'ops' | 'chore';" 13 | "SCOPE = #'[a-zA-Z0-9]+';" 14 | "SUBJECT = TEXT ISSUE-REF? TEXT? !'.';" 15 | "BODY = (!PRE-FOOTER PARAGRAPH) / (!PRE-FOOTER PARAGRAPH ( PARAGRAPH)*);" 16 | "PARAGRAPH = (ISSUE-REF / TEXT / (NEWLINE !NEWLINE))+;" 17 | "PRE-FOOTER = NEWLINE+ FOOTER;" 18 | "FOOTER = FOOTER-ELEMENT ( FOOTER-ELEMENT)*;" 19 | "FOOTER-ELEMENT = FOOTER-TOKEN <':'> FOOTER-VALUE;" 20 | "FOOTER-TOKEN = ('BREAKING CHANGE' (<'('>SCOPE<')'>)?) / #'[a-zA-Z\\-^\\#]+';" 21 | "FOOTER-VALUE = (ISSUE-REF / TEXT)+;" 22 | "GIT-REPORT = ( / ) COMMENT*;" 23 | "COMMENT = <'#'> #'[^\\n]*' ;" 24 | "ISSUE-REF = <'#'> ISSUE-ID;" 25 | "ISSUE-ID = #'([A-Z]+\\-)?[0-9]+';" 26 | "TEXT = #'[^\\n\\#]+';" 27 | "SPACE = ' ';" 28 | "WHITESPACE = #'\\s';" 29 | "NEWLINE = <'\n'>;" 30 | "EMPTY-LINE = <'\n\n'>;")) 31 | 32 | (def parser (insta/parser grammar)) 33 | 34 | (insta/parse parser "feat: adding a new awesome feature") 35 | -------------------------------------------------------------------------------- /src/instaparse/core.bb: -------------------------------------------------------------------------------- 1 | (ns instaparse.core 2 | (:require [babashka.pods :as pods])) 3 | 4 | (pods/load-pod 5 | ;; for local dev: 6 | #_["clojure" "-Sdeps" "{:deps {ip/ip {:local/root \"/Users/borkdude/dev/pod-babashka-instaparse\"}}}" "-M" "-m" "pod.babashka.instaparse"] 7 | 'org.babashka/instaparse "0.0.6") 8 | 9 | (require '[pod.babashka.instaparse :as insta]) 10 | 11 | ;; transform fn implementation 12 | 13 | (defn- map-preserving-meta [f l] 14 | (with-meta (map f l) (meta l))) 15 | 16 | (defn- merge-meta- 17 | "A variation on with-meta that merges the existing metamap into the new metamap, 18 | rather than overwriting the metamap entirely." 19 | [obj metamap] 20 | (with-meta obj (merge metamap (meta obj)))) 21 | 22 | (defn- merge-meta 23 | "This variation of the merge-meta in gll does nothing if obj is not 24 | something that can have a metamap attached." 25 | [obj metamap] 26 | (if (instance? clojure.lang.IObj obj) 27 | (merge-meta- obj metamap) 28 | obj)) 29 | 30 | (defn- throw-illegal-argument-exception 31 | [& message] 32 | (let [^String text (apply str message)] 33 | (-> text 34 | IllegalArgumentException. 35 | throw))) 36 | 37 | (defn- enlive-transform 38 | [transform-map parse-tree] 39 | (let [transform (transform-map (:tag parse-tree))] 40 | (cond 41 | transform 42 | (merge-meta 43 | (apply transform (map (partial enlive-transform transform-map) 44 | (:content parse-tree))) 45 | (meta parse-tree)) 46 | (:tag parse-tree) 47 | (assoc parse-tree :content (map (partial enlive-transform transform-map) 48 | (:content parse-tree))) 49 | :else 50 | parse-tree))) 51 | 52 | (defn- hiccup-transform 53 | [transform-map parse-tree] 54 | (if (and (sequential? parse-tree) (seq parse-tree)) 55 | (if-let [transform (transform-map (first parse-tree))] 56 | (merge-meta 57 | (apply transform (map (partial hiccup-transform transform-map) 58 | (next parse-tree))) 59 | (meta parse-tree)) 60 | (with-meta 61 | (into [(first parse-tree)] 62 | (map (partial hiccup-transform transform-map) 63 | (next parse-tree))) 64 | (meta parse-tree))) 65 | parse-tree)) 66 | 67 | ;; Public functions 68 | 69 | (defprotocol Parser 70 | (parse [this & opts]) 71 | (parses [this & opts]) 72 | (pod-ref [this])) 73 | 74 | (defn parser [& args] 75 | (let [p (apply insta/parser args)] 76 | (reify 77 | clojure.lang.IFn 78 | (invoke [_ text] (insta/parse p text)) 79 | (invoke [_ text & opts] (apply insta/parse p text opts)) 80 | (applyTo [_ args] (apply insta/parse p args)) 81 | Parser 82 | (parse [_ & args] (apply insta/parse p args)) 83 | (parses [_ & args] (apply insta/parses p args)) 84 | (pod-ref [_] p)))) 85 | 86 | (defn failure? [& args] 87 | (apply insta/failure? args)) 88 | 89 | (defmacro defparser 90 | "Replicates the call semantics of the `defparser` macro from instaparse. 91 | String specifications are processed at macro-time, offering a performance boost." 92 | [name grammar & opts] 93 | (if (string? grammar) 94 | (let [p (apply parser grammar opts)] 95 | `(def ~name ~p)) 96 | `(def ~name (parser ~grammar ~@opts)))) 97 | 98 | (defn transform 99 | "Replicates the `transform` function from instaparse." 100 | [transform-map parse-tree] 101 | ;; Detect what kind of tree this is 102 | (cond 103 | (string? parse-tree) 104 | ;; This is a leaf of the tree that should pass through unchanged 105 | parse-tree 106 | 107 | (and (map? parse-tree) (:tag parse-tree)) 108 | ;; This is an enlive tree-seq 109 | (enlive-transform transform-map parse-tree) 110 | 111 | (and (vector? parse-tree) (keyword? (first parse-tree))) 112 | ;; This is a hiccup tree-seq 113 | (hiccup-transform transform-map parse-tree) 114 | 115 | (sequential? parse-tree) 116 | ;; This is either a sequence of parse results, or a tree 117 | ;; with a hidden root tag. 118 | (map-preserving-meta (partial transform transform-map) parse-tree) 119 | 120 | (insta/failure? parse-tree) 121 | ;; pass failures through unchanged 122 | parse-tree 123 | 124 | :else 125 | (throw-illegal-argument-exception 126 | "Invalid parse-tree, not recognized as either enlive or hiccup format."))) 127 | 128 | (defn span [m] (insta/span m)) 129 | -------------------------------------------------------------------------------- /test.clj: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bb 2 | 3 | (require '[instaparse.core :as insta] 4 | '[clojure.string :as str]) 5 | 6 | (def as-and-bs 7 | (insta/parser 8 | "S = AB* 9 | AB = A B 10 | A = 'a'+ 11 | B = 'b'+")) 12 | 13 | (assert (= [:S [:AB [:A "a" "a" "a" "a" "a"] [:B "b" "b" "b"]] [:AB [:A "a" "a" "a" "a"] [:B "b" "b"]]] (insta/parse as-and-bs "aaaaabbbaaaabb"))) 14 | 15 | (def failure (insta/parse as-and-bs "xaaaaabbbaaaabb")) 16 | 17 | (assert (insta/failure? failure) "should be true") 18 | 19 | (def commit-msg-grammar 20 | "A PEG grammar to validate and parse conventional commit messages." 21 | (str 22 | " = (HEADER FOOTER GIT-REPORT? *) 23 | / ( HEADER BODY ( FOOTER)? GIT-REPORT? *) 24 | / (HEADER BODY GIT-REPORT? *) 25 | / (HEADER GIT-REPORT? *);" 26 | "
= TYPE (<'('>SCOPE<')'>)? <':'> SUBJECT;" 27 | "TYPE = 'feat' | 'fix' | 'refactor' | 'perf' | 'style' | 'test' | 'docs' | 'build' | 'ops' | 'chore';" 28 | "SCOPE = #'[a-zA-Z0-9]+';" 29 | "SUBJECT = TEXT ISSUE-REF? TEXT? !'.';" 30 | "BODY = (!PRE-FOOTER PARAGRAPH) / (!PRE-FOOTER PARAGRAPH ( PARAGRAPH)*);" 31 | "PARAGRAPH = (ISSUE-REF / TEXT / (NEWLINE !NEWLINE))+;" 32 | "PRE-FOOTER = NEWLINE+ FOOTER;" 33 | "FOOTER = FOOTER-ELEMENT ( FOOTER-ELEMENT)*;" 34 | "FOOTER-ELEMENT = FOOTER-TOKEN <':'> FOOTER-VALUE;" 35 | "FOOTER-TOKEN = ('BREAKING CHANGE' (<'('>SCOPE<')'>)?) / #'[a-zA-Z\\-^\\#]+';" 36 | "FOOTER-VALUE = (ISSUE-REF / TEXT)+;" 37 | "GIT-REPORT = ( / ) COMMENT*;" 38 | "COMMENT = <'#'> #'[^\\n]*' ;" 39 | "ISSUE-REF = <'#'> ISSUE-ID;" 40 | "ISSUE-ID = #'([A-Z]+\\-)?[0-9]+';" 41 | "TEXT = #'[^\\n\\#]+';" 42 | "SPACE = ' ';" 43 | "WHITESPACE = #'\\s';" 44 | "NEWLINE = <'\n'>;" 45 | "EMPTY-LINE = <'\n\n'>;")) 46 | 47 | 48 | (def commit-msg-parser-hiccup (insta/parser commit-msg-grammar)) 49 | 50 | (def commit-msg-parser-enlive (insta/parser commit-msg-grammar :output-format :enlive)) 51 | 52 | (assert (= '([:TYPE "feat"] [:SUBJECT [:TEXT "adding a new awesome feature"]]) 53 | (insta/parse commit-msg-parser-hiccup "feat: adding a new awesome feature"))) 54 | 55 | (assert (= '("feat::" "ADDING A NEW AWESOME FEATURE") 56 | (insta/transform {:TEXT reverse 57 | :SUBJECT (comp str/reverse str/upper-case str/join) 58 | :TYPE (fn [t] (str t "::"))} 59 | (insta/parse commit-msg-parser-hiccup "feat: adding a new awesome feature")))) 60 | 61 | ;; test enlive 62 | 63 | (assert (= '({:tag :TYPE, :content ("feat")} 64 | {:tag :SUBJECT, 65 | :content ({:tag :TEXT, :content ("adding a new awesome feature")})}) 66 | (insta/parse commit-msg-parser-enlive "feat: adding a new awesome feature"))) 67 | 68 | (assert (= '("feat::" "ADDING A NEW AWESOME FEATURE") 69 | (insta/transform {:TEXT reverse 70 | :SUBJECT (comp str/reverse str/upper-case str/join) 71 | :TYPE (fn [t] (str t "::"))} 72 | (insta/parse commit-msg-parser-enlive "feat: adding a new awesome feature")))) 73 | 74 | ;; test slurp - note the slurp happens inside Clojure code in the pod. 75 | 76 | (assert (= (let [p (insta/parser "test-resources/commit-msg-grammar.txt")] 77 | (insta/parse p "feat: adding a new awesome feature")) 78 | '([:TYPE "feat"] [:SUBJECT [:TEXT "adding a new awesome feature"]]))) 79 | 80 | ;; test IFn - parser is directly callable as a function. 81 | 82 | (assert (= (commit-msg-parser-hiccup "feat: adding a new awesome feature") 83 | '([:TYPE "feat"] [:SUBJECT [:TEXT "adding a new awesome feature"]]))) 84 | 85 | 86 | ;; test defparser 87 | 88 | (defn tidy-string [s] 89 | (-> s str/trim-newline (str/replace #"\"" ""))) 90 | 91 | (def msecs-reg #"^\d*\.?\d*$") 92 | 93 | ;; "A parser to read the output of `time`." 94 | (insta/defparser elapsed-time-parser 95 | (str 96 | " = Msecs ;" 97 | "Preamable = \"Elapsed time: \";" 98 | "Postamble = \" msecs\";" 99 | " = #'[^ ]*'" )) 100 | 101 | (defn read-time [s] 102 | (->> s 103 | tidy-string 104 | (insta/parse elapsed-time-parser) 105 | first 106 | Float.)) 107 | 108 | ;; assert that most of the work is done at compile time with defparser when passed a string 109 | #_(assert (>)) 110 | ;; just evaluate the two times for now. 111 | 112 | (read-time (with-out-str (time (insta/parser "S = A B; A = 'a'+; B = 'b'+")))) 113 | (read-time (with-out-str (time (insta/defparser time-parser "S = A B; A = 'a'+; B = 'b'+")))) 114 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Eclipse Public License - v 1.0 2 | 3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 4 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 5 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 6 | 7 | 1. DEFINITIONS 8 | 9 | "Contribution" means: 10 | 11 | a) in the case of the initial Contributor, the initial code and documentation 12 | distributed under this Agreement, and 13 | b) in the case of each subsequent Contributor: 14 | i) changes to the Program, and 15 | ii) additions to the Program; 16 | 17 | where such changes and/or additions to the Program originate from and are 18 | distributed by that particular Contributor. A Contribution 'originates' from 19 | a Contributor if it was added to the Program by such Contributor itself or 20 | anyone acting on such Contributor's behalf. Contributions do not include 21 | additions to the Program which: (i) are separate modules of software 22 | distributed in conjunction with the Program under their own license 23 | agreement, and (ii) are not derivative works of the Program. 24 | 25 | "Contributor" means any person or entity that distributes the Program. 26 | 27 | "Licensed Patents" mean patent claims licensable by a Contributor which are 28 | necessarily infringed by the use or sale of its Contribution alone or when 29 | combined with the Program. 30 | 31 | "Program" means the Contributions distributed in accordance with this Agreement. 32 | 33 | "Recipient" means anyone who receives the Program under this Agreement, 34 | including all Contributors. 35 | 36 | 2. GRANT OF RIGHTS 37 | a) Subject to the terms of this Agreement, each Contributor hereby grants 38 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 39 | reproduce, prepare derivative works of, publicly display, publicly perform, 40 | distribute and sublicense the Contribution of such Contributor, if any, and 41 | such derivative works, in source code and object code form. 42 | b) Subject to the terms of this Agreement, each Contributor hereby grants 43 | Recipient a non-exclusive, worldwide, royalty-free patent license under 44 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 45 | transfer the Contribution of such Contributor, if any, in source code and 46 | object code form. This patent license shall apply to the combination of the 47 | Contribution and the Program if, at the time the Contribution is added by 48 | the Contributor, such addition of the Contribution causes such combination 49 | to be covered by the Licensed Patents. The patent license shall not apply 50 | to any other combinations which include the Contribution. No hardware per 51 | se is licensed hereunder. 52 | c) Recipient understands that although each Contributor grants the licenses to 53 | its Contributions set forth herein, no assurances are provided by any 54 | Contributor that the Program does not infringe the patent or other 55 | intellectual property rights of any other entity. Each Contributor 56 | disclaims any liability to Recipient for claims brought by any other entity 57 | based on infringement of intellectual property rights or otherwise. As a 58 | condition to exercising the rights and licenses granted hereunder, each 59 | Recipient hereby assumes sole responsibility to secure any other 60 | intellectual property rights needed, if any. For example, if a third party 61 | patent license is required to allow Recipient to distribute the Program, it 62 | is Recipient's responsibility to acquire that license before distributing 63 | the Program. 64 | d) Each Contributor represents that to its knowledge it has sufficient 65 | copyright rights in its Contribution, if any, to grant the copyright 66 | license set forth in this Agreement. 67 | 68 | 3. REQUIREMENTS 69 | 70 | A Contributor may choose to distribute the Program in object code form under its 71 | own license agreement, provided that: 72 | 73 | a) it complies with the terms and conditions of this Agreement; and 74 | b) its license agreement: 75 | i) effectively disclaims on behalf of all Contributors all warranties and 76 | conditions, express and implied, including warranties or conditions of 77 | title and non-infringement, and implied warranties or conditions of 78 | merchantability and fitness for a particular purpose; 79 | ii) effectively excludes on behalf of all Contributors all liability for 80 | damages, including direct, indirect, special, incidental and 81 | consequential damages, such as lost profits; 82 | iii) states that any provisions which differ from this Agreement are offered 83 | by that Contributor alone and not by any other party; and 84 | iv) states that source code for the Program is available from such 85 | Contributor, and informs licensees how to obtain it in a reasonable 86 | manner on or through a medium customarily used for software exchange. 87 | 88 | When the Program is made available in source code form: 89 | 90 | a) it must be made available under this Agreement; and 91 | b) a copy of this Agreement must be included with each copy of the Program. 92 | Contributors may not remove or alter any copyright notices contained within 93 | the Program. 94 | 95 | Each Contributor must identify itself as the originator of its Contribution, if 96 | any, in a manner that reasonably allows subsequent Recipients to identify the 97 | originator of the Contribution. 98 | 99 | 4. COMMERCIAL DISTRIBUTION 100 | 101 | Commercial distributors of software may accept certain responsibilities with 102 | respect to end users, business partners and the like. While this license is 103 | intended to facilitate the commercial use of the Program, the Contributor who 104 | includes the Program in a commercial product offering should do so in a manner 105 | which does not create potential liability for other Contributors. Therefore, if 106 | a Contributor includes the Program in a commercial product offering, such 107 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify 108 | every other Contributor ("Indemnified Contributor") against any losses, damages 109 | and costs (collectively "Losses") arising from claims, lawsuits and other legal 110 | actions brought by a third party against the Indemnified Contributor to the 111 | extent caused by the acts or omissions of such Commercial Contributor in 112 | connection with its distribution of the Program in a commercial product 113 | offering. The obligations in this section do not apply to any claims or Losses 114 | relating to any actual or alleged intellectual property infringement. In order 115 | to qualify, an Indemnified Contributor must: a) promptly notify the Commercial 116 | Contributor in writing of such claim, and b) allow the Commercial Contributor to 117 | control, and cooperate with the Commercial Contributor in, the defense and any 118 | related settlement negotiations. The Indemnified Contributor may participate in 119 | any such claim at its own expense. 120 | 121 | For example, a Contributor might include the Program in a commercial product 122 | offering, Product X. That Contributor is then a Commercial Contributor. If that 123 | Commercial Contributor then makes performance claims, or offers warranties 124 | related to Product X, those performance claims and warranties are such 125 | Commercial Contributor's responsibility alone. Under this section, the 126 | Commercial Contributor would have to defend claims against the other 127 | Contributors related to those performance claims and warranties, and if a court 128 | requires any other Contributor to pay any damages as a result, the Commercial 129 | Contributor must pay those damages. 130 | 131 | 5. NO WARRANTY 132 | 133 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN 134 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 135 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, 136 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each 137 | Recipient is solely responsible for determining the appropriateness of using and 138 | distributing the Program and assumes all risks associated with its exercise of 139 | rights under this Agreement , including but not limited to the risks and costs 140 | of program errors, compliance with applicable laws, damage to or loss of data, 141 | programs or equipment, and unavailability or interruption of operations. 142 | 143 | 6. DISCLAIMER OF LIABILITY 144 | 145 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 146 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 147 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST 148 | PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 149 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 150 | OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS 151 | GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 152 | 153 | 7. GENERAL 154 | 155 | If any provision of this Agreement is invalid or unenforceable under applicable 156 | law, it shall not affect the validity or enforceability of the remainder of the 157 | terms of this Agreement, and without further action by the parties hereto, such 158 | provision shall be reformed to the minimum extent necessary to make such 159 | provision valid and enforceable. 160 | 161 | If Recipient institutes patent litigation against any entity (including a 162 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 163 | (excluding combinations of the Program with other software or hardware) 164 | infringes such Recipient's patent(s), then such Recipient's rights granted under 165 | Section 2(b) shall terminate as of the date such litigation is filed. 166 | 167 | All Recipient's rights under this Agreement shall terminate if it fails to 168 | comply with any of the material terms or conditions of this Agreement and does 169 | not cure such failure in a reasonable period of time after becoming aware of 170 | such noncompliance. If all Recipient's rights under this Agreement terminate, 171 | Recipient agrees to cease use and distribution of the Program as soon as 172 | reasonably practicable. However, Recipient's obligations under this Agreement 173 | and any licenses granted by Recipient relating to the Program shall continue and 174 | survive. 175 | 176 | Everyone is permitted to copy and distribute copies of this Agreement, but in 177 | order to avoid inconsistency the Agreement is copyrighted and may only be 178 | modified in the following manner. The Agreement Steward reserves the right to 179 | publish new versions (including revisions) of this Agreement from time to time. 180 | No one other than the Agreement Steward has the right to modify this Agreement. 181 | The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation 182 | may assign the responsibility to serve as the Agreement Steward to a suitable 183 | separate entity. Each new version of the Agreement will be given a 184 | distinguishing version number. The Program (including Contributions) may always 185 | be distributed subject to the version of the Agreement under which it was 186 | received. In addition, after a new version of the Agreement is published, 187 | Contributor may elect to distribute the Program (including its Contributions) 188 | under the new version. Except as expressly stated in Sections 2(a) and 2(b) 189 | above, Recipient receives no rights or licenses to the intellectual property of 190 | any Contributor under this Agreement, whether expressly, by implication, 191 | estoppel or otherwise. All rights in the Program not expressly granted under 192 | this Agreement are reserved. 193 | 194 | This Agreement is governed by the laws of the State of New York and the 195 | intellectual property laws of the United States of America. No party to this 196 | Agreement will bring a legal action under this Agreement more than one year 197 | after the cause of action arose. Each party waives its rights to a jury trial in 198 | any resulting litigation. 199 | --------------------------------------------------------------------------------