Module: Citrus::GrammarMethods

Defined in:
lib/citrus.rb

Overview

Contains methods that are available to Grammar modules at the class level.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extend_object(obj) ⇒ Object

Raises:

  • (ArgumentError)


377
378
379
380
# File 'lib/citrus.rb', line 377

def self.extend_object(obj)
  raise ArgumentError, "Grammars must be Modules" unless Module === obj
  super
end

Instance Method Details

#all(*args, &block) ⇒ Object

Creates a new Sequence using all arguments. A block may be provided to specify semantic behavior (via #ext).



549
550
551
# File 'lib/citrus.rb', line 549

def all(*args, &block)
  ext(Sequence.new(args), block)
end

#andp(rule, &block) ⇒ Object

Creates a new AndPredicate using the given rule. A block may be provided to specify semantic behavior (via #ext).



509
510
511
# File 'lib/citrus.rb', line 509

def andp(rule, &block)
  ext(AndPredicate.new(rule), block)
end

#any(*args, &block) ⇒ Object

Creates a new Choice using all arguments. A block may be provided to specify semantic behavior (via #ext).



555
556
557
# File 'lib/citrus.rb', line 555

def any(*args, &block)
  ext(Choice.new(args), block)
end

#butp(rule, &block) ⇒ Object

Creates a new ButPredicate using the given rule. A block may be provided to specify semantic behavior (via #ext).



521
522
523
# File 'lib/citrus.rb', line 521

def butp(rule, &block)
  ext(ButPredicate.new(rule), block)
end

#dot(&block) ⇒ Object

Creates a new rule that will match any single character. A block may be provided to specify semantic behavior (via #ext).



497
498
499
# File 'lib/citrus.rb', line 497

def dot(&block)
  ext(Rule.for(DOT), block)
end

#ext(rule, mod = nil, &block) ⇒ Object

Specifies a Module that will be used to extend all matches created with the given rule. A block may also be given that will be used to create an anonymous module. See Rule#extension=.



570
571
572
573
574
575
# File 'lib/citrus.rb', line 570

def ext(rule, mod=nil, &block)
  rule = Rule.for(rule)
  mod = block if block
  rule.extension = mod if mod
  rule
end

#has_rule?(name) ⇒ Boolean

Returns true if this grammar has a rule with the given name.

Returns:

  • (Boolean)


425
426
427
# File 'lib/citrus.rb', line 425

def has_rule?(name)
  rules.key?(name.to_sym)
end

#included_grammarsObject

Returns an array of all grammars that have been included in this grammar in the reverse order they were included.



409
410
411
# File 'lib/citrus.rb', line 409

def included_grammars
  included_modules.select {|mod| mod.include?(Grammar) }
end

#label(rule, label, &block) ⇒ Object

Adds label to the given rule. A block may be provided to specify semantic behavior (via #ext).



561
562
563
564
565
# File 'lib/citrus.rb', line 561

def label(rule, label, &block)
  rule = ext(rule, block)
  rule.label = label
  rule
end

#mod(rule, &block) ⇒ Object

Creates a new Module from the given block and sets it to be the extension of the given rule. See Rule#extension=.



579
580
581
582
# File 'lib/citrus.rb', line 579

def mod(rule, &block)
  rule.extension = Module.new(&block)
  rule
end

#nameObject

Returns the name of this grammar as a string.



403
404
405
# File 'lib/citrus.rb', line 403

def name
  super.to_s
end

#notp(rule, &block) ⇒ Object

Creates a new NotPredicate using the given rule. A block may be provided to specify semantic behavior (via #ext).



515
516
517
# File 'lib/citrus.rb', line 515

def notp(rule, &block)
  ext(NotPredicate.new(rule), block)
end

#one_or_more(rule, &block) ⇒ Object

An alias for #rep.



533
534
535
# File 'lib/citrus.rb', line 533

def one_or_more(rule, &block)
  rep(rule, &block)
end

#parse(source, options = {}) ⇒ Object

Parses the given source using this grammar’s root rule. Accepts the same options as Rule#parse, plus the following:

root

The name of the root rule to start parsing at. Defaults to this grammar’s #root.

Raises:



387
388
389
390
391
392
393
# File 'lib/citrus.rb', line 387

def parse(source, options={})
  rule_name = options.delete(:root) || root
  raise Error, "No root rule specified" unless rule_name
  rule = rule(rule_name)
  raise Error, "No rule named \"#{rule_name}\"" unless rule
  rule.parse(source, options)
end

#parse_file(path, options = {}) ⇒ Object

Parses the contents of the file at the given path using this grammar’s #root rule. Accepts the same options as #parse.



397
398
399
400
# File 'lib/citrus.rb', line 397

def parse_file(path, options={})
  path = Pathname.new(path.to_str) unless Pathname === path
  parse(path, options)
end

#rep(rule, min = 1, max = Infinity, &block) ⇒ Object

Creates a new Repeat using the given rule. min and max specify the minimum and maximum number of times the rule must match. A block may be provided to specify semantic behavior (via #ext).



528
529
530
# File 'lib/citrus.rb', line 528

def rep(rule, min=1, max=Infinity, &block)
  ext(Repeat.new(rule, min, max), block)
end

#root(name = nil) ⇒ Object

Gets/sets the name of the root rule of this grammar. If no root rule is explicitly specified, the name of this grammar’s first rule is returned.



482
483
484
485
486
487
488
489
490
491
492
493
# File 'lib/citrus.rb', line 482

def root(name=nil)
  if name
    @root = name.to_sym
  else
    # The first rule in a grammar is the default root.
    if instance_variable_defined?(:@root)
      @root
    else
      rule_names.first
    end
  end
end

#rule(name, obj = nil, &block) ⇒ Object

Gets/sets the rule with the given name. If obj is given the rule will be set to the value of obj passed through Rule.for. If a block is given, its return value will be used for the value of obj.

It is important to note that this method will also check any included grammars for a rule with the given name if one cannot be found in this grammar.



459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
# File 'lib/citrus.rb', line 459

def rule(name, obj=nil, &block)
  sym = name.to_sym
  obj = block.call if block

  if obj
    rule_names << sym unless has_rule?(sym)

    rule = Rule.for(obj)
    rule.name = name
    setup_super(rule, name)
    rule.grammar = self

    rules[sym] = rule
  end

  rules[sym] || super_rule(sym)
rescue => e
  e.message.replace("Cannot create rule \"#{name}\": #{e.message}")
  raise e
end

#rule_namesObject

Returns an array of all names of rules in this grammar as symbols ordered in the same way they were declared.



415
416
417
# File 'lib/citrus.rb', line 415

def rule_names
  @rule_names ||= []
end

#rulesObject

Returns a hash of all Rule objects in this grammar, keyed by rule name.



420
421
422
# File 'lib/citrus.rb', line 420

def rules
  @rules ||= {}
end

#sup(&block) ⇒ Object

Creates a new Super for the rule currently being defined in the grammar. A block may be provided to specify semantic behavior (via #ext).



503
504
505
# File 'lib/citrus.rb', line 503

def sup(&block)
  ext(Super.new, block)
end

#super_rule(name) ⇒ Object

Searches the inheritance hierarchy of this grammar for a rule named name and returns it on success. Returns nil on failure.



443
444
445
446
447
448
449
450
# File 'lib/citrus.rb', line 443

def super_rule(name)
  sym = name.to_sym
  included_grammars.each do |grammar|
    rule = grammar.rule(sym)
    return rule if rule
  end
  nil
end

#zero_or_more(rule, &block) ⇒ Object

An alias for #rep with a minimum of 0.



538
539
540
# File 'lib/citrus.rb', line 538

def zero_or_more(rule, &block)
  rep(rule, 0, &block)
end

#zero_or_one(rule, &block) ⇒ Object

An alias for #rep with a minimum of 0 and a maximum of 1.



543
544
545
# File 'lib/citrus.rb', line 543

def zero_or_one(rule, &block)
  rep(rule, 0, 1, &block)
end