commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnue] r8362 - trunk/gnue-common/src/formatting/masks


From: jamest
Subject: [gnue] r8362 - trunk/gnue-common/src/formatting/masks
Date: Tue, 4 Apr 2006 21:23:02 -0500 (CDT)

Author: jamest
Date: 2006-04-04 21:23:02 -0500 (Tue, 04 Apr 2006)
New Revision: 8362

Modified:
   trunk/gnue-common/src/formatting/masks/MaskParser.py
Log:
old uncommited changes to MaskParser (all formatting I think)
start of pep8-ification


Modified: trunk/gnue-common/src/formatting/masks/MaskParser.py
===================================================================
--- trunk/gnue-common/src/formatting/masks/MaskParser.py        2006-04-05 
02:15:18 UTC (rev 8361)
+++ trunk/gnue-common/src/formatting/masks/MaskParser.py        2006-04-05 
02:23:02 UTC (rev 8362)
@@ -19,137 +19,140 @@
 # Copyright 2001-2006 Free Software Foundation
 #
 # FILE:
-# masks.py
+# MaskParser
 #
 # DESCRIPTION:
 """
-Parse mask definitions into tokens that the Mask class can use.
+A parser which takes a text based mask and generates a list of
+token class instances that represent that mask.  Any repeaters
+found in the mask ({3}) are replaced with the appropriate number
+of tokens so that the mask class will not have to deal with
+them.
 
-Tokens are ......
+Valid tokens include:
+
 """
-# NOTES:
-#
-from gnue.common.external.plex import *
+__revision__ = "$Id$"
+
+from gnue.common.external.plex import Scanner, Lexicon, Errors, \
+                                      Str, Begin, State, AnyChar, Rep1, Any
 import string
-from Errors import *
+from Errors import MaskDefinitionError
 
-# TODO: Why is this here?
-digit = Any(string.digits)
-
 class BaseToken:
-  """
-  Basic parser token class. 
-  
-  Not used directly,  but inherited by the other defined tokens
-  Literal, Token, etc.
-  """
-  numeric=False
-  date=False
-  text=False
-  literal=False
-  token=False
+    """
+    Basic parser token class.
 
-  def __init__(self, t1, t2=None, *args):
+    Not used directly,  but inherited by the other defined tokens
+    Literal, Token, etc.
     """
-    Token construtor
-    """
-    if t2:
-      self.token = t2
-    else:
-      self.token = t1
+    numeric = False
+    date    = False
+    text    = False
+    literal = False
+    token   = False
 
+    def __init__(self, t1, t2=None, *args):
+        """
+        Token construtor
+        """
+        if t2:
+            self.token = t2
+        else:
+            self.token = t1
+
 # -----------------------------------------------------------------------------
 # Standard token classes
 # -----------------------------------------------------------------------------
 class Token(BaseToken):
-  """
-  Class typically used to create normal tokens as 
-  opposed to special tokens like literal.
-  
-  It sets the standard options so that each individual 
-  token class doesn't need to.
-  """
-  force_lower = False
-  force_upper = False
-  token=True
+    """
+    Class typically used to create normal tokens as
+    opposed to special tokens like literal.
 
