Class: Agent212::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/agent212/parser.rb

Constant Summary collapse

SEPARATORS =
Regexp.escape("()<>@,;:\\\"/[]?={} \t")
TOKEN =

token = 1*<any CHAR except CTLs or separators>

/[^#{SEPARATORS}[[:cntrl:]]]+/
LWS =

LWS = [CRLF] 1*( SP | HT )

/(\r\n)?\ |\t/
PRODUCT =
/TOKEN(\/TOKEN)?/
CTEXT =

ctext = <any TEXT excluding “(” and “)”>

/[^\(\)]+/
CHAR =

quoted-pair = “" CHAR CHAR = <any US-ASCII character (octets 0 - 127)>

/[[:ascii:]]/
QUOTED_PAIR =
/\\#{CHAR}/
SLASH =
/\//
LEFT_BRACKET =
/\(/
RIGHT_BRACKET =
/\)/

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(input) ⇒ Parser

Returns a new instance of Parser.



31
32
33
# File 'lib/agent212/parser.rb', line 31

def initialize(input)
  @input = StringScanner.new(input.to_s.strip)
end

Class Method Details

.parse(input) ⇒ Object



35
36
37
# File 'lib/agent212/parser.rb', line 35

def self.parse(input)
  new(input).parse
end

Instance Method Details

#parseObject

returns an array with the parts from the user_agent string in @input



40
41
42
# File 'lib/agent212/parser.rb', line 40

def parse
  parse_user_agent
end

#parse_commentObject

comment = “(” *( ctext | quoted-pair | comment ) “)” returns a string with the comment including the brackets



94
95
96
97
98
99
100
101
102
# File 'lib/agent212/parser.rb', line 94

def parse_comment
  comment = @input.scan(LEFT_BRACKET) or return nil
  comment << parse_star_comment_contents
  comment << @input.scan(RIGHT_BRACKET) or raise ParseError, "expected ) to end the comment #{comment.inspect}"
rescue => error
  if @input.eos?
    raise ParseError, "unexpected end of string (original error: ##{error}"
  end
end

#parse_ctextObject

ctext = <any TEXT excluding “(” and “)”>



118
119
120
# File 'lib/agent212/parser.rb', line 118

def parse_ctext
  @input.scan(CTEXT)
end

#parse_ctext_or_quotedpair_or_commentObject



113
114
115
# File 'lib/agent212/parser.rb', line 113

def parse_ctext_or_quotedpair_or_comment
  parse_ctext || parse_quotedpair || parse_comment
end

#parse_lwsObject

returns the scanned whitespace or nil



64
65
66
# File 'lib/agent212/parser.rb', line 64

def parse_lws
  @input.scan(LWS)
end

#parse_optional_product_versionObject

“/” product-version

returns nil or the version of the product raises an error if ‘/” is followed by a non-token



80
81
82
83
84
# File 'lib/agent212/parser.rb', line 80

def parse_optional_product_version
  return nil unless @input.scan(SLASH)
  version = parse_product_version or raise ParseError, "expected a product-version at character #{@input.pos}"
  version
end

#parse_productObject

product = token [“/” product-version]



69
70
71
72
73
74
75
# File 'lib/agent212/parser.rb', line 69

def parse_product
  token = parse_token
  return nil if token.nil?
  Product.new(token).tap do |product|
    product.version = parse_optional_product_version
  end
end

#parse_product_or_commentObject

product | comment



59
60
61
# File 'lib/agent212/parser.rb', line 59

def parse_product_or_comment
  parse_product || parse_comment
end

#parse_quotedpairObject

quoted-pair = “" CHAR



123
124
125
# File 'lib/agent212/parser.rb', line 123

def parse_quotedpair
  @input.scan(QUOTED_PAIR)
end

#parse_star_comment_contentsObject

*( ctext | quoted-pair | comment )



105
106
107
108
109
110
111
# File 'lib/agent212/parser.rb', line 105

def parse_star_comment_contents
  contents = ""
  while x = parse_ctext_or_quotedpair_or_comment
    contents << x
  end
  contents
end

#parse_tokenObject Also known as: parse_product_version

returns the token or nil



87
88
89
# File 'lib/agent212/parser.rb', line 87

def parse_token
  @input.scan(TOKEN)
end

#parse_user_agentObject

user agent = 1 * ( product | comment ) meaning AT LEAST ONE product or comment returns an array with all parsed products



47
48
49
50
51
52
53
54
55
56
# File 'lib/agent212/parser.rb', line 47

def parse_user_agent
  parts = []
  parts << parse_product_or_comment || raise(ParseError, 'expected at least one ( product | comment )')
  parse_lws or return parts
  while x = parse_product_or_comment
    parts << x
    parse_lws
  end
  parts
end