Back to index

enigmail  1.4.3
Classes | Functions | Variables
ply.yacc Namespace Reference

Classes

class  PlyLogger
class  NullLogger
class  YaccError
class  YaccSymbol
class  YaccProduction
class  LRParser
class  Production
class  MiniProduction
class  LRItem
class  GrammarError
class  Grammar
class  VersionError
class  LRTable
class  LALRError
class  LRGeneratedTable
class  ParserReflect

Functions

def func_code
def load_ply_lex
def format_result
def format_stack_entry
def rightmost_terminal
def digraph
def traverse
def get_caller_module_dict
def parse_grammar
def yacc

Variables

string __version__ = "3.3"
string __tabversion__ = "3.2"
int yaccdebug = 1
string debug_file = 'parser.out'
string tab_module = 'parsetab'
string default_lr = 'LALR'
int error_count = 3
int yaccdevel = 0
int resultlimit = 40
int pickle_protocol = 0
 MAXINT = sys.maxint
tuple _is_identifier = re.compile(r'^[a-zA-Z0-9_-]+$')

Function Documentation

def ply.yacc.digraph (   X,
  R,
  FP 
)

Definition at line 1898 of file yacc.py.

01898 
01899 def digraph(X,R,FP):
01900     N = { }
01901     for x in X:
01902        N[x] = 0
01903     stack = []
01904     F = { }
01905     for x in X:
01906         if N[x] == 0: traverse(x,N,stack,F,X,R,FP)
01907     return F

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 143 of file yacc.py.

00143 
00144 def format_result(r):
00145     repr_str = repr(r)
00146     if '\n' in repr_str: repr_str = repr(repr_str)
00147     if len(repr_str) > resultlimit:
00148         repr_str = repr_str[:resultlimit]+" ..."
00149     result = "<%s @ 0x%x> (%s)" % (type(r).__name__,id(r),repr_str)
00150     return result
00151 
00152 
# Format stack entries when the parser is running in debug mode

Definition at line 153 of file yacc.py.

00153 
00154 def format_stack_entry(r):
00155     repr_str = repr(r)
00156     if '\n' in repr_str: repr_str = repr(repr_str)
00157     if len(repr_str) < 16:
00158         return repr_str
00159     else:
00160         return "<%s @ 0x%x>" % (type(r).__name__,id(r))
00161 
00162 #-----------------------------------------------------------------------------
00163 #                        ===  LR Parsing Engine ===
00164 #
00165 # The following classes are used for the LR parser itself.  These are not
00166 # used during table construction and are independent of the actual LR
00167 # table generation algorithm
00168 #-----------------------------------------------------------------------------
00169 
00170 # This class is used to hold non-terminal grammar symbols during parsing.
00171 # It normally has the following attributes set:
00172 #        .type       = Grammar symbol type
00173 #        .value      = Symbol value
00174 #        .lineno     = Starting line number
00175 #        .endlineno  = Ending line number (optional, set automatically)
00176 #        .lexpos     = Starting lex position
00177 #        .endlexpos  = Ending lex position (optional, set automatically)

def ply.yacc.func_code (   f)

Definition at line 91 of file yacc.py.

00091 
00092     def func_code(f):
00093         return f.func_code
else:

Here is the caller graph for this function:

Definition at line 2702 of file yacc.py.

02702 
02703 def get_caller_module_dict(levels):
02704     try:
02705         raise RuntimeError
02706     except RuntimeError:
02707         e,b,t = sys.exc_info()
02708         f = t.tb_frame
02709         while levels > 0:
02710             f = f.f_back                   
02711             levels -= 1
02712         ldict = f.f_globals.copy()
02713         if f.f_globals != f.f_locals:
02714             ldict.update(f.f_locals)
02715 
02716         return ldict
02717 
02718 # -----------------------------------------------------------------------------
02719 # parse_grammar()
02720 #
02721 # This takes a raw grammar rule string and parses it into production data
# -----------------------------------------------------------------------------

Here is the caller graph for this function:

Definition at line 104 of file yacc.py.

00104 
00105 def load_ply_lex():
00106     if sys.version_info[0] < 3:
00107         import lex
00108     else:
00109         import ply.lex as lex
00110     return lex
00111 
00112 # This object is a stand-in for a logging object created by the 
00113 # logging module.   PLY will use this by default to create things
00114 # such as the parser.out file.  If a user wants more detailed
00115 # information, they can create their own logging object and pass
00116 # it into PLY.

Here is the caller graph for this function:

def ply.yacc.parse_grammar (   doc,
  file,
  line 
)

Definition at line 2722 of file yacc.py.

