Class: Grammar

Inherits:
Object show all
Defined in:
lib/rpdf2txt-rockit/grammar.rb

Defined Under Namespace

Classes: EpsilonTokenType

Constant Summary collapse

EpsilonToken =
EpsilonTokenType.new

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name = nil, productions = [], tokens = [], priorities = nil, startSymbol = nil, exports = []) ⇒ Grammar

Returns a new instance of Grammar.



493
494
495
496
497
498
499
500
501
502
503
504
505
506
# File 'lib/rpdf2txt-rockit/grammar.rb', line 493

def initialize(name = nil, productions = [], tokens = [], 
 priorities = nil,
 startSymbol = nil, exports = [])
  # NOTE! Beware that the EofToken below wont get a unique index number!!
  @eof_terminal = EofToken.new
  @name, @tokens, @alternatives = name, [@eof_terminal], Hash.new
  @priorities = priorities || ProductionPriorities.new
  @nonterminals = Array.new
  add_tokens(tokens)
  clear_productions
  add_productions(productions)
  init_start_symbol(startSymbol)
  @exports = exports
end

Instance Attribute Details

#eof_terminalObject (readonly)

Returns the value of attribute eof_terminal.



489
490
491
# File 'lib/rpdf2txt-rockit/grammar.rb', line 489

def eof_terminal
  @eof_terminal
end

#exportsObject (readonly)

Returns the value of attribute exports.



488
489
490
# File 'lib/rpdf2txt-rockit/grammar.rb', line 488

def exports
  @exports
end

#nameObject

Returns the value of attribute name.



490
491
492
# File 'lib/rpdf2txt-rockit/grammar.rb', line 490

def name
  @name
end

#original_start_symbolObject (readonly)

Returns the value of attribute original_start_symbol.



489
490
491
# File 'lib/rpdf2txt-rockit/grammar.rb', line 489

def original_start_symbol
  @original_start_symbol
end

#prioritiesObject (readonly)

Returns the value of attribute priorities.



488
489
490
# File 'lib/rpdf2txt-rockit/grammar.rb', line 488

def priorities
  @priorities
end

#productionsObject (readonly)

Returns the value of attribute productions.



488
489
490
# File 'lib/rpdf2txt-rockit/grammar.rb', line 488

def productions
  @productions
end

#start_symbolObject (readonly)

Returns the value of attribute start_symbol.



488
489
490
# File 'lib/rpdf2txt-rockit/grammar.rb', line 488

def start_symbol
  @start_symbol
end

#tokensObject (readonly) Also known as: terminals

Returns the value of attribute tokens.



488
489
490
# File 'lib/rpdf2txt-rockit/grammar.rb', line 488

def tokens
  @tokens
end

Class Method Details

.epsilonObject



593
594
595
# File 'lib/rpdf2txt-rockit/grammar.rb', line 593

def Grammar.epsilon
  EpsilonToken
end

Instance Method Details

#+(otherGrammar) ⇒ Object



555
556
557
558
559
560
561
# File 'lib/rpdf2txt-rockit/grammar.rb', line 555

def +(otherGrammar)
  # NOTE: Maybe check for and/or handle naming conflicts?
  add_tokens(otherGrammar.tokens)
  add_productions(otherGrammar.productions)
  otherGrammar.exports.each {|e| @exports.push(e)}
  self
end

#add_production(production) ⇒ Object



541
542
543
544
545
546
547
548
549
550
551
552
553
# File 'lib/rpdf2txt-rockit/grammar.rb', line 541

def add_production(production)
  unless @productions.include?(production)
    add_unique_symbols(production)
    @productions.push production
    nt = production.nonterminal
    unless @alternatives[nt.name]
	@alternatives[nt.name] = [production]
    else
	@alternatives[nt.name].push production
    end
  end
  @start_symbol = production.nonterminal unless @start_symbol
end

#add_token(token) ⇒ Object



521
522
523
# File 'lib/rpdf2txt-rockit/grammar.rb', line 521

def add_token(token)
  @tokens.push token unless @tokens.include?(token)
end

#add_unique_symbols(production) ⇒ Object



525
526
527
528
# File 'lib/rpdf2txt-rockit/grammar.rb', line 525

def add_unique_symbols(production)
  production.elements = production.elements.map {|e| unique_symbol(e)}
  production.nonterminal = unique_symbol(production.nonterminal)
end

#alternatives(nonterminal) ⇒ Object



508
509
510
# File 'lib/rpdf2txt-rockit/grammar.rb', line 508

def alternatives(nonterminal)
  @alternatives[nonterminal.name]
end

#augmentObject

Augment the grammar by adding new start symbol and production from it to previous start symbol. The added production gets index 0.



599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
# File 'lib/rpdf2txt-rockit/grammar.rb', line 599

def augment
  return true if augmented?
  @original_start_symbol = self.start_symbol
  # Add prim's until unique nonterminal name
  new_name = @original_start_symbol.name + "'"
  while nonterminals.collect{|nt| nt.name}.include?(new_name)
    new_name += "'"
  end
  @start_symbol = NonTerminal.new(new_name)
  add_production(p = Production.new(@start_symbol, [@original_start_symbol]))
  # Make sure its on top
  @productions.delete p
  @productions.unshift p
  @augmented = true
end

#augmented?Boolean

Returns:

  • (Boolean)


569
570
571
# File 'lib/rpdf2txt-rockit/grammar.rb', line 569

def augmented?
  @augmented ? true : false
end

#inspectObject



573
574
575
576
577
578
579
580
581
582
# File 'lib/rpdf2txt-rockit/grammar.rb', line 573

def inspect
  str = "Grammar #{@name}\n"
  str += "Start symbol: #{@start_symbol.inspect}\n" if @start_symbol
  str += "Tokens:\n" + @tokens.map{|t| "  " + t.inspect}.join("\n")
  str += "\nProductions:\n"
  @productions.each do |prod|
    str += "  " + prod.inspect + "\n"
  end
  str
end

#nonterminals(includeStartSymbol = true) ⇒ Object



563
564
565
566
567
# File 'lib/rpdf2txt-rockit/grammar.rb', line 563

def nonterminals(includeStartSymbol = true)
  nts = (@productions.map {|p| p.nonterminal}).equality_uniq
  nts.delete(@start_symbol) unless includeStartSymbol
  nts
end

#normalizeObject



512
513
514
515
516
517
518
519
# File 'lib/rpdf2txt-rockit/grammar.rb', line 512

def normalize
  old_productions = @productions
  clear_productions
  old_productions.each do |production|
    add_productions(production.normalize)
  end
  self
end

#unaugmentObject



615
616
617
618
619
620
# File 'lib/rpdf2txt-rockit/grammar.rb', line 615

def unaugment
  return false unless augmented?
  @start_symbol = @original_start_symbol
  @productions.shift
  @augmented = false
end

#unique_symbol(symbol) ⇒ Object



530
531
532
533
534
535
536
537
538
539
# File 'lib/rpdf2txt-rockit/grammar.rb', line 530

def unique_symbol(symbol)
  existing_symbol = (@tokens + @nonterminals).detect {|e| e==symbol}
  if not existing_symbol
    add_token(symbol) if symbol.kind_of?(Token)
    @nonterminals.push(symbol) if symbol.kind_of?(NonTerminal)
    return symbol
  else
    return existing_symbol
  end
end