shithub: pprolog

ref: 329c6975c44fcbe1cf7c9d93ab6164495f432213
dir: /prettyprint.c/

View raw version
#include <u.h>
#include <libc.h>

#include "dat.h"
#include "fns.h"

Rune *prettyprintlist(Term *, Rune *, int);
Rune *printlist(Term *);
int islist(Term *);

Rune *
prettyprint(Term *t)
{
	Rune *result;
	Rune *args;

	switch(t->tag){
	case CompoundTerm:
		args = printlist(t);
		if(args == nil){
			args = prettyprintlist(t->children, L", ", 0);
			result = runesmprint("%S(%S)", t->text, args);
			free(args);
		}else
			result = runesmprint("[%S]", args);
		break;
	case AtomTerm:
		result = runesmprint("%S", t->text);
		break;
	case VariableTerm:
		result = runesmprint("%S(%ulld)", t->text, t->clausenr);
		break;
	case NumberTerm:
		if(t->numbertype == NumberInt)
			result = runesmprint("%lld", t->ival);
		else
			result = runesmprint("%f", t->dval);
		break;
	case StringTerm:
		result = runesmprint("\"%S\"", t->text);
		break;
	default:
		result = runesmprint("cant print term with tag %d", t->tag);
		break;
	}

	return result;
}

Rune *
prettyprintlist(Term *t, Rune *sep, int end)
{
	if(t == nil){
		if(end)
			return runesmprint("%S", sep);
		else
			return runesmprint("");
	}

	Rune *str = prettyprint(t);
	Rune *rest = prettyprintlist(t->next, sep, end);
	Rune *result;

	if(t->next != nil)
		result = runesmprint("%S%S%S", str, sep, rest);
	else
		result = runesmprint("%S%S", str, end ? rest : L"");

	free(str);
	free(rest);
	return result;
}

/* printlist prints a list's elements but not the surrounding [ and ] */
Rune *
printlist(Term *list)
{
	if(list->tag != CompoundTerm || list->arity != 2 || runestrcmp(L".", list->text) != 0)
		return nil;

	Term *head = list->children;
	Term *tail = head->next;

	Rune *headstr = prettyprint(head);
	Rune *tailstr = nil;
	Rune *result;

	if(tail->tag == CompoundTerm && tail->arity == 2 && runestrcmp(L".", tail->text) == 0){
		tailstr = printlist(tail);
		result = runesmprint("%S, %S", headstr, tailstr);
	}else if(tail->tag == AtomTerm && runestrcmp(L"[]", tail->text) == 0){
		result = runesmprint("%S", headstr);
	}else{
		tailstr = prettyprint(tail);
		result = runesmprint("%S | %S", headstr, tailstr);
	}
	free(headstr);
	free(tailstr);
	return result;
}