001package com.randomnoun.common.jessop.lang;
002
003/* (c) 2016 randomnoun. All Rights Reserved. This work is licensed under a
004 * BSD Simplified License. ( http://www.randomnoun.com/bsd-simplified.html ) 
005 */
006
007import org.apache.log4j.Logger;
008
009import com.randomnoun.common.jessop.AbstractJessopScriptBuilder;
010import com.randomnoun.common.jessop.JessopScriptBuilder;
011
012public class LuaJessopScriptBuilder extends AbstractJessopScriptBuilder implements JessopScriptBuilder {
013
014        Logger logger = Logger.getLogger(LuaJessopScriptBuilder.class);
015        int outputLine = 1;        // current line number in the target script;
016        int lastScriptletLine = 1; // the last line number of the last scriptlet (used for suppressEol)
017
018        public LuaJessopScriptBuilder() {
019        }
020        private void skipToLine(int line) {
021                while (outputLine < line) { print("\n"); }
022        }
023        private void print(String s) {
024                // logger.info("** PRINT " + s);
025                pw.print(s);
026                for (int i=0; i<s.length(); i++) {
027                        if (s.charAt(i)=='\n') { outputLine++; } 
028                }
029        }
030        private static String escapeLua(String string) {
031                /* valid escapes ( https://www.lua.org/pil/2.4.html )
032\a      bell
033\b      back space
034\f      form feed
035\n      newline
036\r      carriage return
037\t      horizontal tab
038\v      vertical tab
039\\      backslash
040\"      double quote
041\'      single quote
042\[      left square bracket
043\]      right square bracket
044                 */
045                
046        StringBuilder sb = new StringBuilder(string.length());
047        String escapeChars = "\u0007" + "\u0008" + "\u000f" + "\n" + "\r" + "\u0009" + "\u000b" + "\\" + "\"" + "'" + "[" + "]";
048        String backslashChars = "abfnrtv\\\"'[]";
049                for (int i = 0; i<string.length(); i++) {
050                        char ch = string.charAt(i);
051                        int pos = escapeChars.indexOf(ch);
052                        if (pos !=- 1) {
053                           sb.append("\\" + backslashChars.charAt(pos));
054                        
055                        // so apparently lua allows any character in a string whatsoever. looking forward to seeing this breaking.
056                        // have seen some examples of, e.g. \006 to represent chars, but nothing in the lua spec
057                           
058                        //} else if (ch=='\\' || ch=='"' || ch=='\'' || ch<32 && ch>126) {
059                        //      String hex = Integer.toString(ch, 16);
060                        //      // sb.append("\\u" + "0000".substring(0, 4-hex.length()) + hex);
061                        //      sb.append(ch); 
062                        } else {
063                                sb.append(ch);
064                        }
065                }
066        return sb.toString();
067    }
068        
069        @Override
070        public void emitText(int line, String s) {
071                skipToLine(line);
072                s = suppressEol(s, declarations.isSuppressEol() && lastScriptletLine == line);
073                print("out:write(\"" + escapeLua(s) + "\")");
074                lastScriptletLine = 0; // don't suppress eols on this line
075        }
076        @Override
077        public void emitExpression(int line, String s) {
078                skipToLine(line);
079                print("out:write((" + s + ") .. \"\")"); // coerce to String
080                lastScriptletLine = 0; // don't suppress eols on this line
081        }
082        @Override
083        public void emitScriptlet(int line, String s) {
084                skipToLine(line);
085                print(s);
086                lastScriptletLine = line;
087                for (int i=0; i<s.length(); i++) { if (s.charAt(i)=='\n') { lastScriptletLine++; } }
088        }
089        @Override
090        public String getLanguage() {
091                return "lua";
092        }
093        @Override
094        public String getDefaultScriptEngineName() {
095                return "luaj";
096        }
097        @Override
098        public String getDefaultExceptionConverterClassName() {
099                return "com.randomnoun.common.jessop.engine.LuajExceptionConverter";
100        }
101
102        
103
104}