Mercurial Hosting > luan
comparison src/luan/modules/parsers/Theme.java @ 775:1a68fc55a80c
simplify dir structure
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 26 Aug 2016 14:36:40 -0600 |
parents | core/src/luan/modules/parsers/Theme.java@c5f5b655f1f7 |
children | 88b5b81cad4a |
comparison
equal
deleted
inserted
replaced
774:3e30cf310e56 | 775:1a68fc55a80c |
---|---|
1 package luan.modules.parsers; | |
2 | |
3 import luan.LuanException; | |
4 | |
5 | |
6 public final class Theme { | |
7 | |
8 public static String toLuan(String source) throws LuanException { | |
9 try { | |
10 return new Theme(source).parse(); | |
11 } catch(ParseException e) { | |
12 throw new LuanException(e.getMessage()); | |
13 } | |
14 } | |
15 | |
16 private final Parser parser; | |
17 | |
18 private Theme(String source) { | |
19 this.parser = new Parser(source); | |
20 } | |
21 | |
22 private ParseException exception(String msg) { | |
23 // parser.failure(); | |
24 return new ParseException(parser,msg); | |
25 } | |
26 | |
27 private String parse() throws ParseException { | |
28 StringBuilder stmts = new StringBuilder(); | |
29 stmts.append( "local M = {}; " ); | |
30 while( !parser.endOfInput() ) { | |
31 String def = parseDef(); | |
32 if( def != null ) { | |
33 stmts.append(def); | |
34 } else { | |
35 // parser.anyChar(); | |
36 stmts.append(parsePadding()); | |
37 } | |
38 } | |
39 stmts.append( "\n\nreturn M\n" ); | |
40 return stmts.toString(); | |
41 } | |
42 | |
43 private String parsePadding() throws ParseException { | |
44 int start = parser.currentIndex(); | |
45 if( parser.match("--") ) { | |
46 while( parser.noneOf("\r\n") ); | |
47 } else if( !parser.anyOf(" \t\r\n") ) { | |
48 throw exception("unexpected text"); | |
49 } | |
50 return parser.textFrom(start); | |
51 } | |
52 | |
53 private String parseDef() throws ParseException { | |
54 int start = parser.begin(); | |
55 if( !parser.match('{') ) | |
56 return parser.failure(null); | |
57 spaces(); | |
58 if( !parser.match("define:") ) | |
59 return parser.failure(null); | |
60 String name = parseName(); | |
61 if( name==null ) | |
62 throw exception("invalid block name"); | |
63 spaces(); | |
64 if( !parser.match('}') ) | |
65 throw exception("unclosed define tag"); | |
66 String block = parseBody("define:"+name); | |
67 String rtn = "function M." + name + "(env) " + block + " end; "; | |
68 return parser.success(rtn); | |
69 } | |
70 | |
71 private String parseBody(String tagName) throws ParseException { | |
72 StringBuilder stmts = new StringBuilder(); | |
73 int start = parser.currentIndex(); | |
74 int end = start; | |
75 while( !matchEndTag(tagName) ) { | |
76 if( parser.endOfInput() ) { | |
77 parser.failure(); | |
78 throw exception("unclosed block"); | |
79 } | |
80 String block = parseBlock(); | |
81 if( block != null ) { | |
82 addText(start,end,stmts); | |
83 start = parser.currentIndex(); | |
84 stmts.append(block); | |
85 continue; | |
86 } | |
87 String simpleTag = parseSimpleTag(); | |
88 if( simpleTag != null ) { | |
89 addText(start,end,stmts); | |
90 start = parser.currentIndex(); | |
91 stmts.append(simpleTag); | |
92 continue; | |
93 } | |
94 if( parser.match("<%") ) { | |
95 addText(start,end,stmts); | |
96 start = parser.currentIndex(); | |
97 stmts.append("%><%='<%'%><%"); | |
98 continue; | |
99 } | |
100 parser.anyChar(); | |
101 end = parser.currentIndex(); | |
102 } | |
103 addText(start,end,stmts); | |
104 return stmts.toString(); | |
105 } | |
106 | |
107 private boolean matchEndTag(String tagName) { | |
108 parser.begin(); | |
109 if( !parser.match('{') ) | |
110 return parser.failure(); | |
111 spaces(); | |
112 if( !(parser.match('/') && parser.match(tagName)) ) | |
113 return parser.failure(); | |
114 spaces(); | |
115 if( !parser.match('}') ) | |
116 return parser.failure(); | |
117 return parser.success(); | |
118 } | |
119 | |
120 private void addText(int start,int end,StringBuilder stmts) { | |
121 if( start < end ) { | |
122 stmts.append( "%>" ).append( parser.text.substring(start,end) ).append( "<%" ); | |
123 } | |
124 } | |
125 | |
126 private String parseBlock() throws ParseException { | |
127 int start = parser.begin(); | |
128 if( !parser.match('{') ) | |
129 return parser.failure(null); | |
130 spaces(); | |
131 if( !parser.match("block:") ) | |
132 return parser.failure(null); | |
133 String name = parseName(); | |
134 if( name==null ) { | |
135 parser.failure(); | |
136 throw exception("invalid block name"); | |
137 } | |
138 spaces(); | |
139 if( !parser.match('}') ) | |
140 return parser.failure(null); | |
141 String block = parseBody("block:"+name); | |
142 String rtn = " env."+ name + "( env, function(env) " + block + "end); "; | |
143 // String rtn = "<% env." + tag.name + "(" + (tag.attrs.isEmpty() ? "nil" : table(tag.attrs)) + ",env,function(env) %>" + block + "<% end) %>"; | |
144 return parser.success(rtn); | |
145 } | |
146 | |
147 private String parseSimpleTag() throws ParseException { | |
148 int start = parser.begin(); | |
149 if( !parser.match('{') ) | |
150 return parser.failure(null); | |
151 spaces(); | |
152 String name = parseName(); | |
153 if( name==null ) | |
154 return parser.failure(null); | |
155 spaces(); | |
156 if( !parser.match('}') ) | |
157 return parser.failure(null); | |
158 // rtn = "<% env." + name + (attrs.isEmpty() ? "()" : table(attrs)) + " %>"; | |
159 String rtn = " env." + name + "(env); "; | |
160 return parser.success(rtn); | |
161 } | |
162 | |
163 private boolean BlankLine() { | |
164 parser.begin(); | |
165 while( parser.anyOf(" \t") ); | |
166 return EndOfLine() ? parser.success() : parser.failure(); | |
167 } | |
168 | |
169 private boolean EndOfLine() { | |
170 return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' ); | |
171 } | |
172 | |
173 private String parseName() throws ParseException { | |
174 int start = parser.begin(); | |
175 if( parser.match('/') ) { | |
176 parser.failure(); | |
177 throw exception("bad closing tag"); | |
178 } | |
179 if( parser.match("define:") ) { | |
180 parser.failure(); | |
181 throw exception("unexpected definition"); | |
182 } | |
183 if( !FirstNameChar() ) | |
184 return parser.failure(null); | |
185 while( NameChar() ); | |
186 String match = parser.textFrom(start); | |
187 return parser.success(match); | |
188 } | |
189 | |
190 private boolean FirstNameChar() { | |
191 return parser.inCharRange('a', 'z') || parser.inCharRange('A', 'Z') || parser.match('_'); | |
192 } | |
193 | |
194 private boolean NameChar() { | |
195 return FirstNameChar() || parser.inCharRange('0', '9'); | |
196 } | |
197 | |
198 private void spaces() { | |
199 while( parser.anyOf(" \t") ); | |
200 } | |
201 | |
202 } |