 # Normal form of the inequality is x + y + c < 0
-class Inequality
+class Inequation
   constructor: (@x, @y, @c) ->
 
   toString: -> "#{@x}x + #{@y}y + #{@c} < 0"
+
+# A non-normalised inequality is made up of multiple terms
+class Term
+  constructor: (@coefficient, @variable) ->
+
+  toString: ->
+    c = "#{@coefficient}"
+    if @variable == 'c'
+      c
+    else
+      "#{c}#{@variable}"
+
+class Inequality
+  constructor: (@sign) ->
+
+  toString: -> @sign
 
 # Tokens have type and value
 class Token

lexers = [
  # Operators follow coefficients and variables. This is highest priority
  # so that x-5y is parsed as [x, -, 5, y], not [x, -5, y].
  new Lexer ["COEFFICIENT", "VARIABLE"], /^[<>+-]/, "OPERATOR"

  # Coefficients can only appear at the start of the expression or after an
  # operator. The value is either a number or "-", which means -1.
  new Lexer [undefined, "OPERATOR"], /^(-?[0-9]+(\.[0-9]+)?)|(-)/, "COEFFICIENT"

  # Variables follow everything except other variables. Only x and y are
  # allowed, since this is a two-variable inequality.
  new Lexer [undefined, "COEFFICIENT", "OPERATOR"], /^[xyXY]/, "VARIABLE"
]

# Given a string and a RegExp.exec result, return the unmatched remainder


  throw "Parse error at '#{input}' (tokens: #{tokens}, last token: #{previous})"

normalise_minus_coefficients = (tokens) ->
  tokens.map (t) ->
    if t.type == "COEFFICIENT" and t.value == "-"
      new Token "COEFFICIENT", "-1"
    else
      t

# Replace all subtract operators with adds, normalising the coefficeints
normalise_coefficients = (tokens, normalised=[]) ->
  if tokens.length == 0
    return normalised

  if tokens[0].type == "OPERATOR" and tokens[0].value == "-"
    if tokens.length == 1
      throw "Unexpected end of expression at operator: #{tokens}"
    operator = new Token "OPERATOR", "+"
    value = parseFloat(tokens[1].value) * -1
    coefficient = new Token "COEFFICIENT", "#{value}"
    return normalise_coefficients tokens.slice(2), normalised.concat(operator, coefficient)

  return normalise_coefficients tokens.slice(1), normalised.concat(tokens[0])

# Parse the lexed tokens into a set of terms
parse = (tokens, terms=[]) ->
  if tokens.length == 0
    return terms

  switch tokens[0].type
    when "VARIABLE"
      term = new Term 1, tokens[0].value
      return parse tokens.slice(1), terms.concat(term)
    when "INEQUALITY"
      term = new Inequality tokens[0].value
      return parse tokens.slice(1), terms.concat(term)
    when "COEFFICIENT"
      if tokens.length > 1 && tokens[1].type == "VARIABLE"
        term = new Term tokens[0].value, tokens[1].value
        return parse tokens.slice(2), terms.concat(term)
      else
        term = new Term tokens[0].value, "c"
        return parse tokens.slice(1), terms.concat(term)
    when "OPERATOR"
      return parse tokens.slice(1), terms
    else
      throw "Unexpected token found: #{tokens[0]}"

# These inputs should all be parseable. Not a maximally reduced set,
# but I think this covers everything
good = ["2x + 0.5y < 350", "-3x+2y-50<0","-x-3y-1>0", "2<x+y", "2x+-5y+5-x+6>0"]

console.log "Good inputs:\n"
for i in good
