├── .gitignore ├── .jshintrc ├── .travis.yml ├── Gruntfile.js ├── README.md ├── grammar └── ingreedy.peg ├── package.json ├── spec ├── AmountParsingSpec.js ├── IngreedySpec.js └── UnitParsingSpec.js └── src └── parser.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "curly" : true, 3 | "eqeqeq" : true, 4 | "immed" : true, 5 | "latedef" : true, 6 | "newcap" : true, 7 | "noarg" : true, 8 | "sub" : true, 9 | "undef" : true, 10 | "boss" : true, 11 | "eqnull" : true, 12 | "node" : true, 13 | "es5" : true, 14 | "globals" : { 15 | "it" : false, 16 | "xit" : false, 17 | "describe" : false, 18 | "xdescribe" : false, 19 | "beforeEach" : false, 20 | "afterEach" : false, 21 | "expect" : false, 22 | "spyOn" : false 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.11' 4 | - '0.10' 5 | - '0.8' 6 | - '0.6' 7 | before_script: 8 | - npm install -g grunt-cli 9 | matrix: 10 | allow_failures: 11 | - node_js: '0.6' 12 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 'use strict'; 3 | 4 | // Project configuration. 5 | grunt.initConfig({ 6 | jasmine : { 7 | src : 'src/**/*.js', 8 | options : { 9 | specs : 'spec/**/*.js' 10 | } 11 | }, 12 | peg: { 13 | ingreedy: { 14 | src: 'grammar/ingreedy.peg', 15 | dest: 'src/parser.js', 16 | options: { exportVar: 'Ingreedy' } 17 | } 18 | }, 19 | watch: { 20 | grammar: { 21 | files: ['grammar/*.peg'], 22 | tasks: ['build', 'test'] 23 | }, 24 | test: { 25 | files: ['spec/**/*.js'], 26 | tasks: ['test'] 27 | } 28 | } 29 | }); 30 | 31 | grunt.loadNpmTasks('grunt-contrib-jasmine'); 32 | grunt.loadNpmTasks('grunt-contrib-watch'); 33 | grunt.loadNpmTasks('grunt-peg'); 34 | 35 | grunt.registerTask('test', ['jasmine']); 36 | grunt.registerTask('build', ['peg']); 37 | 38 | grunt.registerTask('travis', ['build', 'test']); 39 | grunt.registerTask('default', ['build', 'test']); 40 | }; 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | ```javascript 4 | var result = Ingreedy.parse('1 lb. potatoes'); 5 | result.amount 6 | //=> '1' 7 | result.unit 8 | //=> 'lb.' 9 | result.ingredient 10 | //=> "potatoes" 11 | ``` 12 | 13 | # Pieces of Flair 14 | - [![Build 15 | Status](https://secure.travis-ci.org/iancanderson/ingreedy-js.png?branch=master)](http://travis-ci.org/iancanderson/ingreedy-js) 16 | -------------------------------------------------------------------------------- /grammar/ingreedy.peg: -------------------------------------------------------------------------------- 1 | start 2 | = ingredient_addition 3 | 4 | ingredient_additions 5 | = ingredient_addition+ 6 | 7 | ingredient_addition 8 | = amount:amount (ws+)? container:container? unit:unit? (ws+)? ingredient:ingredient? [\n]? { 9 | var result = { 10 | amount: amount, 11 | container: container, 12 | ingredient: ingredient, 13 | unit: unit 14 | }; 15 | 16 | for(var i in result) { 17 | if(result[i] === null || result[i] === undefined) { 18 | delete result[i]; 19 | } 20 | } 21 | 22 | return result; 23 | } 24 | 25 | amount 26 | = float 27 | / mixed_number 28 | / fraction 29 | / integer 30 | 31 | container 32 | = "("? amount:amount (ws+)? unit:unit")"? { 33 | return { amount: amount, unit: unit }; 34 | } 35 | 36 | ws 37 | = " " 38 | / [\t] 39 | 40 | space 41 | = " " 42 | 43 | ingredient 44 | = phrase 45 | 46 | phrase 47 | = $(word (space word)*) 48 | 49 | word 50 | = letters:letter+ { return letters.join(''); } 51 | 52 | float 53 | = $(integer? [.] integer) 54 | 55 | mixed_number 56 | = $(integer space fraction) 57 | 58 | fraction 59 | = $(integer [/] integer) 60 | 61 | integer 62 | = digits:[0-9]+ { return digits.join(''); } 63 | 64 | letter 65 | = [a-zA-Z] 66 | 67 | unit 68 | = $(english_unit !letter) 69 | / $(metric_unit !letter) 70 | / $(imprecise_unit !letter) 71 | 72 | english_unit 73 | = cup 74 | / fluid_ounce 75 | / gallon 76 | / ounce 77 | / pint 78 | / pound 79 | / quart 80 | / tablespoon 81 | / teaspoon 82 | 83 | cup 84 | = 'cups'i 85 | / 'cup'i 86 | / 'c.'i 87 | / 'c'i 88 | 89 | fluid_ounce 90 | = fluid ws ounce 91 | 92 | fluid 93 | = 'fluid'i 94 | / 'fl'i '.'? 95 | 96 | gallon 97 | = 'gallons'i 98 | / 'gallon'i 99 | / 'gal.'i 100 | / 'gal'i 101 | 102 | ounce 103 | = 'ounces'i 104 | / 'ounce'i 105 | / 'oz.'i 106 | / 'oz'i 107 | 108 | pint 109 | = 'pints'i 110 | / 'pint'i 111 | / 'pt.'i 112 | / 'pt'i 113 | 114 | pound 115 | = 'pounds'i 116 | / 'pound'i 117 | / 'lbs.'i 118 | / 'lbs'i 119 | / 'lb.'i 120 | / 'lb'i 121 | 122 | quart 123 | = 'quarts'i 124 | / 'quart'i 125 | / 'qts.'i 126 | / 'qts'i 127 | / 'qt.'i 128 | / 'qt'i 129 | 130 | tablespoon 131 | = 'tablespoons'i 132 | / 'tablespoon'i 133 | / 'tbsp.'i 134 | / 'tbsp'i 135 | / 'tbs.'i 136 | / 'tbs'i 137 | / 'T.' 138 | / 'T' 139 | 140 | teaspoon 141 | = 'teaspoons'i 142 | / 'teaspoon'i 143 | / 'tsp.'i 144 | / 'tsp'i 145 | / 't.' 146 | / 't' 147 | 148 | metric_unit 149 | = gram 150 | / kilogram 151 | / liter 152 | / milligram 153 | / milliliter 154 | 155 | gram 156 | = 'grams'i 157 | / 'gram'i 158 | / 'gr.'i 159 | / 'gr'i 160 | / 'g.'i 161 | / 'g'i 162 | 163 | kilogram 164 | = 'kilograms'i 165 | / 'kilogram'i 166 | / 'kg.'i 167 | / 'kg'i 168 | 169 | liter 170 | = 'liters'i 171 | / 'liter'i 172 | / 'l.'i 173 | / 'l'i 174 | 175 | milligram 176 | = 'milligrams'i 177 | / 'milligram'i 178 | / 'mg.'i 179 | / 'mg'i 180 | 181 | milliliter 182 | = 'milliliters'i 183 | / 'milliliter'i 184 | / 'ml.'i 185 | / 'ml'i 186 | 187 | imprecise_unit 188 | = dash 189 | / handful 190 | / pinch 191 | / touch 192 | 193 | dash 194 | = 'dashes'i 195 | / 'dash'i 196 | 197 | handful 198 | = 'handfuls'i 199 | / 'handful'i 200 | 201 | pinch 202 | = 'pinches'i 203 | / 'pinch'i 204 | 205 | touch 206 | = 'touches'i 207 | / 'touch'i 208 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ingreedy-js", 3 | "description": "natural language parsing for recipe ingredients", 4 | "version": "0.1.0", 5 | "homepage": "https://github.com/iancanderson/ingreedy-js", 6 | "author": { 7 | "name": "Ian C. Anderson", 8 | "email": "ian@iancanderson.com", 9 | "url": "http://iancanderson.com/" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git://github.com/iancanderson/ingreedy-js.git" 14 | }, 15 | "scripts": { 16 | "test": "grunt travis --verbose" 17 | }, 18 | "bugs": { 19 | "url": "https://github.com/iancanderson/ingreedy-js/issues" 20 | }, 21 | "devDependencies": { 22 | "grunt": "~0.4.0", 23 | "grunt-contrib-jasmine": "~0.6.4", 24 | "grunt-contrib-watch": "~0.6.1", 25 | "grunt-peg": "~1.3.1" 26 | }, 27 | "dependencies": {} 28 | } 29 | -------------------------------------------------------------------------------- /spec/AmountParsingSpec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe("Amount parsing", function() { 4 | var parser = Ingreedy; 5 | 6 | it('parses integers', function() { 7 | var result = parser.parse('2 potatoes'); 8 | expect(result.amount).toBe('2'); 9 | }); 10 | 11 | it('parses large integers', function() { 12 | var result = parser.parse('12345 potatoes'); 13 | expect(result.amount).toBe('12345'); 14 | }); 15 | 16 | it('parses simple fractions', function() { 17 | var result = parser.parse('1/2 potato'); 18 | expect(result.amount).toBe('1/2'); 19 | }); 20 | 21 | it('parses mixed numbers', function() { 22 | var result = parser.parse('1 1/2 potatoes'); 23 | expect(result.amount).toBe('1 1/2'); 24 | }); 25 | 26 | it('parses decimals', function() { 27 | var result = parser.parse('1.5 potatoes'); 28 | expect(result.amount).toBe('1.5'); 29 | }); 30 | 31 | it('parses decimals without leading digits', function() { 32 | var result = parser.parse('.5 potatoes'); 33 | expect(result.amount).toBe('.5'); 34 | }); 35 | 36 | }); 37 | -------------------------------------------------------------------------------- /spec/IngreedySpec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var ingreedyMatchers = { 4 | toBeParsedAs: function(util, customEqualityTesters) { 5 | return { 6 | compare: function(inputString, expected) { 7 | var parserResult; 8 | var specResult = {}; 9 | 10 | try { 11 | parserResult = Ingreedy.parse(inputString); 12 | } catch(err) { 13 | specResult.pass = false; 14 | } 15 | 16 | if(specResult.pass !== false) { 17 | specResult.pass = util.equals(parserResult, expected); 18 | } 19 | 20 | if(specResult.pass) { 21 | specResult.message = 'Ingreedy successfully parsed "' + inputString + '"'; 22 | } else { 23 | specResult.message = 'Ingreedy parsed \n' + JSON.stringify(parserResult) + '\ninstead of \n' + JSON.stringify(expected); 24 | } 25 | 26 | return specResult; 27 | } 28 | } 29 | } 30 | }; 31 | 32 | describe("Ingreedy", function() { 33 | var parser = Ingreedy; 34 | 35 | beforeEach(function() { 36 | jasmine.addMatchers(ingreedyMatchers); 37 | }); 38 | 39 | describe('simple ingredient additions', function() { 40 | it('parses the correct values', function() { 41 | expect('1 lb potatoes').toBeParsedAs({ 42 | amount: '1', 43 | unit: 'lb', 44 | ingredient: 'potatoes' 45 | }); 46 | }); 47 | }); 48 | 49 | describe('ingredient additions with a container', function() { 50 | it('parses the correct values', function() { 51 | expect('2 28 oz can tomatoes').toBeParsedAs({ 52 | amount: '2', 53 | ingredient: 'can tomatoes', 54 | container: { 55 | amount: '28', 56 | unit: 'oz' 57 | } 58 | }); 59 | }); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /spec/UnitParsingSpec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var unitMatchers = { 4 | toParseUnit: function(util, customEqualityTesters) { 5 | return { 6 | compare: function(actual, expected) { 7 | var parserResult; 8 | var specResult = {}; 9 | 10 | try { 11 | parserResult = actual.parse(expected); 12 | } catch(err) { 13 | specResult.pass = false; 14 | } 15 | 16 | if(specResult.pass !== false) { 17 | specResult.pass = !util.equals(parserResult.unit, null); 18 | specResult.pass = !util.equals(parserResult.unit, undefined); 19 | } 20 | 21 | if(specResult.pass) { 22 | specResult.message = 'Ingreedy successfully parsed the unit "' + parserResult.unit + '" from "' + expected + '"' 23 | } else { 24 | specResult.message = 'Expected Ingreedy to parse the unit from "' + expected + '", but it didn\'t.' 25 | } 26 | 27 | return specResult; 28 | } 29 | } 30 | } 31 | }; 32 | 33 | describe("Unit parsing", function() { 34 | var parser = Ingreedy; 35 | 36 | beforeEach(function() { 37 | jasmine.addMatchers(unitMatchers); 38 | }); 39 | 40 | describe('ingredients without units', function() { 41 | it("doesn't parse a unit", function() { 42 | expect(parser).not.toParseUnit('2 coconuts'); 43 | }) 44 | 45 | describe('ingredients with names that start with a unit name', function() { 46 | it("doesn't parse a unit", function() { 47 | expect(parser).not.toParseUnit('2 cupcakes'); 48 | }) 49 | }); 50 | }); 51 | 52 | describe('when nothing follows the unit', function() { 53 | it('parses the unit', function() { 54 | expect(parser).toParseUnit('1 lb'); 55 | expect(parser).toParseUnit('1 cup'); 56 | }); 57 | }) 58 | 59 | describe('english units', function() { 60 | it('parses cups', function() { 61 | expect(parser).toParseUnit('2 cups flour'); 62 | expect(parser).toParseUnit('2 CUPS flour'); 63 | expect(parser).toParseUnit('2 Cups flour'); 64 | expect(parser).toParseUnit('2 cup flour'); 65 | expect(parser).toParseUnit('2 c. flour'); 66 | expect(parser).toParseUnit('2 c flour'); 67 | }); 68 | 69 | it('parses fluid ounces', function() { 70 | expect(parser).toParseUnit('2 fluid ounces water'); 71 | expect(parser).toParseUnit('1 fluid ounce water'); 72 | expect(parser).toParseUnit('1 fluid oz. water'); 73 | expect(parser).toParseUnit('1 fluid oz water'); 74 | expect(parser).toParseUnit('1 fl. oz. water'); 75 | expect(parser).toParseUnit('1 fl oz water'); 76 | expect(parser).toParseUnit('1 fl oz. water'); 77 | expect(parser).toParseUnit('1 fl. oz water'); 78 | expect(parser).toParseUnit('1 fl ounces water'); 79 | expect(parser).toParseUnit('1 fl ounce water'); 80 | expect(parser).toParseUnit('1 fl. ounce water'); 81 | }); 82 | 83 | it('parses gallons', function() { 84 | expect(parser).toParseUnit('1 gallon water'); 85 | expect(parser).toParseUnit('2 gallons water'); 86 | expect(parser).toParseUnit('2 gal. water'); 87 | expect(parser).toParseUnit('2 gal water'); 88 | }); 89 | 90 | it('parses ounces', function() { 91 | expect(parser).toParseUnit('1 ounce water'); 92 | expect(parser).toParseUnit('2 ounces water'); 93 | expect(parser).toParseUnit('2 oz water'); 94 | expect(parser).toParseUnit('2 oz. water'); 95 | }); 96 | 97 | it('parses pints', function() { 98 | expect(parser).toParseUnit('1 pint water'); 99 | expect(parser).toParseUnit('2 pints water'); 100 | }); 101 | 102 | it('parses pounds', function() { 103 | expect(parser).toParseUnit('2 pounds chocolate'); 104 | expect(parser).toParseUnit('1 pound chocolate'); 105 | expect(parser).toParseUnit('2 lbs. chocolate'); 106 | expect(parser).toParseUnit('2 lbs chocolate'); 107 | expect(parser).toParseUnit('2 lb. chocolate'); 108 | expect(parser).toParseUnit('2 lb chocolate'); 109 | }); 110 | 111 | it('parses quarts', function() { 112 | expect(parser).toParseUnit('2 quarts water'); 113 | expect(parser).toParseUnit('1 quart water'); 114 | expect(parser).toParseUnit('2 qts. water'); 115 | expect(parser).toParseUnit('2 qts water'); 116 | expect(parser).toParseUnit('2 qt. water'); 117 | expect(parser).toParseUnit('2 qt water'); 118 | }); 119 | 120 | it('parses tablespoons', function() { 121 | expect(parser).toParseUnit('2 tablespoons water'); 122 | expect(parser).toParseUnit('1 tablespoon water'); 123 | expect(parser).toParseUnit('1 tbsp. water'); 124 | expect(parser).toParseUnit('1 tbsp water'); 125 | expect(parser).toParseUnit('1 tbs. water'); 126 | expect(parser).toParseUnit('1 tbs water'); 127 | expect(parser).toParseUnit('1 T. water'); 128 | expect(parser).toParseUnit('1 T water'); 129 | }); 130 | 131 | it('parses teaspoons', function() { 132 | expect(parser).toParseUnit('2 teaspoons water'); 133 | expect(parser).toParseUnit('1 teaspoon water'); 134 | expect(parser).toParseUnit('1 tsp. water'); 135 | expect(parser).toParseUnit('1 tsp water'); 136 | expect(parser).toParseUnit('1 t. water'); 137 | expect(parser).toParseUnit('1 t water'); 138 | }); 139 | }); 140 | 141 | describe('metric units', function() { 142 | it('parses grams', function() { 143 | expect(parser).toParseUnit('2 grams water'); 144 | expect(parser).toParseUnit('1 gram water'); 145 | expect(parser).toParseUnit('1 gr. water'); 146 | expect(parser).toParseUnit('1 gr water'); 147 | expect(parser).toParseUnit('1 g. water'); 148 | expect(parser).toParseUnit('1 g water'); 149 | }); 150 | 151 | it('parses kilograms', function() { 152 | expect(parser).toParseUnit('2 kilograms water'); 153 | expect(parser).toParseUnit('1 kilogram water'); 154 | expect(parser).toParseUnit('1 kg. water'); 155 | expect(parser).toParseUnit('1 kg water'); 156 | }); 157 | 158 | it('parses liters', function() { 159 | expect(parser).toParseUnit('2 liters water'); 160 | expect(parser).toParseUnit('1 liter water'); 161 | expect(parser).toParseUnit('1 L. water'); 162 | expect(parser).toParseUnit('1 l. water'); 163 | expect(parser).toParseUnit('1 L water'); 164 | expect(parser).toParseUnit('1 l water'); 165 | }); 166 | 167 | it('parses milligrams', function() { 168 | expect(parser).toParseUnit('2 milligrams water'); 169 | expect(parser).toParseUnit('1 milligram water'); 170 | expect(parser).toParseUnit('1 mg. water'); 171 | expect(parser).toParseUnit('1 mg water'); 172 | }); 173 | 174 | it('parses milliliters', function() { 175 | expect(parser).toParseUnit('2 milliliters water'); 176 | expect(parser).toParseUnit('1 milliliter water'); 177 | expect(parser).toParseUnit('1 ml. water'); 178 | expect(parser).toParseUnit('1 ml water'); 179 | }); 180 | }); 181 | 182 | describe('imprecise units', function() { 183 | it('parses dashes', function() { 184 | expect(parser).toParseUnit('2 dashes salt'); 185 | expect(parser).toParseUnit('1 dash salt'); 186 | }); 187 | 188 | it('parses handfuls', function() { 189 | expect(parser).toParseUnit('2 handfuls salt'); 190 | expect(parser).toParseUnit('1 handful salt'); 191 | }); 192 | 193 | it('parses pinches', function() { 194 | expect(parser).toParseUnit('2 pinches salt'); 195 | expect(parser).toParseUnit('1 pinch salt'); 196 | }); 197 | 198 | it('parses touches', function() { 199 | expect(parser).toParseUnit('2 touches salt'); 200 | expect(parser).toParseUnit('1 touch salt'); 201 | }); 202 | }); 203 | }); 204 | -------------------------------------------------------------------------------- /src/parser.js: -------------------------------------------------------------------------------- 1 | Ingreedy = (function() { 2 | /* 3 | * Generated by PEG.js 0.8.0. 4 | * 5 | * http://pegjs.majda.cz/ 6 | */ 7 | 8 | function peg$subclass(child, parent) { 9 | function ctor() { this.constructor = child; } 10 | ctor.prototype = parent.prototype; 11 | child.prototype = new ctor(); 12 | } 13 | 14 | function SyntaxError(message, expected, found, offset, line, column) { 15 | this.message = message; 16 | this.expected = expected; 17 | this.found = found; 18 | this.offset = offset; 19 | this.line = line; 20 | this.column = column; 21 | 22 | this.name = "SyntaxError"; 23 | } 24 | 25 | peg$subclass(SyntaxError, Error); 26 | 27 | function parse(input) { 28 | var options = arguments.length > 1 ? arguments[1] : {}, 29 | 30 | peg$FAILED = {}, 31 | 32 | peg$startRuleFunctions = { start: peg$parsestart }, 33 | peg$startRuleFunction = peg$parsestart, 34 | 35 | peg$c0 = [], 36 | peg$c1 = peg$FAILED, 37 | peg$c2 = null, 38 | peg$c3 = /^[\n]/, 39 | peg$c4 = { type: "class", value: "[\\n]", description: "[\\n]" }, 40 | peg$c5 = function(amount, container, unit, ingredient) { 41 | var result = { 42 | amount: amount, 43 | container: container, 44 | ingredient: ingredient, 45 | unit: unit 46 | }; 47 | 48 | for(var i in result) { 49 | if(result[i] === null || result[i] === undefined) { 50 | delete result[i]; 51 | } 52 | } 53 | 54 | return result; 55 | }, 56 | peg$c6 = "(", 57 | peg$c7 = { type: "literal", value: "(", description: "\"(\"" }, 58 | peg$c8 = ")", 59 | peg$c9 = { type: "literal", value: ")", description: "\")\"" }, 60 | peg$c10 = function(amount, unit) { 61 | return { amount: amount, unit: unit }; 62 | }, 63 | peg$c11 = " ", 64 | peg$c12 = { type: "literal", value: " ", description: "\" \"" }, 65 | peg$c13 = /^[\t]/, 66 | peg$c14 = { type: "class", value: "[\\t]", description: "[\\t]" }, 67 | peg$c15 = function(letters) { return letters.join(''); }, 68 | peg$c16 = /^[.]/, 69 | peg$c17 = { type: "class", value: "[.]", description: "[.]" }, 70 | peg$c18 = /^[\/]/, 71 | peg$c19 = { type: "class", value: "[\\/]", description: "[\\/]" }, 72 | peg$c20 = /^[0-9]/, 73 | peg$c21 = { type: "class", value: "[0-9]", description: "[0-9]" }, 74 | peg$c22 = function(digits) { return digits.join(''); }, 75 | peg$c23 = /^[a-zA-Z]/, 76 | peg$c24 = { type: "class", value: "[a-zA-Z]", description: "[a-zA-Z]" }, 77 | peg$c25 = void 0, 78 | peg$c26 = "cups", 79 | peg$c27 = { type: "literal", value: "cups", description: "\"cups\"" }, 80 | peg$c28 = "cup", 81 | peg$c29 = { type: "literal", value: "cup", description: "\"cup\"" }, 82 | peg$c30 = "c.", 83 | peg$c31 = { type: "literal", value: "c.", description: "\"c.\"" }, 84 | peg$c32 = "c", 85 | peg$c33 = { type: "literal", value: "c", description: "\"c\"" }, 86 | peg$c34 = "fluid", 87 | peg$c35 = { type: "literal", value: "fluid", description: "\"fluid\"" }, 88 | peg$c36 = "fl", 89 | peg$c37 = { type: "literal", value: "fl", description: "\"fl\"" }, 90 | peg$c38 = ".", 91 | peg$c39 = { type: "literal", value: ".", description: "\".\"" }, 92 | peg$c40 = "gallons", 93 | peg$c41 = { type: "literal", value: "gallons", description: "\"gallons\"" }, 94 | peg$c42 = "gallon", 95 | peg$c43 = { type: "literal", value: "gallon", description: "\"gallon\"" }, 96 | peg$c44 = "gal.", 97 | peg$c45 = { type: "literal", value: "gal.", description: "\"gal.\"" }, 98 | peg$c46 = "gal", 99 | peg$c47 = { type: "literal", value: "gal", description: "\"gal\"" }, 100 | peg$c48 = "ounces", 101 | peg$c49 = { type: "literal", value: "ounces", description: "\"ounces\"" }, 102 | peg$c50 = "ounce", 103 | peg$c51 = { type: "literal", value: "ounce", description: "\"ounce\"" }, 104 | peg$c52 = "oz.", 105 | peg$c53 = { type: "literal", value: "oz.", description: "\"oz.\"" }, 106 | peg$c54 = "oz", 107 | peg$c55 = { type: "literal", value: "oz", description: "\"oz\"" }, 108 | peg$c56 = "pints", 109 | peg$c57 = { type: "literal", value: "pints", description: "\"pints\"" }, 110 | peg$c58 = "pint", 111 | peg$c59 = { type: "literal", value: "pint", description: "\"pint\"" }, 112 | peg$c60 = "pt.", 113 | peg$c61 = { type: "literal", value: "pt.", description: "\"pt.\"" }, 114 | peg$c62 = "pt", 115 | peg$c63 = { type: "literal", value: "pt", description: "\"pt\"" }, 116 | peg$c64 = "pounds", 117 | peg$c65 = { type: "literal", value: "pounds", description: "\"pounds\"" }, 118 | peg$c66 = "pound", 119 | peg$c67 = { type: "literal", value: "pound", description: "\"pound\"" }, 120 | peg$c68 = "lbs.", 121 | peg$c69 = { type: "literal", value: "lbs.", description: "\"lbs.\"" }, 122 | peg$c70 = "lbs", 123 | peg$c71 = { type: "literal", value: "lbs", description: "\"lbs\"" }, 124 | peg$c72 = "lb.", 125 | peg$c73 = { type: "literal", value: "lb.", description: "\"lb.\"" }, 126 | peg$c74 = "lb", 127 | peg$c75 = { type: "literal", value: "lb", description: "\"lb\"" }, 128 | peg$c76 = "quarts", 129 | peg$c77 = { type: "literal", value: "quarts", description: "\"quarts\"" }, 130 | peg$c78 = "quart", 131 | peg$c79 = { type: "literal", value: "quart", description: "\"quart\"" }, 132 | peg$c80 = "qts.", 133 | peg$c81 = { type: "literal", value: "qts.", description: "\"qts.\"" }, 134 | peg$c82 = "qts", 135 | peg$c83 = { type: "literal", value: "qts", description: "\"qts\"" }, 136 | peg$c84 = "qt.", 137 | peg$c85 = { type: "literal", value: "qt.", description: "\"qt.\"" }, 138 | peg$c86 = "qt", 139 | peg$c87 = { type: "literal", value: "qt", description: "\"qt\"" }, 140 | peg$c88 = "tablespoons", 141 | peg$c89 = { type: "literal", value: "tablespoons", description: "\"tablespoons\"" }, 142 | peg$c90 = "tablespoon", 143 | peg$c91 = { type: "literal", value: "tablespoon", description: "\"tablespoon\"" }, 144 | peg$c92 = "tbsp.", 145 | peg$c93 = { type: "literal", value: "tbsp.", description: "\"tbsp.\"" }, 146 | peg$c94 = "tbsp", 147 | peg$c95 = { type: "literal", value: "tbsp", description: "\"tbsp\"" }, 148 | peg$c96 = "tbs.", 149 | peg$c97 = { type: "literal", value: "tbs.", description: "\"tbs.\"" }, 150 | peg$c98 = "tbs", 151 | peg$c99 = { type: "literal", value: "tbs", description: "\"tbs\"" }, 152 | peg$c100 = "T.", 153 | peg$c101 = { type: "literal", value: "T.", description: "\"T.\"" }, 154 | peg$c102 = "T", 155 | peg$c103 = { type: "literal", value: "T", description: "\"T\"" }, 156 | peg$c104 = "teaspoons", 157 | peg$c105 = { type: "literal", value: "teaspoons", description: "\"teaspoons\"" }, 158 | peg$c106 = "teaspoon", 159 | peg$c107 = { type: "literal", value: "teaspoon", description: "\"teaspoon\"" }, 160 | peg$c108 = "tsp.", 161 | peg$c109 = { type: "literal", value: "tsp.", description: "\"tsp.\"" }, 162 | peg$c110 = "tsp", 163 | peg$c111 = { type: "literal", value: "tsp", description: "\"tsp\"" }, 164 | peg$c112 = "t.", 165 | peg$c113 = { type: "literal", value: "t.", description: "\"t.\"" }, 166 | peg$c114 = "t", 167 | peg$c115 = { type: "literal", value: "t", description: "\"t\"" }, 168 | peg$c116 = "grams", 169 | peg$c117 = { type: "literal", value: "grams", description: "\"grams\"" }, 170 | peg$c118 = "gram", 171 | peg$c119 = { type: "literal", value: "gram", description: "\"gram\"" }, 172 | peg$c120 = "gr.", 173 | peg$c121 = { type: "literal", value: "gr.", description: "\"gr.\"" }, 174 | peg$c122 = "gr", 175 | peg$c123 = { type: "literal", value: "gr", description: "\"gr\"" }, 176 | peg$c124 = "g.", 177 | peg$c125 = { type: "literal", value: "g.", description: "\"g.\"" }, 178 | peg$c126 = "g", 179 | peg$c127 = { type: "literal", value: "g", description: "\"g\"" }, 180 | peg$c128 = "kilograms", 181 | peg$c129 = { type: "literal", value: "kilograms", description: "\"kilograms\"" }, 182 | peg$c130 = "kilogram", 183 | peg$c131 = { type: "literal", value: "kilogram", description: "\"kilogram\"" }, 184 | peg$c132 = "kg.", 185 | peg$c133 = { type: "literal", value: "kg.", description: "\"kg.\"" }, 186 | peg$c134 = "kg", 187 | peg$c135 = { type: "literal", value: "kg", description: "\"kg\"" }, 188 | peg$c136 = "liters", 189 | peg$c137 = { type: "literal", value: "liters", description: "\"liters\"" }, 190 | peg$c138 = "liter", 191 | peg$c139 = { type: "literal", value: "liter", description: "\"liter\"" }, 192 | peg$c140 = "l.", 193 | peg$c141 = { type: "literal", value: "l.", description: "\"l.\"" }, 194 | peg$c142 = "l", 195 | peg$c143 = { type: "literal", value: "l", description: "\"l\"" }, 196 | peg$c144 = "milligrams", 197 | peg$c145 = { type: "literal", value: "milligrams", description: "\"milligrams\"" }, 198 | peg$c146 = "milligram", 199 | peg$c147 = { type: "literal", value: "milligram", description: "\"milligram\"" }, 200 | peg$c148 = "mg.", 201 | peg$c149 = { type: "literal", value: "mg.", description: "\"mg.\"" }, 202 | peg$c150 = "mg", 203 | peg$c151 = { type: "literal", value: "mg", description: "\"mg\"" }, 204 | peg$c152 = "milliliters", 205 | peg$c153 = { type: "literal", value: "milliliters", description: "\"milliliters\"" }, 206 | peg$c154 = "milliliter", 207 | peg$c155 = { type: "literal", value: "milliliter", description: "\"milliliter\"" }, 208 | peg$c156 = "ml.", 209 | peg$c157 = { type: "literal", value: "ml.", description: "\"ml.\"" }, 210 | peg$c158 = "ml", 211 | peg$c159 = { type: "literal", value: "ml", description: "\"ml\"" }, 212 | peg$c160 = "dashes", 213 | peg$c161 = { type: "literal", value: "dashes", description: "\"dashes\"" }, 214 | peg$c162 = "dash", 215 | peg$c163 = { type: "literal", value: "dash", description: "\"dash\"" }, 216 | peg$c164 = "handfuls", 217 | peg$c165 = { type: "literal", value: "handfuls", description: "\"handfuls\"" }, 218 | peg$c166 = "handful", 219 | peg$c167 = { type: "literal", value: "handful", description: "\"handful\"" }, 220 | peg$c168 = "pinches", 221 | peg$c169 = { type: "literal", value: "pinches", description: "\"pinches\"" }, 222 | peg$c170 = "pinch", 223 | peg$c171 = { type: "literal", value: "pinch", description: "\"pinch\"" }, 224 | peg$c172 = "touches", 225 | peg$c173 = { type: "literal", value: "touches", description: "\"touches\"" }, 226 | peg$c174 = "touch", 227 | peg$c175 = { type: "literal", value: "touch", description: "\"touch\"" }, 228 | 229 | peg$currPos = 0, 230 | peg$reportedPos = 0, 231 | peg$cachedPos = 0, 232 | peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }, 233 | peg$maxFailPos = 0, 234 | peg$maxFailExpected = [], 235 | peg$silentFails = 0, 236 | 237 | peg$result; 238 | 239 | if ("startRule" in options) { 240 | if (!(options.startRule in peg$startRuleFunctions)) { 241 | throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); 242 | } 243 | 244 | peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; 245 | } 246 | 247 | function text() { 248 | return input.substring(peg$reportedPos, peg$currPos); 249 | } 250 | 251 | function offset() { 252 | return peg$reportedPos; 253 | } 254 | 255 | function line() { 256 | return peg$computePosDetails(peg$reportedPos).line; 257 | } 258 | 259 | function column() { 260 | return peg$computePosDetails(peg$reportedPos).column; 261 | } 262 | 263 | function expected(description) { 264 | throw peg$buildException( 265 | null, 266 | [{ type: "other", description: description }], 267 | peg$reportedPos 268 | ); 269 | } 270 | 271 | function error(message) { 272 | throw peg$buildException(message, null, peg$reportedPos); 273 | } 274 | 275 | function peg$computePosDetails(pos) { 276 | function advance(details, startPos, endPos) { 277 | var p, ch; 278 | 279 | for (p = startPos; p < endPos; p++) { 280 | ch = input.charAt(p); 281 | if (ch === "\n") { 282 | if (!details.seenCR) { details.line++; } 283 | details.column = 1; 284 | details.seenCR = false; 285 | } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { 286 | details.line++; 287 | details.column = 1; 288 | details.seenCR = true; 289 | } else { 290 | details.column++; 291 | details.seenCR = false; 292 | } 293 | } 294 | } 295 | 296 | if (peg$cachedPos !== pos) { 297 | if (peg$cachedPos > pos) { 298 | peg$cachedPos = 0; 299 | peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }; 300 | } 301 | advance(peg$cachedPosDetails, peg$cachedPos, pos); 302 | peg$cachedPos = pos; 303 | } 304 | 305 | return peg$cachedPosDetails; 306 | } 307 | 308 | function peg$fail(expected) { 309 | if (peg$currPos < peg$maxFailPos) { return; } 310 | 311 | if (peg$currPos > peg$maxFailPos) { 312 | peg$maxFailPos = peg$currPos; 313 | peg$maxFailExpected = []; 314 | } 315 | 316 | peg$maxFailExpected.push(expected); 317 | } 318 | 319 | function peg$buildException(message, expected, pos) { 320 | function cleanupExpected(expected) { 321 | var i = 1; 322 | 323 | expected.sort(function(a, b) { 324 | if (a.description < b.description) { 325 | return -1; 326 | } else if (a.description > b.description) { 327 | return 1; 328 | } else { 329 | return 0; 330 | } 331 | }); 332 | 333 | while (i < expected.length) { 334 | if (expected[i - 1] === expected[i]) { 335 | expected.splice(i, 1); 336 | } else { 337 | i++; 338 | } 339 | } 340 | } 341 | 342 | function buildMessage(expected, found) { 343 | function stringEscape(s) { 344 | function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); } 345 | 346 | return s 347 | .replace(/\\/g, '\\\\') 348 | .replace(/"/g, '\\"') 349 | .replace(/\x08/g, '\\b') 350 | .replace(/\t/g, '\\t') 351 | .replace(/\n/g, '\\n') 352 | .replace(/\f/g, '\\f') 353 | .replace(/\r/g, '\\r') 354 | .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) 355 | .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); }) 356 | .replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); }) 357 | .replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); }); 358 | } 359 | 360 | var expectedDescs = new Array(expected.length), 361 | expectedDesc, foundDesc, i; 362 | 363 | for (i = 0; i < expected.length; i++) { 364 | expectedDescs[i] = expected[i].description; 365 | } 366 | 367 | expectedDesc = expected.length > 1 368 | ? expectedDescs.slice(0, -1).join(", ") 369 | + " or " 370 | + expectedDescs[expected.length - 1] 371 | : expectedDescs[0]; 372 | 373 | foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input"; 374 | 375 | return "Expected " + expectedDesc + " but " + foundDesc + " found."; 376 | } 377 | 378 | var posDetails = peg$computePosDetails(pos), 379 | found = pos < input.length ? input.charAt(pos) : null; 380 | 381 | if (expected !== null) { 382 | cleanupExpected(expected); 383 | } 384 | 385 | return new SyntaxError( 386 | message !== null ? message : buildMessage(expected, found), 387 | expected, 388 | found, 389 | pos, 390 | posDetails.line, 391 | posDetails.column 392 | ); 393 | } 394 | 395 | function peg$parsestart() { 396 | var s0; 397 | 398 | s0 = peg$parseingredient_addition(); 399 | 400 | return s0; 401 | } 402 | 403 | function peg$parseingredient_additions() { 404 | var s0, s1; 405 | 406 | s0 = []; 407 | s1 = peg$parseingredient_addition(); 408 | if (s1 !== peg$FAILED) { 409 | while (s1 !== peg$FAILED) { 410 | s0.push(s1); 411 | s1 = peg$parseingredient_addition(); 412 | } 413 | } else { 414 | s0 = peg$c1; 415 | } 416 | 417 | return s0; 418 | } 419 | 420 | function peg$parseingredient_addition() { 421 | var s0, s1, s2, s3, s4, s5, s6, s7; 422 | 423 | s0 = peg$currPos; 424 | s1 = peg$parseamount(); 425 | if (s1 !== peg$FAILED) { 426 | s2 = []; 427 | s3 = peg$parsews(); 428 | if (s3 !== peg$FAILED) { 429 | while (s3 !== peg$FAILED) { 430 | s2.push(s3); 431 | s3 = peg$parsews(); 432 | } 433 | } else { 434 | s2 = peg$c1; 435 | } 436 | if (s2 === peg$FAILED) { 437 | s2 = peg$c2; 438 | } 439 | if (s2 !== peg$FAILED) { 440 | s3 = peg$parsecontainer(); 441 | if (s3 === peg$FAILED) { 442 | s3 = peg$c2; 443 | } 444 | if (s3 !== peg$FAILED) { 445 | s4 = peg$parseunit(); 446 | if (s4 === peg$FAILED) { 447 | s4 = peg$c2; 448 | } 449 | if (s4 !== peg$FAILED) { 450 | s5 = []; 451 | s6 = peg$parsews(); 452 | if (s6 !== peg$FAILED) { 453 | while (s6 !== peg$FAILED) { 454 | s5.push(s6); 455 | s6 = peg$parsews(); 456 | } 457 | } else { 458 | s5 = peg$c1; 459 | } 460 | if (s5 === peg$FAILED) { 461 | s5 = peg$c2; 462 | } 463 | if (s5 !== peg$FAILED) { 464 | s6 = peg$parsephrase(); 465 | if (s6 === peg$FAILED) { 466 | s6 = peg$c2; 467 | } 468 | if (s6 !== peg$FAILED) { 469 | if (peg$c3.test(input.charAt(peg$currPos))) { 470 | s7 = input.charAt(peg$currPos); 471 | peg$currPos++; 472 | } else { 473 | s7 = peg$FAILED; 474 | if (peg$silentFails === 0) { peg$fail(peg$c4); } 475 | } 476 | if (s7 === peg$FAILED) { 477 | s7 = peg$c2; 478 | } 479 | if (s7 !== peg$FAILED) { 480 | peg$reportedPos = s0; 481 | s1 = peg$c5(s1, s3, s4, s6); 482 | s0 = s1; 483 | } else { 484 | peg$currPos = s0; 485 | s0 = peg$c1; 486 | } 487 | } else { 488 | peg$currPos = s0; 489 | s0 = peg$c1; 490 | } 491 | } else { 492 | peg$currPos = s0; 493 | s0 = peg$c1; 494 | } 495 | } else { 496 | peg$currPos = s0; 497 | s0 = peg$c1; 498 | } 499 | } else { 500 | peg$currPos = s0; 501 | s0 = peg$c1; 502 | } 503 | } else { 504 | peg$currPos = s0; 505 | s0 = peg$c1; 506 | } 507 | } else { 508 | peg$currPos = s0; 509 | s0 = peg$c1; 510 | } 511 | 512 | return s0; 513 | } 514 | 515 | function peg$parseamount() { 516 | var s0; 517 | 518 | s0 = peg$parsefloat(); 519 | if (s0 === peg$FAILED) { 520 | s0 = peg$parsemixed_number(); 521 | if (s0 === peg$FAILED) { 522 | s0 = peg$parsefraction(); 523 | if (s0 === peg$FAILED) { 524 | s0 = peg$parseinteger(); 525 | } 526 | } 527 | } 528 | 529 | return s0; 530 | } 531 | 532 | function peg$parsecontainer() { 533 | var s0, s1, s2, s3, s4, s5; 534 | 535 | s0 = peg$currPos; 536 | if (input.charCodeAt(peg$currPos) === 40) { 537 | s1 = peg$c6; 538 | peg$currPos++; 539 | } else { 540 | s1 = peg$FAILED; 541 | if (peg$silentFails === 0) { peg$fail(peg$c7); } 542 | } 543 | if (s1 === peg$FAILED) { 544 | s1 = peg$c2; 545 | } 546 | if (s1 !== peg$FAILED) { 547 | s2 = peg$parseamount(); 548 | if (s2 !== peg$FAILED) { 549 | s3 = []; 550 | s4 = peg$parsews(); 551 | if (s4 !== peg$FAILED) { 552 | while (s4 !== peg$FAILED) { 553 | s3.push(s4); 554 | s4 = peg$parsews(); 555 | } 556 | } else { 557 | s3 = peg$c1; 558 | } 559 | if (s3 === peg$FAILED) { 560 | s3 = peg$c2; 561 | } 562 | if (s3 !== peg$FAILED) { 563 | s4 = peg$parseunit(); 564 | if (s4 !== peg$FAILED) { 565 | if (input.charCodeAt(peg$currPos) === 41) { 566 | s5 = peg$c8; 567 | peg$currPos++; 568 | } else { 569 | s5 = peg$FAILED; 570 | if (peg$silentFails === 0) { peg$fail(peg$c9); } 571 | } 572 | if (s5 === peg$FAILED) { 573 | s5 = peg$c2; 574 | } 575 | if (s5 !== peg$FAILED) { 576 | peg$reportedPos = s0; 577 | s1 = peg$c10(s2, s4); 578 | s0 = s1; 579 | } else { 580 | peg$currPos = s0; 581 | s0 = peg$c1; 582 | } 583 | } else { 584 | peg$currPos = s0; 585 | s0 = peg$c1; 586 | } 587 | } else { 588 | peg$currPos = s0; 589 | s0 = peg$c1; 590 | } 591 | } else { 592 | peg$currPos = s0; 593 | s0 = peg$c1; 594 | } 595 | } else { 596 | peg$currPos = s0; 597 | s0 = peg$c1; 598 | } 599 | 600 | return s0; 601 | } 602 | 603 | function peg$parsews() { 604 | var s0; 605 | 606 | if (input.charCodeAt(peg$currPos) === 32) { 607 | s0 = peg$c11; 608 | peg$currPos++; 609 | } else { 610 | s0 = peg$FAILED; 611 | if (peg$silentFails === 0) { peg$fail(peg$c12); } 612 | } 613 | if (s0 === peg$FAILED) { 614 | if (peg$c13.test(input.charAt(peg$currPos))) { 615 | s0 = input.charAt(peg$currPos); 616 | peg$currPos++; 617 | } else { 618 | s0 = peg$FAILED; 619 | if (peg$silentFails === 0) { peg$fail(peg$c14); } 620 | } 621 | } 622 | 623 | return s0; 624 | } 625 | 626 | function peg$parsespace() { 627 | var s0; 628 | 629 | if (input.charCodeAt(peg$currPos) === 32) { 630 | s0 = peg$c11; 631 | peg$currPos++; 632 | } else { 633 | s0 = peg$FAILED; 634 | if (peg$silentFails === 0) { peg$fail(peg$c12); } 635 | } 636 | 637 | return s0; 638 | } 639 | 640 | function peg$parsephrase() { 641 | var s0, s1, s2, s3, s4, s5, s6; 642 | 643 | s0 = peg$currPos; 644 | s1 = peg$currPos; 645 | s2 = peg$parseword(); 646 | if (s2 !== peg$FAILED) { 647 | s3 = []; 648 | s4 = peg$currPos; 649 | s5 = peg$parsespace(); 650 | if (s5 !== peg$FAILED) { 651 | s6 = peg$parseword(); 652 | if (s6 !== peg$FAILED) { 653 | s5 = [s5, s6]; 654 | s4 = s5; 655 | } else { 656 | peg$currPos = s4; 657 | s4 = peg$c1; 658 | } 659 | } else { 660 | peg$currPos = s4; 661 | s4 = peg$c1; 662 | } 663 | while (s4 !== peg$FAILED) { 664 | s3.push(s4); 665 | s4 = peg$currPos; 666 | s5 = peg$parsespace(); 667 | if (s5 !== peg$FAILED) { 668 | s6 = peg$parseword(); 669 | if (s6 !== peg$FAILED) { 670 | s5 = [s5, s6]; 671 | s4 = s5; 672 | } else { 673 | peg$currPos = s4; 674 | s4 = peg$c1; 675 | } 676 | } else { 677 | peg$currPos = s4; 678 | s4 = peg$c1; 679 | } 680 | } 681 | if (s3 !== peg$FAILED) { 682 | s2 = [s2, s3]; 683 | s1 = s2; 684 | } else { 685 | peg$currPos = s1; 686 | s1 = peg$c1; 687 | } 688 | } else { 689 | peg$currPos = s1; 690 | s1 = peg$c1; 691 | } 692 | if (s1 !== peg$FAILED) { 693 | s1 = input.substring(s0, peg$currPos); 694 | } 695 | s0 = s1; 696 | 697 | return s0; 698 | } 699 | 700 | function peg$parseword() { 701 | var s0, s1, s2; 702 | 703 | s0 = peg$currPos; 704 | s1 = []; 705 | s2 = peg$parseletter(); 706 | if (s2 !== peg$FAILED) { 707 | while (s2 !== peg$FAILED) { 708 | s1.push(s2); 709 | s2 = peg$parseletter(); 710 | } 711 | } else { 712 | s1 = peg$c1; 713 | } 714 | if (s1 !== peg$FAILED) { 715 | peg$reportedPos = s0; 716 | s1 = peg$c15(s1); 717 | } 718 | s0 = s1; 719 | 720 | return s0; 721 | } 722 | 723 | function peg$parsefloat() { 724 | var s0, s1, s2, s3, s4; 725 | 726 | s0 = peg$currPos; 727 | s1 = peg$currPos; 728 | s2 = peg$parseinteger(); 729 | if (s2 === peg$FAILED) { 730 | s2 = peg$c2; 731 | } 732 | if (s2 !== peg$FAILED) { 733 | if (peg$c16.test(input.charAt(peg$currPos))) { 734 | s3 = input.charAt(peg$currPos); 735 | peg$currPos++; 736 | } else { 737 | s3 = peg$FAILED; 738 | if (peg$silentFails === 0) { peg$fail(peg$c17); } 739 | } 740 | if (s3 !== peg$FAILED) { 741 | s4 = peg$parseinteger(); 742 | if (s4 !== peg$FAILED) { 743 | s2 = [s2, s3, s4]; 744 | s1 = s2; 745 | } else { 746 | peg$currPos = s1; 747 | s1 = peg$c1; 748 | } 749 | } else { 750 | peg$currPos = s1; 751 | s1 = peg$c1; 752 | } 753 | } else { 754 | peg$currPos = s1; 755 | s1 = peg$c1; 756 | } 757 | if (s1 !== peg$FAILED) { 758 | s1 = input.substring(s0, peg$currPos); 759 | } 760 | s0 = s1; 761 | 762 | return s0; 763 | } 764 | 765 | function peg$parsemixed_number() { 766 | var s0, s1, s2, s3, s4; 767 | 768 | s0 = peg$currPos; 769 | s1 = peg$currPos; 770 | s2 = peg$parseinteger(); 771 | if (s2 !== peg$FAILED) { 772 | s3 = peg$parsespace(); 773 | if (s3 !== peg$FAILED) { 774 | s4 = peg$parsefraction(); 775 | if (s4 !== peg$FAILED) { 776 | s2 = [s2, s3, s4]; 777 | s1 = s2; 778 | } else { 779 | peg$currPos = s1; 780 | s1 = peg$c1; 781 | } 782 | } else { 783 | peg$currPos = s1; 784 | s1 = peg$c1; 785 | } 786 | } else { 787 | peg$currPos = s1; 788 | s1 = peg$c1; 789 | } 790 | if (s1 !== peg$FAILED) { 791 | s1 = input.substring(s0, peg$currPos); 792 | } 793 | s0 = s1; 794 | 795 | return s0; 796 | } 797 | 798 | function peg$parsefraction() { 799 | var s0, s1, s2, s3, s4; 800 | 801 | s0 = peg$currPos; 802 | s1 = peg$currPos; 803 | s2 = peg$parseinteger(); 804 | if (s2 !== peg$FAILED) { 805 | if (peg$c18.test(input.charAt(peg$currPos))) { 806 | s3 = input.charAt(peg$currPos); 807 | peg$currPos++; 808 | } else { 809 | s3 = peg$FAILED; 810 | if (peg$silentFails === 0) { peg$fail(peg$c19); } 811 | } 812 | if (s3 !== peg$FAILED) { 813 | s4 = peg$parseinteger(); 814 | if (s4 !== peg$FAILED) { 815 | s2 = [s2, s3, s4]; 816 | s1 = s2; 817 | } else { 818 | peg$currPos = s1; 819 | s1 = peg$c1; 820 | } 821 | } else { 822 | peg$currPos = s1; 823 | s1 = peg$c1; 824 | } 825 | } else { 826 | peg$currPos = s1; 827 | s1 = peg$c1; 828 | } 829 | if (s1 !== peg$FAILED) { 830 | s1 = input.substring(s0, peg$currPos); 831 | } 832 | s0 = s1; 833 | 834 | return s0; 835 | } 836 | 837 | function peg$parseinteger() { 838 | var s0, s1, s2; 839 | 840 | s0 = peg$currPos; 841 | s1 = []; 842 | if (peg$c20.test(input.charAt(peg$currPos))) { 843 | s2 = input.charAt(peg$currPos); 844 | peg$currPos++; 845 | } else { 846 | s2 = peg$FAILED; 847 | if (peg$silentFails === 0) { peg$fail(peg$c21); } 848 | } 849 | if (s2 !== peg$FAILED) { 850 | while (s2 !== peg$FAILED) { 851 | s1.push(s2); 852 | if (peg$c20.test(input.charAt(peg$currPos))) { 853 | s2 = input.charAt(peg$currPos); 854 | peg$currPos++; 855 | } else { 856 | s2 = peg$FAILED; 857 | if (peg$silentFails === 0) { peg$fail(peg$c21); } 858 | } 859 | } 860 | } else { 861 | s1 = peg$c1; 862 | } 863 | if (s1 !== peg$FAILED) { 864 | peg$reportedPos = s0; 865 | s1 = peg$c22(s1); 866 | } 867 | s0 = s1; 868 | 869 | return s0; 870 | } 871 | 872 | function peg$parseletter() { 873 | var s0; 874 | 875 | if (peg$c23.test(input.charAt(peg$currPos))) { 876 | s0 = input.charAt(peg$currPos); 877 | peg$currPos++; 878 | } else { 879 | s0 = peg$FAILED; 880 | if (peg$silentFails === 0) { peg$fail(peg$c24); } 881 | } 882 | 883 | return s0; 884 | } 885 | 886 | function peg$parseunit() { 887 | var s0, s1, s2, s3, s4; 888 | 889 | s0 = peg$currPos; 890 | s1 = peg$currPos; 891 | s2 = peg$parseenglish_unit(); 892 | if (s2 !== peg$FAILED) { 893 | s3 = peg$currPos; 894 | peg$silentFails++; 895 | s4 = peg$parseletter(); 896 | peg$silentFails--; 897 | if (s4 === peg$FAILED) { 898 | s3 = peg$c25; 899 | } else { 900 | peg$currPos = s3; 901 | s3 = peg$c1; 902 | } 903 | if (s3 !== peg$FAILED) { 904 | s2 = [s2, s3]; 905 | s1 = s2; 906 | } else { 907 | peg$currPos = s1; 908 | s1 = peg$c1; 909 | } 910 | } else { 911 | peg$currPos = s1; 912 | s1 = peg$c1; 913 | } 914 | if (s1 !== peg$FAILED) { 915 | s1 = input.substring(s0, peg$currPos); 916 | } 917 | s0 = s1; 918 | if (s0 === peg$FAILED) { 919 | s0 = peg$currPos; 920 | s1 = peg$currPos; 921 | s2 = peg$parsemetric_unit(); 922 | if (s2 !== peg$FAILED) { 923 | s3 = peg$currPos; 924 | peg$silentFails++; 925 | s4 = peg$parseletter(); 926 | peg$silentFails--; 927 | if (s4 === peg$FAILED) { 928 | s3 = peg$c25; 929 | } else { 930 | peg$currPos = s3; 931 | s3 = peg$c1; 932 | } 933 | if (s3 !== peg$FAILED) { 934 | s2 = [s2, s3]; 935 | s1 = s2; 936 | } else { 937 | peg$currPos = s1; 938 | s1 = peg$c1; 939 | } 940 | } else { 941 | peg$currPos = s1; 942 | s1 = peg$c1; 943 | } 944 | if (s1 !== peg$FAILED) { 945 | s1 = input.substring(s0, peg$currPos); 946 | } 947 | s0 = s1; 948 | if (s0 === peg$FAILED) { 949 | s0 = peg$currPos; 950 | s1 = peg$currPos; 951 | s2 = peg$parseimprecise_unit(); 952 | if (s2 !== peg$FAILED) { 953 | s3 = peg$currPos; 954 | peg$silentFails++; 955 | s4 = peg$parseletter(); 956 | peg$silentFails--; 957 | if (s4 === peg$FAILED) { 958 | s3 = peg$c25; 959 | } else { 960 | peg$currPos = s3; 961 | s3 = peg$c1; 962 | } 963 | if (s3 !== peg$FAILED) { 964 | s2 = [s2, s3]; 965 | s1 = s2; 966 | } else { 967 | peg$currPos = s1; 968 | s1 = peg$c1; 969 | } 970 | } else { 971 | peg$currPos = s1; 972 | s1 = peg$c1; 973 | } 974 | if (s1 !== peg$FAILED) { 975 | s1 = input.substring(s0, peg$currPos); 976 | } 977 | s0 = s1; 978 | } 979 | } 980 | 981 | return s0; 982 | } 983 | 984 | function peg$parseenglish_unit() { 985 | var s0; 986 | 987 | s0 = peg$parsecup(); 988 | if (s0 === peg$FAILED) { 989 | s0 = peg$parsefluid_ounce(); 990 | if (s0 === peg$FAILED) { 991 | s0 = peg$parsegallon(); 992 | if (s0 === peg$FAILED) { 993 | s0 = peg$parseounce(); 994 | if (s0 === peg$FAILED) { 995 | s0 = peg$parsepint(); 996 | if (s0 === peg$FAILED) { 997 | s0 = peg$parsepound(); 998 | if (s0 === peg$FAILED) { 999 | s0 = peg$parsequart(); 1000 | if (s0 === peg$FAILED) { 1001 | s0 = peg$parsetablespoon(); 1002 | if (s0 === peg$FAILED) { 1003 | s0 = peg$parseteaspoon(); 1004 | } 1005 | } 1006 | } 1007 | } 1008 | } 1009 | } 1010 | } 1011 | } 1012 | 1013 | return s0; 1014 | } 1015 | 1016 | function peg$parsecup() { 1017 | var s0; 1018 | 1019 | if (input.substr(peg$currPos, 4).toLowerCase() === peg$c26) { 1020 | s0 = input.substr(peg$currPos, 4); 1021 | peg$currPos += 4; 1022 | } else { 1023 | s0 = peg$FAILED; 1024 | if (peg$silentFails === 0) { peg$fail(peg$c27); } 1025 | } 1026 | if (s0 === peg$FAILED) { 1027 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c28) { 1028 | s0 = input.substr(peg$currPos, 3); 1029 | peg$currPos += 3; 1030 | } else { 1031 | s0 = peg$FAILED; 1032 | if (peg$silentFails === 0) { peg$fail(peg$c29); } 1033 | } 1034 | if (s0 === peg$FAILED) { 1035 | if (input.substr(peg$currPos, 2).toLowerCase() === peg$c30) { 1036 | s0 = input.substr(peg$currPos, 2); 1037 | peg$currPos += 2; 1038 | } else { 1039 | s0 = peg$FAILED; 1040 | if (peg$silentFails === 0) { peg$fail(peg$c31); } 1041 | } 1042 | if (s0 === peg$FAILED) { 1043 | if (input.substr(peg$currPos, 1).toLowerCase() === peg$c32) { 1044 | s0 = input.charAt(peg$currPos); 1045 | peg$currPos++; 1046 | } else { 1047 | s0 = peg$FAILED; 1048 | if (peg$silentFails === 0) { peg$fail(peg$c33); } 1049 | } 1050 | } 1051 | } 1052 | } 1053 | 1054 | return s0; 1055 | } 1056 | 1057 | function peg$parsefluid_ounce() { 1058 | var s0, s1, s2, s3; 1059 | 1060 | s0 = peg$currPos; 1061 | s1 = peg$parsefluid(); 1062 | if (s1 !== peg$FAILED) { 1063 | s2 = peg$parsews(); 1064 | if (s2 !== peg$FAILED) { 1065 | s3 = peg$parseounce(); 1066 | if (s3 !== peg$FAILED) { 1067 | s1 = [s1, s2, s3]; 1068 | s0 = s1; 1069 | } else { 1070 | peg$currPos = s0; 1071 | s0 = peg$c1; 1072 | } 1073 | } else { 1074 | peg$currPos = s0; 1075 | s0 = peg$c1; 1076 | } 1077 | } else { 1078 | peg$currPos = s0; 1079 | s0 = peg$c1; 1080 | } 1081 | 1082 | return s0; 1083 | } 1084 | 1085 | function peg$parsefluid() { 1086 | var s0, s1, s2; 1087 | 1088 | if (input.substr(peg$currPos, 5).toLowerCase() === peg$c34) { 1089 | s0 = input.substr(peg$currPos, 5); 1090 | peg$currPos += 5; 1091 | } else { 1092 | s0 = peg$FAILED; 1093 | if (peg$silentFails === 0) { peg$fail(peg$c35); } 1094 | } 1095 | if (s0 === peg$FAILED) { 1096 | s0 = peg$currPos; 1097 | if (input.substr(peg$currPos, 2).toLowerCase() === peg$c36) { 1098 | s1 = input.substr(peg$currPos, 2); 1099 | peg$currPos += 2; 1100 | } else { 1101 | s1 = peg$FAILED; 1102 | if (peg$silentFails === 0) { peg$fail(peg$c37); } 1103 | } 1104 | if (s1 !== peg$FAILED) { 1105 | if (input.charCodeAt(peg$currPos) === 46) { 1106 | s2 = peg$c38; 1107 | peg$currPos++; 1108 | } else { 1109 | s2 = peg$FAILED; 1110 | if (peg$silentFails === 0) { peg$fail(peg$c39); } 1111 | } 1112 | if (s2 === peg$FAILED) { 1113 | s2 = peg$c2; 1114 | } 1115 | if (s2 !== peg$FAILED) { 1116 | s1 = [s1, s2]; 1117 | s0 = s1; 1118 | } else { 1119 | peg$currPos = s0; 1120 | s0 = peg$c1; 1121 | } 1122 | } else { 1123 | peg$currPos = s0; 1124 | s0 = peg$c1; 1125 | } 1126 | } 1127 | 1128 | return s0; 1129 | } 1130 | 1131 | function peg$parsegallon() { 1132 | var s0; 1133 | 1134 | if (input.substr(peg$currPos, 7).toLowerCase() === peg$c40) { 1135 | s0 = input.substr(peg$currPos, 7); 1136 | peg$currPos += 7; 1137 | } else { 1138 | s0 = peg$FAILED; 1139 | if (peg$silentFails === 0) { peg$fail(peg$c41); } 1140 | } 1141 | if (s0 === peg$FAILED) { 1142 | if (input.substr(peg$currPos, 6).toLowerCase() === peg$c42) { 1143 | s0 = input.substr(peg$currPos, 6); 1144 | peg$currPos += 6; 1145 | } else { 1146 | s0 = peg$FAILED; 1147 | if (peg$silentFails === 0) { peg$fail(peg$c43); } 1148 | } 1149 | if (s0 === peg$FAILED) { 1150 | if (input.substr(peg$currPos, 4).toLowerCase() === peg$c44) { 1151 | s0 = input.substr(peg$currPos, 4); 1152 | peg$currPos += 4; 1153 | } else { 1154 | s0 = peg$FAILED; 1155 | if (peg$silentFails === 0) { peg$fail(peg$c45); } 1156 | } 1157 | if (s0 === peg$FAILED) { 1158 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c46) { 1159 | s0 = input.substr(peg$currPos, 3); 1160 | peg$currPos += 3; 1161 | } else { 1162 | s0 = peg$FAILED; 1163 | if (peg$silentFails === 0) { peg$fail(peg$c47); } 1164 | } 1165 | } 1166 | } 1167 | } 1168 | 1169 | return s0; 1170 | } 1171 | 1172 | function peg$parseounce() { 1173 | var s0; 1174 | 1175 | if (input.substr(peg$currPos, 6).toLowerCase() === peg$c48) { 1176 | s0 = input.substr(peg$currPos, 6); 1177 | peg$currPos += 6; 1178 | } else { 1179 | s0 = peg$FAILED; 1180 | if (peg$silentFails === 0) { peg$fail(peg$c49); } 1181 | } 1182 | if (s0 === peg$FAILED) { 1183 | if (input.substr(peg$currPos, 5).toLowerCase() === peg$c50) { 1184 | s0 = input.substr(peg$currPos, 5); 1185 | peg$currPos += 5; 1186 | } else { 1187 | s0 = peg$FAILED; 1188 | if (peg$silentFails === 0) { peg$fail(peg$c51); } 1189 | } 1190 | if (s0 === peg$FAILED) { 1191 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c52) { 1192 | s0 = input.substr(peg$currPos, 3); 1193 | peg$currPos += 3; 1194 | } else { 1195 | s0 = peg$FAILED; 1196 | if (peg$silentFails === 0) { peg$fail(peg$c53); } 1197 | } 1198 | if (s0 === peg$FAILED) { 1199 | if (input.substr(peg$currPos, 2).toLowerCase() === peg$c54) { 1200 | s0 = input.substr(peg$currPos, 2); 1201 | peg$currPos += 2; 1202 | } else { 1203 | s0 = peg$FAILED; 1204 | if (peg$silentFails === 0) { peg$fail(peg$c55); } 1205 | } 1206 | } 1207 | } 1208 | } 1209 | 1210 | return s0; 1211 | } 1212 | 1213 | function peg$parsepint() { 1214 | var s0; 1215 | 1216 | if (input.substr(peg$currPos, 5).toLowerCase() === peg$c56) { 1217 | s0 = input.substr(peg$currPos, 5); 1218 | peg$currPos += 5; 1219 | } else { 1220 | s0 = peg$FAILED; 1221 | if (peg$silentFails === 0) { peg$fail(peg$c57); } 1222 | } 1223 | if (s0 === peg$FAILED) { 1224 | if (input.substr(peg$currPos, 4).toLowerCase() === peg$c58) { 1225 | s0 = input.substr(peg$currPos, 4); 1226 | peg$currPos += 4; 1227 | } else { 1228 | s0 = peg$FAILED; 1229 | if (peg$silentFails === 0) { peg$fail(peg$c59); } 1230 | } 1231 | if (s0 === peg$FAILED) { 1232 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c60) { 1233 | s0 = input.substr(peg$currPos, 3); 1234 | peg$currPos += 3; 1235 | } else { 1236 | s0 = peg$FAILED; 1237 | if (peg$silentFails === 0) { peg$fail(peg$c61); } 1238 | } 1239 | if (s0 === peg$FAILED) { 1240 | if (input.substr(peg$currPos, 2).toLowerCase() === peg$c62) { 1241 | s0 = input.substr(peg$currPos, 2); 1242 | peg$currPos += 2; 1243 | } else { 1244 | s0 = peg$FAILED; 1245 | if (peg$silentFails === 0) { peg$fail(peg$c63); } 1246 | } 1247 | } 1248 | } 1249 | } 1250 | 1251 | return s0; 1252 | } 1253 | 1254 | function peg$parsepound() { 1255 | var s0; 1256 | 1257 | if (input.substr(peg$currPos, 6).toLowerCase() === peg$c64) { 1258 | s0 = input.substr(peg$currPos, 6); 1259 | peg$currPos += 6; 1260 | } else { 1261 | s0 = peg$FAILED; 1262 | if (peg$silentFails === 0) { peg$fail(peg$c65); } 1263 | } 1264 | if (s0 === peg$FAILED) { 1265 | if (input.substr(peg$currPos, 5).toLowerCase() === peg$c66) { 1266 | s0 = input.substr(peg$currPos, 5); 1267 | peg$currPos += 5; 1268 | } else { 1269 | s0 = peg$FAILED; 1270 | if (peg$silentFails === 0) { peg$fail(peg$c67); } 1271 | } 1272 | if (s0 === peg$FAILED) { 1273 | if (input.substr(peg$currPos, 4).toLowerCase() === peg$c68) { 1274 | s0 = input.substr(peg$currPos, 4); 1275 | peg$currPos += 4; 1276 | } else { 1277 | s0 = peg$FAILED; 1278 | if (peg$silentFails === 0) { peg$fail(peg$c69); } 1279 | } 1280 | if (s0 === peg$FAILED) { 1281 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c70) { 1282 | s0 = input.substr(peg$currPos, 3); 1283 | peg$currPos += 3; 1284 | } else { 1285 | s0 = peg$FAILED; 1286 | if (peg$silentFails === 0) { peg$fail(peg$c71); } 1287 | } 1288 | if (s0 === peg$FAILED) { 1289 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c72) { 1290 | s0 = input.substr(peg$currPos, 3); 1291 | peg$currPos += 3; 1292 | } else { 1293 | s0 = peg$FAILED; 1294 | if (peg$silentFails === 0) { peg$fail(peg$c73); } 1295 | } 1296 | if (s0 === peg$FAILED) { 1297 | if (input.substr(peg$currPos, 2).toLowerCase() === peg$c74) { 1298 | s0 = input.substr(peg$currPos, 2); 1299 | peg$currPos += 2; 1300 | } else { 1301 | s0 = peg$FAILED; 1302 | if (peg$silentFails === 0) { peg$fail(peg$c75); } 1303 | } 1304 | } 1305 | } 1306 | } 1307 | } 1308 | } 1309 | 1310 | return s0; 1311 | } 1312 | 1313 | function peg$parsequart() { 1314 | var s0; 1315 | 1316 | if (input.substr(peg$currPos, 6).toLowerCase() === peg$c76) { 1317 | s0 = input.substr(peg$currPos, 6); 1318 | peg$currPos += 6; 1319 | } else { 1320 | s0 = peg$FAILED; 1321 | if (peg$silentFails === 0) { peg$fail(peg$c77); } 1322 | } 1323 | if (s0 === peg$FAILED) { 1324 | if (input.substr(peg$currPos, 5).toLowerCase() === peg$c78) { 1325 | s0 = input.substr(peg$currPos, 5); 1326 | peg$currPos += 5; 1327 | } else { 1328 | s0 = peg$FAILED; 1329 | if (peg$silentFails === 0) { peg$fail(peg$c79); } 1330 | } 1331 | if (s0 === peg$FAILED) { 1332 | if (input.substr(peg$currPos, 4).toLowerCase() === peg$c80) { 1333 | s0 = input.substr(peg$currPos, 4); 1334 | peg$currPos += 4; 1335 | } else { 1336 | s0 = peg$FAILED; 1337 | if (peg$silentFails === 0) { peg$fail(peg$c81); } 1338 | } 1339 | if (s0 === peg$FAILED) { 1340 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c82) { 1341 | s0 = input.substr(peg$currPos, 3); 1342 | peg$currPos += 3; 1343 | } else { 1344 | s0 = peg$FAILED; 1345 | if (peg$silentFails === 0) { peg$fail(peg$c83); } 1346 | } 1347 | if (s0 === peg$FAILED) { 1348 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c84) { 1349 | s0 = input.substr(peg$currPos, 3); 1350 | peg$currPos += 3; 1351 | } else { 1352 | s0 = peg$FAILED; 1353 | if (peg$silentFails === 0) { peg$fail(peg$c85); } 1354 | } 1355 | if (s0 === peg$FAILED) { 1356 | if (input.substr(peg$currPos, 2).toLowerCase() === peg$c86) { 1357 | s0 = input.substr(peg$currPos, 2); 1358 | peg$currPos += 2; 1359 | } else { 1360 | s0 = peg$FAILED; 1361 | if (peg$silentFails === 0) { peg$fail(peg$c87); } 1362 | } 1363 | } 1364 | } 1365 | } 1366 | } 1367 | } 1368 | 1369 | return s0; 1370 | } 1371 | 1372 | function peg$parsetablespoon() { 1373 | var s0; 1374 | 1375 | if (input.substr(peg$currPos, 11).toLowerCase() === peg$c88) { 1376 | s0 = input.substr(peg$currPos, 11); 1377 | peg$currPos += 11; 1378 | } else { 1379 | s0 = peg$FAILED; 1380 | if (peg$silentFails === 0) { peg$fail(peg$c89); } 1381 | } 1382 | if (s0 === peg$FAILED) { 1383 | if (input.substr(peg$currPos, 10).toLowerCase() === peg$c90) { 1384 | s0 = input.substr(peg$currPos, 10); 1385 | peg$currPos += 10; 1386 | } else { 1387 | s0 = peg$FAILED; 1388 | if (peg$silentFails === 0) { peg$fail(peg$c91); } 1389 | } 1390 | if (s0 === peg$FAILED) { 1391 | if (input.substr(peg$currPos, 5).toLowerCase() === peg$c92) { 1392 | s0 = input.substr(peg$currPos, 5); 1393 | peg$currPos += 5; 1394 | } else { 1395 | s0 = peg$FAILED; 1396 | if (peg$silentFails === 0) { peg$fail(peg$c93); } 1397 | } 1398 | if (s0 === peg$FAILED) { 1399 | if (input.substr(peg$currPos, 4).toLowerCase() === peg$c94) { 1400 | s0 = input.substr(peg$currPos, 4); 1401 | peg$currPos += 4; 1402 | } else { 1403 | s0 = peg$FAILED; 1404 | if (peg$silentFails === 0) { peg$fail(peg$c95); } 1405 | } 1406 | if (s0 === peg$FAILED) { 1407 | if (input.substr(peg$currPos, 4).toLowerCase() === peg$c96) { 1408 | s0 = input.substr(peg$currPos, 4); 1409 | peg$currPos += 4; 1410 | } else { 1411 | s0 = peg$FAILED; 1412 | if (peg$silentFails === 0) { peg$fail(peg$c97); } 1413 | } 1414 | if (s0 === peg$FAILED) { 1415 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c98) { 1416 | s0 = input.substr(peg$currPos, 3); 1417 | peg$currPos += 3; 1418 | } else { 1419 | s0 = peg$FAILED; 1420 | if (peg$silentFails === 0) { peg$fail(peg$c99); } 1421 | } 1422 | if (s0 === peg$FAILED) { 1423 | if (input.substr(peg$currPos, 2) === peg$c100) { 1424 | s0 = peg$c100; 1425 | peg$currPos += 2; 1426 | } else { 1427 | s0 = peg$FAILED; 1428 | if (peg$silentFails === 0) { peg$fail(peg$c101); } 1429 | } 1430 | if (s0 === peg$FAILED) { 1431 | if (input.charCodeAt(peg$currPos) === 84) { 1432 | s0 = peg$c102; 1433 | peg$currPos++; 1434 | } else { 1435 | s0 = peg$FAILED; 1436 | if (peg$silentFails === 0) { peg$fail(peg$c103); } 1437 | } 1438 | } 1439 | } 1440 | } 1441 | } 1442 | } 1443 | } 1444 | } 1445 | 1446 | return s0; 1447 | } 1448 | 1449 | function peg$parseteaspoon() { 1450 | var s0; 1451 | 1452 | if (input.substr(peg$currPos, 9).toLowerCase() === peg$c104) { 1453 | s0 = input.substr(peg$currPos, 9); 1454 | peg$currPos += 9; 1455 | } else { 1456 | s0 = peg$FAILED; 1457 | if (peg$silentFails === 0) { peg$fail(peg$c105); } 1458 | } 1459 | if (s0 === peg$FAILED) { 1460 | if (input.substr(peg$currPos, 8).toLowerCase() === peg$c106) { 1461 | s0 = input.substr(peg$currPos, 8); 1462 | peg$currPos += 8; 1463 | } else { 1464 | s0 = peg$FAILED; 1465 | if (peg$silentFails === 0) { peg$fail(peg$c107); } 1466 | } 1467 | if (s0 === peg$FAILED) { 1468 | if (input.substr(peg$currPos, 4).toLowerCase() === peg$c108) { 1469 | s0 = input.substr(peg$currPos, 4); 1470 | peg$currPos += 4; 1471 | } else { 1472 | s0 = peg$FAILED; 1473 | if (peg$silentFails === 0) { peg$fail(peg$c109); } 1474 | } 1475 | if (s0 === peg$FAILED) { 1476 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c110) { 1477 | s0 = input.substr(peg$currPos, 3); 1478 | peg$currPos += 3; 1479 | } else { 1480 | s0 = peg$FAILED; 1481 | if (peg$silentFails === 0) { peg$fail(peg$c111); } 1482 | } 1483 | if (s0 === peg$FAILED) { 1484 | if (input.substr(peg$currPos, 2) === peg$c112) { 1485 | s0 = peg$c112; 1486 | peg$currPos += 2; 1487 | } else { 1488 | s0 = peg$FAILED; 1489 | if (peg$silentFails === 0) { peg$fail(peg$c113); } 1490 | } 1491 | if (s0 === peg$FAILED) { 1492 | if (input.charCodeAt(peg$currPos) === 116) { 1493 | s0 = peg$c114; 1494 | peg$currPos++; 1495 | } else { 1496 | s0 = peg$FAILED; 1497 | if (peg$silentFails === 0) { peg$fail(peg$c115); } 1498 | } 1499 | } 1500 | } 1501 | } 1502 | } 1503 | } 1504 | 1505 | return s0; 1506 | } 1507 | 1508 | function peg$parsemetric_unit() { 1509 | var s0; 1510 | 1511 | s0 = peg$parsegram(); 1512 | if (s0 === peg$FAILED) { 1513 | s0 = peg$parsekilogram(); 1514 | if (s0 === peg$FAILED) { 1515 | s0 = peg$parseliter(); 1516 | if (s0 === peg$FAILED) { 1517 | s0 = peg$parsemilligram(); 1518 | if (s0 === peg$FAILED) { 1519 | s0 = peg$parsemilliliter(); 1520 | } 1521 | } 1522 | } 1523 | } 1524 | 1525 | return s0; 1526 | } 1527 | 1528 | function peg$parsegram() { 1529 | var s0; 1530 | 1531 | if (input.substr(peg$currPos, 5).toLowerCase() === peg$c116) { 1532 | s0 = input.substr(peg$currPos, 5); 1533 | peg$currPos += 5; 1534 | } else { 1535 | s0 = peg$FAILED; 1536 | if (peg$silentFails === 0) { peg$fail(peg$c117); } 1537 | } 1538 | if (s0 === peg$FAILED) { 1539 | if (input.substr(peg$currPos, 4).toLowerCase() === peg$c118) { 1540 | s0 = input.substr(peg$currPos, 4); 1541 | peg$currPos += 4; 1542 | } else { 1543 | s0 = peg$FAILED; 1544 | if (peg$silentFails === 0) { peg$fail(peg$c119); } 1545 | } 1546 | if (s0 === peg$FAILED) { 1547 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c120) { 1548 | s0 = input.substr(peg$currPos, 3); 1549 | peg$currPos += 3; 1550 | } else { 1551 | s0 = peg$FAILED; 1552 | if (peg$silentFails === 0) { peg$fail(peg$c121); } 1553 | } 1554 | if (s0 === peg$FAILED) { 1555 | if (input.substr(peg$currPos, 2).toLowerCase() === peg$c122) { 1556 | s0 = input.substr(peg$currPos, 2); 1557 | peg$currPos += 2; 1558 | } else { 1559 | s0 = peg$FAILED; 1560 | if (peg$silentFails === 0) { peg$fail(peg$c123); } 1561 | } 1562 | if (s0 === peg$FAILED) { 1563 | if (input.substr(peg$currPos, 2).toLowerCase() === peg$c124) { 1564 | s0 = input.substr(peg$currPos, 2); 1565 | peg$currPos += 2; 1566 | } else { 1567 | s0 = peg$FAILED; 1568 | if (peg$silentFails === 0) { peg$fail(peg$c125); } 1569 | } 1570 | if (s0 === peg$FAILED) { 1571 | if (input.substr(peg$currPos, 1).toLowerCase() === peg$c126) { 1572 | s0 = input.charAt(peg$currPos); 1573 | peg$currPos++; 1574 | } else { 1575 | s0 = peg$FAILED; 1576 | if (peg$silentFails === 0) { peg$fail(peg$c127); } 1577 | } 1578 | } 1579 | } 1580 | } 1581 | } 1582 | } 1583 | 1584 | return s0; 1585 | } 1586 | 1587 | function peg$parsekilogram() { 1588 | var s0; 1589 | 1590 | if (input.substr(peg$currPos, 9).toLowerCase() === peg$c128) { 1591 | s0 = input.substr(peg$currPos, 9); 1592 | peg$currPos += 9; 1593 | } else { 1594 | s0 = peg$FAILED; 1595 | if (peg$silentFails === 0) { peg$fail(peg$c129); } 1596 | } 1597 | if (s0 === peg$FAILED) { 1598 | if (input.substr(peg$currPos, 8).toLowerCase() === peg$c130) { 1599 | s0 = input.substr(peg$currPos, 8); 1600 | peg$currPos += 8; 1601 | } else { 1602 | s0 = peg$FAILED; 1603 | if (peg$silentFails === 0) { peg$fail(peg$c131); } 1604 | } 1605 | if (s0 === peg$FAILED) { 1606 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c132) { 1607 | s0 = input.substr(peg$currPos, 3); 1608 | peg$currPos += 3; 1609 | } else { 1610 | s0 = peg$FAILED; 1611 | if (peg$silentFails === 0) { peg$fail(peg$c133); } 1612 | } 1613 | if (s0 === peg$FAILED) { 1614 | if (input.substr(peg$currPos, 2).toLowerCase() === peg$c134) { 1615 | s0 = input.substr(peg$currPos, 2); 1616 | peg$currPos += 2; 1617 | } else { 1618 | s0 = peg$FAILED; 1619 | if (peg$silentFails === 0) { peg$fail(peg$c135); } 1620 | } 1621 | } 1622 | } 1623 | } 1624 | 1625 | return s0; 1626 | } 1627 | 1628 | function peg$parseliter() { 1629 | var s0; 1630 | 1631 | if (input.substr(peg$currPos, 6).toLowerCase() === peg$c136) { 1632 | s0 = input.substr(peg$currPos, 6); 1633 | peg$currPos += 6; 1634 | } else { 1635 | s0 = peg$FAILED; 1636 | if (peg$silentFails === 0) { peg$fail(peg$c137); } 1637 | } 1638 | if (s0 === peg$FAILED) { 1639 | if (input.substr(peg$currPos, 5).toLowerCase() === peg$c138) { 1640 | s0 = input.substr(peg$currPos, 5); 1641 | peg$currPos += 5; 1642 | } else { 1643 | s0 = peg$FAILED; 1644 | if (peg$silentFails === 0) { peg$fail(peg$c139); } 1645 | } 1646 | if (s0 === peg$FAILED) { 1647 | if (input.substr(peg$currPos, 2).toLowerCase() === peg$c140) { 1648 | s0 = input.substr(peg$currPos, 2); 1649 | peg$currPos += 2; 1650 | } else { 1651 | s0 = peg$FAILED; 1652 | if (peg$silentFails === 0) { peg$fail(peg$c141); } 1653 | } 1654 | if (s0 === peg$FAILED) { 1655 | if (input.substr(peg$currPos, 1).toLowerCase() === peg$c142) { 1656 | s0 = input.charAt(peg$currPos); 1657 | peg$currPos++; 1658 | } else { 1659 | s0 = peg$FAILED; 1660 | if (peg$silentFails === 0) { peg$fail(peg$c143); } 1661 | } 1662 | } 1663 | } 1664 | } 1665 | 1666 | return s0; 1667 | } 1668 | 1669 | function peg$parsemilligram() { 1670 | var s0; 1671 | 1672 | if (input.substr(peg$currPos, 10).toLowerCase() === peg$c144) { 1673 | s0 = input.substr(peg$currPos, 10); 1674 | peg$currPos += 10; 1675 | } else { 1676 | s0 = peg$FAILED; 1677 | if (peg$silentFails === 0) { peg$fail(peg$c145); } 1678 | } 1679 | if (s0 === peg$FAILED) { 1680 | if (input.substr(peg$currPos, 9).toLowerCase() === peg$c146) { 1681 | s0 = input.substr(peg$currPos, 9); 1682 | peg$currPos += 9; 1683 | } else { 1684 | s0 = peg$FAILED; 1685 | if (peg$silentFails === 0) { peg$fail(peg$c147); } 1686 | } 1687 | if (s0 === peg$FAILED) { 1688 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c148) { 1689 | s0 = input.substr(peg$currPos, 3); 1690 | peg$currPos += 3; 1691 | } else { 1692 | s0 = peg$FAILED; 1693 | if (peg$silentFails === 0) { peg$fail(peg$c149); } 1694 | } 1695 | if (s0 === peg$FAILED) { 1696 | if (input.substr(peg$currPos, 2).toLowerCase() === peg$c150) { 1697 | s0 = input.substr(peg$currPos, 2); 1698 | peg$currPos += 2; 1699 | } else { 1700 | s0 = peg$FAILED; 1701 | if (peg$silentFails === 0) { peg$fail(peg$c151); } 1702 | } 1703 | } 1704 | } 1705 | } 1706 | 1707 | return s0; 1708 | } 1709 | 1710 | function peg$parsemilliliter() { 1711 | var s0; 1712 | 1713 | if (input.substr(peg$currPos, 11).toLowerCase() === peg$c152) { 1714 | s0 = input.substr(peg$currPos, 11); 1715 | peg$currPos += 11; 1716 | } else { 1717 | s0 = peg$FAILED; 1718 | if (peg$silentFails === 0) { peg$fail(peg$c153); } 1719 | } 1720 | if (s0 === peg$FAILED) { 1721 | if (input.substr(peg$currPos, 10).toLowerCase() === peg$c154) { 1722 | s0 = input.substr(peg$currPos, 10); 1723 | peg$currPos += 10; 1724 | } else { 1725 | s0 = peg$FAILED; 1726 | if (peg$silentFails === 0) { peg$fail(peg$c155); } 1727 | } 1728 | if (s0 === peg$FAILED) { 1729 | if (input.substr(peg$currPos, 3).toLowerCase() === peg$c156) { 1730 | s0 = input.substr(peg$currPos, 3); 1731 | peg$currPos += 3; 1732 | } else { 1733 | s0 = peg$FAILED; 1734 | if (peg$silentFails === 0) { peg$fail(peg$c157); } 1735 | } 1736 | if (s0 === peg$FAILED) { 1737 | if (input.substr(peg$currPos, 2).toLowerCase() === peg$c158) { 1738 | s0 = input.substr(peg$currPos, 2); 1739 | peg$currPos += 2; 1740 | } else { 1741 | s0 = peg$FAILED; 1742 | if (peg$silentFails === 0) { peg$fail(peg$c159); } 1743 | } 1744 | } 1745 | } 1746 | } 1747 | 1748 | return s0; 1749 | } 1750 | 1751 | function peg$parseimprecise_unit() { 1752 | var s0; 1753 | 1754 | s0 = peg$parsedash(); 1755 | if (s0 === peg$FAILED) { 1756 | s0 = peg$parsehandful(); 1757 | if (s0 === peg$FAILED) { 1758 | s0 = peg$parsepinch(); 1759 | if (s0 === peg$FAILED) { 1760 | s0 = peg$parsetouch(); 1761 | } 1762 | } 1763 | } 1764 | 1765 | return s0; 1766 | } 1767 | 1768 | function peg$parsedash() { 1769 | var s0; 1770 | 1771 | if (input.substr(peg$currPos, 6).toLowerCase() === peg$c160) { 1772 | s0 = input.substr(peg$currPos, 6); 1773 | peg$currPos += 6; 1774 | } else { 1775 | s0 = peg$FAILED; 1776 | if (peg$silentFails === 0) { peg$fail(peg$c161); } 1777 | } 1778 | if (s0 === peg$FAILED) { 1779 | if (input.substr(peg$currPos, 4).toLowerCase() === peg$c162) { 1780 | s0 = input.substr(peg$currPos, 4); 1781 | peg$currPos += 4; 1782 | } else { 1783 | s0 = peg$FAILED; 1784 | if (peg$silentFails === 0) { peg$fail(peg$c163); } 1785 | } 1786 | } 1787 | 1788 | return s0; 1789 | } 1790 | 1791 | function peg$parsehandful() { 1792 | var s0; 1793 | 1794 | if (input.substr(peg$currPos, 8).toLowerCase() === peg$c164) { 1795 | s0 = input.substr(peg$currPos, 8); 1796 | peg$currPos += 8; 1797 | } else { 1798 | s0 = peg$FAILED; 1799 | if (peg$silentFails === 0) { peg$fail(peg$c165); } 1800 | } 1801 | if (s0 === peg$FAILED) { 1802 | if (input.substr(peg$currPos, 7).toLowerCase() === peg$c166) { 1803 | s0 = input.substr(peg$currPos, 7); 1804 | peg$currPos += 7; 1805 | } else { 1806 | s0 = peg$FAILED; 1807 | if (peg$silentFails === 0) { peg$fail(peg$c167); } 1808 | } 1809 | } 1810 | 1811 | return s0; 1812 | } 1813 | 1814 | function peg$parsepinch() { 1815 | var s0; 1816 | 1817 | if (input.substr(peg$currPos, 7).toLowerCase() === peg$c168) { 1818 | s0 = input.substr(peg$currPos, 7); 1819 | peg$currPos += 7; 1820 | } else { 1821 | s0 = peg$FAILED; 1822 | if (peg$silentFails === 0) { peg$fail(peg$c169); } 1823 | } 1824 | if (s0 === peg$FAILED) { 1825 | if (input.substr(peg$currPos, 5).toLowerCase() === peg$c170) { 1826 | s0 = input.substr(peg$currPos, 5); 1827 | peg$currPos += 5; 1828 | } else { 1829 | s0 = peg$FAILED; 1830 | if (peg$silentFails === 0) { peg$fail(peg$c171); } 1831 | } 1832 | } 1833 | 1834 | return s0; 1835 | } 1836 | 1837 | function peg$parsetouch() { 1838 | var s0; 1839 | 1840 | if (input.substr(peg$currPos, 7).toLowerCase() === peg$c172) { 1841 | s0 = input.substr(peg$currPos, 7); 1842 | peg$currPos += 7; 1843 | } else { 1844 | s0 = peg$FAILED; 1845 | if (peg$silentFails === 0) { peg$fail(peg$c173); } 1846 | } 1847 | if (s0 === peg$FAILED) { 1848 | if (input.substr(peg$currPos, 5).toLowerCase() === peg$c174) { 1849 | s0 = input.substr(peg$currPos, 5); 1850 | peg$currPos += 5; 1851 | } else { 1852 | s0 = peg$FAILED; 1853 | if (peg$silentFails === 0) { peg$fail(peg$c175); } 1854 | } 1855 | } 1856 | 1857 | return s0; 1858 | } 1859 | 1860 | peg$result = peg$startRuleFunction(); 1861 | 1862 | if (peg$result !== peg$FAILED && peg$currPos === input.length) { 1863 | return peg$result; 1864 | } else { 1865 | if (peg$result !== peg$FAILED && peg$currPos < input.length) { 1866 | peg$fail({ type: "end", description: "end of input" }); 1867 | } 1868 | 1869 | throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos); 1870 | } 1871 | } 1872 | 1873 | return { 1874 | SyntaxError: SyntaxError, 1875 | parse: parse 1876 | }; 1877 | })(); --------------------------------------------------------------------------------