| 1 | # Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved.
 | 
| 2 | # Licensed to PSF under a Contributor Agreement.
 | 
| 3 | 
 | 
| 4 | # Modifications:
 | 
| 5 | # Copyright 2006 Google, Inc. All Rights Reserved.
 | 
| 6 | # Licensed to PSF under a Contributor Agreement.
 | 
| 7 | from __future__ import print_function
 | 
| 8 | 
 | 
| 9 | """Parser driver.
 | 
| 10 | 
 | 
| 11 | A high-level interface to parse a file into a syntax tree.
 | 
| 12 | """
 | 
| 13 | 
 | 
| 14 | __author__ = "Guido van Rossum <guido@python.org>"
 | 
| 15 | 
 | 
| 16 | 
 | 
| 17 | import sys
 | 
| 18 | 
 | 
| 19 | from . import parse, pnode, token, tokenize
 | 
| 20 | 
 | 
| 21 | 
 | 
| 22 | def log(msg, *args):
 | 
| 23 |     if args:
 | 
| 24 |         msg = msg % args
 | 
| 25 |     print(msg, file=sys.stderr)
 | 
| 26 | 
 | 
| 27 | 
 | 
| 28 | def classify(gr, typ, value):
 | 
| 29 |     """Turn a token into a label.  (Internal)"""
 | 
| 30 |     if typ == token.NAME:
 | 
| 31 |         # Keep a listing of all used names
 | 
| 32 |         # OIL note: removed because it's only used by lib2to3
 | 
| 33 |         #self.used_names.add(value)
 | 
| 34 | 
 | 
| 35 |         # Check for reserved words
 | 
| 36 |         ilabel = gr.keywords.get(value)
 | 
| 37 |         if ilabel is not None:
 | 
| 38 |             return ilabel
 | 
| 39 |     ilabel = gr.tokens.get(typ)
 | 
| 40 |     if ilabel is None:
 | 
| 41 |         raise parse.ParseError("bad token", typ, value)
 | 
| 42 |     return ilabel
 | 
| 43 | 
 | 
| 44 | 
 | 
| 45 | def PushTokens(p, tokens, gr, start_symbol, opmap=token.opmap, debug=False):
 | 
| 46 |     """Parse a series of tokens and return the syntax tree.
 | 
| 47 | 
 | 
| 48 |     NOTE: This function is specific to Python's lexer.
 | 
| 49 |     """
 | 
| 50 |     # XXX Move the prefix computation into a wrapper around tokenize.
 | 
| 51 |     # NOTE: It's mainly for lib2to3.
 | 
| 52 | 
 | 
| 53 |     p.setup(gr.symbol2number[start_symbol], pnode.PNodeAllocator())
 | 
| 54 | 
 | 
| 55 |     lineno = 1
 | 
| 56 |     column = 0
 | 
| 57 |     type_ = value = start = end = line_text = None
 | 
| 58 |     prefix = ""
 | 
| 59 |     for quintuple in tokens:
 | 
| 60 |         type_, value, start, end, line_text = quintuple
 | 
| 61 |         #log('token %s %r', type_, value)
 | 
| 62 |         if start != (lineno, column):
 | 
| 63 |             assert (lineno, column) <= start, ((lineno, column), start)
 | 
| 64 |             s_lineno, s_column = start
 | 
| 65 |             if lineno < s_lineno:
 | 
| 66 |                 prefix += "\n" * (s_lineno - lineno)
 | 
| 67 |                 lineno = s_lineno
 | 
| 68 |                 column = 0
 | 
| 69 |             if column < s_column:
 | 
| 70 |                 prefix += line_text[column:s_column]
 | 
| 71 |                 column = s_column
 | 
| 72 |         if type_ in (tokenize.COMMENT, tokenize.NL):
 | 
| 73 |             prefix += value
 | 
| 74 |             lineno, column = end
 | 
| 75 |             if value.endswith("\n"):
 | 
| 76 |                 lineno += 1
 | 
| 77 |                 column = 0
 | 
| 78 |             continue
 | 
| 79 | 
 | 
| 80 |         if type_ == token.OP:
 | 
| 81 |             type_ = opmap[value]
 | 
| 82 | 
 | 
| 83 |         if debug:
 | 
| 84 |             log("%s %r (prefix=%r)", token.tok_name[type_], value, prefix)
 | 
| 85 | 
 | 
| 86 |         ilabel = classify(gr, type_, value)
 | 
| 87 |         opaque = (value, prefix, start)
 | 
| 88 |         if p.addtoken(type_, opaque, ilabel):
 | 
| 89 |             if debug:
 | 
| 90 |                 log("Stop.")
 | 
| 91 |             break
 | 
| 92 |         prefix = ""
 | 
| 93 |         lineno, column = end
 | 
| 94 |         if value.endswith("\n"):
 | 
| 95 |             lineno += 1
 | 
| 96 |             column = 0
 | 
| 97 |     else:
 | 
| 98 |         # We never broke out -- EOF is too soon (how can this happen???)
 | 
| 99 |         opaque = (value, prefix, start)
 | 
| 100 |         raise parse.ParseError("incomplete input", type_, opaque)
 | 
| 101 |     return p.rootnode
 |