File indexing completed on 2024-10-13 04:17:14
0001 # -*- coding: utf-8 -*- 0002 # Copyright 2007-8 Jim Bublitz <jbublitz@nwinternet.com> 0003 # 0004 # This program is free software; you can redistribute it and/or modify 0005 # it under the terms of the GNU General Public License as published by 0006 # the Free Software Foundation; either version 2 of the License, or 0007 # (at your option) any later version. 0008 # 0009 # This program is distributed in the hope that it will be useful, 0010 # but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 # GNU General Public License for more details. 0013 # 0014 # You should have received a copy of the GNU General Public License 0015 # along with this program; if not, write to the 0016 # Free Software Foundation, Inc., 0017 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0018 0019 import ply.lex as lex 0020 import ply.yacc as yacc 0021 0022 # Operators (+,-,*,/,%,|,&,~,^,<<,>>, ||, &&, !, <, <=, >, >=, ==, !=) 0023 operators = ('PLUS', 'MINUS', 'SLASH', 'PERCENT', 'VBAR', 'CARET', #'LSHIFT', 'RSHIFT', 0024 'LOR', 'LAND', 'BANG', 'LE', 'GE', 'EQ', 'NE', 0025 # Increment/decrement (++,--) 0026 'PLUSPLUS', 'MINUSMINUS', 0027 # Assignment (=, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=) 0028 'TIMESEQUAL', 'DIVEQUAL', 'MODEQUAL', 'PLUSEQUAL', 'MINUSEQUAL', 0029 'LSHIFTEQUAL',#'RSHIFTEQUAL', 0030 'ANDEQUAL', 'XOREQUAL', 'OREQUAL','EQUALS', 'ASTERISK', 'AMPERSAND', 'TILDE', 'LT', 'GT' 0031 ) 0032 0033 tokens = operators + ( 0034 # Literals (identifier, integer constant, float constant, string constant, char const) 0035 'ID', 'ICONST', 'OCTCONST', 'HEXCONST', 'FCONST', 'SCONST', 'CCONST', 0036 0037 # Delimeters ( ) [ ] { } , . ; : :: 0038 'LPAREN', 'RPAREN', 0039 'LBRACKET', 'RBRACKET', 0040 'LBRACE', 'RBRACE', 0041 'COMMA', 'PERIOD', 'SEMI', 'COLON', 'COLON2', 0042 0043 'ARRAYOP', 'FUNCPTR', 'defined' 0044 ) 0045 0046 # Completely ignored characters 0047 t_ANY_ignore = ' \t\x0c' 0048 0049 # Operators 0050 t_PLUS = r'\+' 0051 t_MINUS = r'-' 0052 t_ASTERISK = r'\*' 0053 t_SLASH = r'/' 0054 t_PERCENT = r'%' 0055 t_VBAR = r'\|' 0056 t_AMPERSAND = r'&' 0057 t_TILDE = r'~' 0058 t_CARET = r'\^' 0059 #t_LSHIFT = r'<<' 0060 #t_RSHIFT = r'>>' 0061 t_LOR = r'\|\|' 0062 t_LAND = r'&&' 0063 t_BANG = r'!' 0064 t_LT = r'<' 0065 t_GT = r'>' 0066 t_LE = r'<=' 0067 t_GE = r'>=' 0068 t_EQ = r'==' 0069 t_NE = r'!=' 0070 0071 # Assignment operators 0072 0073 t_EQUALS = r'=' 0074 t_TIMESEQUAL = r'\*=' 0075 t_DIVEQUAL = r'/=' 0076 t_MODEQUAL = r'%=' 0077 t_PLUSEQUAL = r'\+=' 0078 t_MINUSEQUAL = r'-=' 0079 t_LSHIFTEQUAL = r'<<=' 0080 #t_RSHIFTEQUAL = r'>>=' 0081 t_ANDEQUAL = r'&=' 0082 t_OREQUAL = r'\|=' 0083 t_XOREQUAL = r'^=' 0084 0085 # Increment/decrement 0086 t_PLUSPLUS = r'\+\+' 0087 t_MINUSMINUS = r'--' 0088 0089 # Delimeters 0090 t_LPAREN = r'\(' 0091 t_RPAREN = r'\)' 0092 t_LBRACKET = r'\[' 0093 t_RBRACKET = r'\]' 0094 t_LBRACE = r'\{' 0095 t_RBRACE = r'\}' 0096 t_COMMA = r',' 0097 t_PERIOD = r'\.' 0098 t_SEMI = r';' 0099 t_COLON = r':' 0100 t_COLON2 = r'::' 0101 0102 # Hex Literal 0103 def t_HEXCONST (t): 0104 r'0[x|X][\da-fA-F]+' 0105 t.value = eval (t.value) 0106 return t 0107 0108 # Octal Literal 0109 t_OCTCONST = r'0[0-7]{3}?' 0110 0111 # Floating literal 0112 def t_FCONST (t): 0113 r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?' 0114 t.value = float (t.value) 0115 return t 0116 0117 # Integer literal 0118 def t_ICONST (t): 0119 r'\d+([uU]|[lL]|[uU][lL]|[lL][uU])?' 0120 t.value = int (t.value) 0121 return t 0122 0123 # Array operator 0124 t_ARRAYOP = r'[[].*[]]' 0125 0126 # Function pointer 0127 t_FUNCPTR = r'\(\s*\*' 0128 0129 # String literal 0130 t_SCONST = r'\"([^\\\n]|(\\.))*?\"' 0131 0132 # Character constant 'c' or L'c' 0133 t_CCONST = r'(L)?\'([^\\\n]|(\\.))*?\'' 0134 # Newlines 0135 0136 # def t_CONTINUATION (t): 0137 # r'\\\n' 0138 # t.lexer.lineno += t.value.count("\n") 0139 0140 def t_ANY_NEWLINE(t): 0141 r'\n+' 0142 t.lexer.lineno += t.value.count("\n") 0143 0144 0145 def t_ID(t): 0146 r'[A-Za-z_][\w_]*' 0147 if t.value == 'defined': 0148 t.type = 'defined' 0149 return t 0150 0151 0152 # Comments 0153 def t_ANY_comment(t): 0154 r' /\*(.|\n)*?\*/' 0155 t.lineno += t.value.count('\n') 0156 0157 t_ANY_ignore_cppcomment = '//[^/].*' 0158 0159 0160 def t_ANY_error(t): 0161 print("Illegal character %s" % repr(t.value[0])) 0162 t.lexer.skip(1) 0163 0164 0165 exprLexer = lex.lex () 0166 0167 class ExpressionParser(object): 0168 precedence = (('left','PLUS','MINUS'), ('left','ASTERISK','SLASH'), ('right','UMINUS'), ) 0169 0170 def __init__ (self): 0171 self.lexer = exprLexer 0172 self.test = [] 0173 self.tokens = tokens 0174 yacc.yacc (module = self, tabmodule = "expressionParserTab") 0175 self._parse = yacc.parse 0176 0177 self.values = {} 0178 0179 def parse (self, s, mode = 'calc', values = None): 0180 self.values = values 0181 self.lexer.input (s) 0182 self.mode = mode 0183 self.result = None 0184 self._parse (debug = 0, lexer = self.lexer) 0185 return self.result 0186 0187 def p_expression_result (self, p): 0188 'expression_result : expression' 0189 p [0] = p [1] 0190 self.result = p [0] 0191 0192 def p_expression0 (self, p): 0193 """expression : add_expression 0194 | sub_expression 0195 | mult_expression 0196 | div_expression 0197 | mod_expression 0198 | unary_expression 0199 | or_expression 0200 | and_expression 0201 | xor_expression 0202 | bitor_expression 0203 | bitand_expression 0204 | lt_expression 0205 | le_expression 0206 | eq_expression 0207 | ge_expression 0208 | gt_expression 0209 | lshift_expression 0210 | rshift_expression 0211 | ICONST 0212 | FCONST 0213 | HEXCONST""" 0214 p [0] = p [1] 0215 0216 def p_expression1 (self, p): 0217 'expression : LPAREN expression RPAREN' 0218 p [0] = p [2] 0219 0220 def p_expression2 (self, p): 0221 'expression : ID' 0222 if self.mode == 'calc': 0223 p [0] = self.values [p [1]] 0224 elif self.mode == 'def': 0225 p [0] = p [1] in self.values 0226 0227 def p_unary_expression (self, p): 0228 """unary_expression : sign_expression 0229 | not_expression 0230 | bitnot_expression 0231 | defined_expression""" 0232 p [0] = p [1] 0233 0234 def p_add_expression (self, p): 0235 'add_expression : expression PLUS expression' 0236 p [0] = p [1] + p [3] 0237 0238 def p_sub_expression (self, p): 0239 'sub_expression : expression MINUS expression' 0240 p [0] = p [1] - p [3] 0241 0242 def p_mult_expression (self, p): 0243 'mult_expression : expression ASTERISK expression' 0244 p [0] = p [1] * p [3] 0245 0246 def p_div_expression (self, p): 0247 'div_expression : expression SLASH expression' 0248 p [0] = p [1] / p [3] 0249 0250 def p_mod_expression (self, p): 0251 'mod_expression : expression PERCENT expression' 0252 p [0] = p [1] % p [3] 0253 0254 def p_sign_expression (self, p): 0255 'sign_expression : MINUS expression %prec UMINUS' 0256 p [0] = - p [2] 0257 0258 def p_or_expression (self, p): 0259 'or_expression : expression LOR expression' 0260 p [0] = p [1] or p [3] 0261 0262 def p_and_expression (self, p): 0263 'and_expression : expression LAND expression' 0264 p [0] = p [1] and p [3] 0265 0266 def p_xor_expression (self, p): 0267 'xor_expression : expression CARET expression' 0268 p [0] = p [1] ^ p [3] 0269 0270 def p_bitor_expression (self, p): 0271 'bitor_expression : expression VBAR expression' 0272 p [0] = p [1] | p [3] 0273 0274 def p_bitand_expression (self, p): 0275 'bitand_expression : expression AMPERSAND expression' 0276 p [0] = p [1] & p [3] 0277 0278 def p_lt_expression (self, p): 0279 'lt_expression : expression LT expression' 0280 p [0] = p [1] < p [3] 0281 0282 def p_le_expression (self, p): 0283 'le_expression : expression LE expression' 0284 p [0] = p [1] <= p [3] 0285 0286 def p_eq_expression (self, p): 0287 'eq_expression : expression EQ expression' 0288 p [0] = p [1] == p [3] 0289 0290 def p_ge_expression (self, p): 0291 'ge_expression : expression GE expression' 0292 p [0] = p [1] >= p [3] 0293 0294 def p_gt_expression (self, p): 0295 'gt_expression : expression GT expression' 0296 p [0] = p [1] > p [3] 0297 0298 def p_lshift_expression (self, p): 0299 'lshift_expression : expression GT GT expression' 0300 p [0] = p [1] >> p [4] 0301 0302 def p_rshift_expression (self, p): 0303 'rshift_expression : expression LT LT expression' 0304 p [0] = p [1] << p [4] 0305 0306 def p_not_expression (self, p): 0307 'not_expression : BANG expression' 0308 p [0] = not p [2] 0309 0310 def p_bitnot_expression (self, p): 0311 'bitnot_expression : TILDE expression' 0312 p [0] = ~ p[2] 0313 0314 def p_defined_expression0 (self, p): 0315 'defined_expression : defined ID' 0316 p [0] = p[2] in self.values 0317 0318 def p_defined_expression1 (self, p): 0319 'defined_expression : defined LPAREN ID RPAREN' 0320 p [0] = p[3] in self.values 0321 0322 def p_error(self, p): 0323 print("Syntax error at '%s'" % p.value) 0324 0325 0326 if __name__ == '__main__': 0327 text = '2 +\ 0328 2' 0329 0330 parser = ExpressionParser () 0331 # exprLexer.input (text) 0332 # print parser.parse (text, None) 0333 values = {'x': 2.0, 'macro': None} 0334 while 1: 0335 try: 0336 s = raw_input('calc > ') 0337 except EOFError: 0338 break 0339 if not s: continue 0340 print(parser.parse(s, values))