pyemaps 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. pyemaps/COPYING +798 -0
  2. pyemaps/CifFile/CifFile_module.py +3117 -0
  3. pyemaps/CifFile/StarFile.py +2496 -0
  4. pyemaps/CifFile/TypeContentsParser.py +82 -0
  5. pyemaps/CifFile/YappsStarParser_1_0.py +289 -0
  6. pyemaps/CifFile/YappsStarParser_1_1.py +288 -0
  7. pyemaps/CifFile/YappsStarParser_2_0.py +369 -0
  8. pyemaps/CifFile/YappsStarParser_STAR2.py +382 -0
  9. pyemaps/CifFile/__init__.py +7 -0
  10. pyemaps/CifFile/drel/__init__.py +1 -0
  11. pyemaps/CifFile/drel/drel_ast_yacc.py +582 -0
  12. pyemaps/CifFile/drel/drel_lex.py +228 -0
  13. pyemaps/CifFile/drel/drel_runtime.py +126 -0
  14. pyemaps/CifFile/drel/parsetab.py +185 -0
  15. pyemaps/CifFile/drel/py_from_ast.py +628 -0
  16. pyemaps/CifFile/parsetab.py +185 -0
  17. pyemaps/CifFile/yapps3_compiled_rt.py +390 -0
  18. pyemaps/README.md +201 -0
  19. pyemaps/__config__.py +91 -0
  20. pyemaps/__init__.py +233 -0
  21. pyemaps/__main__.py +219 -0
  22. pyemaps/__version__.py +1 -0
  23. pyemaps/cdata/Aluminium.xtl +4 -0
  24. pyemaps/cdata/AluminiumOxide.xtl +5 -0
  25. pyemaps/cdata/Aluminium_FCC.xtl +4 -0
  26. pyemaps/cdata/BariumTitanate_180k.xtl +6 -0
  27. pyemaps/cdata/BariumTitanate_270k.xtl +7 -0
  28. pyemaps/cdata/BariumTitanate_Tetra.xtl +7 -0
  29. pyemaps/cdata/BiMnO3.xtl +27 -0
  30. pyemaps/cdata/Boron_Tetra.xtl +8 -0
  31. pyemaps/cdata/CadmiumSelenide_Hex.xtl +5 -0
  32. pyemaps/cdata/CadmiumSulfide_Cubic.xtl +5 -0
  33. pyemaps/cdata/CadmiumSulfide_Hex.xtl +5 -0
  34. pyemaps/cdata/Chromium_BCC.xtl +4 -0
  35. pyemaps/cdata/CoSb3_Skutterudite.xtl +5 -0
  36. pyemaps/cdata/CopperOxide.xtl +5 -0
  37. pyemaps/cdata/Copper_FCC.xtl +4 -0
  38. pyemaps/cdata/Cu2O_Cuprite.xtl +5 -0
  39. pyemaps/cdata/Diamond.xtl +4 -0
  40. pyemaps/cdata/ErbiumPyrogermanate.xtl +9 -0
  41. pyemaps/cdata/FePd_Tetra.xtl +5 -0
  42. pyemaps/cdata/FeS2_Pyrite.xtl +15 -0
  43. pyemaps/cdata/GalliumAntimonide.xtl +5 -0
  44. pyemaps/cdata/GalliumArsenide.xtl +5 -0
  45. pyemaps/cdata/GalliumNitride.xtl +5 -0
  46. pyemaps/cdata/Germanium.xtl +4 -0
  47. pyemaps/cdata/Gold_FCC.xtl +4 -0
  48. pyemaps/cdata/IndiumArsenide.xtl +5 -0
  49. pyemaps/cdata/LaMnO3.xtl +7 -0
  50. pyemaps/cdata/LeadZirconateTitanate.xtl +8 -0
  51. pyemaps/cdata/Li2MnO3.xtl +13 -0
  52. pyemaps/cdata/NaFeO2.xtl +6 -0
  53. pyemaps/cdata/Nb3Sn.xtl +5 -0
  54. pyemaps/cdata/Pentacene.xtl +39 -0
  55. pyemaps/cdata/Silicon.xtl +4 -0
  56. pyemaps/cdata/StrontiumTitanate.xtl +6 -0
  57. pyemaps/cdata/TelluriumDioxide.xtl +5 -0
  58. pyemaps/cdata/TinDioxide_RT.xtl +5 -0
  59. pyemaps/cdata/TitaniumDioxide_Anatase.xtl +5 -0
  60. pyemaps/cdata/TitaniumDioxide_Rutile.xtl +5 -0
  61. pyemaps/cdata/TungstenDiselenide.xtl +5 -0
  62. pyemaps/cdata/VanadiumDioxide_RT.xtl +6 -0
  63. pyemaps/cdata/ZincOxide.xtl +5 -0
  64. pyemaps/cdata/Zinc_HCP.xtl +4 -0
  65. pyemaps/cdata/ZirconiumNitride.xtl +5 -0
  66. pyemaps/cdata/limno2.xtl +6 -0
  67. pyemaps/crystals.py +1415 -0
  68. pyemaps/ddiffs.py +147 -0
  69. pyemaps/diffract/__init__.py +70 -0
  70. pyemaps/diffract/bloch_dec.py +779 -0
  71. pyemaps/diffract/csf_dec.py +242 -0
  72. pyemaps/diffract/dif_dec.py +519 -0
  73. pyemaps/diffract/dpgen_dec.py +175 -0
  74. pyemaps/diffract/mxtal_dec.py +201 -0
  75. pyemaps/diffract/powder_dec.py +137 -0
  76. pyemaps/diffract/stereo_dec.py +111 -0
  77. pyemaps/display.py +791 -0
  78. pyemaps/emcontrols.py +1017 -0
  79. pyemaps/errors.py +266 -0
  80. pyemaps/fileutils.py +1001 -0
  81. pyemaps/kdiffs.py +1221 -0
  82. pyemaps/license.txt +42 -0
  83. pyemaps/samples/adf.py +137 -0
  84. pyemaps/samples/al.img +0 -0
  85. pyemaps/samples/al_dpgen.py +57 -0
  86. pyemaps/samples/al_ediom.py +94 -0
  87. pyemaps/samples/convert_image.py +88 -0
  88. pyemaps/samples/dm_diff.py +225 -0
  89. pyemaps/samples/mask.im3 +0 -0
  90. pyemaps/samples/powder.py +51 -0
  91. pyemaps/samples/raw.img +0 -0
  92. pyemaps/samples/si_bloch.py +120 -0
  93. pyemaps/samples/si_constructor.py +51 -0
  94. pyemaps/samples/si_csf.py +59 -0
  95. pyemaps/samples/si_dif.py +134 -0
  96. pyemaps/samples/si_lacbed.py +59 -0
  97. pyemaps/samples/si_pyemaps.py +80 -0
  98. pyemaps/samples/si_scm.py +156 -0
  99. pyemaps/samples/si_stereo.py +116 -0
  100. pyemaps/scattering/__init__.py +26 -0
  101. pyemaps/scattering/sct_dec.py +31 -0
  102. pyemaps/spg/__init__.py +25 -0
  103. pyemaps/spg/spg_dec.py +60 -0
  104. pyemaps/stackimg.py +1031 -0
  105. pyemaps/xtal.py +222 -0
  106. pyemaps-2.0.0.dist-info/METADATA +231 -0
  107. pyemaps-2.0.0.dist-info/RECORD +112 -0
  108. pyemaps-2.0.0.dist-info/WHEEL +5 -0
  109. pyemaps-2.0.0.dist-info/entry_points.txt +2 -0
  110. pyemaps-2.0.0.dist-info/licenses/COPYING +798 -0
  111. pyemaps-2.0.0.dist-info/licenses/license.txt +42 -0
  112. pyemaps-2.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,582 @@
