diff 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
line wrap: on
line diff
--- a/src/luan/modules/parsers/LuanToString.java	Mon Jul 26 11:51:56 2021 -0600
+++ b/src/luan/modules/parsers/LuanToString.java	Sun Aug 01 18:59:01 2021 -0600
@@ -13,14 +13,37 @@
 
 
 public final class LuanToString {
+	private static final Set<String> settingsKeys = new HashSet<String>();
+	static {
+		Collections.addAll(settingsKeys
+			,"strict"
+			,"number_types"
+			,"compressed"
+			,"long_strings"
+			,"inline"
+			,"no_name_keys"
+		);
+	}
+
+	private static void checkOptions(LuanTable options) throws LuanException {
+		for( Map.Entry entry : options.rawIterable() ) {
+			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 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;
+		public boolean noNameKeys = false;
 
 		void applyOptions(LuanTable options) throws LuanException {
+			checkOptions(options);
 			Boolean b;
 			b = (Boolean)options.rawGet("strict");
 			if( b != null )
@@ -37,6 +60,9 @@
 			b = (Boolean)options.rawGet("inline");
 			if( b != null )
 				inline = b;
+			b = (Boolean)options.rawGet("no_name_keys");
+			if( b != null )
+				noNameKeys = b;
 		}
 
 		public Settings cloneSettings() {
@@ -48,42 +74,43 @@
 		}
 	}
 	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.rawIterable() ) {
-			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();
-	public Luan luan = null;
-	private final LuanTable subOptions;
+	private final Luan luan;
+	private final LuanFunction fnOptions;
+	private final LuanTable stack = new LuanTable();
+
+	public LuanToString() {
+		this.luan = null;
+		this.fnOptions = null;
+	}
 
-	public LuanToString(LuanTable options,LuanTable subOptions) throws LuanException {
-		this.subOptions = subOptions;
-		if( options != null ) {
-			checkOptions(options);
+	public LuanToString(Luan luan) throws LuanException {
+		this.luan = luan;
+		this.fnOptions = null;
+	}
+
+	public LuanToString(Luan luan,LuanTable options) throws LuanException {
+		this.luan = luan;
+		this.fnOptions = null;
+		settingsInit.applyOptions(options);
+	}
+
+	public LuanToString(Luan luan,LuanFunction fnOptions) throws LuanException {
+		this.luan = luan;
+		this.fnOptions = fnOptions;
+		LuanTable options = getOptions();
+		if( options != null )
 			settingsInit.applyOptions(options);
-		}
-		if( subOptions != null ) {
-			for( Map.Entry entry : subOptions.rawIterable() ) {
-/*
-				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);
-			}
-		}
+	}
+
+	private LuanTable getOptions() throws LuanException {
+		if( fnOptions == null )
+			return null;
+		Object rtn = fnOptions.call(luan,stack);
+		if( !(rtn==null || rtn instanceof LuanTable) )
+			throw new LuanException("options-function must return table or nil");
+		return (LuanTable)rtn;
 	}
 
 	public String toString(Object obj) throws LuanException {
@@ -212,9 +239,11 @@
 		return;
 	}
 
-	private void toString(Map.Entry entry,StringBuilder sb,int indented,Settings settings) throws LuanException {
+	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]*") ) {
+		if( key instanceof String && !settings.noNameKeys && ((String)key).matches("[a-zA-Z_][a-zA-Z_0-9]*") ) {
 			sb.append( (String)key );
 		} else {
 			sb.append( '[' );
@@ -222,14 +251,14 @@
 			sb.append( ']' );
 		}
 		sb.append( settings.compressed ? "=" : " = " );
-		if( subOptions != null ) {
-			LuanTable options = (LuanTable)subOptions.rawGet(key);
-			if( options != null ) {
-				settings = settings.cloneSettings();
-				settings.applyOptions(options);
-			}
+		stack.rawAdd(key);  // push
+		LuanTable options = getOptions();
+		if( options != null ) {
+			settings = settings.cloneSettings();
+			settings.applyOptions(options);
 		}
 		toString( entry.getValue(), sb, indented, settings );
+		stack.removeFromList(stack.rawLength());  // pop
 	}
 
 	private void indent(StringBuilder sb,int indented) {