Exemple #1
0
class MacroParser(Parser):
  rnormalize = {
    re.compile(r'\s+'): ''
  }
  
  def __init__(self, nonTerminalParser, terminalParser, sListMacroParser, nListMacroParser, tListMacroParser, mListMacroParser, optionalMacroParser, expand=True):
    self.__dict__.update(locals())
    self.logger = LoggerFactory().getClassLogger(__name__, self.__class__.__name__)

  def parse(self, string):
    self.logger.debug('Parsing macro %s' % (string))
    if string[:5].lower() == 'tlist':
      macro = self.tListMacroParser.parse(string, self.expand)
    elif string[:5].lower() == 'mlist':
      macro = self.mListMacroParser.parse(string, self.expand)
    elif string[:8].lower() == 'optional':
      macro = self.optionalMacroParser.parse(string, self.expand)
    elif string[:4].lower() == 'list':
      (nonterminal, separator, minimum) = pad(3, string[5:-1].split(','))
      if separator:
        macro = self.sListMacroParser.parse(string, self.expand)
      else:
        macro = self.nListMacroParser.parse(string, self.expand)
    self.logger.debug('Parsed macro: %s' % (macro))
    return macro
Exemple #2
0
class Rule:
    def __init__(self, nonterminal, production, id=None, root=None, ast=None):
        self.__dict__.update(locals())
        self.logger = LoggerFactory().getClassLogger(__name__,
                                                     self.__class__.__name__)

    def __copy__(self):
        return Rule(self.nonterminal,
                    Production(copy(self.production.morphemes)), self.id,
                    self.root, self.ast)

    def isTokenAlias(self):
        if len(self.production.morphemes) == 1 and isinstance(
                self.production.morphemes[0], Terminal):
            return self.production.morphemes[0]
        return False

    def isAliasFor(self, terminal_str):
        # terminal alias rule is a rule in the form nt := 'terminal'
        return len(self.production.morphemes) == 1 and isinstance(
            self.production.morphemes[0],
            Terminal) and self.production.morphemes[0].string == terminal_str

    def expand(self):
        morphemes = []
        rules = []
        for m in self.production.morphemes:
            if isinstance(m, LL1ListMacro):
                rules.extend(m.rules)
                morphemes.append(m.start_nt)
            else:
                morphemes.append(m)
        rules.append(
            Rule(self.nonterminal, Production(morphemes), self.id, self.root,
                 self.ast))
        self.logger.debug('[rule expansion] %s becomes %s' %
                          (self, ', '.join([str(x) for x in rules])))
        return rules

    def str(self, theme=None):
        return self.__str__(theme)

    def __str__(self, theme=None):
        astString = ''
        if self.ast and not (isinstance(self.ast, AstTranslation)
                             and self.ast.idx == 0):
            astString = ' -> %s' % (self.ast.str(theme) if theme else self.ast)

        nonterminal = self.nonterminal.str(theme) if theme else str(
            self.nonterminal)
        production = self.production.str(theme) if theme else str(
            self.production)
        rule = "%s := %s%s" % (nonterminal, production, astString)
        return theme.rule(rule) if theme else rule

    def getProduction(self):
        return self.production

    def getNonTerminal(self):
        return self.nonterminal