02722 
02723 def parse_grammar(doc,file,line):
02724     grammar = []
02725     # Split the doc string into lines
02726     pstrings = doc.splitlines()
02727     lastp = None
02728     dline = line
02729     for ps in pstrings:
02730         dline += 1
02731         p = ps.split()
02732         if not p: continue
02733         try:
02734             if p[0] == '|':
02735                 # This is a continuation of a previous rule
02736                 if not lastp:
02737                     raise SyntaxError("%s:%d: Misplaced '|'" % (file,dline))
02738                 prodname = lastp
02739                 syms = p[1:]
02740             else:
02741                 prodname = p[0]
02742                 lastp = prodname
02743                 syms   = p[2:]
02744                 assign = p[1]
02745                 if assign != ':' and assign != '::=':
02746                     raise SyntaxError("%s:%d: Syntax error. Expected ':'" % (file,dline))
02747 
02748             grammar.append((file,dline,prodname,syms))
02749         except SyntaxError:
02750             raise
02751         except Exception:
02752             raise SyntaxError("%s:%d: Syntax error in rule '%s'" % (file,dline,ps.strip()))
02753 
02754     return grammar
02755 
02756 # -----------------------------------------------------------------------------
02757 # ParserReflect()
02758 #
02759 # This class represents information extracted for building a parser including
02760 # start symbol, error function, tokens, precedence list, action functions,
02761 # etc.
# -----------------------------------------------------------------------------

Here is the caller graph for this function:

def ply.yacc.rightmost_terminal (   symbols,
  terminals 
)

Definition at line 1296 of file yacc.py.

01296 
01297 def rightmost_terminal(symbols, terminals):
01298     i = len(symbols) - 1
01299     while i >= 0:
01300         if symbols[i] in terminals:
01301             return symbols[i]
01302         i -= 1
01303     return None
01304 
01305 # -----------------------------------------------------------------------------
01306 #                           === GRAMMAR CLASS ===
01307 #
01308 # The following class represents the contents of the specified grammar along
01309 # with various computed properties such as first sets, follow sets, LR items, etc.
01310 # This data is used for critical parts of the table generation process later.
01311 # -----------------------------------------------------------------------------

Here is the caller graph for this function:

def ply.yacc.traverse (   x,
  N,
  stack,
  F,
  X,
  R,
  FP 
)

Definition at line 1908 of file yacc.py.

01908 
01909 def traverse(x,N,stack,F,X,R,FP):
01910     stack.append(x)
01911     d = len(stack)
01912     N[x] = d
01913     F[x] = FP(x)             # F(X) <- F'(x)
01914 
01915     rel = R(x)               # Get y's related to x
01916     for y in rel:
01917         if N[y] == 0:
01918              traverse(y,N,stack,F,X,R,FP)
01919         N[x] = min(N[x],N[y])
01920         for a in F.get(y,[]):
01921             if a not in F[x]: F[x].append(a)
01922     if N[x] == d:
01923        N[stack[-1]] = MAXINT
01924        F[stack[-1]] = F[x]
01925        element = stack.pop()
01926        while element != x:
01927            N[stack[-1]] = MAXINT
01928            F[stack[-1]] = F[x]
01929            element = stack.pop()

Here is the caller graph for this function:

def ply.yacc.yacc (   method = 'LALR',
  debug = yaccdebug,
  module = None,
  tabmodule = tab_module,
  start = None,
  check_recursion = 1,
  optimize = 0,
  write_tables = 1,
  debugfile = debug_file,
  outputdir = '',
  debuglog = None,
  errorlog = None,
  picklefile = None 
)

Definition at line 3038 of file yacc.py.

