def p_UnaryExpr(p): """UnaryExpr : PrimaryExpr | unary_op UnaryExpr """ if len(p) == 2: # PrimaryExpr p[0] = p[1] else: # unary_op used if isinstance(p[2], GoBasicLit): # Direct calculation error = False try: if p[2].dtype.name in ("string", "rune"): # Error error = True elif p[1][0] == "+": pass elif p[1][0] == "-": p[2].item = -1 * p[2].item elif p[1][0] == "!": p[2].item = not p[2].item elif p[1][0] == "^": if p[2].dtype.name == "int": p[2].item = ~p[2].item else: error = True elif p[1][0] == "*": error = True elif p[1][0] == "++": # p[2].item += 1 error = True elif p[1][0] == "--": # p[2].item -= 1 error = True else: error = True except Exception: error = True if error: position = go_traceback(p.slice[1].value) print( 'SyntaxError: Unary operator "{}" not applicable for ' 'argument of type "{}" at position {}'.format( p[1][0], p[2].dtype.name.lower(), position ) ) exit(1) else: p[0] = p[2] else: # 1st arg. is expression, 2nd arg. is unary_op if p[1][0] in ["++", "--"]: position = go_traceback(p.slice[1].value) # XXX TODO : lineno. and position in error message print( 'SyntaxError: Unary operator "{}" not applicable ' "at position {}".format(p[1][0], position) ) exit(1) p[0] = GoUnaryExpr(p[2], p[1][0]) p[0].lineno = adjust_lineno(p[1][1])
def p_InterfaceType(p): """InterfaceType : INTERFACE LCURLBR MethodSpecList RCURLBR """ try: p[0] = GoInterfaceType(p[3]) except ValueError as msg: position = go_traceback(p.slice[1]) print("{} at position {}".format(msg, position)) exit(1)
def p_StructType(p): """StructType : STRUCT LCURLBR FieldDeclList RCURLBR """ try: p[0] = GoStruct(p[3]) p[0].lineno = adjust_lineno(p.slice[1].lineno) except ValueError as msg: position = go_traceback(p.slice[1]) print("{} at position {}".format(msg, position)) exit(1)
def p_Expression(p): """Expression : UnaryExpr | Expression LOGOR Expression | Expression LOGAND Expression | Expression EQUALS Expression | Expression NOTEQ Expression | Expression LESS Expression | Expression LESSEQ Expression | Expression GREAT Expression | Expression GREATEQ Expression | Expression PLUS Expression | Expression MINUS Expression | Expression BITOR Expression | Expression BITXOR Expression | Expression MULT Expression | Expression DIV Expression | Expression MODULO Expression | Expression LSHIFT Expression | Expression RSHIFT Expression | Expression BITAND Expression | Expression BITCLR Expression """ if len(p) == 2: # UnaryExpr given p[0] = p[1] else: if isinstance(p[1], GoBasicLit) and isinstance(p[3], GoBasicLit): # Direct calculation error = False try: p[0] = GoBasicLit(p[1].item, None) p[0].lineno = adjust_lineno(p.slice[2].lineno) if p[2] == "||": if p[1].dtype.name != "bool" or p[3].dtype.name != "bool": error = True else: p[0].item = p[1].item or p[3].item elif p[2] == "&&": if p[1].dtype.name != "bool" or p[3].dtype.name != "bool": error = True else: p[0].item = p[1].item and p[3].item elif p[2] == "==": p[0].item = p[1].item == p[3].item elif p[2] == "!=": p[0].item = p[1].item != p[3].item elif p[2] == "<": p[0].item = p[1].item < p[3].item elif p[2] == "<=": p[0].item = p[1].item <= p[3].item elif p[2] == ">": p[0].item = p[1].item > p[3].item elif p[2] == ">=": p[0].item = p[1].item >= p[3].item elif p[2] == "+": p[0].item += p[3].item elif p[2] == "-": p[0].item -= p[3].item elif p[2] == "|": if p[1].dtype.name != "int" or p[3].dtype.name != "int": error = True else: p[0].item |= p[3].item elif p[2] == "^": if p[1].dtype.name != "int" or p[3].dtype.name != "int": error = True else: p[0].item ^= p[3].item elif p[2] == "*": p[0].item *= p[3].item elif p[2] == "/": if p[1].dtype.name == "int" and p[3].dtype.name == "int": p[0].item //= p[3].item else: p[0].item /= p[3].item elif p[2] == "%": if p[1].dtype.name != "int" or p[3].dtype.name != "int": error = True else: p[0].item %= p[3].item elif p[2] == "<<": if p[1].dtype.name != "int" or p[3].dtype.name != "int": error = True else: p[0].item <<= p[3].item elif p[2] == ">>": if p[1].dtype.name != "int" or p[3].dtype.name != "int": error = True else: p[0].item >>= p[3].item elif p[2] == "&": if p[1].dtype.name != "int" or p[3].dtype.name != "int": error = True else: p[0].item &= p[3].item elif p[2] == "&^": if p[1].dtype.name != "int" or p[3].dtype.name != "int": error = True else: p[0].item &= ~p[3].item else: error = True precedence = ["complex", "float", "int"] if p[2] in [">", "<", "==", "!=", ">=", "<="]: p[0].dtype = GoType( "bool", p[1].dtype.basic_lit & p[3].dtype.basic_lit ) elif p[1].dtype == p[3].dtype or precedence.index( p[1].dtype.name ) < precedence.index(p[3].dtype.name): p[0].dtype = p[1].dtype else: p[0].dtype = p[3].dtype except Exception: error = True if error: go_traceback("") print( 'SyntaxError: Binary operator "{}" not applicable for ' 'arguments of types "{}" and "{}"'.format( p[2], p[1].dtype.name, p[3].dtype.name ) ) exit(1) else: # 1st arg. is LHS, 2nd is RHS, 3rd is the operator p[0] = GoExpression(p[1], p[3], p[2]) p[0].lineno = adjust_lineno(p.slice[2].lineno)