Class: PageTemplate::Parser

Inherits:
Object
  • Object
show all
Includes:
NamespaceItem
Defined in:
lib/PageTemplate/parser.rb

Overview

The big ass parser that does all the dirty work of turning templates into compiled commands.

Parser.new() accepts a hash as an argument, and looks for these keys: (with defaults)

'namespace' => A namespace object. (A new namespace)
'glossary'  => A SyntaxGlossary class singleton. (DefaultGlossary)
'preprocessor' => The preprocessor. (DefaultPreprocessor)
'default_processor' => The processor. (:process)
'source' => The Source for templates. (FileSource)

Once the parser is created, it can compile and parse any number of templates.

It can be treated as a one-template item by using Parser#load(template), and calling Parser.output

To create separate generated templates from the same engine, use Parser#parse, or Parser#load. (It will still keep the most recent one it’s #load’d, but that will not affect previously parsed or loaded)

Instance Attribute Summary collapse

Attributes included from NamespaceItem

#object, #parent

Class Method Summary collapse

Instance Method Summary collapse

Methods included from NamespaceItem

#clear, #get, #set, #true?

Constructor Details

#initialize(args = {}) ⇒ Parser

Parser.new() accepts a hash as an argument, and looks for these keys: (with defaults)

'namespace' => A namespace object. (A new namespace)
'glossary'  => A SyntaxGlossary object. (a dup of DEFAULTGLOSSARY)
'preprocessor' => The preprocessor. (DefaultPreprocessor)
'default_processor' => The processor. (:process)
'source' => The Source for templates. (FileSource)


467
468
469
470
471
472
473
474
475
476
477
478
# File 'lib/PageTemplate/parser.rb', line 467

def initialize(args = {})
  @namespace    = self
  @@recent_parser = self
  @args         = args # For sub-commands
  @parent       = args['namespace'] || nil
  @glossary     = args['glossary'] || DefaultGlossary
  @preprocessor = args['preprocessor'] || DefaultPreprocessor
  @default_processor = args['default_processor'] || :unescaped
  @method_separators = args['method_separators'] || './'
  @source       = (args['source'] || FileSource).new(@args)
  @commands     = nil
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



452
453
454
# File 'lib/PageTemplate/parser.rb', line 452

def args
  @args
end

#commandsObject (readonly)

Returns the value of attribute commands.



452
453
454
# File 'lib/PageTemplate/parser.rb', line 452

def commands
  @commands
end

#default_processorObject (readonly)

Returns the value of attribute default_processor.



450
451
452
# File 'lib/PageTemplate/parser.rb', line 450

def default_processor
  @default_processor
end

#glossaryObject (readonly)

Returns the value of attribute glossary.



451
452
453
# File 'lib/PageTemplate/parser.rb', line 451

def glossary
  @glossary
end

#method_separatorsObject (readonly)

Returns the value of attribute method_separators.



452
453
454
# File 'lib/PageTemplate/parser.rb', line 452

def method_separators
  @method_separators
end

#namespaceObject (readonly)

Returns the value of attribute namespace.



451
452
453
# File 'lib/PageTemplate/parser.rb', line 451

def namespace
  @namespace
end

#preprocessorObject (readonly)

Returns the value of attribute preprocessor.



450
451
452
# File 'lib/PageTemplate/parser.rb', line 450

def preprocessor
  @preprocessor
end

#sourceObject (readonly)

Returns the value of attribute source.



451
452
453
# File 'lib/PageTemplate/parser.rb', line 451

def source
  @source
end

Class Method Details

.recent_parserObject

This is corny, but recent_parser returns the most recently created Parser.



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

def Parser.recent_parser
  @@recent_parser
end

Instance Method Details

#clearCommandsObject

Not really of any point, but clears the saved commands.



562
563
564
# File 'lib/PageTemplate/parser.rb', line 562

def clearCommands
  @commands = nil
end

#compile(name) ⇒ Object

Load name from a template, but do not save it.



485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
# File 'lib/PageTemplate/parser.rb', line 485

def compile(name)
  body = @source.get(name)
  case
  when body.is_a?(Command)
    body
  when body
    cmds = parse(body)
    @source.cache(name,cmds) if @source.respond_to?(:cache)
    cmds
  else
    cmds = Template.new(self)
    cmds.add TextCommand.new("[ Template '#{name}' not found ]")
    cmds
  end
end

#load(name) ⇒ Object

Load name from a template, and save it to allow this parser to use it for output.



481
482
483
# File 'lib/PageTemplate/parser.rb', line 481

def load(name)
  @commands = compile(name)
end

#output(*args) ⇒ Object

If any commands are loaded and saved, return a string of it.



566
567
568
569
# File 'lib/PageTemplate/parser.rb', line 566

def output(*args)
  return '' unless @commands
  @commands.output(*args)
end

#parse(body) ⇒ Object

Compile a Template (BlockCommand) from a string. Does not save the commands.



502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
# File 'lib/PageTemplate/parser.rb', line 502

def parse(body)
  rx = @glossary.directive
  stack = [Template.new(self)]
  stack[0].parent = self
  last = stack.last
  modifier = nil
  closer = nil
  while (m = rx.match(body))
    pre = m.pre_match
    command = m[1..-1].compact.first.strip.gsub(/\s+/,' ')
    body = m.post_match
    
    # Convert all pre-text to a TextCommand
    if (pre && pre.length > 0)
      stack.last.add TextCommand.new(pre)
    end

    # If the command at the top of the stack is a 'Stacker',
    # Does this command modify it? If so, just skip back.
    next if modifier && @glossary.modifies?(modifier,last,command)

    # If it closes, we're done changing this. Pop it off the
    # Stack and add it to the one above it.
    if closer and @glossary.modifies?(closer,last,command)
      cmd = stack.pop
      last = stack.last
      last.add(cmd)
      modifier = last.class.modifier
      closer = last.class.closer
      next
    end

    # Create the command
    cmd = @glossary.lookup(command)
    
    # If it's a stacking command, push it on the stack
    if cmd.is_a?(StackableCommand)
      modifier = cmd.class.modifier
      closer   = cmd.class.closer
      stack.push cmd
      last = cmd
    else
      last.add cmd
    end
  end
  stack.last.add TextCommand.new(body) if body && body.length > 0
  if (stack.length > 1)
    raise ArgumentError, 'Mismatched command closures in template'
  end
  stack[0]
end

#parserObject

But redefine parser



557
558
559
# File 'lib/PageTemplate/parser.rb', line 557

def parser
  self
end