03038 
03039          debuglog=None, errorlog = None, picklefile=None):
03040 
03041     global parse                 # Reference to the parsing method of the last built parser
03042 
03043     # If pickling is enabled, table files are not created
03044 
03045     if picklefile:
03046         write_tables = 0
03047 
03048     if errorlog is None:
03049         errorlog = PlyLogger(sys.stderr)
03050 
03051     # Get the module dictionary used for the parser
03052     if module:
03053         _items = [(k,getattr(module,k)) for k in dir(module)]
03054         pdict = dict(_items)
03055     else:
03056         pdict = get_caller_module_dict(2)
03057 
03058     # Collect parser information from the dictionary
03059     pinfo = ParserReflect(pdict,log=errorlog)
03060     pinfo.get_all()
03061 
03062     if pinfo.error:
03063         raise YaccError("Unable to build parser")
03064 
03065     # Check signature against table files (if any)
03066     signature = pinfo.signature()
03067 
03068     # Read the tables
03069     try:
03070         lr = LRTable()
03071         if picklefile:
03072             read_signature = lr.read_pickle(picklefile)
03073         else:
03074             read_signature = lr.read_table(tabmodule)
03075         if optimize or (read_signature == signature):
03076             try:
03077                 lr.bind_callables(pinfo.pdict)
03078                 parser = LRParser(lr,pinfo.error_func)
03079                 parse = parser.parse
03080                 return parser
03081             except Exception:
03082                 e = sys.exc_info()[1]
03083                 errorlog.warning("There was a problem loading the table file: %s", repr(e))
03084     except VersionError:
03085         e = sys.exc_info()
03086         errorlog.warning(str(e))
03087     except Exception:
03088         pass
03089 
03090     if debuglog is None:
03091         if debug:
03092             debuglog = PlyLogger(open(debugfile,"w"))
03093         else:
03094             debuglog = NullLogger()
03095 
03096     debuglog.info("Created by PLY version %s (http://www.dabeaz.com/ply)", __version__)
03097 
03098 
03099     errors = 0
03100 
03101     # Validate the parser information
03102     if pinfo.validate_all():
03103         raise YaccError("Unable to build parser")
03104     
03105     if not pinfo.error_func:
03106         errorlog.warning("no p_error() function is defined")
03107 
03108     # Create a grammar object
03109     grammar = Grammar(pinfo.tokens)
03110 
03111     # Set precedence level for terminals
03112     for term, assoc, level in pinfo.preclist:
03113         try:
03114             grammar.set_precedence(term,assoc,level)
03115         except GrammarError:
03116             e = sys.exc_info()[1]
03117             errorlog.warning("%s",str(e))
03118 
03119     # Add productions to the grammar
03120     for funcname, gram in pinfo.grammar:
03121         file, line, prodname, syms = gram
03122         try:
03123             grammar.add_production(prodname,syms,funcname,file,line)
03124         except GrammarError:
03125             e = sys.exc_info()[1]
03126             errorlog.error("%s",str(e))
03127             errors = 1
03128 
03129     # Set the grammar start symbols
03130     try:
03131         if start is None:
03132             grammar.set_start(pinfo.start)
03133         else:
03134             grammar.set_start(start)
03135     except GrammarError:
03136         e = sys.exc_info()[1]
03137         errorlog.error(str(e))
03138         errors = 1
03139 
03140     if errors:
03141         raise YaccError("Unable to build parser")
03142 
03143     # Verify the grammar structure
03144     undefined_symbols = grammar.undefined_symbols()
03145     for sym, prod in undefined_symbols:
03146         errorlog.error("%s:%d: Symbol '%s' used, but not defined as a token or a rule",prod.file,prod.line,sym)
03147         errors = 1
03148 
03149     unused_terminals = grammar.unused_terminals()
03150     if unused_terminals:
03151         debuglog.info("")
03152         debuglog.info("Unused terminals:")
03153         debuglog.info("")
03154         for term in unused_terminals:
03155             errorlog.warning("Token '%s' defined, but not used", term)
03156             debuglog.info("    %s", term)
03157 
03158     # Print out all productions to the debug log
03159     if debug:
03160         debuglog.info("")
03161         debuglog.info("Grammar")
03162         debuglog.info("")
03163         for n,p in enumerate(grammar.Productions):
03164             debuglog.info("Rule %-5d %s", n, p)
03165 
03166     # Find unused non-terminals
03167     unused_rules = grammar.unused_rules()
03168     for prod in unused_rules:
03169         errorlog.warning("%s:%d: Rule '%s' defined, but not used", prod.file, prod.line, prod.name)
03170 
03171     if len(unused_terminals) == 1:
03172         errorlog.warning("There is 1 unused token")
03173     if len(unused_terminals) > 1:
03174         errorlog.warning("There are %d unused tokens", len(unused_terminals))
03175 
03176     if len(unused_rules) == 1:
03177         errorlog.warning("There is 1 unused rule")
03178     if len(unused_rules) > 1:
03179         errorlog.warning("There are %d unused rules", len(unused_rules))
03180 
03181     if debug:
03182         debuglog.info("")
03183         debuglog.info("Terminals, with rules where they appear")
03184         debuglog.info("")
03185         terms = list(grammar.Terminals)
03186         terms.sort()
03187         for term in terms:
03188             debuglog.info("%-20s : %s", term, " ".join([str(s) for s in grammar.Terminals[term]]))
03189         
03190         debuglog.info("")
03191         debuglog.info("Nonterminals, with rules where they appear")
03192         debuglog.info("")
03193         nonterms = list(grammar.Nonterminals)
03194         nonterms.sort()
03195         for nonterm in nonterms:
03196             debuglog.info("%-20s : %s", nonterm, " ".join([str(s) for s in grammar.Nonterminals[nonterm]]))
03197         debuglog.info("")
03198 
03199     if check_recursion:
03200         unreachable = grammar.find_unreachable()
03201         for u in unreachable:
03202             errorlog.warning("Symbol '%s' is unreachable",u)
03203 
03204         infinite = grammar.infinite_cycles()
03205         for inf in infinite:
03206             errorlog.error("Infinite recursion detected for symbol '%s'", inf)
03207             errors = 1
03208         
03209     unused_prec = grammar.unused_precedence()
03210     for term, assoc in unused_prec:
03211         errorlog.error("Precedence rule '%s' defined for unknown symbol '%s'", assoc, term)
03212         errors = 1
03213 
03214     if errors:
03215         raise YaccError("Unable to build parser")
03216     
03217     # Run the LRGeneratedTable on the grammar
03218     if debug:
03219         errorlog.debug("Generating %s tables", method)
03220             
03221     lr = LRGeneratedTable(grammar,method,debuglog)
03222 
03223     if debug:
03224         num_sr = len(lr.sr_conflicts)
03225 
03226         # Report shift/reduce and reduce/reduce conflicts
03227         if num_sr == 1:
03228             errorlog.warning("1 shift/reduce conflict")
03229         elif num_sr > 1:
03230             errorlog.warning("%d shift/reduce conflicts", num_sr)
03231 
03232         num_rr = len(lr.rr_conflicts)
03233         if num_rr == 1:
03234             errorlog.warning("1 reduce/reduce conflict")
03235         elif num_rr > 1:
03236             errorlog.warning("%d reduce/reduce conflicts", num_rr)
03237 
03238     # Write out conflicts to the output file
03239     if debug and (lr.sr_conflicts or lr.rr_conflicts):
03240         debuglog.warning("")
03241         debuglog.warning("Conflicts:")
03242         debuglog.warning("")
03243 
03244         for state, tok, resolution in lr.sr_conflicts:
03245             debuglog.warning("shift/reduce conflict for %s in state %d resolved as %s",  tok, state, resolution)
03246         
03247         already_reported = {}
03248         for state, rule, rejected in lr.rr_conflicts:
03249             if (state,id(rule),id(rejected)) in already_reported:
03250                 continue
03251             debuglog.warning("reduce/reduce conflict in state %d resolved using rule (%s)", state, rule)
03252             debuglog.warning("rejected rule (%s) in state %d", rejected,state)
03253             errorlog.warning("reduce/reduce conflict in state %d resolved using rule (%s)", state, rule)
03254             errorlog.warning("rejected rule (%s) in state %d", rejected, state)
03255             already_reported[state,id(rule),id(rejected)] = 1
03256         
03257         warned_never = []
03258         for state, rule, rejected in lr.rr_conflicts:
03259             if not rejected.reduced and (rejected not in warned_never):
03260                 debuglog.warning("Rule (%s) is never reduced", rejected)
03261                 errorlog.warning("Rule (%s) is never reduced", rejected)
03262                 warned_never.append(rejected)
03263 
03264     # Write the table file if requested
03265     if write_tables:
03266         lr.write_table(tabmodule,outputdir,signature)
03267 
03268     # Write a pickled version of the tables
03269     if picklefile:
03270         lr.pickle_table(picklefile,signature)
03271 
03272     # Build the parser
03273     lr.bind_callables(pinfo.pdict)
03274     parser = LRParser(lr,pinfo.error_func)
03275 
03276     parse = parser.parse
03277     return parser

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

string ply.yacc.__tabversion__ = "3.2"

Definition at line 63 of file yacc.py.

string ply.yacc.__version__ = "3.3"

Definition at line 62 of file yacc.py.

tuple ply.yacc._is_identifier = re.compile(r'^[a-zA-Z0-9_-]+$')

Definition at line 1126 of file yacc.py.

string ply.yacc.debug_file = 'parser.out'

Definition at line 74 of file yacc.py.

string ply.yacc.default_lr = 'LALR'

Definition at line 76 of file yacc.py.

Definition at line 78 of file yacc.py.

ply.yacc.MAXINT = sys.maxint

Definition at line 99 of file yacc.py.

Definition at line 85 of file yacc.py.

Definition at line 83 of file yacc.py.

string ply.yacc.tab_module = 'parsetab'

Definition at line 75 of file yacc.py.

Definition at line 71 of file yacc.py.

Definition at line 80 of file yacc.py.