diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/modules/parsers/Theme.java	Fri Aug 26 14:36:40 2016 -0600
@@ -0,0 +1,202 @@
+package luan.modules.parsers;
+
+import luan.LuanException;
+
+
+public final class Theme {
+
+	public static String toLuan(String source) throws LuanException {
+		try {
+			return new Theme(source).parse();
+		} catch(ParseException e) {
+			throw new LuanException(e.getMessage());
+		}
+	}
+
+	private final Parser parser;
+
+	private Theme(String source) {
+		this.parser = new Parser(source);
+	}
+
+	private ParseException exception(String msg) {
+//		parser.failure();
+		return new ParseException(parser,msg);
+	}
+
+	private String parse() throws ParseException {
+		StringBuilder stmts = new StringBuilder();
+		stmts.append( "local M = {};  " );
+		while( !parser.endOfInput() ) {
+			String def = parseDef();
+			if( def != null ) {
+				stmts.append(def);
+			} else {
+//				parser.anyChar();
+				stmts.append(parsePadding());
+			}
+		}
+		stmts.append( "\n\nreturn M\n" );
+		return stmts.toString();
+	}
+
+	private String parsePadding() throws ParseException {
+		int start = parser.currentIndex();
+		if( parser.match("--") ) {
+			while( parser.noneOf("\r\n") );
+		} else if( !parser.anyOf(" \t\r\n") ) {
+			throw exception("unexpected text");
+		}
+		return parser.textFrom(start);
+	}
+
+	private String parseDef() throws ParseException {
+		int start = parser.begin();
+		if( !parser.match('{') )
+			return parser.failure(null);
+		spaces();
+		if( !parser.match("define:") )
+			return parser.failure(null);
+		String name = parseName();
+		if( name==null )
+			throw exception("invalid block name");
+		spaces();
+		if( !parser.match('}') )
+			throw exception("unclosed define tag");
+		String block = parseBody("define:"+name);
+		String rtn = "function M." + name + "(env) " + block + " end;  ";
+		return parser.success(rtn);
+	}
+
+	private String parseBody(String tagName) throws ParseException {
+		StringBuilder stmts = new StringBuilder();
+		int start = parser.currentIndex();
+		int end = start;
+		while( !matchEndTag(tagName) ) {
+			if( parser.endOfInput() ) {
+				parser.failure();
+				throw exception("unclosed block");
+			}
+			String block = parseBlock();
+			if( block != null ) {
+				addText(start,end,stmts);
+				start = parser.currentIndex();
+				stmts.append(block);
+				continue;
+			}
+			String simpleTag = parseSimpleTag();
+			if( simpleTag != null ) {
+				addText(start,end,stmts);
+				start = parser.currentIndex();
+				stmts.append(simpleTag);
+				continue;
+			}
+			if( parser.match("<%") ) {
+				addText(start,end,stmts);
+				start = parser.currentIndex();
+				stmts.append("%><%='<%'%><%");
+				continue;
+			}
+			parser.anyChar();
+			end = parser.currentIndex();
+		}
+		addText(start,end,stmts);
+		return stmts.toString();
+	}
+
+	private boolean matchEndTag(String tagName) {
+		parser.begin();
+		if( !parser.match('{') )
+			return parser.failure();
+		spaces();
+		if( !(parser.match('/') && parser.match(tagName)) )
+			return parser.failure();
+		spaces();
+		if( !parser.match('}') )
+			return parser.failure();
+		return parser.success();
+	}
+
+	private void addText(int start,int end,StringBuilder stmts) {
+		if( start < end ) {
+			stmts.append( "%>" ).append( parser.text.substring(start,end) ).append( "<%" );
+		}
+	}
+
+	private String parseBlock() throws ParseException {
+		int start = parser.begin();
+		if( !parser.match('{') )
+			return parser.failure(null);
+		spaces();
+		if( !parser.match("block:") )
+			return parser.failure(null);
+		String name = parseName();
+		if( name==null ) {
+			parser.failure();
+			throw exception("invalid block name");
+		}
+		spaces();
+		if( !parser.match('}') )
+			return parser.failure(null);
+		String block = parseBody("block:"+name);
+		String rtn = " env."+ name + "( env, function(env) " + block + "end); ";
+//		String rtn = "<% env." + tag.name + "(" + (tag.attrs.isEmpty() ? "nil" : table(tag.attrs)) + ",env,function(env) %>" + block + "<% end) %>";
+		return parser.success(rtn);
+	}
+
+	private String parseSimpleTag() throws ParseException {
+		int start = parser.begin();
+		if( !parser.match('{') )
+			return parser.failure(null);
+		spaces();
+		String name = parseName();
+		if( name==null )
+			return parser.failure(null);
+		spaces();
+		if( !parser.match('}') )
+			return parser.failure(null);
+//		rtn = "<% env." + name + (attrs.isEmpty() ? "()" : table(attrs)) + " %>";
+		String rtn = " env." + name + "(env); ";
+		return parser.success(rtn);
+	}
+
+	private boolean BlankLine() {
+		parser.begin();
+		while( parser.anyOf(" \t") );
+		return EndOfLine() ? parser.success() : parser.failure();
+	}
+
+	private boolean EndOfLine() {
+		return parser.match( "\r\n" ) || parser.match( '\r' ) || parser.match( '\n' );
+	}
+
+	private String parseName() throws ParseException {
+		int start = parser.begin();
+		if( parser.match('/') ) {
+			parser.failure();
+			throw exception("bad closing tag");
+		}
+		if( parser.match("define:") ) {
+			parser.failure();
+			throw exception("unexpected definition");
+		}
+		if( !FirstNameChar() )
+			return parser.failure(null);
+		while( NameChar() );
+		String match = parser.textFrom(start);
+		return parser.success(match);
+	}
+
+	private boolean FirstNameChar() {
+		return parser.inCharRange('a', 'z') || parser.inCharRange('A', 'Z') || parser.match('_');
+	}
+
+	private boolean NameChar() {
+		return FirstNameChar() || parser.inCharRange('0', '9');
+	}
+
+	private void spaces() {
+		while( parser.anyOf(" \t") );
+	}
+
+}