shithub: pprolog

Download patch

ref: 50768fba487e1ec08278cdc4be614863db32a5c4
parent: 64a411ede2df42eea0e6905a4985a3e54057c677
author: Peter Mikkelsen <peter@pmikkelsen.com>
date: Tue Jun 29 14:21:31 EDT 2021

Make parse return a list of clauses. Also pretty print the entire list of clauses.

--- a/example.pl
+++ b/example.pl
@@ -16,6 +16,7 @@
 could_be_friends(Person1, Person2) :-
 	likes(Person1, Thing1),
 	likes(Person2, Thing2),
+	!,
 	Thing1 = Thing2.
 
 list1(A) :- A = [1,2,3,4].
--- a/fns.h
+++ b/fns.h
@@ -1,5 +1,5 @@
 /* parser.c */
-void parse(int);
+Term *parse(int);
 
 /* prettyprint.c */
 Rune *prettyprint(Term *);
--- a/main.c
+++ b/main.c
@@ -29,7 +29,10 @@
 		int fd = open(parsetestfile, OREAD);
 		if(fd < 0)
 			exits("open");
-		parse(fd);
+		Term *prog = parse(fd);
+		Term *clause;
+		for(clause = prog; clause != nil; clause = clause->next)
+			print("%S.\n", prettyprint(clause));
 	}
 
 	exits(nil);
--- a/parser.c
+++ b/parser.c
@@ -7,9 +7,6 @@
 
 #define PrecedenceLevels 1200
 
-/* The parser doesn't produce an ast for now, it only acts like a recognizer,
-   printing errors if it fails */
-
 typedef struct Token Token;
 typedef struct Operator Operator;
 typedef struct OpInfo OpInfo;
@@ -79,50 +76,48 @@
 Term *parseoperators(Term *);
 void match(int);
 void syntaxerror(char *);
-void prologtext(void);
+Term *prologtext(void);
 
-void
+Term *
 parse(int fd)
 {
 	parsein = Bfdopen(fd, OREAD);
 	if(parsein == nil){
 		print("Could not open file\n");
-		return;
+		return nil;
 	}
 	initoperators();
 	nexttoken();
 
-	prologtext();
+	return prologtext();
 }
 
-void
+Term *
 prologtext(void)
 {
 	if(lookahead.tag == EofTok)
-		return;
+		return nil;
 
 	Term *t = fullterm(AtomTok, L".", nil);
+	if(lookahead.tag == AtomTok && runestrcmp(lookahead.text, L".") == 0)
+		match(AtomTok);
+	else
+		syntaxerror("prologtext");
 
 	if(t->tag == CompoundTerm && runestrcmp(t->text, L":-") == 0 && t->arity == 1){
 		/* A Directive */
 		print("Got directive: %S\n", prettyprint(t));
+		t = prologtext();
 	}else if(t->tag == CompoundTerm && runestrcmp(t->text, L":-") == 0 && t->arity == 2){
-		/* A clause with a body */
-		print("Got clause with body: %S\n", prettyprint(t));
+		t->next = prologtext();
 	}else if(t->tag == AtomTerm || t->tag == CompoundTerm){
-		/* A clause without a body */
-		print("Got clause without body: %S\n", prettyprint(t));
+		t->next = prologtext();
 	}else{
 		print("Expected directive or clause as toplevel\n");
 		syntaxerror("prologtext");
 	}
 
-	if(lookahead.tag == AtomTok && runestrcmp(lookahead.text, L".") == 0)
-		match(AtomTok);
-	else
-		syntaxerror("prologtext");
-
-	prologtext();
+	return t;
 }
 
 Term *
@@ -567,7 +562,7 @@
 	}
 
 	/* Other */
-	if(runestrchr(L",.()]}|", peek)){
+	if(runestrchr(L",.()]}|!", peek)){
 		switch(peek){
 		case L',': lookahead.tag = CommaTok; break;
 		case L'(': lookahead.tag = ParenLeftTok; break;
@@ -575,6 +570,7 @@
 		case L']': lookahead.tag = SquareBracketRightTok; break;
 		case L'}': lookahead.tag = CurlyBracketRightTok; break;
 		case L'|': lookahead.tag = PipeTok; break;
+		case L'!': lookahead.tag = AtomTok; lookahead.text = runestrdup(L"!"); break;
 		}
 		return;
 	}