class Conditional extends Statement:
  # Expression test; Statement then_branch, else_branch
  # else_branch == null means "if... then"
  test
  then_branch
  else_branch
  function Conditional(t, tb, eb = None)
    this.test = t
    this.then_branch = tb
    if eb is None:
      this.else_branch = new Skip()
    else:
      this.else_branch = eb
  function to_string():
    # Гишүүдээр нь тайлбарласан хэвлэх функц
class Operator:
  val
  function Operator(s):
    this.val = s
class Binary extends Expression:
  function Binary(o, left, right):
    this.op = o
    this.term1 = left
    this.term2 = right
  function to_string():
    # Гишүүдээ хүнд ойлгомжтойгоор хэвлэх
class Unary extends Expression:
  function Unary(o, e):
    this.op = o
    this.term = e
  function to_string():
    ...
class BoolValue extends Value:
  boolean value
  function BoolValue (v = None):
    if v is None:
      this.value = False
    else:
      this.value = v
      this.undef = False
class CharValue extends Value:
  char value = ' '
  ...
class FloatValue extends Value:
  float value = 0.0
  ...
class Parser
  ...
  function statement():
    ...
    else if this.current_token is If:
      s = this.if_statement()
    ...
  function if_statement():
    this.current_token = this.lexer.next_token()
    this.match(Left_Paren)
    t = this.expression()
    this.match(Right_Paren)
    s = this.statement()
    if this.current_token is Else:
      this.current_token = this.lexer.next_token()
      return Conditional(t, s, this.statement())
    return Conditional(t, s)
  function expression():
    e = this.conjunction()
    while this.current_token is Or:
      op = Operator(this.current_token.value)
      term1 = e
      this.current_token = this.lexer.next_token()
      term2 = this.conjunction()
      e = Binary(op, term1, term2)
    return e
  function conjunction():
    e = this.equality()
    while this.current_token is And:
      op = Operator(this.current_token.value)
      this.current_token = this.lexer.next_token()
      term2 = this.equality()
      binary = Binary(op, e, term2)
      e = binary
    return e
  function equality():
    e = this.relation()
    while this.current_token is Equals|Not_Equals:
      op = Operator(this.current_token.value)
      this.current_token = this.lexer.next_token()
      term2 = this.relation()
      e = Binary(op, e, term2)
    return e
  function relation()
    e = this.addition()
    while this.current_token is Less|Less_Equal|Greater|Greater_Equal:
      op = Operator(this.current_token.value)
      this.current_token = this.lexer.next_token()
      term2 = this.addition()
      e = Binary(op, e, term2)
    return e
  
  function addition():
    e = this.term()
    while this.current_token is Plus|Minus:
      op = Operator(this.current_token.type)
      term2 = this.term()
      e = Binary(op, e, term2)
    return e
  function term():
    e = this.factor()
    while this.current_token is Multiply|Divide:
      op = Operator(this.current_token.value)
      term2 = this.factor()
      e = Binary(op, e, term2)
    return e
  function factor():
    if this.current_token is Not|Minus:
      op = Operator(this.current_token.value)
      term = this.primary()
      return Unary(op, term)
    else:
      return this.primary()
  function primary():
    e = None
    if this.current_token is Identifier:
      e = Variable(this.current_token.value)
    else if this.current_token is IntLiteral|BoolLiteral|FloatLiteral| CharLiteral:
      e = this.literal()
    else if this.current_token is Left_Paren:
      this.current_token = this.lexer.next_token()
      e = this.expression()
      this.match(Right_Paren)
    else if this.current_token is Int|Char|Float|Bool:
      op = Operator(this.current_token.value)
      this.match(Left_Paren)
      term = this.expression()
      this.match(Right_Paren)
      e = Unary(op, term)
    else:
      print "Sum Ting Wong"
      sys.exit()
    return e
  function literal():
    if this.current_token.type is Int:
      s = this.match(TokenType.INT_LITERAL)
      return IntValue(int(s))
    else if this.current_token.type is Char:
      s = this.match(TokenType.CHAR_LITERAL)
      return CharValues(s[0])
    else if this.current_token.type is True:
      s = this.match(TokenType.TRUE)
      return BoolValue(true)
    else if this.current_token.type is False:
      s = this.match(TokenType.FALSE)
      return BoolValue(false)
    else if this.current_token is Float:
      s = this.match(TokenType.FLOAT_LITERAL)
      return FloatValue(float(s))
    throw "Энд хүрэх ёсгүй байсан"