comparison src/luan/modules/parsers/LuanToString.java @ 1623:582384548a69

LuanToString takes function
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 01 Aug 2021 18:59:01 -0600
parents a37ffe2d1b14
children f8f5c51f5b36
comparison
equal deleted inserted replaced
1622:b7f8418fb7ba 1623:582384548a69
11 import luan.LuanException; 11 import luan.LuanException;
12 import luan.LuanRuntimeException; 12 import luan.LuanRuntimeException;
13 13
14 14
15 public final class LuanToString { 15 public final class LuanToString {
16 private static final Set<String> settingsKeys = new HashSet<String>();
17 static {
18 Collections.addAll(settingsKeys
19 ,"strict"
20 ,"number_types"
21 ,"compressed"
22 ,"long_strings"
23 ,"inline"
24 ,"no_name_keys"
25 );
26 }
27
28 private static void checkOptions(LuanTable options) throws LuanException {
29 for( Map.Entry entry : options.rawIterable() ) {
30 if( !settingsKeys.contains(entry.getKey()) )
31 throw new LuanException("invalid option: "+entry.getKey());
32 if( !(entry.getValue() instanceof Boolean) )
33 throw new LuanException("options values must be boolean");
34 }
35 }
36
16 public static class Settings implements Cloneable { 37 public static class Settings implements Cloneable {
17 public boolean strict = false; 38 public boolean strict = false;
18 public boolean numberTypes = false; 39 public boolean numberTypes = false;
19 public boolean compressed = false; 40 public boolean compressed = false;
20 public boolean longStrings = false; 41 public boolean longStrings = false;
21 public boolean inline = false; 42 public boolean inline = false;
43 public boolean noNameKeys = false;
22 44
23 void applyOptions(LuanTable options) throws LuanException { 45 void applyOptions(LuanTable options) throws LuanException {
46 checkOptions(options);
24 Boolean b; 47 Boolean b;
25 b = (Boolean)options.rawGet("strict"); 48 b = (Boolean)options.rawGet("strict");
26 if( b != null ) 49 if( b != null )
27 strict = b; 50 strict = b;
28 b = (Boolean)options.rawGet("number_types"); 51 b = (Boolean)options.rawGet("number_types");
35 if( b != null ) 58 if( b != null )
36 longStrings = b; 59 longStrings = b;
37 b = (Boolean)options.rawGet("inline"); 60 b = (Boolean)options.rawGet("inline");
38 if( b != null ) 61 if( b != null )
39 inline = b; 62 inline = b;
63 b = (Boolean)options.rawGet("no_name_keys");
64 if( b != null )
65 noNameKeys = b;
40 } 66 }
41 67
42 public Settings cloneSettings() { 68 public Settings cloneSettings() {
43 try { 69 try {
44 return (Settings)clone(); 70 return (Settings)clone();
46 throw new RuntimeException(e); 72 throw new RuntimeException(e);
47 } 73 }
48 } 74 }
49 } 75 }
50 private static final Settings keySettings = new Settings(); 76 private static final Settings keySettings = new Settings();
51 private static final Set<String> settingsKeys = new HashSet<String>();
52 static {
53 Collections.addAll(settingsKeys,"strict","number_types","compressed","long_strings","inline");
54 }
55
56 private static void checkOptions(LuanTable options) throws LuanException {
57 for( Map.Entry entry : options.rawIterable() ) {
58 if( !settingsKeys.contains(entry.getKey()) )
59 throw new LuanException("invalid option: "+entry.getKey());
60 if( !(entry.getValue() instanceof Boolean) )
61 throw new LuanException("options values must be boolean");
62 }
63 }
64 77
65 public final Settings settingsInit = new Settings(); 78 public final Settings settingsInit = new Settings();
66 public Luan luan = null; 79 private final Luan luan;
67 private final LuanTable subOptions; 80 private final LuanFunction fnOptions;
68 81 private final LuanTable stack = new LuanTable();
69 public LuanToString(LuanTable options,LuanTable subOptions) throws LuanException { 82
70 this.subOptions = subOptions; 83 public LuanToString() {
71 if( options != null ) { 84 this.luan = null;
72 checkOptions(options); 85 this.fnOptions = null;
86 }
87
88 public LuanToString(Luan luan) throws LuanException {
89 this.luan = luan;
90 this.fnOptions = null;
91 }
92
93 public LuanToString(Luan luan,LuanTable options) throws LuanException {
94 this.luan = luan;
95 this.fnOptions = null;
96 settingsInit.applyOptions(options);
97 }
98
99 public LuanToString(Luan luan,LuanFunction fnOptions) throws LuanException {
100 this.luan = luan;
101 this.fnOptions = fnOptions;
102 LuanTable options = getOptions();
103 if( options != null )
73 settingsInit.applyOptions(options); 104 settingsInit.applyOptions(options);
74 } 105 }
75 if( subOptions != null ) { 106
76 for( Map.Entry entry : subOptions.rawIterable() ) { 107 private LuanTable getOptions() throws LuanException {
77 /* 108 if( fnOptions == null )
78 if( !(entry.getKey() instanceof String) ) 109 return null;
79 throw new LuanException("sub_options keys must be strings"); 110 Object rtn = fnOptions.call(luan,stack);
80 */ 111 if( !(rtn==null || rtn instanceof LuanTable) )
81 if( !(entry.getValue() instanceof LuanTable) ) 112 throw new LuanException("options-function must return table or nil");
82 throw new LuanException("sub_options keys must be tables"); 113 return (LuanTable)rtn;
83 LuanTable tbl = (LuanTable)entry.getValue();
84 checkOptions(tbl);
85 }
86 }
87 } 114 }
88 115
89 public String toString(Object obj) throws LuanException { 116 public String toString(Object obj) throws LuanException {
90 StringBuilder sb = new StringBuilder(); 117 StringBuilder sb = new StringBuilder();
91 toString(obj,sb,0,settingsInit); 118 toString(obj,sb,0,settingsInit);
210 } 237 }
211 sb.append( '}' ); 238 sb.append( '}' );
212 return; 239 return;
213 } 240 }
214 241
215 private void toString(Map.Entry entry,StringBuilder sb,int indented,Settings settings) throws LuanException { 242 private void toString(Map.Entry entry,StringBuilder sb,int indented,Settings settings)
243 throws LuanException
244 {
216 Object key = entry.getKey(); 245 Object key = entry.getKey();
217 if( key instanceof String && ((String)key).matches("[a-zA-Z_][a-zA-Z_0-9]*") ) { 246 if( key instanceof String && !settings.noNameKeys && ((String)key).matches("[a-zA-Z_][a-zA-Z_0-9]*") ) {
218 sb.append( (String)key ); 247 sb.append( (String)key );
219 } else { 248 } else {
220 sb.append( '[' ); 249 sb.append( '[' );
221 toString( key, sb, indented, keySettings ); 250 toString( key, sb, indented, keySettings );
222 sb.append( ']' ); 251 sb.append( ']' );
223 } 252 }
224 sb.append( settings.compressed ? "=" : " = " ); 253 sb.append( settings.compressed ? "=" : " = " );
225 if( subOptions != null ) { 254 stack.rawAdd(key); // push
226 LuanTable options = (LuanTable)subOptions.rawGet(key); 255 LuanTable options = getOptions();
227 if( options != null ) { 256 if( options != null ) {
228 settings = settings.cloneSettings(); 257 settings = settings.cloneSettings();
229 settings.applyOptions(options); 258 settings.applyOptions(options);
230 }
231 } 259 }
232 toString( entry.getValue(), sb, indented, settings ); 260 toString( entry.getValue(), sb, indented, settings );
261 stack.removeFromList(stack.rawLength()); // pop
233 } 262 }
234 263
235 private void indent(StringBuilder sb,int indented) { 264 private void indent(StringBuilder sb,int indented) {
236 sb.append( '\n' ); 265 sb.append( '\n' );
237 for( int i=0; i<indented; i++ ) { 266 for( int i=0; i<indented; i++ ) {