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}