# -*- Mode: Python; tab-width: 4 -*-

import kjParseBuild
import string

grammar = """
	exp ::
	@R r_exp_1			:: exp >> int
	@R r_exp_2			:: exp >> varref
	@R r_exp_3			:: exp >> operator operands
	@R r_exp_4			:: exp >> if exp then exp else exp
	@R r_operator_1		:: operator >> varref
	@R r_operator_2		:: operator >> ( exp )
	@R r_operands_1		:: operands >> ( )
	@R r_operands_2		:: operands >> ( operand_list )
	@R r_operand_list_1	:: operand_list >> operand
	@R r_operand_list_2	:: operand_list >> operand_list , operand
	@R r_operand		:: operand >> exp
	@R r_varref			:: varref >> var
"""

int_regex = "\(-\)?[0-9]+"
var_regex = "[A-Za-z_+*-][A-Za-z0-9+*-]*"

def int_interp (str):
	return string.atoi (str)

def identity (str):
	return str

def build_grammar():
	g = kjParseBuild.NullCGrammar()
	g.Addterm ("int", int_regex, int_interp)
	g.Addterm ("var", var_regex, identity)
	g.Keywords ("if then else")
	g.punct ("(),")
	g.Nonterms ("exp operator operands operand_list operand varref")
	g.Declarerules (grammar)
	g.Compile()
	return g

def bind_rules (g):

	def r_exp_1 (list, context):
		return ['lit', list[0]]

	def r_exp_2 (list, context):
		return list[0]

	def r_exp_3 (list, context):
		return ['app', list[0], list[1]]

	def r_exp_4 (list, context):
		return ['conditional', list[1], list[3], list[5]]

	def r_operator_1 (list, context):
		return list[0]

	def r_operator_2 (list, context):
		return list[1]

	def r_operands_1 (list, context):
		return []
	
	def r_operands_2 (list, context):
		return list[1]

	def r_operand_list_1 (list, context):
		return [list[0]]

	def r_operand_list_2 (list, context):
		return list[0] + [list[2]]
						  
	def r_operand (list, context):
		return list[0]

	def r_varref (list, context):
		return ['varref', list[0]]

	for n,f in (
		("r_exp_1",				r_exp_1),
		("r_exp_2",				r_exp_2),
		("r_exp_3",				r_exp_3),
		("r_exp_4",				r_exp_4),
		("r_operator_1",		r_operator_1),
		("r_operator_2",		r_operator_2),
		("r_operands_1",		r_operands_1),
		("r_operands_2",		r_operands_2),
		("r_operand_list_1",	r_operand_list_1),
		("r_operand_list_2",	r_operand_list_2),
		("r_operand",			r_operand),
		("r_varref",			r_varref),
		):
		g.Bind (n,f)

def make_grammar():
	print 'building parser...'
	g = build_grammar()
	bind_rules (g)
	print 'done.'
	return g