1
+ # A dREL grammar written for python-ply
2
+ #
3
+ # The output is an Abstract Syntax Tree that represents a
4
+ # function fragment that needs to be wrapped with information
5
+ # appropriate to the target language.
6
+
7
+ # The grammar is based on the Python 2.7 grammar, in
8
+ # consultation with Doug du Boulay's JsCifBrowser
9
+ # grammar (also derived from a Python grammar).
10
+
11
+ # To maximize python3/python2 compatibility
12
+ from __future__ import print_function
13
+ from __future__ import unicode_literals
14
+ from __future__ import absolute_import
15
+
16
+ from .drel_lex import lexer,tokens
17
+ import ply.yacc as yacc
18
+
19
+ # Overall translation unit
20
+
21
+ # Our input is a sequence of statements
22
+ def p_input(p):
23
+ '''input : maybe_nline statement
24
+ | input statement '''
25
+ if p[1] is None:
26
+ p[0] = p[2]
27
+ else:
28
+ so_far = p[1][1]
29
+ new_statements = p[2][1]
30
+ p[0] = ["STATEMENTS",p[1][1] + p[2][1]]
31
+ #print('input now {!r}'.format(p[0]))
32
+
33
+ # We distinguish between compound statements and
34
+ # small statements. Small statements may be
35
+ # chained together on a single line with semicolon
36
+ # separators. Compound statements are not separated
37
+ # in this way, and will always be terminated by
38
+ # a newline.
39
+ def p_statement(p):
40
+ '''statement : simple_stmt newlines
41
+ | simple_stmt ";" newlines
42
+ | compound_stmt '''
43
+ p[0] = p[1]
44
+
45
+ # A simple statement is a sequence of small statements terminated by
46
+ # a NEWLINE or EOF
47
+ def p_simple_stmt(p):
48
+ ''' simple_stmt : small_stmt
49
+ | simple_stmt ";" small_stmt '''
50
+ if len(p) == 2:
51
+ p[0] = ["STATEMENTS",[p[1]]]
52
+ else:
53
+ p[0] = ["STATEMENTS",p[1][1] + [p[3]]]
54
+
55
+ # This production appears inside a set of braces. Any statement
56
+ # will be automatically terminated by a newline so we do not
57
+ # need to include that here
58
+ def p_statements(p):
59
+ '''statements : statement
60
+ | statements statement '''
61
+ if len(p) == 2: p[0] = p[1]
62
+ else: p[0] = ["STATEMENTS", p[1][1] + [p[2]]]
63
+
64
+ def p_small_stmt(p):
65
+ '''small_stmt : expr_stmt
66
+ | print_stmt
67
+ | break_stmt
68
+ | next_stmt'''
69
+ p[0] = p[1]
70
+
71
+ def p_break_stmt(p):
72
+ '''break_stmt : BREAK'''
73
+ p[0] = ["BREAK"]
74
+
75
+ def p_next_stmt(p):
76
+ '''next_stmt : NEXT'''
77
+ p[0] = ["NEXT"]
78
+
79
+ def p_print_stmt(p):
80
+ '''print_stmt : PRINT expression '''
81
+ p[0] = ['PRINT', p[2]]
82
+
83
+ # Note here that a simple testlist_star_expr is useless as in our
84
+ # side-effect-free world it will be evaluated and discarded. We
85
+ # could just drop it right now but we let it go through to the
86
+ # AST processor for language-dependent processing
87
+ def p_expr_stmt(p):
88
+ ''' expr_stmt : testlist_star_expr
89
+ | testlist_star_expr AUGOP testlist_star_expr
90
+ | testlist_star_expr "=" testlist_star_expr
91
+ | fancy_drel_assignment_stmt '''
92
+ if len(p) == 2 and p[1][0] != 'FANCY_ASSIGN': # we have a list of expressions which we
93
+ p[0] = ["EXPRLIST",p[1]]
94
+ elif len(p) == 2 and p[1][0] == 'FANCY_ASSIGN':
95
+ p[0] = p[1]
96
+ else:
97
+ p[0] = ["ASSIGN",p[1],p[2],p[3]]
98
+
99
+ def p_testlist_star_expr(p): # list of expressions in fact
100
+ ''' testlist_star_expr : expression
101
+ | testlist_star_expr "," maybe_nline expression '''
102
+ if len(p) == 2:
103
+ p[0] = [p[1]]
104
+ else:
105
+ p[0] = p[1] + [p[4]]
106
+
107
+ # Simplified from the python 2.5 version due to apparent conflict with
108
+ # the other type of IF expression...
109
+ #
110
+ def p_expression(p):
111
+ '''expression : or_test '''
112
+ p[0] = ["EXPR",p[1]]
113
+
114
+ # This is too generous, as it allows a function call on the
115
+ # LHS to be assigned to. This will cause a syntax error on
116
+ # execution.
117
+
118
+ def p_or_test(p):
119
+ ''' or_test : and_test
120
+ | or_test OR and_test
121
+ | or_test BADOR and_test'''
122
+ if len(p) == 2: p[0] = p[1]
123
+ else: p[0] = ["MATHOP","or",p[1],p[3]]
124
+
125
+ def p_and_test(p):
126
+ '''and_test : not_test
127
+ | and_test AND not_test
128
+ | and_test BADAND not_test'''
129
+ if len(p) == 2: p[0] = p[1]
130
+ else: p[0] = ["MATHOP","and", p[1],p[3]]
131
+
132
+ def p_not_test(p):
133
+ '''not_test : comparison
134
+ | NOT not_test'''
135
+ if len(p) == 2: p[0] = p[1]
136
+ else: p[0] = ["UNARY","not",p[2]]
137
+
138
+ def p_comparison(p):
139
+ '''comparison : a_expr
140
+ | a_expr comp_operator a_expr'''
141
+ if len(p) == 2: p[0] = p[1]
142
+ else:
143
+ p[0] = ["MATHOP",p[2],p[1],p[3]]
144
+
145
+ def p_comp_operator(p):
146
+ '''comp_operator : restricted_comp_operator
147
+ | IN
148
+ | NOT IN '''
149
+ if len(p)==3:
150
+ p[0] = "not in"
151
+ else: p[0] = p[1]
152
+
153
+ def p_restricted_comp_operator(p): #for loop tests
154
+ '''restricted_comp_operator : "<"
155
+ | ">"
156
+ | GTE
157
+ | LTE
158
+ | NEQ
159
+ | ISEQUAL '''
160
+ p[0] = p[1]
161
+
162
+ def p_a_expr(p):
163
+ '''a_expr : m_expr
164
+ | a_expr "+" m_expr
165
+ | a_expr "-" m_expr'''
166
+ if len(p) == 2:
167
+ p[0] = p[1]
168
+ else:
169
+ p[0] = ["MATHOP",p[2], p[1], p[3]]
170
+
171
+ def p_m_expr(p): #note bitwise and and or are pycifrw extensions
172
+ '''m_expr : u_expr
173
+ | m_expr "*" u_expr
174
+ | m_expr "/" u_expr
175
+ | m_expr "^" u_expr
176
+ | m_expr "&" u_expr
177
+ | m_expr "|" u_expr '''
178
+ if len(p) == 2:
179
+ p[0] = p[1]
180
+ else:
181
+ p[0] = ["MATHOP",p[2],p[1],p[3]]
182
+
183
+ def p_u_expr(p):
184
+ '''u_expr : power
185
+ | "-" u_expr
186
+ | "+" u_expr'''
187
+ if len(p) == 2:
188
+ p[0] = p[1]
189
+ else:
190
+ p[0] = ["SIGN",p[1],p[2]]
191
+
192
+ def p_power(p):
193
+ '''power : primary
194
+ | primary POWER u_expr'''
195
+ if len(p) == 2:
196
+ p[0] = p[1]
197
+ else:
198
+ p[0] = ["MATHOP","**",p[1] , p[3]]
199
+ # print('At power: p[0] is {!r}'.format(p[0]))
200
+
201
+ def p_primary(p):
202
+ '''primary : atom
203
+ | attributeref
204
+ | subscription
205
+ | slicing
206
+ | call'''
207
+ # print 'Primary -> %s' % repr(p[1])
208
+ p[0] = p[1]
209
+
210
+ def p_atom(p):
211
+ '''atom : ID
212
+ | item_tag
213
+ | literal
214
+ | enclosure'''
215
+ # print 'Atom -> %s' % repr(p[1])
216
+ p[0] = ["ATOM",p[1]]
217
+
218
+ def p_item_tag(p):
219
+ '''item_tag : ITEM_TAG'''
220
+ p[0] = ["ITEM_TAG",p[1]]
221
+
222
+ def p_literal(p):
223
+ '''literal : stringliteral
224
+ | INTEGER
225
+ | HEXINT
226
+ | OCTINT
227
+ | BININT
228
+ | REAL
229
+ | IMAGINARY'''
230
+ # print 'literal-> %s' % repr(p[1])
231
+ p[0] = ["LITERAL",p[1]]
232
+
233
+ def p_stringliteral(p):
234
+ '''stringliteral : STRPREFIX SHORTSTRING
235
+ | STRPREFIX LONGSTRING
236
+ | SHORTSTRING
237
+ | LONGSTRING'''
238
+ if len(p)==3: p[0] = p[1]+p[2]
239
+ else: p[0] = p[1]
240
+
241
+ def p_enclosure(p):
242
+ '''enclosure : parenth_form
243
+ | string_conversion
244
+ | list_display
245
+ | table_display '''
246
+ p[0]=p[1]
247
+
248
+ def p_parenth_form(p):
249
+ '''parenth_form : OPEN_PAREN testlist_star_expr CLOSE_PAREN
250
+ | OPEN_PAREN CLOSE_PAREN '''
251
+ if len(p) == 3: p[0] = ["GROUP"]
252
+ else:
253
+ p[0] = ["GROUP",p[2]]
254
+ # print('Parens: {!r}'.format(p[0]))
255
+
256
+ def p_string_conversion(p):
257
+ '''string_conversion : "`" testlist_star_expr "`" '''
258
+ # WARNING: NOT IN PUBLISHED dREL papaer
259
+ p[0] = ["FUNC_CALL","str",p[2]]
260
+
261
+ def p_list_display(p):
262
+ ''' list_display : "[" maybe_nline listmaker maybe_nline "]"
263
+ | "[" maybe_nline "]" '''
264
+ if len(p) == 4: p[0] = ["LIST"]
265
+ else:
266
+ p[0] = ["LIST"] + p[3]
267
+
268
+
269
+ # scrap the trailing comma
270
+ def p_listmaker(p):
271
+ '''listmaker : expression listmaker2 '''
272
+ p[0] = [p[1]] + p[2]
273
+ # print('listmaker: {!r}'.format(p[0]))
274
+
275
+ def p_listmaker2(p):
276
+ '''listmaker2 : "," maybe_nline expression
277
+ | listmaker2 "," maybe_nline expression
278
+ | '''
279
+ if len(p) == 4:
280
+ p[0] = [p[3]]
281
+ elif len(p) < 2:
282
+ p[0] = []
283
+ else:
284
+ p[0] = p[1] + [p[4]]
285
+
286
+ # define tables
287
+ def p_table_display(p):
288
+ ''' table_display : "{" maybe_nline tablemaker maybe_nline "}"
289
+ | "{" maybe_nline "}" '''
290
+ if len(p) == 4:
291
+ p[0] = ["TABLE"]
292
+ else:
293
+ p[0] = ["TABLE"] + p[3]
294
+
295
+ def p_tablemaker(p):
296
+ '''tablemaker : stringliteral ":" expression tablemaker2 '''
297
+ p[0] = [(p[1],p[3])] + p[4]
298
+
299
+ def p_tablemaker2(p):
300
+ '''tablemaker2 : "," maybe_nline stringliteral ":" expression
301
+ | tablemaker2 "," maybe_nline stringliteral ":" expression
302
+ | '''
303
+ if len(p) == 6:
304
+ p[0] = [(p[3],p[5])]
305
+ elif len(p) < 2:
306
+ p[0] = []
307
+ else:
308
+ p[0] = p[1] + [(p[4],p[6])]
309
+
310
+ # Note that we need to catch tags of the form 't.12', which
311
+ # our lexer will interpret as ID REAL. We therefore also
312
+ # accept t.12(3), which is not allowed, but we don't bother
313
+ # trying to catch this error here.
314
+
315
+ def p_attributeref(p):
316
+ '''attributeref : primary attribute_tag '''
317
+ p[0] = ["ATTRIBUTE",p[1],p[2]]
318
+
319
+ def p_attribute_tag(p):
320
+ '''attribute_tag : "." ID
321
+ | REAL '''
322
+ if len(p) == 3:
323
+ p[0] = p[2]
324
+ else:
325
+ p[0] = p[1][1:]
326
+
327
+ def p_subscription(p):
328
+ '''subscription : primary "[" expression "]" '''
329
+ p[0] = ["SUBSCRIPTION",p[1],p[3]]
330
+
331
+ def p_slicing(p):
332
+ '''slicing : primary "[" proper_slice "]"
333
+ | primary "[" slice_list "]" '''
334
+ p[0] = ["SLICE", p[1], p[3] ]
335
+
336
+ def p_proper_slice(p):
337
+ '''proper_slice : short_slice
338
+ | long_slice '''
339
+ p[0] = [p[1]]
340
+
341
+ # Our AST slice convention is that, if anything is mentioned,
342
+ # the first element is always
343
+ # explicitly mentioned. A single element will be a starting
344
+ # element. Two elements are start and finish. An empty list
345
+ # is all elements. Three elements are start, finish, step.
346
+ # We combine these into a list of slices.
347
+
348
+ def p_short_slice(p):
349
+ '''short_slice : ":"
350
+ | expression ":" expression
351
+ | ":" expression
352
+ | expression ":" '''
353
+ if len(p) == 2: p[0] = []
354
+ if len(p) == 4: p[0] = [p[1],p[3]]
355
+ if len(p) == 3 and p[1] == ":":
356
+ p[0] = [0,p[2]]
357
+ if len(p) == 3 and p[2] == ":":
358
+ p[0] = [p[1]]
359
+
360
+ def p_long_slice(p):
361
+ '''long_slice : short_slice ":" expression '''
362
+ if len(p) == 4:
363
+ p[0] = p[1] + [p[3]]
364
+ else:
365
+ p[0] = p[1]
366
+
367
+ def p_slice_list(p):
368
+ ''' slice_list : slice_item
369
+ | slice_list "," slice_item '''
370
+ if len(p) == 2:
371
+ p[0] = [p[1]]
372
+ else:
373
+ p[0] = p[1] + [p[3]]
374
+
375
+ def p_slice_item(p):
376
+ ''' slice_item : expression
377
+ | proper_slice '''
378
+ p[0] = p[1]
379
+
380
+ def p_call(p):
381
+ '''call : ID OPEN_PAREN CLOSE_PAREN
382
+ | ID OPEN_PAREN argument_list CLOSE_PAREN '''
383
+ if len(p) == 4:
384
+ p[0] = ["FUNC_CALL",p[1],[]]
385
+ else:
386
+ p[0] = ["FUNC_CALL",p[1],p[3]]
387
+ #print("Function call: {!r}".format(p[0]))
388
+
389
+ # These are the arguments to a call, not a definition
390
+
391
+ def p_argument_list(p):
392
+ '''argument_list : func_arg
393
+ | argument_list "," func_arg '''
394
+ if len(p) == 2:
395
+ p[0] = [p[1]]
396
+ else:
397
+ p[0] = p[1] + [p[3]]
398
+
399
+ def p_func_arg(p):
400
+ '''func_arg : expression '''
401
+ p[0] = p[1]
402
+
403
+ def p_fancy_drel_assignment_stmt(p):
404
+ '''fancy_drel_assignment_stmt : ID OPEN_PAREN dotlist CLOSE_PAREN '''
405
+ p[0] = ["FANCY_ASSIGN",p[1],p[3]]
406
+ # print("Fancy assignment -> {!r}".format(p[0]))
407
+
408
+ # Something made up specially for drel. A newline is OK between assignments
409
+
410
+ def p_dotlist(p):
411
+ '''dotlist : "." ID "=" expression
412
+ | dotlist "," "." ID "=" expression '''
413
+ if len(p) <= 5: #first element of dotlist
414
+ p[0] = [[p[2],p[4]]]
415
+ else: #append to previous elements
416
+ p[0] = p[1] + [[p[4],p[6]]]
417
+
418
+ def p_exprlist(p):
419
+ ''' exprlist : a_expr
420
+ | exprlist "," a_expr '''
421
+ if len(p) == 2:
422
+ p[0] = [p[1]]
423
+ else: p[0] = p[1] + [p[3]]
424
+
425
+ # a (potentially enclosed) list of ids
426
+ def p_id_list(p):
427
+ ''' id_list : ID
428
+ | id_list "," ID '''
429
+
430
+ if len(p) == 2:
431
+ p[0] = [p[1]]
432
+ else:
433
+ p[0] = p[1] + [p[3]]
434
+
435
+ # now for the compound statements. We prepare them as a "STATEMENT"
436
+ # list for smooth processing in the simple_stmt production
437
+
438
+ def p_compound_stmt(p):
439
+ '''compound_stmt : if_stmt
440
+ | if_else_stmt
441
+ | for_stmt
442
+ | do_stmt
443
+ | loop_stmt
444
+ | with_stmt
445
+ | repeat_stmt
446
+ | funcdef '''
447
+ p[0] = ["STATEMENTS",[p[1]]]
448
+ #print "Compound statement: \n" + p[0]
449
+
450
+ # There must only be one else statement at the end of the else if statements,
451
+ # so we show this by creating a separate production
452
+ def p_if_else_stmt(p):
453
+ '''if_else_stmt : if_stmt ELSE suite'''
454
+ p[0] = p[1]
455
+ p[0].append(p[3])
456
+
457
+ # The AST node is [IF_EXPR,cond, suite,[[elseif cond1,suite],[elseifcond2,suite]...]]
458
+ def p_if_stmt(p):
459
+ '''if_stmt : IF OPEN_PAREN expression CLOSE_PAREN maybe_nline suite
460
+ | if_stmt ELSEIF OPEN_PAREN expression CLOSE_PAREN maybe_nline suite '''
461
+ if len(p) == 7:
462
+ p[0] = ["IF_EXPR"]
463
+ p[0].append(p[3])
464
+ p[0].append(p[6])
465
+ p[0].append([])
466
+ else:
467
+ p[0] = p[1]
468
+ p[0][3].append([p[4],p[7]])
469
+
470
+ # Note the dREL divergence from Python here: we allow compound
471
+ # statements to follow without a separate block (like C etc.) Where
472
+ # we have a single statement immediately following we have to make the
473
+ # statement block. A small_stmt will be a single production, so must
474
+ # be put into a list in order to match the 'statements' structure
475
+ # (i.e. 2nd element is a list of statements). A compound_stmt is thus
476
+ # forced to be also a non-listed object.
477
+
478
+ def p_suite(p):
479
+ '''suite : statement
480
+ | "{" maybe_nline statements "}" maybe_nline '''
481
+ if len(p) == 2:
482
+ p[0] = p[1]
483
+ else:
484
+ p[0] = p[3] #already have a statement block
485
+
486
+ def p_for_stmt(p):
487
+ '''for_stmt : FOR id_list IN testlist_star_expr suite
488
+ | FOR "[" id_list "]" IN testlist_star_expr suite '''
489
+ if len(p)==6:
490
+ p[0] = ["FOR", p[2], p[4], p[5]]
491
+ else:
492
+ p[0] = ["FOR", p[3], p[6], p[7]]
493
+
494
+ def p_loop_stmt(p):
495
+ '''loop_stmt : loop_head suite '''
496
+ p[0] = ["LOOP"] + p[1] + [p[2]]
497
+
498
+ # We capture a list of all the actually present items in the current
499
+ # datafile
500
+ def p_loop_head(p):
501
+ '''loop_head : LOOP ID AS ID
502
+ | LOOP ID AS ID ":" ID
503
+ | LOOP ID AS ID ":" ID restricted_comp_operator ID '''
504
+
505
+ p[0] = [p[2],p[4]]
506
+ if len(p)>= 7:
507
+ p[0] = p[0] + [p[6]]
508
+ else: p[0] = p[0] + [""]
509
+ if len(p) >= 9:
510
+ p[0] = p[0] + [p[7],p[8]]
511
+ else: p[0] = p[0] + ["",""]
512
+
513
+ def p_do_stmt(p):
514
+ '''do_stmt : do_stmt_head suite '''
515
+ p[0] = p[1] + [p[2]]
516
+
517
+ # To translate the dREL do to a for statement, we need to make the
518
+ # end of the range included in the range
519
+
520
+ def p_do_stmt_head(p):
521
+ '''do_stmt_head : DO ID "=" expression "," expression
522
+ | DO ID "=" expression "," expression "," expression'''
523
+
524
+ p[0] = ["DO",p[2],p[4],p[6]]
525
+ if len(p)==9:
526
+ p[0] = p[0] + [p[8]]
527
+ else:
528
+ p[0] = p[0] + [["EXPR",["LITERAL","1"]]]
529
+
530
+ def p_repeat_stmt(p):
531
+ '''repeat_stmt : REPEAT suite'''
532
+ p[0] = ["REPEAT",p[2]]
533
+
534
+ def p_with_stmt(p):
535
+ '''with_stmt : with_head maybe_nline suite'''
536
+ p[0] = p[1]+[p[3]]
537
+
538
+ def p_with_head(p):
539
+ '''with_head : WITH ID AS ID'''
540
+ p[0] = ["WITH",p[2],p[4]]
541
+
542
+ def p_funcdef(p):
543
+ ''' funcdef : FUNCTION ID OPEN_PAREN arglist CLOSE_PAREN suite '''
544
+ p[0] = ["FUNCTION",p[2],p[4],p[6]]
545
+
546
+ def p_arglist(p):
547
+ ''' arglist : ID ":" list_display
548
+ | arglist "," ID ":" list_display '''
549
+ if len(p) == 4: p[0] = [(p[1],p[2])]
550
+ else: p[0] = p[1] + [(p[3],p[5])]
551
+
552
+ # This production allows us to insert optional newlines
553
+
554
+ def p_maybe_nline(p):
555
+ ''' maybe_nline : newlines
556
+ | empty '''
557
+ pass
558
+
559
+ # We need to allow multiple newlines here and not just in the lexer as
560
+ # an intervening comment can cause multiple newline tokens to appear
561
+
562
+ def p_newlines(p):
563
+ ''' newlines : NEWLINE
564
+ | newlines NEWLINE '''
565
+ pass
566
+
567
+ def p_empty(p):
568
+ ''' empty : '''
569
+ pass
570
+
571
+ def p_error(p):
572
+ try:
573
+ print('Syntax error at position %d, line %d token %s, value %s' % (p.lexpos,p.lineno,p.type,p.value))
574
+ print('Surrounding text: ' + p.lexer.lexdata[max(p.lexpos - 100,0): p.lexpos] + "*" + \
575
+ p.lexer.lexdata[p.lexpos:min(p.lexpos + 100,len(p.lexer.lexdata))])
576
+ except:
577
+ pass
578
+ parser.restart()
579
+ raise SyntaxError
580
+
581
+ #lexer = drel_lex.lexer
582
+ parser = yacc.yacc()