summaryrefslogtreecommitdiff
path: root/prolog
diff options
context:
space:
mode:
Diffstat (limited to 'prolog')
-rw-r--r--prolog/parser.py68
1 files changed, 25 insertions, 43 deletions
diff --git a/prolog/parser.py b/prolog/parser.py
index ec42b5b..456539f 100644
--- a/prolog/parser.py
+++ b/prolog/parser.py
@@ -3,6 +3,7 @@
import ply.yacc as yacc
from .lexer import operators, tokens
from .util import Token
+from monkey.graph import Node
# PARSER
precedence = (
@@ -20,22 +21,9 @@ precedence = (
('nonassoc', 'LBRACKET', 'RBRACKET', 'LPAREN', 'RPAREN', 'COMMA', 'SEMI', 'PIPE', 'LBRACE', 'RBRACE')
)
-class Node:
- def __init__(self, type, children=None, data=None):
- self.type = type
- self.data = data
- self.children = children if children else []
-
- def __str__(self):
- val = self.type
- if self.children:
- val += ' ' + ' '.join([str(c) for c in self.children])
- val = '({})'.format(val)
- return val
-
def make_token(p, n):
lextoken = p.slice[n]
- return Token(lextoken.type, lextoken.value, lextoken.lexpos)
+ return Node(data=Token(lextoken.type, lextoken.value, lextoken.lexpos))
def p_text_empty(p):
'text : '
@@ -43,7 +31,7 @@ def p_text_empty(p):
def p_text_clause(p):
'text : text clause'
p[0] = p[1]
- p[0].children.append(p[2])
+ p[0].eout.append(p[2])
def p_clause_head(p):
'clause : head PERIOD'
@@ -53,7 +41,7 @@ def p_clause_rule(p):
p[0] = Node('clause', [p[1], make_token(p, 2), p[3], make_token(p, 4)])
def p_clause_error(p):
'clause : error PERIOD'
- p[0] = Node('error')
+ p[0] = Node('clause', [Node('error'), make_token(p, 2)])
def p_head(p):
'head : term'
@@ -64,12 +52,12 @@ def p_or_single(p):
p[0] = p[1]
def p_or_if(p):
'or : or SEMI if'
- if p[1].type == 'or':
+ if p[1].data == 'or':
p[0] = p[1]
else:
p[0] = Node('or', [p[1]])
- p[0].children.append(make_token(p, 2))
- p[0].children.append(p[3])
+ p[0].eout.append(make_token(p, 2))
+ p[0].eout.append(p[3])
def p_if_single(p):
'if : and'
@@ -83,18 +71,18 @@ def p_and_single(p):
p[0] = p[1]
def p_and_term(p):
'and : and COMMA term'
- if p[1].type == 'and':
+ if p[1].data == 'and':
p[0] = p[1]
else:
p[0] = Node('and', [p[1]])
- p[0].children.append(make_token(p, 2))
- p[0].children.append(p[3])
+ p[0].eout.append(make_token(p, 2))
+ p[0].eout.append(p[3])
def p_term_functor(p):
'term : functor LPAREN args RPAREN'
# No whitespace allowed between functor and LPAREN.
t2 = make_token(p, 2)
- if p[1].children[0].pos + len(p[1].children[0].val) < t2.pos:
+ if p[1].eout[0].data.pos + len(p[1].eout[0].data.val) < t2.data.pos:
raise SyntaxError('whitespace before ' + str(t2))
p[0] = Node('term', [p[1], t2, p[3], make_token(p, 4)])
def p_term_or(p):
@@ -152,31 +140,25 @@ def p_args_single(p):
def p_args_term(p):
'args : args COMMA term'
p[0] = p[1]
- p[0].children.append(make_token(p, 2))
- p[0].children.append(p[3])
-
-def p_list_empty(p):
- 'list : LBRACKET RBRACKET'
- p[0] = Node('list', [make_token(p, 1), make_token(p, 2)])
-def p_list_term(p):
- 'list : LBRACKET listexpr RBRACKET'
- p[0] = Node('list', [make_token(p, 1), p[2], make_token(p, 3)])
-def p_listexpr_single(p):
- 'listexpr : term'
- p[0] = Node('listexpr', [p[1]])
-def p_listexpr_term(p):
- 'listexpr : term COMMA listexpr'
- p[0] = Node('listexpr', [p[1], make_token(p, 2), p[3]])
-def p_listexpr_pipe(p):
- 'listexpr : term PIPE term'
- p[0] = Node('listexpr', [p[1], make_token(p, 2), p[3]])
+ p[0].eout.append(make_token(p, 2))
+ p[0].eout.append(p[3])
+
+def p_list(p):
+ 'list : LBRACKET args RBRACKET'
+ p[0] = Node('list', [make_token(p, 1)] + p[2].eout + [make_token(p, 3)])
+def p_list_tail(p):
+ 'list : LBRACKET args PIPE term RBRACKET'
+ p[0] = Node('list', [make_token(p, 1)] + p[2].eout + [make_token(p, 3), p[4], make_token(p, 5)])
def p_functor(p):
'functor : NAME'
p[0] = Node('functor', [make_token(p, 1)])
-def p_error(p):
- print('Syntax error in input: ' + str(p))
+def p_error(t):
+ if t is None:
+ print('unexpected end of file')
+ else:
+ print('{}: unexpected {}'.format(t.lexpos, t.value))
parser = yacc.yacc()