public BinaryTree Term(int n)
{
int m = 0;
BinaryTree ast = null;
_scanner.Next();
switch (_scanner.Current.Kind)
{
case PrologToken.LPAREN:
ast = Term(1200);
_scanner.Next();
if (_scanner.Current.Kind != PrologToken.RPAREN)
{
_errors.Add(new PrologCompilerError("P0003", "Expected ) after term", "", false, _scanner.Current.Line, _scanner.Current.Column));
}
break;
// Handle list terms here...
case PrologToken.LBRACKET:
ArrayList listArguments = new ArrayList();
// Peek after [ token
if (_scanner.Lookahead.Kind == PrologToken.RBRACKET)
{
_scanner.Next();
// return a nil atom: []
ast = new BinaryList(); // empty list
break;
}
listArguments.Add(Term(999));
_scanner.Next();
// if , is encountered
while (_scanner.Current.Kind == PrologToken.COMMA)
{
listArguments.Add(Term(999));
_scanner.Next();
}
if (_scanner.Current.Kind == PrologToken.LIST_SEP)
{
listArguments.Add(Term(999));
_scanner.Next();
}
else
{
listArguments.Add(new BinaryList());
}
if (_scanner.Current.Kind != PrologToken.RBRACKET)
{
_errors.Add(new PrologCompilerError("P0004", "Unterminated list, expected ]", "", false, _scanner.Current.Line, _scanner.Current.Column));
}
int i = listArguments.Count - 1;
BinaryList list = new BinaryList((BinaryTree)listArguments[i - 1], (BinaryTree)listArguments[i]);
i -= 2;
while (i > -1)
{
list = new BinaryList((BinaryTree)listArguments[i--], list);
}
ast = list;
break;
case PrologToken.RPAREN:
case PrologToken.RBRACKET:
case PrologToken.COMMA:
case PrologToken.DOT:
_errors.Add(new PrologCompilerError("P0005", "Unexpected closure of term", "", false, _scanner.Current.Line, _scanner.Current.Column));
return null;
case PrologToken.ATOM:
case PrologToken.VARIABLE:
string atomName = _scanner.Current.StringValue;
if (_scanner.Lookahead.Kind == PrologToken.LPAREN)
{
ArrayList arguments = new ArrayList();
_scanner.Next();
arguments.Add(Term(1200));
_scanner.Next();
while (_scanner.Current.Kind == PrologToken.COMMA)
{
arguments.Add(Term(1200));
_scanner.Next();
}
if (_scanner.Current.Kind != PrologToken.RPAREN)
{
_errors.Add(new PrologCompilerError("P0005", "Unexpected closure of term", "", false, _scanner.Current.Line, _scanner.Current.Column));
return null;
}
ast = new BinaryTree(atomName, arguments);
break;
}
if (_operators.IsOperator(_scanner.Current.StringValue))
{
PrologOperator op = _operators.GetOperator(_scanner.Current.StringValue);
if (op.IsPrefix)
{
// prefix operator
if (n < op.PrefixPrecedence)
{
ParserError("prefix precedence error", _scanner.Current.Line, _scanner.Current.Column);
return null;
}
switch (_scanner.Lookahead.Kind)
{
case PrologToken.LPAREN:
case PrologToken.LBRACKET:
ast = new BinaryTree(op.Name, Term(op.PrefixRightPrecedence));
m = op.PrefixPrecedence;
Right(n, m, ref ast);
break;
case PrologToken.RPAREN:
case PrologToken.RBRACKET:
case PrologToken.DOT:
case PrologToken.LIST_SEP:
if (n < m)
{
_errors.Add(new PrologCompilerError("P0006", "Unexpected atom '" + _scanner.Lookahead.StringValue + "'", "", false, _scanner.Current.Line, _scanner.Current.Column));
return null;
}
ast = new BinaryTree(_scanner.Current.StringValue);
Right(n, m, ref ast);
break;
case PrologToken.ATOM:
if (_operators.IsOperator(_scanner.Lookahead.StringValue))
{
PrologOperator atomOp = _operators.GetOperator(_scanner.Lookahead.StringValue);
if (atomOp.IsInfix && m <= atomOp.InfixLeftPrecedence)
{
if (n < m)
{
ParserError("n < m", _scanner.Lookahead.Line, _scanner.Current.Column);
return null;
}
ast = new BinaryTree(_scanner.Lookahead.StringValue);
Right(n, m, ref ast);
break;
}
else if (atomOp.IsPostfix && m <= atomOp.PostfixLeftPrecedence)
{
if (n < m)
{
ParserError("n < m", _scanner.Current.Line, _scanner.Current.Column);
return null;
}
ast = new BinaryTree(_scanner.Current.StringValue);
Right(n, m, ref ast);
break;
}
// Just added on 6/23/2006. Might not fix anything.
else
{
ast = new BinaryTree(_scanner.Current.StringValue, null, Term(op.InfixRightPrecedence));
m = op.PrefixPrecedence;
Right(n, m, ref ast);
break;
}
}
else
{
ast = new BinaryTree(_scanner.Current.StringValue, null, Term(op.InfixRightPrecedence));
m = op.PrefixPrecedence;
Right(n, m, ref ast);
}
break;
default:
ParserError("Unknown internal error", _scanner.Current.Line, _scanner.Current.Column);
return null;
}
}
}
else
{
ast = new BinaryTree(_scanner.Current.StringValue);
}
break;
default:
ParserError("Unknown internal error", _scanner.Current.Line, _scanner.Current.Column);
return null;
}
Right(n, m, ref ast);
return ast;
}