-
Notifications
You must be signed in to change notification settings - Fork 94
/
Copy pathasy-list.py
145 lines (121 loc) · 5.3 KB
/
asy-list.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
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env python3
#####
# asy-list.py
#
# Build asy-keywords.el from a list of Asymptote global functions and
# variables. This script reads definitions from 'camp.l' and writes Emacs Lisp
# code to 'asy-keywords.el'.
#
#####
import argparse
import re
import textwrap
parser = argparse.ArgumentParser()
parser.add_argument(
"--asy-list-file", type=str, required=True, help="Path to the asy list file"
)
parser.add_argument("--revision", type=str, required=True, help="Revision identifier")
parser.add_argument(
"--output-file", type=str, required=True, help="Path to output file"
)
args = parser.parse_args()
# Open the file 'asy-keywords.el' for writing.
with open(args.output_file, "w", encoding="utf-8") as keywords:
# Write header information to 'asy-keywords.el'.
# This includes comments and the definition of 'asy-keywords-version' using a
# command-line argument.
keywords.write(
textwrap.dedent(
f"""\
;;
;; This file is automatically generated by asy-list.py.
;; Changes will be overwritten.
;;
(defvar asy-keywords-version "{args.revision}")
"""
)
)
# Define a function 'add' that adds a keyword to the output file.
def add(keyword):
keywords.write(keyword + " ")
# Write the beginning of the Emacs Lisp definition for 'asy-keyword-name'.
keywords.write("(defvar asy-keyword-name '(\n")
# Open the file 'camp.l' for reading.
with open("camp.l", "r", encoding="utf-8") as camp:
# Read lines from 'camp.l' until reaching a line that contains only '%%'.
for line in camp:
if re.search(r"^%%\s*$", line):
break
# Continue reading lines from 'camp.l' after the '%%' line.
for line in camp:
if re.search(r"^%%\s*$", line):
# Exit the loop when a second '%%' line is found, indicating the end of
# the section.
break
# Match lines that start with a word (the keyword) followed by optional
# whitespace and a '{'.
match = re.search(r"^(\w+)\s*\{", line)
if match:
# Write the keyword followed by a space.
keywords.write(match.group(1) + " ")
# Open an input file specified in the command-line arguments.
with open(args.asy_list_file, "r", encoding="utf-8") as asylist:
# Lists to store types, functions, and variables found in the file.
types = [] # List to hold data types.
functions = [] # List to hold function names.
variables = [] # List to hold variable names.
# Read each line from the file handle asylist.
for line in asylist:
# Match lines that define functions.
# The pattern looks for:
# - An optional word (\w*) representing the return type.
# - Any number of non-space characters ([^ ]*), which may include
# modifiers.
# - A space character.
# - Capture the function name (\w*).
# - An opening parenthesis '(', indicating the start of the parameter
# list.
matchFun = re.search(r"^(\w*)[^ ]* (\w*)\(", line)
if matchFun:
types.append(matchFun.group(1))
functions.append(matchFun.group(2))
# Match lines that declare variables.
# The pattern looks for:
# - Any non-space characters before a space ([^ ]*), representing the
# type.
# - A space character.
# - Capture the variable name (\w*).
# - A semicolon ';', indicating the end of the declaration.
matchVarDec = re.search(r"^([^ ]*) (\w*);", line)
if matchVarDec:
variables.append(matchVarDec.group(2))
# Remove duplicates and sort the lists.
types = sorted(set(types))
functions = sorted(set(functions))
variables = sorted(set(variables))
# Write the closing parentheses for the 'asy-keyword-name' definition in the
# output file.
keywords.write("))\n\n")
# Write the beginning of the 'asy-type-name' definition to the output file.
keywords.write("(defvar asy-type-name '(\n")
# Write each type from types to the output file.
for t in types:
keywords.write(t + " ") # Write the type followed by a space.
# Write the closing parentheses for the 'asy-type-name' definition.
keywords.write("))\n\n")
# Write the beginning of the 'asy-function-name' definition to the output
# file.
keywords.write("(defvar asy-function-name '(\n")
# Write each function name from functions to the output file.
for f in functions:
keywords.write(f + " ") # Write the function name followed by a space.
# Write the closing parentheses for the 'asy-function-name' definition.
keywords.write("))\n\n")
# Write the beginning of the 'asy-variable-name' definition to the output
# file.
keywords.write("(defvar asy-variable-name '(\n")
# Write each variable name from variables to the output file.
for v in variables:
keywords.write(v + " ") # Write the variable name followed by a space.
# Write the closing parentheses for the 'asy-variable-name' definition.
keywords.write("))\n")