package org.lateralgm.libmaker.code;
import java.awt.Color;
import java.awt.Font;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.lateralgm.joshedit.DefaultTokenMarker.KeywordSet;
public class GmlSyntax
{
public static Construct[] CONSTRUCTS;
public static Operator[] OPERATORS;
public static Variable[] VARIABLES;
public static Constant[] CONSTANTS;
public static Function[] FUNCTIONS;
public static final Keyword[][] GML_KEYWORDS = { CONSTRUCTS,FUNCTIONS,VARIABLES,OPERATORS,
CONSTANTS };
private static final Color BROWN = new Color(128,0,0);
private static final Color FUNCTION = new Color(0,0,128);
static KeywordSet constructs, functions, operators, constants, variables;
static
{
populateFunctions();
populateKeywords();
functions = new KeywordSet("Functions",FUNCTION,Font.PLAIN);
constructs = new KeywordSet("Constructs",Color.BLACK,Font.BOLD);
operators = new KeywordSet("Operators",Color.BLACK,Font.BOLD);
constants = new KeywordSet("Constants",BROWN,Font.PLAIN);
variables = new KeywordSet("Variables",Color.BLUE,Font.ITALIC);
}
private static void populateFunctions()
{
final String fn2 = "functions.txt";
InputStream is2 = GmlSyntax.class.getResourceAsStream(fn2);
BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));
ArrayList<Function> list = new ArrayList<Function>();
try
{
String func;
while ((func = br2.readLine()) != null)
{
String args = br2.readLine();
String desc = br2.readLine();
list.add(new Function(func,args,desc));
}
}
catch (IOException e)
{
e.printStackTrace();
}
FUNCTIONS = list.toArray(new Function[0]);
}
private static void populateKeywords()
{
Properties KEYWORD_PROPS = new Properties();
try
{
KEYWORD_PROPS.load(GmlSyntax.class.getResourceAsStream("gmlkeywords.properties")); //$NON-NLS-1$
}
catch (IOException e)
{
//Silently revert (probably to C++ keywords)
return;
}
String[] s = KEYWORD_PROPS.getProperty("CONSTRUCTS").split("\\s+");
CONSTRUCTS = new Construct[s.length];
for (int i = 0; i < s.length; i++)
CONSTRUCTS[i] = new Construct(s[i]);
s = KEYWORD_PROPS.getProperty("OPERATORS").split("\\s+");
OPERATORS = new Operator[s.length];
for (int i = 0; i < s.length; i++)
OPERATORS[i] = new Operator(s[i]);
s = KEYWORD_PROPS.getProperty("VARIABLES").split("\\s+");
VARIABLES = new Variable[s.length];
for (int i = 0; i < s.length; i++)
VARIABLES[i] = new Variable(s[i]);
s = KEYWORD_PROPS.getProperty("CONSTANTS").split("\\s+");
CONSTANTS = new Constant[s.length];
for (int i = 0; i < s.length; i++)
CONSTANTS[i] = new Constant(s[i]);
KEYWORD_PROPS.clear();
}
private GmlSyntax()
{
}
public abstract static class Keyword
{
protected String name;
public String getName()
{
return name;
}
}
public static class Construct extends Keyword
{
public Construct(String input)
{
name = input;
}
}
public static class Operator extends Keyword
{
public Operator(String input)
{
name = input;
}
}
public static class Variable extends Keyword
{
public final boolean readOnly;
public final int arraySize;
public Variable(String input)
{
Matcher m = Pattern.compile("(\\w+)(\\[(\\d+)])?(\\*)?").matcher(input);
if (!m.matches()) System.err.println("Invalid variable: " + input);
name = m.group(1);
String s = m.group(3);
arraySize = s != null ? Integer.valueOf(m.group(3)) : 0;
readOnly = "*".equals(m.group(4));
}
}
public static class Constant extends Keyword
{
public Constant(String input)
{
name = input;
}
}
public static class Function extends Keyword
{
public final String description;
public final String[] arguments;
public final int dynArgIndex;
public final int dynArgMin;
public final int dynArgMax;
public Function(String input)
{
// 1 1 23 3 245 5 6 6 7 7 8 84 9 9
// /(\w+)\(((\w+,)*)((\w+)\{(\d+),(\d+)}((?=\))|,))?(\w+)?\)/
// fun ( arg, arg { 0 , 9 } , arg )
String re = "(\\w+)\\(((\\w+,)*)((\\w+)\\{(\\d+),(\\d+)}((?=\\))|,))?(\\w+)?\\)";
Matcher m = Pattern.compile(re).matcher(input);
if (!m.matches()) System.err.println("Invalid function: " + input);
name = m.group(1); //the function name
String a1 = m.group(2); //plain arguments with commas
String da = m.group(5); //argument with range
String daMin = m.group(6); //range min
String daMax = m.group(7); //range max
String a2 = m.group(9); //last argument
String[] aa1 = a1.length() > 0 ? a1.split(",") : new String[0];
arguments = new String[aa1.length + (da != null ? 1 : 0) + (a2 != null ? 1 : 0)];
System.arraycopy(aa1,0,arguments,0,aa1.length);
if (da == null)
{
dynArgIndex = -1;
dynArgMin = 0;
dynArgMax = 0;
}
else
{
dynArgIndex = aa1.length;
dynArgMin = Integer.parseInt(daMin);
dynArgMax = Integer.parseInt(daMax);
arguments[aa1.length] = da;
}
if (a2 != null) arguments[arguments.length - 1] = a2;
description = "";
}
public Function(String func, String args, String desc)
{
name = func;
arguments = args.split(",");
description = desc;
dynArgIndex = -1;
dynArgMin = 0;
dynArgMax = 0;
}
}
}