Class: Oga::CSS::Parser Private

Inherits:
LL::Driver
  • Object
show all
Defined in:
lib/oga/css/parser.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

AST parser for CSS expressions.

This parser does not build a CSS specific AST, instead it directly produces an XPath AST. This removes the need to transform the AST or generate corresponding XPath expressions as a String.

Similar to XPath::Parser this parser only takes String instances as input.

Constant Summary collapse

CONFIG =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

LL::DriverConfig.new
CACHE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

LRU.new

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ Parser

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Parser

Parameters:

  • data (String)

    The input to parse.



249
250
251
# File 'lib/oga/css/parser.rb', line 249

def initialize(data)
  @lexer = Lexer.new(data)
end

Class Method Details

.parse_with_cache(data) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • data (String)

Returns:

  • (AST::Node)


244
245
246
# File 'lib/oga/css/parser.rb', line 244

def self.parse_with_cache(data)
  CACHE.get_or_set(data) { new(data).parse }
end

Instance Method Details

#current_elementAST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the node test for the current element.

Returns:

  • (AST::Node)


279
280
281
# File 'lib/oga/css/parser.rb', line 279

def current_element
  @current_element ||= s(:test, nil, '*')
end

#each_token {|| ... } ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Yields the next token from the lexer.

Yield Parameters:

  • (Array)


268
269
270
271
272
273
274
# File 'lib/oga/css/parser.rb', line 268

def each_token
  @lexer.advance do |*args|
    yield args
  end

  yield [-1, -1]
end

#on_op_ends_with(attr, value) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the $= operator.

Parameters:

  • attr (AST::Node)
  • value (AST::Node)

Returns:

  • (AST::Node)


465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
# File 'lib/oga/css/parser.rb', line 465

def on_op_ends_with(attr, value)
  s(
    :eq,
    s(
      :call,
      'substring',
      attr,
      s(
        :add,
        s(
          :sub,
          s(:call, 'string-length', attr),
          s(:call, 'string-length', value)
        ),
        s(:int, 1)
      ),
      s(:call, 'string-length', value)
    ),
    value
  )
end

#on_op_eq(attr, value) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the = operator.

Parameters:

  • attr (AST::Node)
  • value (AST::Node)

Returns:

  • (AST::Node)


433
434
435
# File 'lib/oga/css/parser.rb', line 433

def on_op_eq(attr, value)
  s(:eq, attr, value)
end

#on_op_hyphen_in(attr, value) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the |= operator.

Parameters:

  • attr (AST::Node)
  • value (AST::Node)

Returns:

  • (AST::Node)


501
502
503
504
505
506
507
508
509
510
511
512
# File 'lib/oga/css/parser.rb', line 501

def on_op_hyphen_in(attr, value)
  s(
    :or,
    s(:eq, attr, value),
    s(
      :call,
      'starts-with',
      attr,
      s(:call, 'concat', value, s(:string, '-'))
    )
  )
end

#on_op_in(attr, value) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the *= operator.

Parameters:

  • attr (AST::Node)
  • value (AST::Node)

Returns:

  • (AST::Node)


492
493
494
# File 'lib/oga/css/parser.rb', line 492

def on_op_in(attr, value)
  s(:call, 'contains', attr, value)
end

#on_op_space_in(attr, value) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the ~= operator.

Parameters:

  • attr (AST::Node)
  • value (AST::Node)

Returns:

  • (AST::Node)


442
443
444
445
446
447
448
449
# File 'lib/oga/css/parser.rb', line 442

def on_op_space_in(attr, value)
  s(
    :call,
    'contains',
    s(:call, 'concat', s(:string, ' '), attr, s(:string, ' ')),
    s(:call, 'concat', s(:string, ' '), value, s(:string, ' '))
  )
end

#on_op_starts_with(attr, value) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the ^= operator.

Parameters:

  • attr (AST::Node)
  • value (AST::Node)

Returns:

  • (AST::Node)


456
457
458
# File 'lib/oga/css/parser.rb', line 456

def on_op_starts_with(attr, value)
  s(:call, 'starts-with', attr, value)
end

#on_pseudo_class(name, arg = nil) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • name (String)
  • arg (AST::Node) (defaults to: nil)

Returns:

  • (AST::Node)


308
309
310
311
312
# File 'lib/oga/css/parser.rb', line 308

def on_pseudo_class(name, arg = nil)
  handler = "on_pseudo_class_#{name.gsub('-', '_')}"

  arg ? send(handler, arg) : send(handler)
end

#on_pseudo_class_emptyAST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the :empty selector.

Returns:

  • (AST::Node)


406
407
408
# File 'lib/oga/css/parser.rb', line 406

def on_pseudo_class_empty
  s(:call, 'not', s(:axis, 'child', s(:type_test, 'node')))
end

#on_pseudo_class_first_childAST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the :first-child selector.

Returns:

  • (AST::Node)


364
365
366
# File 'lib/oga/css/parser.rb', line 364

def on_pseudo_class_first_child
  generate_no_siblings('preceding-sibling')
end

#on_pseudo_class_first_of_typeAST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the :first-of-type selector.

