forked from cappuccino/socratic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
TMLanguageGrammar.j
129 lines (92 loc) · 3.49 KB
/
TMLanguageGrammar.j
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
@import <Foundation/CPObject.j>
@import "TMLanguageRule.j"
var PLIST = require("objective-j/plist");
var GrammarsForFileTypes = nil,
GrammarsForScopeNames = nil;
@implementation TMLanguageGrammar : CPObject
{
CPString name @accessors(readonly);
CPSet fileTypes @accessors(readonly);
CPString scopeName @accessors(readonly);
CPString UUID @accessors(readonly);
RegExp firstLineMatch @accessors(readonly);
RegExp foldingStartMarker @accessors(readonly);
RegExp foldingStopMarker @accessors(readonly);
TMLanguageRule baseRule @accessors(readonly);
CPDictionary repository @accessors(readonly);
}
+ (void)initialize
{
if (self !== [TMLanguageGrammar class])
return;
GrammarsForFileTypes = [CPDictionary dictionary];
GrammarsForScopeNames = [CPDictionary dictionary];
}
+ (TMLanguageGrammar)grammarForFileAtURL:(CPURL)aURL
{
// Check the file type.
var absolutePath = [aURL absoluteString],
grammar = [self grammarForFileType:FILE.extension(absolutePath)];
if (grammar)
return grammar;
// If not check the first line.
var file = FILE.open(absolutePath, { charset: "UTF-8" }),
firstLine = nil;
// Skip space lines.
while ((firstLine = file.readLine()).trim().length === 0) ;
if (!firstLine)
return nil;
var grammarEnumerator = [grammars objectEnumerator];
while (grammar = [grammarEnumerator nextObject])
if (firstLine.match([grammar firstLineMatch]))
return grammar;
return nil;
}
+ (TMLanguageGrammar)grammarForFileType:(CPString)aFileType
{
if (aFileType.charAt(0) === '.')
aFileType = aFileType.substr(1);
return [GrammarsForFileTypes objectForKey:aFileType];
}
+ (TMLanguageGrammar)grammarWithScopeName:(CPString)aScopeName
{
return [GrammarsForScopeNames objectForKey:aScopeName];
}
+ (void)_registerGrammar:(TMLanguageGrammar)aGrammar
{
[GrammarsForScopeNames setObject:aGrammar forKey:[aGrammar scopeName]];
var fileType = nil,
fileTypeEnumerator = [[aGrammar fileTypes] objectEnumerator];
while (fileType = [fileTypeEnumerator nextObject])
[GrammarsForFileTypes setObject:aGrammar forKey:fileType];
}
- (id)initWithDictionary:(CPDictionary)aDictionary
{
self = [super init];
if (self)
{
name = [aDictionary objectForKey:@"name"];
fileTypes = [CPSet setWithArray:[aDictionary objectForKey:"fileTypes"]];
scopeName = [aDictionary objectForKey:@"scopeName"];
UUID = [aDictionary objectForKey:@"uuid"];
firstLineMatch = RegExpOrNil([aDictionary objectForKey:"firstLineMatch"]);
foldingStartMarker = RegExpOrNil([aDictionary objectForKey:"foldingStartMarker"]);
foldingStopMarker = RegExpOrNil([aDictionary objectForKey:"foldingStopMarker"]);
baseRule = [TMLanguageRule ruleWithDictionary:aDictionary grammar:self];
repository = [[aDictionary objectForKey:@"repository"] toLanguageRulesDictionaryWithGrammar:self];
[TMLanguageGrammar _registerGrammar:self];
}
return self;
}
- (id)initWithContentsOfURL:(CPURL)aURL
{
return [self initWithDictionary:PLIST.readPlist([aURL absoluteString])];
}
- (void)description
{
return [super description] +
(name ? "\n\tname: " + name : "") +
(scopeName ? "\n\tscopeName: " + scopeName : "") +
(baseRule ? "\n\trule: " + [baseRule description].split('\n').join("\n\t") : "");
}
@end