Skip to content

Commit

Permalink
🚧 initiating development of a brand new YAML parser
Browse files Browse the repository at this point in the history
  • Loading branch information
arnaudroques committed Feb 4, 2025
1 parent 2f79134 commit 65db45c
Show file tree
Hide file tree
Showing 5 changed files with 370 additions and 0 deletions.
143 changes: 143 additions & 0 deletions src/net/sourceforge/plantuml/yaml/parser/YamlLine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2024, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*/
package net.sourceforge.plantuml.yaml.parser;

import java.util.Optional;

import net.sourceforge.plantuml.annotation.DuplicateCode;

public class YamlLine {

private final int indent;
private final String key;
private final String value;
private final boolean listItem;

public static Optional<YamlLine> build(String line) {
int count = 0;
while (count < line.length() && line.charAt(count) == ' ')
count++;

String trimmedLine = removeYamlComment(line.substring(count).trim());

if (trimmedLine.isEmpty())
return Optional.empty();

final boolean listItem = trimmedLine.startsWith("- ");

if (listItem) {
count += 2;
trimmedLine = trimmedLine.substring(2);
}

final int colonIndex = trimmedLine.indexOf(':');
if (colonIndex == -1)
return Optional.empty();

final String rawKey = trimmedLine.substring(0, colonIndex).trim();
final String rawValue = trimmedLine.substring(colonIndex + 1).trim();

return Optional.of(new YamlLine(count, unquote(rawKey), unquote(rawValue), listItem));

}

private YamlLine(int indent, String key, String value, boolean listItem) {
this.indent = indent;
this.key = key;
this.value = value;
this.listItem = listItem;
}

private static String unquote(String str) {
if (str == null || str.length() < 2)
return str;

final char first = str.charAt(0);
final char last = str.charAt(str.length() - 1);
if ((first == '"' && last == '"') || (first == '\'' && last == '\''))
return str.substring(1, str.length() - 1);

return str;
}

public int getIndent() {
return indent;
}

@DuplicateCode(reference = "YamlLines")
private static String removeYamlComment(String s) {
if (s == null || s.isEmpty())
return s;

char inQuoteChar = '\0';

if (s.charAt(0) == '#')
return "";

for (int i = 0; i < s.length(); i++) {
final char c = s.charAt(i);

if (c == '\'' || c == '"')
if (inQuoteChar == '\0')
inQuoteChar = c;
else if (c == inQuoteChar)
inQuoteChar = '\0';

if (inQuoteChar == '\0' && i < s.length() - 1 && c == ' ' && s.charAt(i + 1) == '#')
return s.substring(0, i);

}

return s;
}

public String getKey() {
return key;
}

public String getValue() {
return value;
}

public boolean isListItem() {
return listItem;
}

@Override
public String toString() {
return "YamlLine(indent=" + indent + ", key=" + key + ", value=" + value + ")";
}

}
51 changes: 51 additions & 0 deletions src/net/sourceforge/plantuml/yaml/parser/YamlParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2024, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*/
package net.sourceforge.plantuml.yaml.parser;

import java.util.List;

public class YamlParser {

public YamlParser(int indentSize) {
}

// In some future, we will return something
public void parse(List<String> lines) {
System.err.println(lines);

}


}
42 changes: 42 additions & 0 deletions src/net/sourceforge/plantuml/yaml/parser/YamlSyntaxException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2024, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*/
package net.sourceforge.plantuml.yaml.parser;

public class YamlSyntaxException extends RuntimeException {

public YamlSyntaxException(String message) {
super(message);
}
}
111 changes: 111 additions & 0 deletions test/net/sourceforge/plantuml/yaml/parser/YamlLineTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package net.sourceforge.plantuml.yaml.parser;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

class YamlLineTest {

@Test
void testSimple() {
YamlLine yamlLine = YamlLine.build(" name: vibrant").get();
assertEquals(2, yamlLine.getIndent());
assertEquals("name", yamlLine.getKey());
assertEquals("vibrant", yamlLine.getValue());
}

@Test
void testQuotedKey() {
YamlLine yamlLine = YamlLine.build(" \"name\": vibrant").get();
assertEquals(2, yamlLine.getIndent());
assertEquals("name", yamlLine.getKey());
assertEquals("vibrant", yamlLine.getValue());
}

@Test
void testQuotedValue() {
YamlLine yamlLine = YamlLine.build(" name: \"vibrant\"").get();
assertEquals(2, yamlLine.getIndent());
assertEquals("name", yamlLine.getKey());
assertEquals("vibrant", yamlLine.getValue());
}

@Test
void testQuotedKeyAndValue() {
YamlLine yamlLine = YamlLine.build(" \"name\": \"vibrant\"").get();
assertEquals(2, yamlLine.getIndent());
assertEquals("name", yamlLine.getKey());
assertEquals("vibrant", yamlLine.getValue());
}

@Test
void testKeyWithSpaces() {
YamlLine yamlLine = YamlLine.build(" \"full name\": \"John Doe\"").get();
assertEquals(2, yamlLine.getIndent());
assertEquals("full name", yamlLine.getKey());
assertEquals("John Doe", yamlLine.getValue());
}

@Test
void testValueWithComment() {
YamlLine yamlLine = YamlLine.build(" name: vibrant # primary color").get();
assertEquals(2, yamlLine.getIndent());
assertEquals("vibrant", yamlLine.getValue());
assertEquals("name", yamlLine.getKey());
}

@Test
void testCommentLineOnly() {
assertFalse(YamlLine.build(" # This is a comment").isPresent());
}

@Test
void testNoIndent() {
YamlLine yamlLine = YamlLine.build("name: vibrant").get();
assertEquals(0, yamlLine.getIndent());
assertEquals("name", yamlLine.getKey());
assertEquals("vibrant", yamlLine.getValue());
}

@Test
void testExtraSpacesAroundColon() {
YamlLine yamlLine = YamlLine.build(" name : vibrant ").get();
assertEquals(2, yamlLine.getIndent());
assertEquals("name", yamlLine.getKey());
assertEquals("vibrant", yamlLine.getValue());
}

@Test
void testMissingValue() {
YamlLine yamlLine = YamlLine.build(" name:").get();
assertEquals(2, yamlLine.getIndent());
assertEquals("name", yamlLine.getKey());
assertEquals("", yamlLine.getValue());
}

@Test
void testSharpInString() {
YamlLine yamlLine = YamlLine.build(" \"full name\": \"John # Doe\"").get();
assertEquals(2, yamlLine.getIndent());
assertEquals("full name", yamlLine.getKey());
assertEquals("John # Doe", yamlLine.getValue());
}

@Test
void testMissingColon() {
assertFalse(YamlLine.build(" name vibrant").isPresent());
}


@Test
void testIsListItem() {
YamlLine yamlLine = YamlLine.build(" - primary: ffcc00").get();
assertEquals(6, yamlLine.getIndent());
assertTrue(yamlLine.isListItem());
assertEquals("primary", yamlLine.getKey());
assertEquals("ffcc00", yamlLine.getValue());
}

}
23 changes: 23 additions & 0 deletions test/net/sourceforge/plantuml/yaml/parser/YamlParserTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package net.sourceforge.plantuml.yaml.parser;

import java.util.Arrays;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

class YamlParserTest {

@ParameterizedTest
@ValueSource(strings = {
"metadata:",
" name: vibrant:",
" type: \"dark\":"
})
void testSimple(String s) {
YamlParser parser = new YamlParser(2);
List<String> list = Arrays.asList(s);
parser.parse(list);
}
}

0 comments on commit 65db45c

Please sign in to comment.