forked from bmajoros/python
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathEssexParser.py
executable file
·86 lines (76 loc) · 2.85 KB
/
EssexParser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#=========================================================================
# This is OPEN SOURCE SOFTWARE governed by the Gnu General Public
# License (GPL) version 3, as described at www.opensource.org.
# Copyright (C)2016 William H. Majoros ([email protected]).
#=========================================================================
import os
from .EssexNode import EssexNode
from .EssexScanner import EssexScanner
######################################################################
#
# A parser for the Essex language, which is a simple alternative to XML
# and looks like LISP programs ("S-Expressions" -- hence the name "Essex").
# It generates tree data structures built out of EssexNode objects.
#
# Attributes:
# file : file handle
# isOpen : boolean
# scanner : EssexScanner
# Methods:
# parser=EssexParser(filename) # filename is optional
# parser.open(filename) # unnecessary if you gave filename to ctor
# parser.close()
# tree=parser.nextElem() # returns root of the tree
# forest=parser.parseAll() # returns an array of trees
# Class methods:
# forest=EssexParser.loadFile(filename) # returns array of trees
######################################################################
class EssexParser:
def __init__(self,filename=None):
self.isOpen=False
if(filename): self.open(filename)
def open(self,filename):
if(self.isOpen): self.close()
if(not os.path.exists(filename)):
raise Exception(filename+" does not exist")
file=self.file=open(filename,"r")
self.isOpen=True
self.scanner=EssexScanner(file)
def close(self):
if(self.isOpen):
self.file.close()
self.isOpen=False
self.scanner=None
def parseAll(self):
forest=[]
while(True):
tree=self.nextElem()
if(not tree): break
forest.append(tree)
return forest
@classmethod
def loadFile(cls,filename):
parser=EssexParser(filename)
return parser.parseAll()
def nextElem(self):
if(not self.isOpen): raise Exception("file is not open")
scanner=self.scanner
token=scanner.nextToken()
if(not token): return None
if(token.isOpenParen()): return self.parseTuple()
elif(token.isLiteral()): return token.getLexeme()
else:
lexeme=token.getLexeme()
exit("Syntax error near \n"+token+"\n")
def parseTuple(self):
"""PRECONDITION: a "(" has already been matched"""
elements=[]
scanner=self.scanner
while(True):
token=scanner.nextToken()
if(not token): break
if(token.isOpenParen()):
elements.append(self.parseTuple())
elif(token.isCloseParen()): break
else: elements.append(token.getLexeme())
return EssexNode(elements)