Exemple #3
0
class Rule:
  def __init__( self, nonterminal, production, id=None, root=None, ast=None):
    self.__dict__.update(locals())
    self.logger = LoggerFactory().getClassLogger(__name__, self.__class__.__name__)
  def __copy__( self ):
    return Rule(self.nonterminal, Production(copy(self.production.morphemes)), self.id, self.root, self.ast)
  def isTokenAlias(self):
    if len(self.production.morphemes) == 1 and isinstance(self.production.morphemes[0], Terminal):
      return self.production.morphemes[0]
    return False
  def isAliasFor(self, terminal_str):
    # terminal alias rule is a rule in the form nt := 'terminal'
    return len(self.production.morphemes) == 1 and isinstance(self.production.morphemes[0], Terminal) and self.production.morphemes[0].string == terminal_str
  def expand( self ):
    morphemes = []
    rules = []
    for m in self.production.morphemes:
      if isinstance(m, LL1ListMacro):
        rules.extend(m.rules)
        morphemes.append(m.start_nt)
      else:
        morphemes.append(m)
    rules.append(Rule(self.nonterminal, Production(morphemes), self.id, self.root, self.ast))
    self.logger.debug('[rule expansion] %s becomes %s' % (self, ', '.join([str(x) for x in rules])))
    return rules

  def str( self, theme = None ):
    return self.__str__( theme )

  def __str__( self, theme = None ):
    astString = ''
    if self.ast and not (isinstance(self.ast, AstTranslation) and self.ast.idx == 0):
      astString = ' -> %s' % (self.ast.str(theme) if theme else self.ast)

    nonterminal = self.nonterminal.str(theme) if theme else str(self.nonterminal)
    production = self.production.str(theme) if theme else str(self.production)
    rule = "%s := %s%s" % ( nonterminal, production, astString)
    return theme.rule(rule) if theme else rule
  
  def getProduction(self):
    return self.production

  def getNonTerminal(self):
    return self.nonterminal
Exemple #4
0
 def __init__( self, nonterminal, production, id=None, root=None, ast=None):
   self.__dict__.update(locals())
   self.logger = LoggerFactory().getClassLogger(__name__, self.__class__.__name__)
Exemple #5
0
 def __init__(self, nonTerminalParser, terminalParser, sListMacroParser, nListMacroParser, tListMacroParser, mListMacroParser, optionalMacroParser, expand=True):
   self.__dict__.update(locals())
   self.logger = LoggerFactory().getClassLogger(__name__, self.__class__.__name__)
Exemple #6
0
 def __init__(self, nonterminal, production, id=None, root=None, ast=None):
     self.__dict__.update(locals())
     self.logger = LoggerFactory().getClassLogger(__name__,
                                                  self.__class__.__name__)
Exemple #7
0
def Cli():

  ver = sys.version_info

  # Version 3.2 required for argparse
  if ver.major < 3 or (ver.major == 3 and ver.minor < 2):
    print("Python 3.2+ required. %d.%d.%d installed" %(ver.major, ver.minor, ver.micro))
    sys.exit(-1)

  parser = argparse.ArgumentParser(
              description = 'Hermes Parser Generator',
              epilog = '(c) 2011-2012 Scott Frazer')

  parser.add_argument('action',
              choices = ['analyze', 'generate'],
              help = 'Parser Generator Actions')

  parser.add_argument('grammar',
              metavar = 'GRAMMAR',
              nargs = '+',
              help = 'Grammar file')

  parser.add_argument('--version',
              action='version',
              version=str(pkg_resources.get_distribution('hermes-parser')))

  parser.add_argument('-D', '--debug',
              required = False,
              action='store_true',
              help = 'Open the floodgates')

  parser.add_argument('-d', '--directory',
              required=False,
              default='.',
              help='Directory to write generated code to')

  parser.add_argument('-l', '--language',
              required = False,
              default='python',
              choices=['c', 'java', 'python'],
              help = 'Language for generated parser')

  parser.add_argument('--java-package',
              required = False,
              help = 'If generating Java code, this is the package.')

  parser.add_argument('-c', '--color',
              required = False,
              action = 'store_true',
              help = 'Prints things in color!  For the colorblind, this is a no-op.')

  parser.add_argument('-m', '--add-main',
              required = False,
              action = 'store_true',
              help = 'If this is specified, a main() function will be generated in the source code.')

  cli = parser.parse_args()
  logger = LoggerFactory().initialize(cli.debug)
  logger.debug('CLI Parameters: %s' % (cli))

  factory = HermesParserFactory()
  fp = GrammarFileParser(factory.create())

  grammars = []
  for grammar in cli.grammar:
    if not os.path.isfile( grammar ):
      sys.stderr.write("Error: Grammar file doesn't exist\n")
      sys.exit(-1)

    name = os.path.basename(grammar)

    if not name.endswith('.zgr'):
      sys.stderr.write("Error: Grammar file must have .zgr extension\n")
      sys.exit(-1)

    name = name[:-4]
    grammars.append( fp.parse(name, open(grammar)) )

  if cli.action == 'analyze':

    if cli.color:
      theme = TerminalColorTheme()
    else:
      theme = TerminalDefaultTheme()

    for grammar in grammars:
      analyzer = GrammarAnalyzer(grammar)
      analyzer.analyze( theme=theme )

  if cli.action == 'generate':
    cli.directory = os.path.abspath(os.path.expanduser(cli.directory))

    if not os.path.isdir( cli.directory ):
      sys.stderr.write("Error: Directory doesn't exist\n")
      sys.exit(-1)
    elif not os.access(cli.directory, os.W_OK):
      sys.stderr.write("Error: Directory not writable\n")
      sys.exit(-1)

    templateFactory = TemplateFactoryFactory().create(outputLanguage=cli.language.lower())
    templateWriter = TemplateWriter(templateFactory)
    templateWriter.write(grammars, cli.directory, addMain=cli.add_main, javaPackage=cli.java_package)