Returns:

  • (AST::Node)


378
379
380
# File 'lib/oga/css/parser.rb', line 378

def on_pseudo_class_first_of_type
  generate_no_siblings('preceding-sibling', current_element)
end

#on_pseudo_class_last_childAST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the :last-child selector.

Returns:

  • (AST::Node)


371
372
373
# File 'lib/oga/css/parser.rb', line 371

def on_pseudo_class_last_child
  generate_no_siblings('following-sibling')
end

#on_pseudo_class_last_of_typeAST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the :last-of-type selector.

Returns:

  • (AST::Node)


385
386
387
# File 'lib/oga/css/parser.rb', line 385

def on_pseudo_class_last_of_type
  generate_no_siblings('following-sibling', current_element)
end

#on_pseudo_class_not(arg) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the :not selector.

Parameters:

  • arg (AST::Node)

Returns:

  • (AST::Node)


414
415
416
417
418
419
420
421
422
423
424
425
426
# File 'lib/oga/css/parser.rb', line 414

def on_pseudo_class_not(arg)
  # Unpacks (axis "descendant" (test nil "x")) into just (test nil "x") as
  # in this case we want to wrap the (test) node in a (axis "self") node.
  if arg.type == :axis
    arg = s(:axis, 'self', arg.children[1])

  # Unpack (predicate (eq ...)) into just (eq)
  elsif arg.type == :predicate
    arg = arg.children[1]
  end

  s(:call, 'not', arg)
end

#on_pseudo_class_nth(arg) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the nth pseudo class.

Parameters:

  • arg (AST::Node)

Returns:

  • (AST::Node)


357
358
359
# File 'lib/oga/css/parser.rb', line 357

def on_pseudo_class_nth(arg)
  s(:eq, s(:call, 'position'), arg)
end

#on_pseudo_class_nth_child(arg) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the nth-child pseudo class.

Parameters:

  • arg (AST::Node)

Returns:

  • (AST::Node)


325
326
327
# File 'lib/oga/css/parser.rb', line 325

def on_pseudo_class_nth_child(arg)
  generate_nth_child('preceding-sibling', arg)
end

#on_pseudo_class_nth_last_child(arg) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the nth-last-child pseudo class.

Parameters:

  • arg (AST::Node)

Returns:

  • (AST::Node)


333
334
335
# File 'lib/oga/css/parser.rb', line 333

def on_pseudo_class_nth_last_child(arg)
  generate_nth_child('following-sibling', arg)
end

#on_pseudo_class_nth_last_of_type(arg) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the nth-last-of-type pseudo class.

Parameters:

  • arg (AST::Node)

Returns:

  • (AST::Node)


349
350
351
# File 'lib/oga/css/parser.rb', line 349

def on_pseudo_class_nth_last_of_type(arg)
  generate_nth_child('following-sibling', arg, current_element)
end

#on_pseudo_class_nth_of_type(arg) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the nth-of-type pseudo class.

Parameters:

  • arg (AST::Node)

Returns:

  • (AST::Node)


341
342
343
# File 'lib/oga/css/parser.rb', line 341

def on_pseudo_class_nth_of_type(arg)
  generate_nth_child('preceding-sibling', arg, current_element)
end

#on_pseudo_class_only_childAST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the :only-child selector.

Returns:

  • (AST::Node)


392
393
394
# File 'lib/oga/css/parser.rb', line 392

def on_pseudo_class_only_child
  s(:and, on_pseudo_class_first_child, on_pseudo_class_last_child)
end

#on_pseudo_class_only_of_typeAST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the :only-of-type selector.

Returns:

  • (AST::Node)


399
400
401
# File 'lib/oga/css/parser.rb', line 399

def on_pseudo_class_only_of_type
  s(:and, on_pseudo_class_first_of_type, on_pseudo_class_last_of_type)
end

#on_pseudo_class_rootAST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for the root pseudo class.

Returns:

  • (AST::Node)


317
318
319
# File 'lib/oga/css/parser.rb', line 317

def on_pseudo_class_root
  s(:call, 'not', s(:axis, 'parent', s(:test, nil, '*')))
end

#on_test(namespace, name) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Generates the AST for a node test.

Parameters:

  • namespace (String)
  • name (String)

Returns:

  • (AST::Node)


301
302
303
# File 'lib/oga/css/parser.rb', line 301

def on_test(namespace, name)
  @current_element = s(:test, namespace, name)
end

#parseAST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parses the input and returns the corresponding AST.

Examples:

parser = Oga::CSS::Parser.new('foo.bar')
ast    = parser.parse

Returns:

  • (AST::Node)


290
291
292
293
294
# File 'lib/oga/css/parser.rb', line 290

def parse
  reset

  super
end

#resetObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Resets the internal state of the parser.



254
255
256
# File 'lib/oga/css/parser.rb', line 254

def reset
  @current_element = nil
end

#s(type, *children) ⇒ AST::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • type (Symbol)
  • children (Array)

Returns:

  • (AST::Node)


261
262
263
# File 'lib/oga/css/parser.rb', line 261

def s(type, *children)
  AST::Node.new(type, children)
end