+    It sets the standard options so that each individual
+    token class doesn't need to.
+    """
+    force_lower = False
+    force_upper = False
+    token = True
+
 class NumberToken(Token):
-  """
-  Numeric token (#9-,.)
-  """
-  numeric = True
+    """
+    Numeric token (#9-,.)
+    """
+    numeric = True
 
 class DateToken(Token):
-  """
-  Date token (MDYyHIS:/)
-  """
-  date=True
+    """
+    Date token (MDYyHIS:/)
+    """
+    date = True
 
 class TextToken(Token):
-  """
-  Text token
-  
-  A test token represents 1 standard alphanumeric character.
-  """
-  text = True
+    """
+    Text token
 
+    A test token represents 1 standard alphanumeric character.
+    """
+    text = True
+
 class TokenSet(Token):
-  """
-  Token defined by user with [] notation.
-  Can behave like a  NumberToken or TextToken,
-  depending on contents of [].
-  """
-  def __init__(self, token, *args):
-    # TODO: Expand the set
-    # Are we all-numeric?
-    self.numeric = token.isdigit()
-    self.token = token
+    """
+    Token defined by user with [] notation.
+    Can behave like a  NumberToken or TextToken,
+    depending on contents of [].
+    """
+    def __init__(self, token, *args):
+        # TODO: Expand the set
+        # Are we all-numeric?
+        self.numeric = token.isdigit()
+        self.token = token
 
-    if not self.numeric:
-      self.text = True
+        if not self.numeric:
+            self.text = True
 
 # -----------------------------------------------------------------------------
 # Special token classes
 # -----------------------------------------------------------------------------
 class Literal(BaseToken):
-  """
-  A literal string that the developer wants in the string.
-  Note that for our purposes, the basic "literals" aren't
-  really Literals(), but special cases of Token classes.
-  So all literals represented by this class are denoted
-  with \ or "" syntaxes.
-  """
-  literal=True
+    """
+    A literal string that the developer wants in the string.
+    Note that for our purposes, the basic "literals" aren't
+    really Literals(), but special cases of Token classes.
+    So all literals represented by this class are denoted
+    with \ or "" syntaxes.
+    """
+    literal = True
 
 
 class RightToLeft(BaseToken):
-  """
-  Temporary token class used to note the
-  position of ! modifiers
-  """
-  numeric = True
+    """
+    Temporary token class used to note the
+    position of ! modifiers
+    """
+    numeric = True
 
 class CaseModifier:
-  """
-  Temporary token class used to record > and <
-  markers. These cause the modified token to have
-  either force_upper or force_lower set, so the
-  other classes won't ever see CaseModifier
-  instances.
-  """
-  pass
+    """
+    Temporary token class used to record > and <
+    markers. These cause the modified token to have
+    either force_upper or force_lower set, so the
+    other classes won't ever see CaseModifier
+    instances.
+    """
+    pass
 
 class Repeater:
-  """
-  Temporary token class used to record {#}
-  markers. These are replaced with the actual
-  represented tokens before being passed out
-  of MaskParser (i.e., 0{3} would be returned
-  as 000, so the other classes won't ever see
-  Repeater instances.
-  """
-  def __init__(self, count):
-    self.count = count
+    """
+    Temporary token class used to record {#}
+    markers. These are replaced with the actual
+    represented tokens before being passed out
+    of MaskParser (i.e., 0{3} would be returned
+    as 000, so the other classes won't ever see
+    Repeater instances.
+    """
+    def __init__(self, count):
+        self.count = count
 
 ##
 ##
@@ -158,390 +161,394 @@
 # Input mask parser
 # =============================================================================
 class InputMaskParser(Scanner):
-  """
-  Custom plex scanner used to contstruct the TODO: put name here
-  from an input mask passed in during initialization.
-  
-  Takes a file handle containing an input mask and creates a 
-  list of Tokens which define the input mask
-  """
-
-
-  def getType(self):
     """
-    Returns the apparent type of this mask.
-    
-    @rtype: string
-    @return: The value 'text', 'numeric', or 'date'
-    """
-    return type
+    Custom plex scanner used to contstruct the TODO: put name here
+    from an input mask passed in during initialization.
 
-  def getTokens(self):
+    Takes a file handle containing an input mask and creates a
+    list of Tokens which define the input mask
     """
-    Returns a list of the tokens after parsing the input mask.
-    
-    @rtype: list
-    @return: The list of tokens
-    """
-    return self.tokens[:]
 
-  # ===========================================================================
-  # Private stuff
-  # ===========================================================================
-  
-  # ---------------------------------------------------------------------------
-  # Lexicon action functions
-  # ---------------------------------------------------------------------------
-  def _check_single(self, text):
-    """
-    Function to add single instance tokens to the input mask.
-    
-    A single instance token is something that can appear only once
-    in an input mask.
-    """
-    if text in self.__singles:
-      raise Errors.UnrecognizedInput(self, 'Mask can only have one "%s" token' 
%text)
-    self.__singles.append(text)
-    if text == '!':
-      self.produce (RightToLeft(text))
-    elif text in '.+,':
-      self.produce(NumberToken(text))
-    else:
-      self.produce(TextToken(text))
 
-  def _literal(self, text):
-    """
-    A text literal that should appear as is in the mask
-    """
-    print "literal %s" % text
-    self.produce(Literal(text))
+    def getType(self):
+        """
+        Returns the apparent type of this mask.
 
-  def _literal_2nd(self, text):
-    """
-    Closes the literal string
-    """
-    print "literal 2nd %s" % text    
-    return self.literal(text[1:])
+        @rtype: string
+        @return: The value 'text', 'numeric', or 'date'
+        """
+        return type
 
-  def _escape(self, text):
-    """
-    An escaped character such as \$ to display a $ 
-    """
-    print "escape %s" % text
-    self.begin('')
-    self.produce(Literal(text))
+    def getTokens(self):
+        """
+        Returns a list of the tokens after parsing the input mask.
 
-  def _repeater(self, text):  
-    """
-    Action to process an input mask repeater.
-    
-    A repeater tells the parser to repeat the previous token a
-    specified number of times.  
-    
-    @param text: The value pulled from between the {} which
-                 denotes the number of times to repeat.
-    """
-    self.produce(Repeater(int(text)))
+        @rtype: list
+        @return: The list of tokens
+        """
+        return self.tokens[:]
 
-  def _begin_set(self, text):
-    """
-    Action to process the start of a set of valid characters.
-    
-    The scanner will be placed into set state and the list
-    of valid characters will be reset.
-    """
-    self.begin('set')
-    self._set = ""
+    # 
===========================================================================
+    # Private stuff
+    # 
===========================================================================
 
-  def _add_set(self, text):
-    """
-    Action to add a character to the set currently being constructed.
-    
-    Only called when the scanner is in state "set".  
-    
-    The character read will be added to the character sting 
-    containing the possible valid values.  
-    """
-    self._set += text
+    # 
---------------------------------------------------------------------------
+    # Lexicon action functions
+    # 
---------------------------------------------------------------------------
+    def _check_single(self, text):
+        """
+        Function to add single instance tokens to the input mask.
 
-  def _add_set_2nd(self, text):
-    """
-    Action to add a special character to a set being built.
-    
-    Used when an escaped set character \[ or \] is found
-    in the list of valid characters to be added to the set
-    """
-    return self.add_set(text[1:])
+        A single instance token is something that can appear only once
+        in an input mask.
+        """
+        if text in self.__singles:
+            raise Errors.UnrecognizedInput(self, 'Mask can only have one "%s" 
token' %text)
+        self.__singles.append(text)
+        if text == '!':
+            self.produce (RightToLeft(text))
+        elif text in '.+,':
+            self.produce(NumberToken(text))
+        else:
+            self.produce(TextToken(text))
 
-  def _end_set(self, text):
-    """
-    Action to process the end of a set.
-    
-    Only called when the scanner is in state "set".
-    
-    The list of possible characters that were defined in the set will be used
-    to build an instance of a TokenSet class.  As part of this function the
-    scanner will set to default state.
-    """
-    self.begin('')
-    self.produce(TokenSet(self._set))
+    def _literal(self, text):
+        """
+        A text literal that should appear as is in the mask
+        """
+        print "literal %s" % text
+        self.produce(Literal(text))
 
-  # ===========================================================================
-  # Lexicon defintions
-  # ===========================================================================
-  #
-  # ---------------------------------------------------------------------------
-  # Base Lexicon definition
-  # ---------------------------------------------------------------------------
-  # This lexicon is the base used by all masks
-  #
-  _lexicon = [
-      # -----------------------------------------------------------------------
-      # Default state definitions
-      # -----------------------------------------------------------------------
-      (Str('\\'),          Begin('escape')),   # found \, set state to escape
-                                               #
-      (Str("'"),           Begin('quoted')),   # found ', set state to quoted
-                                               #
-      (Str('"'),           Begin('quoted2')),  # found ", set state to qoute2
-                                               #
-      (Str('{'),           Begin('repeater')), # found {, set state to repeater
-                                               #
-      (Str('['),           _begin_set),        # found [, execute _begin_set
-                                               # the function will set state 
-                                               # to set when executed
-                                               #
-      (Str(' '),           Literal),           # found a space
-                                               # reutrn a literal char instance
-                                               #
-      (Any('+.,'),         _check_single),     # these characters can appear
-                                               # only once in an input mask
-                                               #
-      (Any('_?AaLlCc'),    TextToken),         # found a text character 
-                                               # return a text token instance
-                                               #
-      (Any('MDYyHISPp:/'), DateToken),         # found a date character
-                                               # return a date token instance
-                                               #
-      (Any('#0'),          NumberToken),       # found a number character
-                                               # return a number token instance
-                                               #
-      (Any('<>'),          CaseModifier),      # found a case modifier
-                                               # return case modifier instance
-      
-      # -----------------------------------------------------------------------
-      # Escape State
-      # -----------------------------------------------------------------------
-      # The escape state is entered whenever a backslash is encountered while
-      # in the default state.  It's purpose is to allow the placement of what
-      # would normally be reserved characters into the input mask
-      # 
-      State('escape',  [
-          (AnyChar,        _escape), # No matter which character is next 
-                                     # execute _escape, the function will
-                                     # create a literal instance and set
-                                     # the state back to default
-        ]),
+    def _literal_2nd(self, text):
+        """
+        Closes the literal string
+        """
+        print "literal 2nd %s" % text
+        return self.literal(text[1:])
 
-      # -----------------------------------------------------------------------
-      # Quoted state
-      # -----------------------------------------------------------------------
-      # The quoted state is entered whenevre a single quote is encountered
-      # thile in the default state.  It's purpose is to allow quoted strings
-      # inside the input mask to sent through as their literal value
-      #
-      State('quoted',  [
-          (Str("\\")+Str("'"), _literal_2nd), # Handle \' in the string
-          (Str("'"),           Begin('')),    # found ', set state to default
-          (AnyChar,            _literal)      # Process as literal character
-        ]),
+    def _escape(self, text):
+        """
+        An escaped character such as \$ to display a $
+        """
+        print "escape %s" % text
+        self.begin('')
+        self.produce(Literal(text))
 
-      # -----------------------------------------------------------------------
-      # quote2 state
-      # -----------------------------------------------------------------------
-      # This works the exact same way as the quoted state but is used
-      # when a double quote is encountered.  ' and " get seperate states
-      # so that one type can always enclose the other
-      #
-      # Example : "Today's date: "
-      #
-      State('quoted2',  [
-          (Str("\\")+Str('"'), _literal_2nd), # Handle \" in the string
-          (Str('"'),           Begin('')),    # found ", set state to default
-          (AnyChar,            _literal)      # Process as literal character
-        ]),
+    def _repeater(self, text):
+        """
+        Action to process an input mask repeater.
 
-      # -----------------------------------------------------------------------
-      # repeater state
-      # -----------------------------------------------------------------------
-      # The repeater state is entered whenever a { is encountered
-      # while in the default state.  This state allows an input
-      # mask to include a number inside of {} to cause the previous
-      # token to repeat
-      #
-      # Example : A{5} is the same as AAAAA
-      #
-      State('repeater',  [
-          (Str('}'),       Begin('')), # found }, set state to default
-          (Rep1(digit),    _repeater)  # grab all digits inside the {}
-                                       # execute _repeater, the function
-                                       # will recreate a repeater instance
-                                       # containing the obtained number
-        ]),
+        A repeater tells the parser to repeat the previous token a
+        specified number of times.
 
-      # -----------------------------------------------------------------------
-      # Set state
-      # -----------------------------------------------------------------------
-      # The set state is entered whenever a [ is encountered while in the 
-      # default state.  This provides basic regex set support where any
-      # character inside the [] is matched.
-      #
-      # Example : [ABCDEF]
-      #
-      State('set',  [
-          (Str("\\")+Any('[]'),  _add_set_2nd), # 
-          (Str(']'),             _end_set),     # 
-          (AnyChar,              _add_set)      # 
-        ]),
-  ]
+        @param text: The value pulled from between the {} which
+                     denotes the number of times to repeat.
+        """
+        self.produce(Repeater(int(text)))
 
-  # ---------------------------------------------------------------------------
-  # Additional lexicon definitions for input masks
-  # ---------------------------------------------------------------------------
-  _extra_lexicon = [
-        (Any('!'),        _check_single),
-  ]
+    def _begin_set(self, text):
+        """
+        Action to process the start of a set of valid characters.
 
-  def __process(self, token):
-    """
-    Adds a token class instance to this instances list of tokens.
-    
-    As token instances are generated from the input mask they
-    are processed and then added to the scanners working list 
-    of tokens.  Special tokens such as repeater and case modifiers
-    are processed during this state.
-    """
-    
-    if isinstance(token,Repeater):
-      # If the incoming token is a repeater then replace 
-      # the repeater with the appropriate number of the
-      # previous token.
-      for i in range(0, token.count-1):
-        self.__process(self.__last)
-    elif isinstance(token, CaseModifier):
-      # If then incomming token is a case modifier
-      # then add the modifier token to the list of 
-      # modifiers stored in the scanner
-      self.__modify.append(token)
-    else:
-      # Standard tokens
-      if self.__modify and isinstance(token, TextToken):
-        # If a case modifier is stored and the incoming 
-        # token is text then force case based upon the
-        # modifier
-        mod = self.__modify.pop(0)
-        if mod.token == '<':
-          token.force_upper = True
-        elif mod.token == '>':
-          token.force_lower = True
+        The scanner will be placed into set state and the list
+        of valid characters will be reset.
+        """
+        self.begin('set')
+        self._set = ""
 
-      self.tokens.append(token)
+    def _add_set(self, text):
+        """
+        Action to add a character to the set currently being constructed.
 
-    # TODO: Should this be storing modifiers and the like? It is.
-    self.__last = token 
+        Only called when the scanner is in state "set".
 
-  def __init__(self, file, name, numeric=False, date=False):
-    """
-    Input mask scanner constructor.
-    
-    The input mask scanner will create a list of class instances
-    that describe the input mask.
-    
-    @type file: input stream
-    @param file: The text to be used as the mask
-    @type name: string
-    @param name: The name of the input mask(TODO: ?)
-    @type numeric: boolean
-    @param numeric: Is this a numeric input mask
-    @type date: boolean
-    @param date: Is this a numeric input mask
-    """
-    self.__singles = []
-    self.tokens = []
-    self.__last = None  # The last token generated from the input mask
-    self.__modify = []
-    
-    
-    # -------------------------------------------------------------------------
-    # Read the input mask and convert into instances of Token classes
-    # -------------------------------------------------------------------------
-    try:
-      Scanner.__init__(self, Lexicon(self._lexicon + self._extra_lexicon), 
file, name)
+        The character read will be added to the character sting
+        containing the possible valid values.
+        """
+        self._set += text
 
-      while True:
-        token, extra = self.read()
-        if token is None:
-          break
-        
-        # Process the returned token 
-        self.__process(token)
-        
-    except Errors.PlexError, msg:
-      raise MaskDefinitionError, msg
+    def _add_set_2nd(self, text):
+        """
+        Action to add a special character to a set being built.
 
-    if self.__modify:
-      print "WARNING: Modifier found at end of mask."
+        Used when an escaped set character \[ or \] is found
+        in the list of valid characters to be added to the set
+        """
+        return self.add_set(text[1:])
 
-    # -------------------------------------------------------------------------
-    # Build a count of the various token types created during parsing
-    # -------------------------------------------------------------------------
+    def _end_set(self, text):
+        """
+        Action to process the end of a set.
+
+        Only called when the scanner is in state "set".
+
+        The list of possible characters that were defined in the set will be 
used
+        to build an instance of a TokenSet class.  As part of this function the
+        scanner will set to default state.
+        """
+        self.begin('')
+        self.produce(TokenSet(self._set))
+
+    # 
===========================================================================
+    # Lexicon defintions
+    # 
===========================================================================
     #
-    num_markers   = 0 # Number of numeric token instances found
-    date_markers  = 0 # Number of date token instances found
-    text_markers  = 0 # Number of text token instances found
-    rtl_pos = -1      # Right to left token
-                      # TODO: Unknown functionality at this time
+    # 
---------------------------------------------------------------------------
+    # Base Lexicon definition
+    # 
---------------------------------------------------------------------------
+    # This lexicon is the base used by all masks
+    #
 
-    for (position, token) in enumerate(self.tokens):
-      if isinstance(token,RightToLeft):
-        rtl_pos = position
-      if not isinstance(token, Literal):
-        if token.numeric:
-          num_markers += 1
-        elif token.date:
-          date_markers += 1
+    _lexicon = [
+        # 
-----------------------------------------------------------------------
+        # Default state definitions
+        # 
-----------------------------------------------------------------------
+        (Str('\\'),          Begin('escape')),   # found \, set state to escape
+                                                 #
+        (Str("'"),           Begin('quoted')),   # found ', set state to quoted
+                                                 #
+        (Str('"'),           Begin('quoted2')),  # found ", set state to qoute2
+                                                 #
+        (Str('{'),           Begin('repeater')), # found {, set state to 
repeater
+                                                 #
+        (Str('['),           _begin_set),        # found [, execute _begin_set
+                                                 # the function will set state
+                                                 # to set when executed
+                                                 #
+        (Str(' '),           Literal),           # found a space
+                                                 # reutrn a literal char 
instance
+                                                 #
+        (Any('+.,'),         _check_single),     # these characters can appear
+                                                 # only once in an input mask
+                                                 #
+        (Any('_?AaLlCc'),    TextToken),         # found a text character
+                                                 # return a text token instance
+                                                 #
+        (Any('MDYyHISPp:/'), DateToken),         # found a date character
+                                                 # return a date token instance
+                                                 #
+        (Any('#0'),          NumberToken),       # found a number character
+                                                 # return a number token 
instance
+                                                 #
+        (Any('<>'),          CaseModifier),      # found a case modifier
+                                                 # return case modifier 
instance
+
+        # 
-----------------------------------------------------------------------
+        # Escape State
+        # 
-----------------------------------------------------------------------
+        # The escape state is entered whenever a backslash is encountered while
+        # in the default state.  It's purpose is to allow the placement of what
+        # would normally be reserved characters into the input mask
+        #
+        State('escape',  [
+            (AnyChar,        _escape), # No matter which character is next
+                                       # execute _escape, the function will
+                                       # create a literal instance and set
+                                       # the state back to default
+          ]),
+
+        # 
-----------------------------------------------------------------------
+        # Quoted state
+        # 
-----------------------------------------------------------------------
+        # The quoted state is entered whenever a single quote is encountered
+        # thile in the default state.  It's purpose is to allow quoted strings
+        # inside the input mask to sent through as their literal value
+        #
+        State('quoted',  [
+            (Str("\\")+Str("'"), _literal_2nd), # Handle \' in the string
+            (Str("'"),           Begin('')),    # found ', set state to default
+            (AnyChar,            _literal)      # Process as literal character
+          ]),
+
+        # 
-----------------------------------------------------------------------
+        # quote2 state
+        # 
-----------------------------------------------------------------------
+        # This works the exact same way as the quoted state but is used
+        # when a double quote is encountered.  ' and " get seperate states
+        # so that one type can always enclose the other
+        #
+        # Example : "Today's date: "
+        #
+        State('quoted2',  [
+            (Str("\\")+Str('"'), _literal_2nd), # Handle \" in the string
+            (Str('"'),           Begin('')),    # found ", set state to default
+            (AnyChar,            _literal)      # Process as literal character
+          ]),
+
+        # 
-----------------------------------------------------------------------
+        # repeater state
+        # 
-----------------------------------------------------------------------
+        # The repeater state is entered whenever a { is encountered
+        # while in the default state.  This state allows an input
+        # mask to include a number inside of {} to cause the previous
+        # token to repeat
+        #
+        # Example : A{5} is the same as AAAAA
+        #
+        State('repeater',  [
+            (Str('}'),                 Begin('')),# found }, set state to 
default
+            (Rep1(Any(string.digits)), _repeater) # grab all digits inside the 
{}
+                                                  # execute _repeater, the
+                                                  # function will recreate a
+                                                  # repeater instance 
containing
+                                                  # the obtained number
+          ]),
+
+        # 
-----------------------------------------------------------------------
+        # Set state
+        # 
-----------------------------------------------------------------------
+        # The set state is entered whenever a [ is encountered while in the
+        # default state.  This provides basic regex set support where any
+        # character inside the [] is matched.
+        #
+        # Example : [ABCDEF]
+        #
+        State('set',  [
+            (Str("\\")+Any('[]'),  _add_set_2nd), #
+            (Str(']'),             _end_set),     #
+            (AnyChar,              _add_set)      #
+          ]),
+    ]
+
+    # 
---------------------------------------------------------------------------
+    # Additional lexicon definitions for input masks
+    # 
---------------------------------------------------------------------------
+    _extra_lexicon = [
+          (Any('!'),        _check_single),
+    ]
+
+    def __process(self, token):
+        """
+        Adds a token class instance to this instances list of tokens.
+
+        As token instances are generated from the input mask they
+        are processed and then added to the scanners working list
+        of tokens.  Special tokens such as repeater and case modifiers
+        are processed during this state.
+        """
+
+        if isinstance(token, Repeater):
+            # If the incoming token is a repeater then replace
+            # the repeater with the appropriate number of the
+            # previous token.
+            for i in range(0, token.count-1):
+                self.__process(self.__last)
+        elif isinstance(token, CaseModifier):
+            # If then incomming token is a case modifier
+            # then add the modifier token to the list of
+            # modifiers stored in the scanner
+            self.__modify.append(token)
         else:
-          text_markers += 1
-    
-    # Check for "!" in non-numeric mask
-    if rtl_pos >= 0:
-      self.tokens.pop(rtl_pos)
-    else:
-      rtl_pos = 0
+            # Standard tokens
+            if self.__modify and isinstance(token, TextToken):
+                # If a case modifier is stored and the incoming
+                # token is text then force case based upon the
+                # modifier
+                mod = self.__modify.pop(0)
+                if mod.token == '<':
+                    token.force_upper = True
+                elif mod.token == '>':
+                    token.force_lower = True
 
-    self.rtl_pos = rtl_pos
+            self.tokens.append(token)
 
-    # -------------------------------------------------------------------------
-    # Check for errors and mixed marker types
-    # -------------------------------------------------------------------------
-    if not (num_markers or date_markers or text_markers):
-      raise MaskDefinitionError, 'Mask has no character tokens'
+        # TODO: Should this be storing modifiers and the like? It is.
+        self.__last = token
 
-    if numeric and (date_markers or text_markers):
-      raise MaskDefinitionError, 'Numeric mask has non-numeric tokens'
+    def __init__(self, mask, name, numeric=False, date=False):
+        """
+        Input mask scanner constructor.
 
-    if date and (num_markers or text_markers):
-      raise MaskDefinitionError, 'Date/Time mask has non-date tokens'
+        The input mask scanner will create a list of class instances
+        that describe the input mask.
 
-    # -------------------------------------------------------------------------
-    # Set the type of parser based upon the marker counts
-    # -------------------------------------------------------------------------
-    # If any two of these are non-zero, then the mask is a text mask, 
-    # not date or numeric.
-    #
-    if (num_markers and date_markers) or text_markers:
-      self.type = 'text'
-    elif num_markers:
-      self.type = 'numeric'
-    else:
-      self.type = 'date'
+        @type mask: input stream
+        @param mask: The text to be used as the mask
+        @type name: string
+        @param name: The name of the input mask(TODO: ?)
+        @type numeric: boolean
+        @param numeric: Is this a numeric input mask
+        @type date: boolean
+        @param date: Is this a numeric input mask
+        """
+        self.__singles = []
+        self.tokens = []
+        self.__last = None  # The last token generated from the input mask
+        self.__modify = []
+
+
+        # 
-------------------------------------------------------------------------
+        # Read the input mask and convert into instances of Token classes
+        # 
-------------------------------------------------------------------------
+        try:
+            Scanner.__init__(self,
+                             Lexicon(self._lexicon + self._extra_lexicon),
+                             mask, name)
+
+            while True:
+                token, extra = self.read()
+                if token is None:
+                    break
+
+                # Process the returned token
+                self.__process(token)
+
+        except Errors.PlexError, msg:
+            raise MaskDefinitionError, msg
+
+        if self.__modify:
+            print "WARNING: Modifier found at end of mask."
+
+        # 
-------------------------------------------------------------------------
+        # Build a count of the various token types created during parsing
+        # 
-------------------------------------------------------------------------
+        #
+        num_markers   = 0 # Number of numeric token instances found
+        date_markers  = 0 # Number of date token instances found
+        text_markers  = 0 # Number of text token instances found
+        rtl_pos = -1      # Right to left token
+                          # TODO: Unknown functionality at this time
+
+        for (position, token) in enumerate(self.tokens):
+            if isinstance(token, RightToLeft):
+                rtl_pos = position
+            if not isinstance(token, Literal):
+                if token.numeric:
+                    num_markers += 1
+                elif token.date:
+                    date_markers += 1
+                else:
+                    text_markers += 1
+
+        # Check for "!" in non-numeric mask
+        if rtl_pos >= 0:
+            self.tokens.pop(rtl_pos)
+        else:
+            rtl_pos = 0
+
+        self.rtl_pos = rtl_pos
+
+        # 
-------------------------------------------------------------------------
+        # Check for errors and mixed marker types
+        # 
-------------------------------------------------------------------------
+        if not (num_markers or date_markers or text_markers):
+            raise MaskDefinitionError, 'Mask has no character tokens'
+
+        if numeric and (date_markers or text_markers):
+            raise MaskDefinitionError, 'Numeric mask has non-numeric tokens'
+
+        if date and (num_markers or text_markers):
+            raise MaskDefinitionError, 'Date/Time mask has non-date tokens'
+
+        # 
-------------------------------------------------------------------------
+        # Set the type of parser based upon the marker counts
+        # 
-------------------------------------------------------------------------
+        # If any two of these are non-zero, then the mask is a text mask,
+        # not date or numeric.
+        #
+        if (num_markers and date_markers) or text_markers:
+            self.type = 'text'
+        elif num_markers:
+            self.type = 'numeric'
+        else:
+            self.type = 'date'





reply via email to

[Prev in Thread] Current Thread [Next in Thread]