Exemple #8
0
def Cli():

    ver = sys.version_info

    # Version 3.2 required for argparse
    if ver.major < 3 or (ver.major == 3 and ver.minor < 2):
        print("Python 3.2+ required. %d.%d.%d installed" %
              (ver.major, ver.minor, ver.micro))
        sys.exit(-1)

    parser = argparse.ArgumentParser(description='Hermes Parser Generator',
                                     epilog='(c) 2011-2012 Scott Frazer')

    parser.add_argument('action',
                        choices=['analyze', 'generate'],
                        help='Parser Generator Actions')

    parser.add_argument('grammar',
                        metavar='GRAMMAR',
                        nargs='+',
                        help='Grammar file')

    parser.add_argument('--version',
                        action='version',
                        version=str(
                            pkg_resources.get_distribution('hermes-parser')))

    parser.add_argument('-D',
                        '--debug',
                        required=False,
                        action='store_true',
                        help='Open the floodgates')

    parser.add_argument('-d',
                        '--directory',
                        required=False,
                        default='.',
                        help='Directory to write generated code to')

    parser.add_argument('-l',
                        '--language',
                        required=False,
                        default='python',
                        choices=['c', 'java', 'python'],
                        help='Language for generated parser')

    parser.add_argument('--java-package',
                        required=False,
                        help='If generating Java code, this is the package.')

    parser.add_argument(
        '-c',
        '--color',
        required=False,
        action='store_true',
        help='Prints things in color!  For the colorblind, this is a no-op.')

    parser.add_argument(
        '-m',
        '--add-main',
        required=False,
        action='store_true',
        help=
        'If this is specified, a main() function will be generated in the source code.'
    )

    cli = parser.parse_args()
    logger = LoggerFactory().initialize(cli.debug)
    logger.debug('CLI Parameters: %s' % (cli))

    factory = HermesParserFactory()
    fp = GrammarFileParser(factory.create())

    grammars = []
    for grammar in cli.grammar:
        if not os.path.isfile(grammar):
            sys.stderr.write("Error: Grammar file doesn't exist\n")
            sys.exit(-1)

        name = os.path.basename(grammar)

        if not name.endswith('.zgr'):
            sys.stderr.write("Error: Grammar file must have .zgr extension\n")
            sys.exit(-1)

        name = name[:-4]
        grammars.append(fp.parse(name, open(grammar)))

    if cli.action == 'analyze':

        if cli.color:
            theme = TerminalColorTheme()
        else:
            theme = TerminalDefaultTheme()

        for grammar in grammars:
            analyzer = GrammarAnalyzer(grammar)
            analyzer.analyze(theme=theme)

    if cli.action == 'generate':
        cli.directory = os.path.abspath(os.path.expanduser(cli.directory))

        if not os.path.isdir(cli.directory):
            sys.stderr.write("Error: Directory doesn't exist\n")
            sys.exit(-1)
        elif not os.access(cli.directory, os.W_OK):
            sys.stderr.write("Error: Directory not writable\n")
            sys.exit(-1)

        templateFactory = TemplateFactoryFactory().create(
            outputLanguage=cli.language.lower())
        templateWriter = TemplateWriter(templateFactory)
        templateWriter.write(grammars,
                             cli.directory,
                             addMain=cli.add_main,
                             javaPackage=cli.java_package)