From 31f6e12844125f7902a71901512ff35c1d1d4365 Mon Sep 17 00:00:00 2001 From: Andrew Miner Date: Wed, 13 Apr 2016 22:31:11 -0700 Subject: [PATCH] wip --- src/client/models/parsing-2/parser.coffee | 84 +++++++++++--- ...parser_state.coffee => parser_data.coffee} | 51 ++++++--- .../models/parsing-2/parser_data.test.coffee | 55 +++++++++ .../models/parsing-2/parser_extension.coffee | 91 +++++++++++---- .../parser_extensions/current_pe_v1.coffee | 12 +- .../current_pe_v1.test.coffee | 19 ++- .../parser_extensions/item_pe_v1.coffee | 33 +++++- .../parser_extensions/item_pe_v1.test.coffee | 30 +++-- .../parser_extensions/mod_pe_v1.coffee | 15 ++- .../parser_extensions/mod_pe_v1.test.coffee | 30 +++-- .../mod_version_pe_v1.coffee | 13 ++- .../mod_version_pe_v1.test.coffee | 26 ++--- .../parser_extensions/recipe_pe_v1.coffee | 27 +++-- .../recipe_pe_v1.test.coffee | 89 +++++++-------- .../models/parsing-2/parser_state.test.coffee | 108 ------------------ 15 files changed, 386 insertions(+), 297 deletions(-) rename src/client/models/parsing-2/{parser_state.coffee => parser_data.coffee} (66%) create mode 100644 src/client/models/parsing-2/parser_data.test.coffee delete mode 100644 src/client/models/parsing-2/parser_state.test.coffee diff --git a/src/client/models/parsing-2/parser.coffee b/src/client/models/parsing-2/parser.coffee index 8ac9e597f..90dc5d19b 100644 --- a/src/client/models/parsing-2/parser.coffee +++ b/src/client/models/parsing-2/parser.coffee @@ -6,49 +6,73 @@ # LexicalAnalyzer = require './lexical_analyzer' -ParserState = require './parser_state' +ModPack = require '../game/mod_pack' +ParserData = require './parser_data' ######################################################################################################################## module.exports = class Parser - constructor: (state, fileName, rawText)-> - if not state? then throw new Error 'state is required' - + constructor: (modPack, fileName, rawText)-> @_extensions = [] @_fileName = fileName @_lexer = new LexicalAnalyzer fileName, rawText - @_state = state + @_modPack = new ModPack + @_data = new ParserData + + modPackData = @_data.create {}, 'modPack' + modPackData.instance = @_modPack @_loadSchema() # Public Methods ############################################################################### - processNextCommand: w.lift -> - command = @_lexer.next() - return unless command? - - for extension in @_extensions - continue unless extension.accepts command - extension.execute command - return - - throw new Error "unknown command: #{command.name}" + next: -> + if not @_lexer.isFinished + @_processNextCommand() + else if not @_data.isValidated + @_validateNextEntry() + else if not @_data.isBuilt + @_buildNextEntry() + else if not @_data.isAssembled + @_assembleNextEntry() # Property Methods ############################################################################# getIsFinished: -> - return @_lexer.isFinished + return @_lexer.isFinished and @_data.isValidated and @_data.isBuilt and @_data.isAssembled - getState: -> - return @_state + getData: -> + return @_data + + getModPack: -> + return @_modPack Object.defineProperties @prototype, + data: { get:@::getData } isFinished: { get:@::getIsFinished } - state: { get:@::getState } + modPack: { get:@::getModPack } # Private Methods ############################################################################## + _assembleNextEntry: -> + entry = @_data.popNextToAssemble() + return unless entry? + + for extensions in @_extensions + continue unless extension.canAssemble entry + extension.assemble entry + return + + _buildNextEntry: -> + entry = @_data.popNextToBuild() + return unless entry? + + for extensions in @_extensions + continue unless extension.canBuild entry + extension.build entry + return + _loadSchema: -> command = @_lexer.next() if command.name isnt 'schema' then throw new Error "#{@_fileName} must start with the \"schema\" command" @@ -56,11 +80,33 @@ module.exports = class Parser schema = command.argText if schema is '1' @_use new require './parser_extensions/current_pe_v1' + @_use new require './parser_extensions/item_pe_v1' @_use new require './parser_extensions/mod_pe_v1' @_use new require './parser_extensions/mod_version_pe_v1' + @_use new require './parser_extensions/recipe_pe_v1' else throw new Error "unknown schema version: #{schema}" + _processNextCommand: -> + command = @_lexer.next() + return unless command? + + for extension in @_extensions + continue unless extension.canExecute command + extension.execute command + return + + @_data.addError command, "unknown command: #{command.name}" + _use: (parserExtension)-> parserExtension.state = @_state @_extensions.push parserExtension + + _validateNextEntry: -> + entry = @_data.popNextToValidate() + return unless entry? + + for extensions in @_extensions + continue unless extension.canValidate entry + extension.validate entry + return diff --git a/src/client/models/parsing-2/parser_state.coffee b/src/client/models/parsing-2/parser_data.coffee similarity index 66% rename from src/client/models/parsing-2/parser_state.coffee rename to src/client/models/parsing-2/parser_data.coffee index 24a36b721..08885a395 100644 --- a/src/client/models/parsing-2/parser_state.coffee +++ b/src/client/models/parsing-2/parser_data.coffee @@ -1,5 +1,5 @@ # -# Crafting Guide - parser_state.coffee +# Crafting Guide - parser_data.coffee # # Copyright © 2014-2016 by Redwood Labs # All rights reserved. @@ -7,11 +7,15 @@ ######################################################################################################################## -module.exports = class ParserState +module.exports = class ParserData constructor: -> @clear() + @_toAssemble = [] + @_toBuild = [] + @_toValidate = [] + # Public Methods ############################################################################### addError: (command, message)-> @@ -24,6 +28,11 @@ module.exports = class ParserState typeData = @_findOrCreateType type itemData = @_current = typeData['current'] = typeData[id] = id:id, command:command, type:type + + @_toAssemble.push itemData + @_toBuild.push itemData + @_toValidate.push itemData + return itemData clear: -> @@ -31,20 +40,6 @@ module.exports = class ParserState @_data = {} @_errors = [] - each: (callback)-> - for type, typeData of @_data - for id, itemData of typeData - continue if id is 'current' - continue if id is 'type' - callback itemData - - eachOfType: (type, callback)-> - typeData = @_findOrCreateType type - for id, itemData of typeData - continue if id is 'current' - continue if id is 'type' - callback itemData - get: (type, id)-> typeData = @_findOrCreateType type itemData = typeData[id] or null @@ -57,13 +52,35 @@ module.exports = class ParserState current = typeData['current'] or null return current + popNextToAssemble: -> + return @_toAssemble.pop() or null + + popNextToBuild: -> + return @_toBuild.pop() or null + + popNextToValidate: -> + return @_toValidate.pop() or null + # Property Methods ############################################################################# getErrors: -> return @_errors[..] + getIsAssembled: -> + return @_toAssemble.length > 0 + + getIsBuilt: -> + return @_toBuild.length > 0 + + getIsValidated: -> + return @_toValidate.length > 0 + Object.defineProperties @prototype, - errors: { get:@::getErrors } + errors: { get:@::getErrors } + isAssembled: { get:@::getIsAssembled } + isBuilt: { get:@::getIsBuilt } + isValidated: { get:@::getIsValidated } + # Private Methods ############################################################################## diff --git a/src/client/models/parsing-2/parser_data.test.coffee b/src/client/models/parsing-2/parser_data.test.coffee new file mode 100644 index 000000000..07acdf842 --- /dev/null +++ b/src/client/models/parsing-2/parser_data.test.coffee @@ -0,0 +1,55 @@ +# +# Crafting Guide - parser_data.test.coffee +# +# Copyright © 2014-2016 by Redwood Labs +# All rights reserved. +# + +ParserCommand = require './parser_command' +ParserData = require './parser_data' + +######################################################################################################################## + +command = state = null + +######################################################################################################################## + +describe 'parser_data.coffee', -> + + beforeEach -> + state = new ParserData + command = new ParserCommand name:'alpha', fileName:'file.cg', lineNumber:1 + + describe 'create', -> + + it 'returns an object with the given id', -> + alpha = state.create command, 'alpha', 0 + alpha.id.should.equal 0 + alpha.command.location.should.equal 'file.cg:1' + + it 'returns an object with a newly created id when none is given', -> + alpha = state.create command, 'alpha' + alpha.id.should.not.be.null + alpha.id.should.match /^alpha-[0-9]+$/ + alpha.command.location.should.equal 'file.cg:1' + + describe 'get', -> + + it 'returns a previously created item', -> + alpha1 = state.create command, 'alpha', 0 + alpha2 = state.get 'alpha', 0 + alpha1.should.equal alpha2 + + it 'returns null when no such item exists', -> + alpha = state.create command, 'alpha', 0 + expect(state.get 'alpha', 1).to.be.null + expect(state.get 'bravo', 0).to.be.null + + describe 'getCurrent', -> + + it 'returns the new item each time one is created', -> + alpha1 = state.create command, 'alpha', 0 + state.getCurrent('alpha').id.should.equal 0 + + alpha2 = state.create command, 'alpha', 1 + state.getCurrent('alpha').id.should.equal 1 diff --git a/src/client/models/parsing-2/parser_extension.coffee b/src/client/models/parsing-2/parser_extension.coffee index cf37c315b..f3e059215 100644 --- a/src/client/models/parsing-2/parser_extension.coffee +++ b/src/client/models/parsing-2/parser_extension.coffee @@ -9,55 +9,77 @@ module.exports = class ParserExtension - constructor: (state)-> - @state = state + constructor: (data, type, commandFunctions)-> + @data = data + + @_commandFunctions = commandFunctions or {} + @_type = type or null # Public Methods ############################################################################### - accepts: (command)-> - return @_findCommandMethod(command)? + canAssemble: (entry)-> + return entry.type is @_type - execute: w.lift (command)-> - if not @_state? then throw new Error '@state must be defined before executing commands' + canBuild: (entry)-> + return entry.type is @_type - method = @_findCommandMethod command - method.call this, command + canExecute: (command)-> + _.isFunction @_commandFunctions[command.name] + + canValidate: (entry)-> + return entry.type is @_type + + execute: (command)-> + if not @_data? then throw new Error '@data must be defined before executing commands' + + func = @_commandFunctions[command.name] + if not func then throw new Error "#{@constructor.name} cannot handle command: #{command.name}" + + func.call this, command + return this # Error Checking Helpers ####################################################################### alreadyExists: (command, type, id)-> - obj = @state.get(type, id) + obj = @data.get(type, id) if obj? - @state.addError command, "a #{type} called #{id} has already been declared" + @data.addError command, "a #{type} called #{id} has already been declared" return true return false duplicateField: (command, obj, field)-> if obj[field]? - @state.addError command, "duplicate #{field}" + @data.addError command, "duplicate #{field}" return true return false missingCurrent: (command, type)-> - obj = @state.getCurrent type + obj = @data.getCurrent type if not obj? - @state.addError command, "you must declare a #{type} before using #{command.name}" + @data.addError command, "you must declare a #{type} before using #{command.name}" return true return false missingArgs: (command)-> if not command.args or command.args.length is 0 - @state.addError command, "#{command.name} requires at least one item" + @data.addError command, "#{command.name} requires at least one item" return true return false missingArgText: (command)-> if command.argText.length is 0 - @state.addError command, "#{command.name} cannot be empty" + @data.addError command, "#{command.name} cannot be empty" + return true + + return false + + tooFewArguments: (command, minimum)-> + if command.args.length < minimum + @data.addError command, "#{command.name} requires at least #{minimum} arguments" return true return false @@ -71,7 +93,7 @@ module.exports = class ParserExtension when "yes" then return true when "no" then return false - @state.addError command, "#{command.name} requires \"yes\" or \"no\"" + @data.addError command, "#{command.name} requires \"yes\" or \"no\"" return null parseInt: (command, text)-> @@ -86,20 +108,43 @@ module.exports = class ParserExtension # Property Methods ############################################################################# - getState: -> - return @_state + getData: -> + return @_data - setState: (state)-> - if not state? then throw new Error 'state cannot be undefined' - @_state = state + setData: (data)-> + if not data? then throw new Error 'data cannot be undefined' + @_data = data Object.defineProperties @prototype, - state: { get:@::getState, set:@::setState } + data: { get:@::getData, set:@::setData } + + # Overridable Methods ########################################################################## + + assmeble: (entry)-> + throw new Error "#{@constructor.name} must override the `assemble` method" + + build: (entry)-> + throw new Error "#{@constructor.name} must override the `build` method" + + validate: (entry)-> + throw new Error "#{@constructor.name} must override the `validate` method" # Private Methods ############################################################################## + _findBuildMethod: (entry)-> + methodName = "_build_#{entry.type}" + method = this[methodName] + return null unless _.isFunction method + return method + _findCommandMethod: (command)-> methodName = "_command_#{command.name}" method = this[methodName] - return null unless _.isFunction(method) + return null unless _.isFunction method + return method + + _findValidateMethod: (command)-> + methodName = "_validate_#{command.name}" + method = this[methodName] + return null unless _.isFunction method return method diff --git a/src/client/models/parsing-2/parser_extensions/current_pe_v1.coffee b/src/client/models/parsing-2/parser_extensions/current_pe_v1.coffee index 0f0c93b7d..f5d3cfd9e 100644 --- a/src/client/models/parsing-2/parser_extensions/current_pe_v1.coffee +++ b/src/client/models/parsing-2/parser_extensions/current_pe_v1.coffee @@ -11,24 +11,30 @@ ParserExtension = require '../parser_extension' module.exports = class CurrentParserExtensionV1 extends ParserExtension + constructor: (data)-> + super data, null, + documentationUrl: @_command_documentationUrl + description: @_command_description + name: @_command_name + # Command Methods ############################################################################## _command_documentationUrl: (command)-> - current = @state.getCurrent() + current = @data.getCurrent() return if @duplicateField command, current, 'documentationUrl' return if @missingArgText command current.documentationUrl = command.argText _command_description: (command)-> - current = @state.getCurrent() + current = @data.getCurrent() return if @duplicateField command, current, 'description' return if @missingArgText command current.description = command.argText _command_name: (command)-> - current = @state.getCurrent() + current = @data.getCurrent() return if @duplicateField command, current, 'name' return if @missingArgText command diff --git a/src/client/models/parsing-2/parser_extensions/current_pe_v1.test.coffee b/src/client/models/parsing-2/parser_extensions/current_pe_v1.test.coffee index be4c8bb40..0b6f2ef5c 100644 --- a/src/client/models/parsing-2/parser_extensions/current_pe_v1.test.coffee +++ b/src/client/models/parsing-2/parser_extensions/current_pe_v1.test.coffee @@ -6,7 +6,7 @@ # CurrentParserExtensionV1 = require './current_pe_v1' -ParserState = require '../parser_state' +ParserData = require '../parser_data' ######################################################################################################################## @@ -17,7 +17,7 @@ parser = state = null describe 'current_pe_v1.coffee', -> beforeEach -> - state = new ParserState + state = new ParserData parser = new CurrentParserExtensionV1 state state.create {}, 'alpha' @@ -26,22 +26,19 @@ describe 'current_pe_v1.coffee', -> it 'assigns to the current object', -> parser.execute name:'documentationUrl', argText:'bravo' - .then -> - state.getCurrent().documentationUrl.should.equal 'bravo' - state.errors.should.eql [] + state.getCurrent().documentationUrl.should.equal 'bravo' + state.errors.should.eql [] describe 'description', -> it 'assigns to the current object', -> parser.execute name:'description', argText:'bravo' - .then -> - state.getCurrent().description.should.equal 'bravo' - state.errors.should.eql [] + state.getCurrent().description.should.equal 'bravo' + state.errors.should.eql [] describe 'name', -> it 'assigns to the current object', -> parser.execute name:'name', argText:'bravo' - .then -> - state.getCurrent().name.should.equal 'bravo' - state.errors.should.eql [] + state.getCurrent().name.should.equal 'bravo' + state.errors.should.eql [] diff --git a/src/client/models/parsing-2/parser_extensions/item_pe_v1.coffee b/src/client/models/parsing-2/parser_extensions/item_pe_v1.coffee index a646552e8..9dbc48efd 100644 --- a/src/client/models/parsing-2/parser_extensions/item_pe_v1.coffee +++ b/src/client/models/parsing-2/parser_extensions/item_pe_v1.coffee @@ -11,6 +11,22 @@ ParserExtension = require '../parser_extension' module.exports = class ItemParserExtensionV1 extends ParserExtension + constructor: (data)-> + super data, 'item', + gatherable: @_command_gatherable + item: @_command_item + + # ParserExtensions Overrides ################################################################### + + assmeble: (entry)-> + throw new Error "#{@constructor.name} must override the `assemble` method" + + build: (entry)-> + entry.instance = new + throw new Error "#{@constructor.name} must override the `build` method" + + validate: (entry)-> # do nothing + # Command Methods ############################################################################## _command_gatherable: (command)-> @@ -18,7 +34,7 @@ module.exports = class ItemParserExtensionV1 extends ParserExtension return if @missingCurrent command, 'item' - item = @state.getCurrent 'item' + item = @data.getCurrent 'item' return if @duplicateField command, 'gatherable', item gatherable = @parseBoolean command, command.argText @@ -31,10 +47,19 @@ module.exports = class ItemParserExtensionV1 extends ParserExtension return if @missingCurrent command, 'modVersion' return if @alreadyExists command, 'item', command.argText - item = @state.create command, 'item', command.argText + item = @data.create command, 'item', command.argText item.name = command.argText - group = @state.getCurrent 'itemGroup' + group = @data.getCurrent 'itemGroup' if group? then item.group = group - item.modVersion = @state.getCurrent 'modVersion' + item.modVersion = @data.getCurrent 'modVersion' + + _command_video: (command)-> + return if @missingArgs command + return if @missingCurrent command, 'item' + return if @tooFewArguments command, 2 + + item = @data.getCurrent 'item' + item.videos ?= [] + item.videos.push youTubeId:command.args[0], caption:command.args[1..].join(', ') diff --git a/src/client/models/parsing-2/parser_extensions/item_pe_v1.test.coffee b/src/client/models/parsing-2/parser_extensions/item_pe_v1.test.coffee index c334d2de3..4a405562d 100644 --- a/src/client/models/parsing-2/parser_extensions/item_pe_v1.test.coffee +++ b/src/client/models/parsing-2/parser_extensions/item_pe_v1.test.coffee @@ -6,41 +6,39 @@ # ItemParserExtensionV1 = require './item_pe_v1' -ParserState = require '../parser_state' +ParserData = require '../parser_data' ######################################################################################################################## -parser = state = null +parser = data = null ######################################################################################################################## describe 'item_pe_v1.coffee', -> beforeEach -> - state = new ParserState - parser = new ItemParserExtensionV1 state + data = new ParserData + parser = new ItemParserExtensionV1 data - state.create {}, 'modVersion', 0 + data.create {}, 'modVersion', 0 describe 'gatherable', -> it 'assigns to the current item', -> - state.create {}, 'item', 1 + data.create {}, 'item', 1 parser.execute name:'gatherable', argText:'yes' - .then -> - state.getCurrent('item').gatherable.should.be.true - state.errors.should.eql [] + data.getCurrent('item').gatherable.should.be.true + data.errors.should.eql [] describe 'item', -> it 'creates a new item', -> - state.create {}, 'itemGroup', 2 + data.create {}, 'itemGroup', 2 parser.execute name:'item', argText:'alpha' - .then -> - item = state.getCurrent 'item' - item.id.should.equal 'alpha' - item.name.should.equal 'alpha' - item.modVersion.id.should.equal 0 - item.group.id.should.equal 2 + item = data.getCurrent 'item' + item.id.should.equal 'alpha' + item.name.should.equal 'alpha' + item.modVersion.id.should.equal 0 + item.group.id.should.equal 2 diff --git a/src/client/models/parsing-2/parser_extensions/mod_pe_v1.coffee b/src/client/models/parsing-2/parser_extensions/mod_pe_v1.coffee index edcfb696c..d5ac7bd41 100644 --- a/src/client/models/parsing-2/parser_extensions/mod_pe_v1.coffee +++ b/src/client/models/parsing-2/parser_extensions/mod_pe_v1.coffee @@ -11,12 +11,19 @@ ParserExtension = require '../parser_extension' module.exports = class ModParserExtensionV1 extends ParserExtension + constructor: (data)-> + super data, 'mod', + author: @_command_author + downloadUrl: @_command_downloadUrl + homePageUrl: @_command_homePageUrl + mod: @_command_mod + # Command Methods ############################################################################## _command_author: (command)-> return if @missingCurrent command, 'mod' - mod = @state.getCurrent 'mod' + mod = @data.getCurrent 'mod' return if @duplicateField command, mod, 'author' return if @missingArgText command @@ -25,7 +32,7 @@ module.exports = class ModParserExtensionV1 extends ParserExtension _command_downloadUrl: (command)-> return if @missingCurrent command, 'mod' - mod = @state.getCurrent 'mod' + mod = @data.getCurrent 'mod' return if @duplicateField command, mod, 'downloadUrl' return if @missingArgText command @@ -34,7 +41,7 @@ module.exports = class ModParserExtensionV1 extends ParserExtension _command_homePageUrl: (command)-> return if @missingCurrent command, 'mod' - mod = @state.getCurrent 'mod' + mod = @data.getCurrent 'mod' return if @duplicateField command, mod, 'homePageUrl' return if @missingArgText command @@ -44,4 +51,4 @@ module.exports = class ModParserExtensionV1 extends ParserExtension return if @missingArgText command return if @alreadyExists command, 'mod', command.argText - @state.create command, 'mod', command.argText + @data.create command, 'mod', command.argText diff --git a/src/client/models/parsing-2/parser_extensions/mod_pe_v1.test.coffee b/src/client/models/parsing-2/parser_extensions/mod_pe_v1.test.coffee index 771a43a17..f199ae807 100644 --- a/src/client/models/parsing-2/parser_extensions/mod_pe_v1.test.coffee +++ b/src/client/models/parsing-2/parser_extensions/mod_pe_v1.test.coffee @@ -6,50 +6,46 @@ # ModParserExtensionV1 = require './mod_pe_v1' -ParserState = require '../parser_state' +ParserData = require '../parser_data' ######################################################################################################################## -parser = state = null +parser = data = null ######################################################################################################################## describe 'mod_pe_v1.coffee', -> beforeEach -> - state = new ParserState - parser = new ModParserExtensionV1 state + data = new ParserData + parser = new ModParserExtensionV1 data - state.create {}, 'mod', 0 + data.create {}, 'mod', 0 describe 'author', -> it 'assigns to the current mod', -> parser.execute name:'author', argText:'alpha' - .then -> - state.getCurrent('mod').author.should.equal 'alpha' - state.errors.should.eql [] + data.getCurrent('mod').author.should.equal 'alpha' + data.errors.should.eql [] describe 'downloadUrl', -> it 'assigns to the current mod', -> parser.execute name:'downloadUrl', argText:'alpha' - .then -> - state.getCurrent('mod').downloadUrl.should.equal 'alpha' - state.errors.should.eql [] + data.getCurrent('mod').downloadUrl.should.equal 'alpha' + data.errors.should.eql [] describe 'homePageUrl', -> it 'assigns to the current mod', -> parser.execute name:'homePageUrl', argText:'alpha' - .then -> - state.getCurrent('mod').homePageUrl.should.equal 'alpha' - state.errors.should.eql [] + data.getCurrent('mod').homePageUrl.should.equal 'alpha' + data.errors.should.eql [] describe 'mod', -> it 'creates a new mod', -> parser.execute name:'mod', argText:'alpha' - .then -> - mod = state.getCurrent 'mod' - mod.id.should.equal 'alpha' + mod = data.getCurrent 'mod' + mod.id.should.equal 'alpha' diff --git a/src/client/models/parsing-2/parser_extensions/mod_version_pe_v1.coffee b/src/client/models/parsing-2/parser_extensions/mod_version_pe_v1.coffee index 72631d8dc..cf4d109c6 100644 --- a/src/client/models/parsing-2/parser_extensions/mod_version_pe_v1.coffee +++ b/src/client/models/parsing-2/parser_extensions/mod_version_pe_v1.coffee @@ -11,18 +11,23 @@ ParserExtension = require '../parser_extension' module.exports = class ModVersionParserExtensionV1 extends ParserExtension + constructor: (data)-> + super data, 'modVersion', + group: @_command_group + version: @_command_version + # Command Methods ############################################################################## _command_group: (command)-> return if @missingArgText command return if @missingCurrent command, 'modVersion' - group = @state.create command, 'itemGroup', command.argText - group.modVersion = @state.getCurrent 'modVersion' + group = @data.create command, 'itemGroup', command.argText + group.modVersion = @data.getCurrent 'modVersion' _command_version: (command)-> return if @missingArgText command return if @missingCurrent command, 'mod' - modVersion = @state.create command, 'modVersion', command.argText - modVersion.mod = @state.getCurrent 'mod' + modVersion = @data.create command, 'modVersion', command.argText + modVersion.mod = @data.getCurrent 'mod' diff --git a/src/client/models/parsing-2/parser_extensions/mod_version_pe_v1.test.coffee b/src/client/models/parsing-2/parser_extensions/mod_version_pe_v1.test.coffee index 529f756d1..413721b68 100644 --- a/src/client/models/parsing-2/parser_extensions/mod_version_pe_v1.test.coffee +++ b/src/client/models/parsing-2/parser_extensions/mod_version_pe_v1.test.coffee @@ -6,38 +6,36 @@ # ModVersionParserExtensionV1 = require './mod_version_pe_v1' -ParserState = require '../parser_state' +ParserData = require '../parser_data' ######################################################################################################################## -parser = state = null +parser = data = null ######################################################################################################################## describe 'mod_version_pe_v1.coffee', -> beforeEach -> - state = new ParserState - parser = new ModVersionParserExtensionV1 state + data = new ParserData + parser = new ModVersionParserExtensionV1 data - state.create {}, 'mod', 0 + data.create {}, 'mod', 0 describe 'group', -> it 'creates a new item group', -> - state.create {}, 'modVersion', 1 + data.create {}, 'modVersion', 1 parser.execute name:'group', argText:'alpha' - .then -> - itemGroup = state.getCurrent('itemGroup') - itemGroup.id.should.equal 'alpha' - itemGroup.modVersion.id.should.equal 1 + itemGroup = data.getCurrent('itemGroup') + itemGroup.id.should.equal 'alpha' + itemGroup.modVersion.id.should.equal 1 describe 'version', -> it 'creates a new mod version', -> parser.execute name:'version', argText:'alpha' - .then -> - modVersion = state.getCurrent 'modVersion' - modVersion.id.should.equal 'alpha' - modVersion.mod.id.should.equal 0 + modVersion = data.getCurrent 'modVersion' + modVersion.id.should.equal 'alpha' + modVersion.mod.id.should.equal 0 diff --git a/src/client/models/parsing-2/parser_extensions/recipe_pe_v1.coffee b/src/client/models/parsing-2/parser_extensions/recipe_pe_v1.coffee index 207ec1e72..e4d79732b 100644 --- a/src/client/models/parsing-2/parser_extensions/recipe_pe_v1.coffee +++ b/src/client/models/parsing-2/parser_extensions/recipe_pe_v1.coffee @@ -11,6 +11,17 @@ ParserExtension = require '../parser_extension' module.exports = class RecipeParserExtensionV1 extends ParserExtension + constructor: (data)-> + super data, 'recipe', + extras: @_command_extras + input: @_command_input + pattern: @_command_pattern + recipe: @_command_recipe + quantity: @_command_quantity + tools: @_command_tools + + # Class Methods ################################################################################ + @::PATTERN = /[0-9. ]+/ @::STACK = /^([0-9]+) +(.+)$/ @@ -20,7 +31,7 @@ module.exports = class RecipeParserExtensionV1 extends ParserExtension invalidPattern: (command)-> match = command.argText.match @PATTERN if not match? - @state.addError command, "invalid pattern: \"#{command.argText}\"" + @data.addError command, "invalid pattern: \"#{command.argText}\"" return true return false @@ -31,7 +42,7 @@ module.exports = class RecipeParserExtensionV1 extends ParserExtension return if @missingCurrent command, 'recipe' return if @missingArgs command - recipe = @state.getCurrent 'recipe' + recipe = @data.getCurrent 'recipe' return if @duplicateField command, 'extras', recipe recipe.extras = command.args @@ -40,7 +51,7 @@ module.exports = class RecipeParserExtensionV1 extends ParserExtension return if @missingCurrent command, 'recipe' return if @missingArgs command - recipe = @state.getCurrent 'recipe' + recipe = @data.getCurrent 'recipe' return if @duplicateField command, 'input', recipe recipe.input = (@_parseStack(arg) for arg in command.args) @@ -50,7 +61,7 @@ module.exports = class RecipeParserExtensionV1 extends ParserExtension return if @missingArgText command return if @invalidPattern command - recipe = @state.getCurrent 'recipe' + recipe = @data.getCurrent 'recipe' return if @duplicateField command, 'pattern', recipe recipe.pattern = command.argText @@ -58,8 +69,8 @@ module.exports = class RecipeParserExtensionV1 extends ParserExtension _command_recipe: (command)-> return if @missingCurrent command, 'item' - recipe = @state.create command, 'recipe' - recipe.item = @state.getCurrent 'item' + recipe = @data.create command, 'recipe' + recipe.item = @data.getCurrent 'item' _command_quantity: (command)-> return if @missingCurrent command, 'recipe' @@ -68,7 +79,7 @@ module.exports = class RecipeParserExtensionV1 extends ParserExtension value = @parseInt command, command.argText return unless value? - recipe = @state.getCurrent 'recipe' + recipe = @data.getCurrent 'recipe' return if @duplicateField command, 'quantity', recipe recipe.quantity = value @@ -77,7 +88,7 @@ module.exports = class RecipeParserExtensionV1 extends ParserExtension return if @missingCurrent command, 'recipe' return if @missingArgs command - recipe = @state.getCurrent 'recipe' + recipe = @data.getCurrent 'recipe' return if @duplicateField command, 'tools', recipe recipe.tools = (@_parseStack(arg) for arg in command.args) diff --git a/src/client/models/parsing-2/parser_extensions/recipe_pe_v1.test.coffee b/src/client/models/parsing-2/parser_extensions/recipe_pe_v1.test.coffee index 86e09bb86..60470263b 100644 --- a/src/client/models/parsing-2/parser_extensions/recipe_pe_v1.test.coffee +++ b/src/client/models/parsing-2/parser_extensions/recipe_pe_v1.test.coffee @@ -6,109 +6,100 @@ # RecipeParserExtensionV1 = require './recipe_pe_v1' -ParserState = require '../parser_state' +ParserData = require '../parser_data' ######################################################################################################################## -parser = state = null +parser = data = null ######################################################################################################################## describe 'recipe_pe_v1.coffee', -> beforeEach -> - state = new ParserState - parser = new RecipeParserExtensionV1 state + data = new ParserData + parser = new RecipeParserExtensionV1 data - state.create {}, 'item', 0 + data.create {}, 'item', 0 describe 'extras', -> it 'assigns to the current recipe', -> - state.create {}, 'recipe' + data.create {}, 'recipe' parser.execute name:'extras', args:['bravo'] - .then -> - recipe = state.getCurrent 'recipe' - recipe.extras.should.eql ['bravo'] - state.errors.should.eql [] + recipe = data.getCurrent 'recipe' + recipe.extras.should.eql ['bravo'] + data.errors.should.eql [] describe 'input', -> it 'correctly reads a single item', -> - state.create {}, 'recipe' + data.create {}, 'recipe' parser.execute name:'input', args:['bravo'] - .then -> - recipe = state.getCurrent 'recipe' - recipe.input.should.eql [name:'bravo', quantity:1] - state.errors.should.eql [] + recipe = data.getCurrent 'recipe' + recipe.input.should.eql [name:'bravo', quantity:1] + data.errors.should.eql [] it 'correctly reads multiple items', -> - state.create {}, 'recipe' + data.create {}, 'recipe' parser.execute name:'input', args:['bravo', 'charlie'] - .then -> - recipe = state.getCurrent 'recipe' - recipe.input.should.eql [{name:'bravo', quantity:1}, {name:'charlie', quantity:1}] - state.errors.should.eql [] + recipe = data.getCurrent 'recipe' + recipe.input.should.eql [{name:'bravo', quantity:1}, {name:'charlie', quantity:1}] + data.errors.should.eql [] it 'correctly reads a stack', -> - state.create {}, 'recipe' + data.create {}, 'recipe' parser.execute name:'input', args:['10 bravo'] - .then -> - recipe = state.getCurrent 'recipe' - recipe.input.should.eql [name:'bravo', quantity:10] - state.errors.should.eql [] + recipe = data.getCurrent 'recipe' + recipe.input.should.eql [name:'bravo', quantity:10] + data.errors.should.eql [] describe 'pattern', -> it 'assigns to the current recipe', -> - state.create {}, 'recipe' + data.create {}, 'recipe' parser.execute name:'pattern', argText:'00. 00. ...' - .then -> - recipe = state.getCurrent 'recipe' - recipe.pattern.should.equal '00. 00. ...' - state.errors.should.eql [] + recipe = data.getCurrent 'recipe' + recipe.pattern.should.equal '00. 00. ...' + data.errors.should.eql [] it 'rejects an invalid pattern', -> - state.create {}, 'recipe' + data.create {}, 'recipe' parser.execute name:'pattern', argText:'alpha' - .then -> - recipe = state.getCurrent 'recipe' - expect(recipe.pattern).to.be.undefined - (e.message for e in state.errors).should.eql ['invalid pattern: "alpha"'] + recipe = data.getCurrent 'recipe' + expect(recipe.pattern).to.be.undefined + (e.message for e in data.errors).should.eql ['invalid pattern: "alpha"'] describe 'recipe', -> it 'creates a new recipe', -> parser.execute name:'recipe' - .then -> - recipe = state.getCurrent 'recipe' - recipe.item.id.should.equal 0 - state.errors.should.eql [] + recipe = data.getCurrent 'recipe' + recipe.item.id.should.equal 0 + data.errors.should.eql [] describe 'quantity', -> it 'assigns to the current recipe', -> - state.create {}, 'recipe' + data.create {}, 'recipe' parser.execute name:'quantity', argText:'42' - .then -> - recipe = state.getCurrent 'recipe' - recipe.quantity.should.equal 42 - state.errors.should.eql [] + recipe = data.getCurrent 'recipe' + recipe.quantity.should.equal 42 + data.errors.should.eql [] describe 'tools', -> it 'assigns to the current recipe', -> - state.create {}, 'recipe' + data.create {}, 'recipe' parser.execute name:'tools', args:['bravo'] - .then -> - recipe = state.getCurrent 'recipe' - recipe.tools.should.eql [name:'bravo', quantity:1] - state.errors.should.eql [] + recipe = data.getCurrent 'recipe' + recipe.tools.should.eql [name:'bravo', quantity:1] + data.errors.should.eql [] diff --git a/src/client/models/parsing-2/parser_state.test.coffee b/src/client/models/parsing-2/parser_state.test.coffee deleted file mode 100644 index 50c4135fb..000000000 --- a/src/client/models/parsing-2/parser_state.test.coffee +++ /dev/null @@ -1,108 +0,0 @@ -# -# Crafting Guide - parser_state.test.coffee -# -# Copyright © 2014-2016 by Redwood Labs -# All rights reserved. -# - -ParserCommand = require './parser_command' -ParserState = require './parser_state' - -######################################################################################################################## - -command = state = null - -######################################################################################################################## - -describe 'parser_state.coffee', -> - - beforeEach -> - state = new ParserState - command = new ParserCommand name:'alpha', fileName:'file.cg', lineNumber:1 - - describe 'create', -> - - it 'returns an object with the given id', -> - alpha = state.create command, 'alpha', 0 - alpha.id.should.equal 0 - alpha.command.location.should.equal 'file.cg:1' - - it 'returns an object with a newly created id when none is given', -> - alpha = state.create command, 'alpha' - alpha.id.should.not.be.null - alpha.id.should.match /^alpha-[0-9]+$/ - alpha.command.location.should.equal 'file.cg:1' - - describe 'each', -> - - it 'ignores the callback when there are no items', -> - items = [] - state.each (item)-> items.push item - items.length.should.equal 0 - - it 'calls the callback once with a single item', -> - state.create command, 'alpha', 0 - items = [] - state.each (item)-> items.push item - items.length.should.equal 1 - items[0].id.should.equal 0 - - it 'calls the callback for each item of a single type', -> - state.create command, 'alpha', 0 - state.create command, 'alpha', 1 - state.create command, 'alpha', 2 - - ids = [] - state.each (item)-> ids.push item.id - ids.should.eql [0, 1, 2] - - it 'calls the callback for each item across multiple types', -> - state.create command, 'alpha', 0 - state.create command, 'alpha', 1 - state.create command, 'bravo', 0 - state.create command, 'bravo', 1 - - ids = [] - state.each (item)-> ids.push "#{item.type}-#{item.id}" - ids.should.eql ['alpha-0', 'alpha-1', 'bravo-0', 'bravo-1'] - - describe 'eachOfType', -> - - it 'ignores the callback if there are no items of that type', -> - state.create command, 'alpha', 0 - state.create command, 'alpha', 1 - - ids = [] - state.eachOfType 'bravo', (item)-> ids.push "#{item.type}-#{item.id}" - ids.length.should.equal 0 - - it 'calls the callback once for each item of the given type', -> - state.create command, 'alpha', 0 - state.create command, 'alpha', 1 - state.create command, 'bravo', 0 - state.create command, 'bravo', 1 - - ids = [] - state.eachOfType 'bravo', (item)-> ids.push "#{item.type}-#{item.id}" - ids.should.eql ['bravo-0', 'bravo-1'] - - describe 'get', -> - - it 'returns a previously created item', -> - alpha1 = state.create command, 'alpha', 0 - alpha2 = state.get 'alpha', 0 - alpha1.should.equal alpha2 - - it 'returns null when no such item exists', -> - alpha = state.create command, 'alpha', 0 - expect(state.get 'alpha', 1).to.be.null - expect(state.get 'bravo', 0).to.be.null - - describe 'getCurrent', -> - - it 'returns the new item each time one is created', -> - alpha1 = state.create command, 'alpha', 0 - state.getCurrent('alpha').id.should.equal 0 - - alpha2 = state.create command, 'alpha', 1 - state.getCurrent('alpha').id.should.equal 1