File: parser_data.py

package info (click to toggle)
pyxplot 0.9.2-14
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 10,288 kB
  • sloc: ansic: 50,373; xml: 1,339; python: 570; sh: 318; makefile: 89
file content (167 lines) | stat: -rw-r--r-- 6,461 bytes parent folder | download | duplicates (3)
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# parser_data.py
#
# The code in this file is part of Pyxplot
# <http://www.pyxplot.org.uk>
#
# Copyright (C) 2006-2012 Dominic Ford <coders@pyxplot.org.uk>
#               2008-2012 Ross Church
#
# $Id: parser_data.py 1261 2012-07-11 21:38:05Z dcf21 $
#
# Pyxplot is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# You should have received a copy of the GNU General Public License along with
# Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin
# Street, Fifth Floor, Boston, MA  02110-1301, USA

# ----------------------------------------------------------------------------

# Generate table of positions of variables by name
globalVarNames = []
globalVarTable = {}

def processVarTable(vt, directive, setOption):
 global globalVarNames,globalVarTable
 if '%' in directive: return
 key = "%s_%s"%(directive,setOption)
 globalVarTable[key] = vt
 for name,pos in vt.items():
  if name not in globalVarNames: globalVarNames.append(name)

def printVarTable():
 global globalVarNames,globalVarTable,f_h,f_c
 globalVarNames = sorted(globalVarNames)
 for i in range(len(globalVarNames)):
   f_h.write("#define PARSE_INDEX_%s %d\n"%(sanitize(globalVarNames[i]),i))
 keys = sorted(globalVarTable.keys())
 for k in keys:
   d = globalVarTable[k]
   f_h.write("extern const int PARSE_TABLE_%s[];\n"%k)
   f_c.write("const int PARSE_TABLE_%s[] = {"%k)
   for i in range(len(globalVarNames)):
     item = globalVarNames[i]
     if (i!=0)   : f_c.write(",")
     if item in d: f_c.write("%d"%d[item])
     else        : f_c.write("-1");
   f_c.write("};\n")

# Generate specification of commands that Pyxplot recognises

def sanitize(instr):
  outstr = ""
  for i in range(len(instr)):
    if (instr[i].isalnum() or instr[i]=='_'): outstr+=instr[i]
  return outstr

f_in = open("buildScripts/parser_data.dat","r")

# Output C files containing command definitions

f_h  = open("src/parser/cmdList.h","w")
f_c  = open("src/parser/cmdList.c","w")
includeKeys = {}

f_h.write("""// This file autogenerated by parser_data.py

#ifndef _CMDLIST_H
#define _CMDLIST_H 1

extern const char ppl_cmdList[];
""")

f_c.write("""// This file autogenerated by parser_data.py

const char ppl_cmdList[] = "\\
""")

# Loop through command definitions

linecount = 0
for line in f_in:
  linecount+=1
  line = line.strip();
  if len(line)<1: continue
  if line.startswith("#"): continue

  outline        = ""
  directive      = "undefined"
  setoption      = ""
  stack          = []
  stack_varnames = []
  listsizes      = []
  varnames       = {"directive":0 , "editno":1, "set_option":2, "X":3}
  vartable       = varnames.copy()
  varcount       = len(varnames)
  words = line.split()
  for word in words:
    if word in ["=","(","~",")","{","}","<","|",">","["]: # Grammar characters are passed straight through
      outline += "%s "%word
      if word=="[": # Lists are placed on the stack, and the number of variables in each list counted
        stack.append(varcount)
        stack_varnames.append(varnames)
        varcount=1 # Start counting from variable 1 inside a list, as first value is pointer to next list item
        varnames={}
      continue
    parts = word[1:].split(":")
    parts[0] = word[0]+parts[0] # If first character is a colon, it should match a literal :, not act as a separator
    subparts = parts[0].split("@") # Match string has form plot@1, meaning 'p' is short for 'plot'
    if len(parts)<2:
      parts.append("X") # If output variable name is not specified, stick it in 'X'.
    if len(subparts)>1:
      if subparts[1]=="n": subparts[1]=-1 # An auto-complete length of 'n' is stored as -1
      parts.append("%s"%subparts[1])
      parts[0] = subparts[0]
    else:
      parts.append("%s"%len(parts[0])) # If no auto-complete length is specified, whole string must be matched
    if len(parts)==3: parts.insert(2,"") # At this point, parts is [ match string , output variable , string to store (blank if equals match string) , auto-complete len ]
    assert len(parts)==4, "Syntax error in word '%s'."%word
    varname = parts[1]
    if word.startswith("]:"):
      parts = [ "]" , word[2:] , "" , "1" ]
      listsizes.append(varcount)
      varcount=stack.pop()
      for key,item in varnames.items(): stack_varnames[-1]["%s_%s"%(key,varname)] = item
      varnames=stack_varnames.pop()
    if varname=='directive': # Directive names are stored for use in #defines to convert variable names into output slot numbers
      if parts[2]=="": directive = parts[0]
      else           : directive = parts[2]
    if varname=='set_option': # Set options are also used in #defines
      if parts[2]=="": setoption = parts[0]+"_"
      else           : setoption = parts[2]+"_"
      if (setoption[0]=="%"): setoption=""
    if varname not in varnames:
      varnames[varname] = varcount
      vartable[varname] = varcount
      if   (parts[0]=="%p"): varcount += 2 # Position vectors require 2 or 3 slots
      elif (parts[0]=="%P"): varcount += 3
      else                 : varcount += 1 # Varcount keeps track of the slot number to place the next variable in
    elif (parts[0] in ["%p","%P"]): print("Danger in command %s: sharing position variable name with other variables of different lengths"%directive)
    outnum = varnames[varname]
    parts.append("%s"%outnum) # parts[4] = slot number
    if word.startswith("]:"):
      initial = ""
      parts.append("%s"%listsizes[-1]) # parts[5] = list length for ] (number of slots needed for this list's variables)
    else:
      initial = "@"
      parts.append("0") # ... or zero otherwise
    outline += initial + "@".join(parts) + " "
  f_c.write("%d "%(varcount)) # First word on each statement definition line is the number of variables in the root slotspace
  f_c.write("%s\\n\\\n"%outline)
  processVarTable(vartable,directive,setoption)
  for i,j in varnames.items():
   if '%' not in directive:
    key = "PARSE_%s_%s%s"%(directive,setoption,sanitize(i))
    if (key in includeKeys) and (includeKeys[key]!=j): print("Repetition of key %s"%key)
    includeKeys[key] = j
    f_h.write("#define %s %d\n"%(key,j)) # Write #defines to convert variable names into slot numbers

# Finish up

f_c.write("""";\n""");
printVarTable()
f_h.write("""\n\n#endif"""); f_h.close()
f_c.close()