# Path: pydsl/exceptions.py
# class ParseError(Exception):
# 
#     def __init__(self, msg, offset):
#         self.msg = msg
#         self.offset = offset
# 
#     def __repr__(self):
#         return "ParseError(%r, %r)" % (self.msg, self.offset)
# 
#     def __str__(self):
#         return "%s at position %s" % (self.msg, self.offset + 1)


from ply.lex import TOKEN
from pydsl.exceptions import ParseError
# Needed because Python's regular expression matcher
# uses "first match" not "longest match" rules.
# For example, "C|Cl" matches only the "C" in "Cl"
# The "-" in "-len(symbol)" is a trick to reverse the sort order.
#
#   - then by the full symbol, to make it easier for people

# (This is more complicated than needed; it's to show how
# this approach can scale to all 100+ known and named elements)

atom_names = sorted(
    mw_table.keys(),
    key = lambda symbol: (symbol[0], -len(symbol), symbol))

# Creates a pattern like:  Cl|C|H|O|S
atom_pattern = "|".join(atom_names)

# Use a relatively new PLY feature to set the __doc__
# string based on a Python variable.
@TOKEN(atom_pattern)
def t_ATOM(t):
    t.value = mw_table[t.value]
    return t

def t_DIGITS(t):
    r"\d+"
    t.value = int(t.value)
    return t

def t_error(t):

# Path: pydsl/exceptions.py
# class ParseError(Exception):
# 
#     def __init__(self, msg, offset):
#         self.msg = msg
#         self.offset = offset
# 
#     def __repr__(self):
#         return "ParseError(%r, %r)" % (self.msg, self.offset)
# 
#     def __str__(self):
#         return "%s at position %s" % (self.msg, self.offset + 1)


# Path: pydsl/contrib/grammar/example_ply.py
from ply.lex import TOKEN
from pydsl.exceptions import ParseError

# Needed because Python's regular expression matcher
# uses "first match" not "longest match" rules.
# For example, "C|Cl" matches only the "C" in "Cl"
# The "-" in "-len(symbol)" is a trick to reverse the sort order.
#
#   - then by the full symbol, to make it easier for people

# (This is more complicated than needed; it's to show how
# this approach can scale to all 100+ known and named elements)

atom_names = sorted(
    mw_table.keys(),
    key = lambda symbol: (symbol[0], -len(symbol), symbol))

# Creates a pattern like:  Cl|C|H|O|S
atom_pattern = "|".join(atom_names)

# Use a relatively new PLY feature to set the __doc__
# string based on a Python variable.
@TOKEN(atom_pattern)
def t_ATOM(t):
    t.value = mw_table[t.value]
    return t

def t_DIGITS(t):
    r"\d+"
    t.value = int(t.value)
    return t

def t_error(t):

    raise ParseError("unknown character", t.lexpos)