Package pyfics :: Package parser :: Module ficsparser
[hide private]

Source Code for Module pyfics.parser.ficsparser

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  # vim: set sw=4 ts=4 sts=4 et tw=79 : 
  4  # Copyright 2006-2007 Ali Polatel <polatel@gmail.com> 
  5  # Distributed under the terms of the GNU General Public License v3 
  6   
  7  """Fics parser module for pyfics 
  8   
  9  This module has necessary parsers to parse Fics output and generate 
 10  pyparsing.ParserResult objects 
 11  """ 
 12   
 13  import re 
 14  from pyfics.parser import * 
 15  from telnetlib import IAC, WILL, WONT, ECHO 
 16  from pyparsing import alphas, nums 
 17  from pyparsing import Literal, Regex, Suppress, Word 
 18  from pyparsing import LineStart, LineEnd, StringStart 
 19  from pyparsing import Optional, oneOf, OneOrMore, Or, TokenConverter, ZeroOrMore 
 20   
21 -class SanitizeNewline(TokenConverter):
22 """Convert server's line sep to \n"""
23 - def postParse( self, instring, loc, tokenlist ):
24 return tokenlist[0].replace(server.ifs, '\n')
25
26 -class ToInteger(TokenConverter):
27 """Converter to make token into an integer."""
28 - def postParse( self, instring, loc, tokenlist ):
29 return int(tokenlist[0])
30 31 # Callback functions
32 -def on_login(s, loc, toks):
33 """Callback function called when login parser matches. 34 """ 35 # XXX fics doesn't seem to check the validity of interface variables. 36 # So we don't wait for #Ivars set. message to confirm interface variables 37 # are set. 38 ivars = protocol.server.genloginstr(protocol.server.ivars) 39 protocol.transport.write(ivars + '\n') 40 protocol.transport.write(protocol.server.login + '\n')
41
42 -def on_password(s, loc, toks):
43 """Callback function called when password parser matches. 44 """ 45 protocol.transport.write(protocol.server.password + '\n')
46
47 -def on_sessionstart(s, loc, toks):
48 """Callback function called when sessionstart parser matches. 49 """ 50 mainparser = parser
51
52 -def on_invalidlogin(s, loc, toks):
53 """Callback function called when invalidlogin parser matches. 54 """ 55 if protocol.server.misc_login: 56 protocol.transport.write('\n') 57 else: 58 raise InvalidUsername, "%s is invalid." % server.username
59
60 -def on_invalidpass(s, loc, expr, err):
61 """Callback function called when invalidpass parser matches. 62 """ 63 raise InvalidPassword, err
64 65 # Authentication 66 beginbr = Suppress("(") 67 endbr = Suppress(")") 68 handle = Word(alphas, min=3, max=17).setResultsName('handle') 69 tag = beginbr + oneOf("CA SR TM TD C U *").setResultsName('tag') + endbr 70 line = Regex(".*") 71 72 login = Literal("login: ") 73 password = Literal("password: ") 74 ivars_set = Literal("#Ivars set.") 75 stars = Suppress("*" * 4) 76 sessionstart = stars + Literal("Starting FICS session as") + handle + tag + stars 77 invalidlogin = oneOf(["Press return to enter the server as", "Logging you in as" ]) 78 invalidpass = stars + Literal("Invalid password!") + stars 79 telnet_seq = Suppress(IAC + oneOf([WILL, WONT]) + ECHO) 80 81 # Main parser 82 integer = ToInteger(Word(nums)) 83 wrap = Suppress("\\ ") 84 ch = beginbr + integer + endbr 85 rating = Regex(r"[\d\+]{1,4}") # can be '++++', too 86 rating_ex = Regex(r"[\d]{1,4}[PE ]") # can be '1650 ' or '0P' etc. 87 result = oneOf("1-0 0-1 1/2-1/2 *") # * is for aborted games in gameresult. 88 rated = oneOf("r u") 89 tp = oneOf("blitz standard") 90 colour = oneOf("? white black") 91 auto = oneOf("t f") 92 formula = oneOf("t f") 93 94 nick = handle + Optional(OneOrMore(tag)) 95 eol = Suppress(LineEnd() + LineStart()) + Optional(wrap) 96 msg = line + ZeroOrMore(eol + line) 97 98 say = nick + Literal("says:") + msg 99 tell = nick + Literal("tells you:") + msg 100 ctell = nick + ch + Literal(":") + msg 101 qtell = Literal(":") + msg 102 shout = nick + Literal("shouts:") + msg 103 cshout = nick + Literal("c-shouts:") + msg 104 it = Literal("-->") + nick + msg 105 state = oneOf([ "arrived", "departed" ]) # FIXME there are two more 106 notify = Literal("Notification:") + \ 107 nick + Literal("has") + state + Literal(".") 108 109 110 msgs = Literal("You have") + integer + Literal("messages") + beginbr + integer + Literal("unread.") 111 adj = Literal("You have") + integer + Literal("adjourned games.") 112 inc = Literal("Present company includes:") + OneOrMore(handle) 113 114 # seeks 115 # only enabled with seekinfo 116 si = Literal("<s>") + integer + Literal("w=") + handle +\ 117 Literal("ti=") + integer + Literal("rt=") + rating_ex +\ 118 Literal("t=") + integer + Literal("i=") + integer + Literal("r=") +\ 119 rated + Literal("tp=") + tp + Literal("c=") + colour +\ 120 Literal("rr=") + rating + Literal("-") + rating + Literal("a=") +\ 121 auto + Literal("f=") + formula 122 sr = Literal("<sr>") + OneOrMore(integer) 123 124 # set callbacks 125 login.setParseAction(on_login) 126 password.setParseAction(on_password) 127 sessionstart.setParseAction(on_sessionstart) 128 invalidlogin.setParseAction(on_invalidlogin) 129 invalidpass.setParseAction(on_invalidpass) 130 131 # Name results 132 login = login.setResultsName('LOGIN') 133 password = password.setResultsName('PASSWORD') 134 invalidlogin = invalidlogin.setResultsName('INVALIDLOGIN') 135 invalidpass = invalidpass.setResultsName('INVALIDPASS') 136 sessionstart = sessionstart.setResultsName('SESSIONSTART') 137 unknown = line.setResultsName('UNKNOWN') 138 139 authparser = login | password | sessionstart | invalidlogin | invalidpass | telnet_seq | unknown 140 parser = adj | inc | say | tell | ctell | qtell | shout | cshout |\ 141 it | state | notify | msgs | si | sr | line 142 mainparser = authparser 143
144 -def parse(line):
145 """ Return default parser """ 146 return mainparser.parseString(line)
147