-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpml.py
executable file
·134 lines (110 loc) · 4.14 KB
/
pml.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
PML Parser
Jared Patrick <[email protected]> -- 2014.06.18
"""
# stdlib
import os
import re
import code
class PMLParser(object):
"""Utility to parse pml script files"""
def __init__(self, pml_file='index.pml'):
self.pml_file = pml_file
self.in_pml = False
self.stream = ''
self.code = ''
self._exec = []
self.indent = False
self.indent_buffer = 0
def main(self):
"""Run the script"""
self.user = raw_input("What is your name?: ")
os.system('clear')
self.read()
# return the stream for rendering
return self.stream
def read(self):
"""Read the pml file and detect pml tags to pass to parser"""
with open(self.pml_file, 'r') as pml_file:
for line in pml_file.readlines():
if self.in_pml:
if re.match(r'.*</pml>.*', line): # reached end of tag
self.exit()
continue
# in pml logic if </pml> closing tag has not been reached
self._exec.append(line.strip())
continue
# _execute only if out of pml
check_tag = re.match(r'.*<pml>(.*)', line)
if check_tag:
# single line logic
try:
# regex match checks for text immediately after the
# opening <pml> tag
line = check_tag.groups()[0]
# if closing tag is on the same line, strip the closing
# tag and append the line to the _exec
if re.match(r'.*</pml>.*', line):
self._exec.append(re.sub('</pml>',
'',
line.strip()))
self.exit()
continue
elif len(line) > 0:
# closing tag not yet encountered. append normally
self._exec.append(line.strip())
except IndexError:
pass
# not on a single line, but in pml tag
self.in_pml = True
else:
# no pml encountered, write html to stream
self.stream += line.strip() + '\n'
def exit(self):
"""Exit the pml code block"""
# break loop if closing pml is matched
self.in_pml = False
self.parse()
self._exec = []
def parse(self):
"""Parse the code in the pml block"""
for snippet in self._exec:
# empty string indicates a newline
if snippet == '':
self.indent = False
self.indent_buffer = 0
# indent text after :(semi-colon)
elif self.indent == True:
self.code += ('\t' * self.indent_buffer) + snippet
# check for :(semi-colon) inside indented block to increment
# the indent buffer
if re.match(r'.*:$', snippet):
self.indent_buffer += 1
# if indent is false, check that current does not end with :
# (semi-colon)
elif re.match(r'.*:$', snippet):
self.code += snippet
self.indent = True
self.indent_buffer += 1
# concatenate standard line
else:
self.code += snippet
# add newline per iteration
self.code += '\n'
self.execute()
def execute(self):
"""Execute the code block"""
env = {'USER': self.user}
source = code.compile_command(self.code, '<stdio>', 'exec')
exec(source, env)
try:
self.stream += env['pml'] + '\n'
except NameError:
pass
# pml set to '' to "flush the pml buffer"
pml = ''
if __name__ == '__main__':
PARSER = PMLParser('index.pml')
print PARSER.main()