Class: Gamefic::Syntax

Inherits:
Object
  • Object
show all
Defined in:
lib/gamefic/syntax.rb

Overview

Syntaxes provide rules for matching input patterns to existing responses. Common uses are to provide synonyms for response verbs and allow for variations in sentence structure.

The template and command patterns use words beginning with a colon (e.g., ‘:thing`) to identify phrases that should be tokenized into arguments.

Examples:

All of these syntaxes will translate input into a command of the

form "look thing container"

  Syntax.new('examine :thing in :container', 'look :thing :container')
  Syntax.new('look at :thing inside :container', 'look :thing :container')
  Syntax.new('search :container for :thing', 'look :thing :container')

Constant Summary collapse

PARAM_REGEXP =
/^:[a-z0-9_]+$/i.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(template, command) ⇒ Syntax

Returns a new instance of Syntax.

Parameters:



45
46
47
48
49
50
51
# File 'lib/gamefic/syntax.rb', line 45

def initialize(template, command)
  @template = template.normalize
  @params = @template.keywords.select { |word| word.start_with?(':') }
  @command = command.normalize
  @verb = Syntax.literal_or_nil(@command.keywords[0])
  @replace = parse_replace
end

Instance Attribute Details

#commandString (readonly)

The pattern that will be used to tokenize the input into a command.

Returns:



32
33
34
# File 'lib/gamefic/syntax.rb', line 32

def command
  @command
end

#paramsArray<String> (readonly)

Returns:



27
28
29
# File 'lib/gamefic/syntax.rb', line 27

def params
  @params
end

#templateString (readonly)

Returns:



24
25
26
# File 'lib/gamefic/syntax.rb', line 24

def template
  @template
end

#verbSymbol (readonly)

The response verb to which the command will be translated.

Examples:

syntax = Syntax.new('examine :thing', 'look :thing')
syntax.verb #=> :look

Returns:

  • (Symbol)


41
42
43
# File 'lib/gamefic/syntax.rb', line 41

def verb
  @verb
end

Class Method Details

.literal_or_nil(string) ⇒ Symbol?

Parameters:

Returns:

  • (Symbol, nil)


118
119
120
# File 'lib/gamefic/syntax.rb', line 118

def self.literal_or_nil(string)
  string.start_with?(':') ? nil : string.to_sym
end

.split(template) ⇒ Array<String>

Split a syntax template by words and expressions.

Parameters:

Returns:



126
127
128
129
130
131
132
133
134
135
136
# File 'lib/gamefic/syntax.rb', line 126

def self.split(template)
  parens = 0
  result = template.normalize.chars.each.with_object(['']) do |char, result|
    parens = parse_token(char, parens, result)
  end
  raise "Unbalanced parentheses in syntax '#{template}'" unless parens.zero?

  result.pop if result.last.empty?

  result
end

.tokenize(text, syntaxes) ⇒ Array<Expression>

Tokenize an array of commands from the specified text. The resulting array is in descending order of precision, i.e., most to least matched tokens.

Parameters:

  • text (String)

    The text to tokenize.

  • syntaxes (Array<Syntax>)

    The syntaxes to use.

Returns:



108
109
110
111
112
113
114
# File 'lib/gamefic/syntax.rb', line 108

def self.tokenize(text, syntaxes)
  syntaxes
    .map { |syn| syn.tokenize(text) }
    .compact
    .uniq { |exp| [exp.verb, exp.tokens] }
    .sort_by { |exp| [-exp.tokens.compact.length] }
end

Instance Method Details

#==(other) ⇒ Object



97
98
99
# File 'lib/gamefic/syntax.rb', line 97

def ==(other)
  signature == other&.signature
end

#match?(text) ⇒ Boolean Also known as: accept?

Determine if the specified text matches the syntax’s expected pattern.

Parameters:

Returns:

  • (Boolean)


85
86
87
# File 'lib/gamefic/syntax.rb', line 85

def match?(text)
  !!text.match(regexp)
end

#regexpRegexp

Returns:

  • (Regexp)


66
67
68
# File 'lib/gamefic/syntax.rb', line 66

def regexp
  @regexp ||= Regexp.new("^#{make_tokens.join(' ')}$", Regexp::IGNORECASE)
end

#signatureObject

Get a signature that identifies the form of the Syntax. Signatures are used to compare Syntaxes to each other.



93
94
95
# File 'lib/gamefic/syntax.rb', line 93

def signature
  [regexp, replace]
end

#synonymSymbol

A symbol for the first word in the template. Used by rulebooks to classify groups of related syntaxes.

Examples:

syntax = Syntax.new('examine :thing', 'look :thing')
syntax.synonym #=> :examine

Returns:

  • (Symbol)


61
62
63
# File 'lib/gamefic/syntax.rb', line 61

def synonym
  @synonym ||= Syntax.literal_or_nil(template.keywords.first)
end

#tokenize(text) ⇒ Expression?

Convert a String into a Command.

Parameters:

Returns:



74
75
76
77
78
79
# File 'lib/gamefic/syntax.rb', line 74

def tokenize(text)
  match = text&.match(regexp)
  return nil unless match

  Expression.new(verb, match_to_args(match))
end