-
Notifications
You must be signed in to change notification settings - Fork 0
/
make_asy_grammar.py
149 lines (136 loc) · 5.53 KB
/
make_asy_grammar.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
146
147
148
149
#!/usr/bin/env python3
import cson
import io
import sys
import datetime
def generate_base_pattern():
return [
{ 'match': '//.*$', 'name':'comment.line.double-slash' },
{
'match' : '\\b(const|static|explicit|struct|typedef)\\b', 'name' : 'storage.modifier'
},
{ 'begin' : '/\\*', 'end' : '\\*/', 'name' : 'comment.block' },
{
'match':'([:blank:]{1}?)("{1})(.*)("{1})',
'name': 'string.quoted.double'
},
{
'begin':'([^[:blank:]]{1}?)("{1})',
'beginCaptures':
{
'2': 'string.quoted.double'
},
'end':'("{1})',
'endCaptures':
{
'1': 'string.quoted.double'
},
'patterns': [ {'include': 'text.tex.latex'} ]
},
{ 'match' : '\'.*?\'', 'name' : 'string.quoted.single' },
{ 'match' :
'\\b(if|else|while|for|do|break|return|continue|unravel)\\b',
'name' : 'keyword.control' },
{ 'match' :'\\b(new|operator)\\b', 'name' : 'keyword.operator' },
{ 'match' : '\\b(import|include|as|access|from)\\b',
'name' : 'keyword.other' },
{ 'match' : '\\b(\\d*)(\\.?)\\d+', 'name' : 'constant.numeric'}
]
def generate_preamble():
text_list = ['# Asymptote.cson Grammar file for Atom']
text_list.append(str.format('# Generated on {0}', str(datetime.datetime.now())))
text_list.append('# Do not modify this file as changes may not be saved.\n')
text_list.append('# asymptote.cson - Syntax Hightling compoenent for asymptote')
text_list.append(str.format('# Copyright (C) 2017-{0} Supakorn Rassameemasmuang', datetime.datetime.now().year))
text_list.extend([
'# ',
'# This program 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 3 of the License, or',
'# (at your option) any later version.',
'# ',
'# This program is distributed in the hope that it will be useful,',
'# but WITHOUT ANY WARRANTY; without even the implied warranty of',
'# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the',
'# GNU General Public License for more details.',
'# ',
'# You should have received a copy of the GNU General Public License',
'# ',
''
])
return '\n'.join(text_list)
def main():
print_output = True
output_file_name = 'asymptote.cson'
base_grammar = {
'scopeName': 'source.asymptote',
'name': 'Asymptote',
'fileTypes': ['asy']
}
# basic semantics not covered by asy -l
base_pattern = generate_base_pattern()
matched_words = set()
try:
asy_list_file = io.open('asy.list')
asy_list_raw = asy_list_file.read()
asy_list_file.close()
except (FileNotFoundError, IOError):
return 2
operator_list = []
for asy_def in asy_list_raw.split(';'):
asy_def = asy_def.strip()
if not asy_def:
continue
asy_type, asy_signature = asy_def.split(' ', 1)
if '(' in asy_signature:
if 'operator' in asy_signature:
if 'init()' in asy_signature: # type
match_word = str.format('\\b({0})\\b', asy_type)
match_type = 'storage.type'
elif 'cast(' not in asy_signature: # operator
operator_signature = asy_signature.split(' ', 1)[1]
operator_symbol = operator_signature.split('(')[0]
parsed_operator = []
for character in operator_symbol:
if character in {'|', '+', '*', '$', '.', '\\', '^'}:
parsed_operator.append('\\' + character)
else:
parsed_operator.append(character)
parsed_op_text = ''.join(parsed_operator)
if parsed_op_text.isalpha():
match_word = str.format('\\b({0})\\b', parsed_op_text)
else:
if parsed_op_text not in matched_words and ' ' not in parsed_op_text:
matched_words.add(parsed_op_text)
operator_list.append(parsed_op_text)
continue
match_type = 'keyword.operator'
else: # function
function_name = asy_signature.split('(')[0]
match_word = str.format('\\b({0})\\b', function_name)
match_type = 'support.function'
else: # constant
match_word = str.format('\\b({0})\\b', asy_signature)
match_type = 'constant.language'
if match_word not in matched_words:
base_pattern.append({
'match' : match_word,
'name' : match_type
})
matched_words.add(match_word)
base_pattern.append({
'match': '|'.join(operator_list),
'name' : 'keyword.operator'
})
base_grammar['patterns'] = base_pattern
final_output = cson.dumps(base_grammar, indent=True)
if print_output:
print(generate_preamble() + final_output)
else:
output_file = io.open(output_file_name, 'w')
output_file.write(generate_preamble())
output_file.write(final_output)
output_file.close()
print('Done!')
if __name__ == '__main__':
sys.exit(main() or 0)