Mercurial Hosting > luan
view src/luan/modules/parsers/LuanToString.java @ 1562:b89212fd04b5
remove table.luan
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 08 Nov 2020 16:50:59 -0700 |
parents | 83249ce59d13 |
children | 8fbcc4747091 |
line wrap: on
line source
package luan.modules.parsers; import java.util.List; import java.util.Map; import java.util.Set; import java.util.HashSet; import java.util.Collections; import luan.Luan; import luan.LuanTable; import luan.LuanException; import luan.LuanRuntimeException; public final class LuanToString { public static class Settings implements Cloneable { public boolean strict = false; public boolean numberTypes = false; public boolean compressed = false; public boolean longStrings = false; public boolean inline = false; void applyOptions(Luan luan,LuanTable options) throws LuanException { Boolean b; b = (Boolean)options.get(luan,"strict"); if( b != null ) strict = b; b = (Boolean)options.get(luan,"number_types"); if( b != null ) numberTypes = b; b = (Boolean)options.get(luan,"compressed"); if( b != null ) compressed = b; b = (Boolean)options.get(luan,"long_strings"); if( b != null ) longStrings = b; b = (Boolean)options.get(luan,"inline"); if( b != null ) inline = b; } public Settings cloneSettings() { try { return (Settings)clone(); } catch(CloneNotSupportedException e) { throw new RuntimeException(e); } } } private static final Settings keySettings = new Settings(); private static final Set<String> settingsKeys = new HashSet<String>(); static { Collections.addAll(settingsKeys,"strict","number_types","compressed","long_strings","inline"); } private static void checkOptions(LuanTable options) throws LuanException { for( Map.Entry entry : options.iterable() ) { if( !settingsKeys.contains(entry.getKey()) ) throw new LuanException("invalid option: "+entry.getKey()); if( !(entry.getValue() instanceof Boolean) ) throw new LuanException("options values must be boolean"); } } public final Settings settingsInit = new Settings(); private final Luan luan; private final LuanTable subOptions; public LuanToString(Luan luan,LuanTable options,LuanTable subOptions) throws LuanException { this.luan = luan; this.subOptions = subOptions; if( options != null ) { checkOptions(options); settingsInit.applyOptions(luan,options); } if( subOptions != null ) { for( Map.Entry entry : subOptions.iterable() ) { /* if( !(entry.getKey() instanceof String) ) throw new LuanException("sub_options keys must be strings"); */ if( !(entry.getValue() instanceof LuanTable) ) throw new LuanException("sub_options keys must be tables"); LuanTable tbl = (LuanTable)entry.getValue(); checkOptions(tbl); } } } public String toString(Object obj) throws LuanException { StringBuilder sb = new StringBuilder(); toString(obj,sb,0,settingsInit); return sb.toString(); } private void toString(Object obj,StringBuilder sb,int indented,Settings settings) throws LuanException { if( obj == null ) { sb.append( "nil" ); return; } if( obj instanceof Boolean ) { sb.append( obj ); return; } if( obj instanceof Number ) { toString((Number)obj,sb,settings); return; } if( obj instanceof String ) { toString((String)obj,sb,settings); return; } if( obj instanceof LuanTable ) { toString((LuanTable)obj,sb,indented,settings); return; } if( settings.strict ) throw new LuanException("can't handle type "+Luan.type(obj)); sb.append( '<' ); sb.append( obj ); sb.append( '>' ); } private void toString(LuanTable tbl,StringBuilder sb,int indented,Settings settings) throws LuanException { List list = tbl.asList(); Map map = tbl.rawMap(); sb.append( '{' ); boolean first = true; for( Object obj : list ) { if( settings.compressed ) { if( first ) first = false; else sb.append( ',' ); } else if( settings.inline ) { if( first ) { first = false; sb.append( ' ' ); } else sb.append( ", " ); } else { indent(sb,indented+1); } toString(obj,sb,indented+1,settings); } for( Object obj : map.entrySet() ) { Map.Entry entry = (Map.Entry)obj; if( settings.compressed ) { if( first ) first = false; else sb.append( ',' ); } else if( settings.inline ) { if( first ) { first = false; sb.append( ' ' ); } else sb.append( ", " ); } else { indent(sb,indented+1); } toString(entry,sb,indented+1,settings); } if( !list.isEmpty() || !map.isEmpty() ) { if( settings.compressed ) { } else if( settings.inline ) { sb.append( ' ' ); } else { indent(sb,indented); } } sb.append( '}' ); return; } private void toString(Map.Entry entry,StringBuilder sb,int indented,Settings settings) throws LuanException { Object key = entry.getKey(); if( key instanceof String && ((String)key).matches("[a-zA-Z_][a-zA-Z_0-9]*") ) { sb.append( (String)key ); } else { sb.append( '[' ); toString( key, sb, indented, keySettings ); sb.append( ']' ); } sb.append( settings.compressed ? "=" : " = " ); if( subOptions != null ) { LuanTable options = (LuanTable)subOptions.get(luan,key); if( options != null ) { settings = settings.cloneSettings(); settings.applyOptions(luan,options); } } toString( entry.getValue(), sb, indented, settings ); } private void indent(StringBuilder sb,int indented) { sb.append( '\n' ); for( int i=0; i<indented; i++ ) { sb.append( '\t' ); } } private void toString(Number n,StringBuilder sb,Settings settings) throws LuanException { if( settings.numberTypes ) { sb.append( n.getClass().getSimpleName().toLowerCase() ); sb.append( '(' ); } sb.append( Luan.toString(n) ); if( settings.numberTypes ) sb.append( ')' ); } public static void addNumberTypes(Luan luan,LuanTable env) { try { LuanTable module = (LuanTable)luan.require("luan:Number.luan"); env.put( luan, "double", module.fn(luan,"double") ); env.put( luan, "float", module.fn(luan,"float") ); env.put( luan, "integer", module.fn(luan,"integer") ); env.put( luan, "long", module.fn(luan,"long") ); } catch(LuanException e) { throw new LuanRuntimeException(e); } } private void toString(String s,StringBuilder sb,Settings settings) { if( settings.longStrings ) { StringBuilder start = new StringBuilder("[["); if( s.indexOf('\n') != -1 ) start.append('\n'); StringBuilder end = new StringBuilder("]]"); while( s.contains(end) ) { start.insert(1,'='); end.insert(1,'='); } sb.append(start); sb.append(s); sb.append(end); return; } sb.append( '"' ); sb.append( Luan.stringEncode(s) ); sb.append( '"' ); } }