From 39e828ff1032d441e41188b7e1a07e0cdb9566c3 Mon Sep 17 00:00:00 2001 From: "moandji.ezana" Date: Mon, 11 Aug 2014 00:51:21 +0200 Subject: [PATCH] Handle nested arrays --- .../moandjiezana/toml/ParboiledParser.java | 55 +++++++++ .../com/moandjiezana/toml/RegexParser.java | 5 - .../com/moandjiezana/toml/ValueAnalysis.java | 113 +++++++----------- 3 files changed, 96 insertions(+), 77 deletions(-) create mode 100644 src/main/java/com/moandjiezana/toml/ParboiledParser.java diff --git a/src/main/java/com/moandjiezana/toml/ParboiledParser.java b/src/main/java/com/moandjiezana/toml/ParboiledParser.java new file mode 100644 index 0000000..5a63477 --- /dev/null +++ b/src/main/java/com/moandjiezana/toml/ParboiledParser.java @@ -0,0 +1,55 @@ +package com.moandjiezana.toml; + +import java.util.ArrayList; +import java.util.List; + +import org.parboiled.BaseParser; +import org.parboiled.Rule; + +public class ParboiledParser extends BaseParser> { + + public Rule Array() { + return Sequence('[', startList(), ArrayDo(), ']', endList()); + } + + Rule ArrayDo() { + return OneOrMore(TestNot(']'), FirstOf(String(), Array(), ',', ' ', OtherValue())); + } + + Rule String() { + return Sequence(Sequence('"', ZeroOrMore(TestNot('"'), ANY), '"'), pushToken(match())); + } + + Rule OtherValue() { + return Sequence(ZeroOrMore(NoneOf("],")), pushToken(match())); + } + +// private Rule Comment() { +// return Sequence('#' , ZeroOrMore(TestNot(EOI), ANY)); +// } + + boolean startList() { + ArrayList newTokens = new ArrayList(); + + if (!getContext().getValueStack().isEmpty()) { + peek().add(newTokens); + } + push(newTokens); + + return true; + } + + boolean endList() { + if (getContext().getValueStack().size() > 1) { + pop(); + } + + return true; + } + + boolean pushToken(String s) { + peek().add(s); + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/com/moandjiezana/toml/RegexParser.java b/src/main/java/com/moandjiezana/toml/RegexParser.java index 11609b6..b2c2367 100644 --- a/src/main/java/com/moandjiezana/toml/RegexParser.java +++ b/src/main/java/com/moandjiezana/toml/RegexParser.java @@ -11,10 +11,6 @@ public class RegexParser { private static final Pattern MULTILINE_ARRAY_REGEX = Pattern.compile("\\s*\\[([^\\]]*)"); private static final Pattern MULTILINE_ARRAY_REGEX_END = Pattern.compile("\\s*\\]"); - public static void main(String[] args) { - System.out.println(MULTILINE_ARRAY_REGEX.matcher(" [ ]").matches()); - } - private final Results results = new Results(); public Results run(String tomlString) { @@ -161,5 +157,4 @@ public class RegexParser { return line; } - } diff --git a/src/main/java/com/moandjiezana/toml/ValueAnalysis.java b/src/main/java/com/moandjiezana/toml/ValueAnalysis.java index bf56693..c422308 100644 --- a/src/main/java/com/moandjiezana/toml/ValueAnalysis.java +++ b/src/main/java/com/moandjiezana/toml/ValueAnalysis.java @@ -6,17 +6,19 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.parboiled.Parboiled; +import org.parboiled.parserunners.ReportingParseRunner; +import org.parboiled.support.ParsingResult; + class ValueAnalysis { static final Object INVALID = new Object(); + private static final List INVALID_ARRAY = new ArrayList(); - private static final Pattern STRING_REGEX = Pattern.compile("\"(.*)\"(.*)"); private static final Pattern BOOLEAN_REGEX = Pattern.compile("(true|false)(.*)"); private static final Pattern FLOAT_REGEX = Pattern.compile("(-?[0-9\\.]*)(.*)"); private static final Pattern INTEGER_REGEX = Pattern.compile("(-?[0-9]*)(.*)"); private static final Pattern DATE_REGEX = Pattern.compile("(\\d{4}-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-5][0-9]Z)(.*)"); - private static final Pattern LIST_REGEX = Pattern.compile("(\\[(.*)\\])(.*)"); private static final Pattern UNICODE_REGEX = Pattern.compile("\\\\u(.*)"); - private static final Pattern RESERVED_CHARACTER_REGEX = Pattern.compile("\\\\[^bfntr\"/\\\\]"); private final String rawValue; private Matcher chosenMatcher; @@ -38,17 +40,14 @@ class ValueAnalysis { return Double.valueOf(chosenMatcher.group(1)); } else if (isBoolean(value)) { return Boolean.valueOf(chosenMatcher.group(1)); - } else if (isList(value)) { - ArrayList values = new ArrayList(); - value = chosenMatcher.group(1); - String[] split = value.substring(1, value.length() - 1).split(","); - for (String s : split) { - Object converted = convert(s.trim()); - if (values.isEmpty() || values.get(0).getClass().isAssignableFrom(converted.getClass()) || converted.getClass().isAssignableFrom(values.get(0).getClass())) { - values.add(converted); - } else { - return INVALID; - } + } else if (isArray(value)) { + ParboiledParser parser = Parboiled.createParser(ParboiledParser.class); + ParsingResult> parsingResult = new ReportingParseRunner>(parser.Array()).run(value); + List tokens = parsingResult.resultValue; + List values = convertList(tokens); + + if (values == INVALID_ARRAY) { + return INVALID; } return values; @@ -80,18 +79,6 @@ class ValueAnalysis { } return false; -// char[] chars = value.toCharArray(); -// -// for (int i = 0; i < chars.length; i++) { -// char ch = chars[i]; -// if (Character.isDigit(ch) || ch == '.' || (i == 0 && ch == '-')) { -// continue; -// } -// -// return false; -// } -// -// return true; } private boolean isDate(String value) { @@ -114,56 +101,14 @@ class ValueAnalysis { } return false; -// char[] chars = s.toCharArray(); -// -// for (int i = 0; i < chars.length; i++) { -// if (Character.isDigit(chars[i]) || (i == 0 && chars[i] == '-')) { -// continue; -// } -// -// return false; -// } -// -// return true; } - private boolean isList(String s) { - Matcher matcher = LIST_REGEX.matcher(s); - - if (matcher.matches()) { - chosenMatcher = matcher; - - return true; - } - - return false; + private boolean isArray(String s) { + return s.startsWith("["); } - private List tokenizeList(String list) { - ArrayList strings = new ArrayList(); - char[] chars = list.toCharArray(); - int openIndex = -1; - - for (int i = 0; i < chars.length && openIndex < 0; i++) { - - } - - StringBuilder token = new StringBuilder(); - boolean ignore = false; - for (int i = 0; i < chars.length; i++) { - if (ignore) { - continue; - } - if (chars[i] == '[') - if (chars[i] != ',') { - token.append(chars[i]); - } else { - strings.add(token.toString().trim()); - token = new StringBuilder(); - } - } - - return strings; + private boolean isHomogenousArray(Object o, List values) { + return values.get(0).getClass().isAssignableFrom(o.getClass()) || o.getClass().isAssignableFrom(values.get(0).getClass()); } private boolean isBoolean(String s) { @@ -232,6 +177,30 @@ class ValueAnalysis { return value; } + private List convertList(List tokens) { + ArrayList nestedList = new ArrayList(); + + for (Object token : tokens) { + if (token instanceof String) { + Object converted = convert(((String) token).trim()); + if (nestedList.isEmpty() || isHomogenousArray(converted, nestedList)) { + nestedList.add(converted); + } else { + return INVALID_ARRAY; + } + } else if (token instanceof List) { + List convertedList = convertList((List) token); + if (convertedList != INVALID_ARRAY) { + nestedList.add(convertedList); + } else { + return INVALID_ARRAY; + } + } + } + + return nestedList; + } + private String replaceUnicodeCharacters(String value) { Matcher unicodeMatcher = UNICODE_REGEX.matcher(value);