mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Добавлен модуль yaml
This commit is contained in:
parent
29d40a554f
commit
31b4539fd8
@ -57,6 +57,7 @@ dependencies {
|
||||
exclude group: 'org.json', module: 'json'
|
||||
}
|
||||
compile 'org.json:json:20160212'
|
||||
compile 'org.yaml:snakeyaml:1.17'
|
||||
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile 'org.openjdk.jmh:jmh-core:1.13'
|
||||
|
44
examples/formats/yaml.own
Normal file
44
examples/formats/yaml.own
Normal file
@ -0,0 +1,44 @@
|
||||
use "yaml"
|
||||
|
||||
println "Yaml encode"
|
||||
println yamlencode({
|
||||
"name": "Yaml Example",
|
||||
"version": 1,
|
||||
"arrayData": [
|
||||
1, 2, 3, 4
|
||||
],
|
||||
"objectData": {
|
||||
"key": "value",
|
||||
10: "1000"
|
||||
}
|
||||
})
|
||||
|
||||
println "\nYaml decode"
|
||||
x = yamldecode("
|
||||
name: \"std\"
|
||||
scope: \"both\"
|
||||
desc: \"Contains common functions\"
|
||||
desc_ru: \"Содержит вспомогательные функции общего назначения\"
|
||||
constants: []
|
||||
functions:
|
||||
-
|
||||
name: \"arrayCombine\"
|
||||
args: \"keys, values\"
|
||||
desc: \"creates map by combining two arrays\"
|
||||
desc_ru: \"создаёт объект на основе двух массивов\"
|
||||
-
|
||||
name: \"typeof\"
|
||||
args: \"value\"
|
||||
desc: \"returns the type of value\"
|
||||
desc_ru: \"возвращает тип переданного значения\"
|
||||
example: |-
|
||||
print typeof(1) // 1 (NUMBER)
|
||||
print typeof(\"text\") // 2 (STRING)
|
||||
print typeof([]) // 3 (ARRAY)
|
||||
")
|
||||
println x.name + ", scope: " + x.scope
|
||||
println x.desc
|
||||
for func : x.functions {
|
||||
println " - " + func.name + "(" + func.args + ")"
|
||||
println " " + func.desc
|
||||
}
|
17
src/main/java/com/annimon/ownlang/modules/yaml/yaml.java
Normal file
17
src/main/java/com/annimon/ownlang/modules/yaml/yaml.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.annimon.ownlang.modules.yaml;
|
||||
|
||||
import com.annimon.ownlang.lib.*;
|
||||
import com.annimon.ownlang.modules.Module;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class yaml implements Module {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Functions.set("yamlencode", new yaml_encode());
|
||||
Functions.set("yamldecode", new yaml_decode());
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package com.annimon.ownlang.modules.yaml;
|
||||
|
||||
import com.annimon.ownlang.lib.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
public final class yaml_decode implements Function {
|
||||
|
||||
@Override
|
||||
public Value execute(Value... args) {
|
||||
Arguments.check(1, args.length);
|
||||
try {
|
||||
final String yamlRaw = args[0].asString();
|
||||
final Object root = new Yaml().load(yamlRaw);
|
||||
final Value process = process(root);
|
||||
return process;
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException("Error while parsing yaml", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Value process(Object obj) {
|
||||
if (obj instanceof Map) {
|
||||
return process((Map) obj);
|
||||
}
|
||||
if (obj instanceof List) {
|
||||
return process((List) obj);
|
||||
}
|
||||
if (obj instanceof String) {
|
||||
return new StringValue((String) obj);
|
||||
}
|
||||
if (obj instanceof Number) {
|
||||
return NumberValue.of(((Number) obj));
|
||||
}
|
||||
if (obj instanceof Boolean) {
|
||||
return NumberValue.fromBoolean((Boolean) obj);
|
||||
}
|
||||
// NULL or other
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
private MapValue process(Map<Object, Object> map) {
|
||||
final MapValue result = new MapValue(map.size());
|
||||
for (Map.Entry<Object, Object> entry : map.entrySet()) {
|
||||
final String key = entry.getKey().toString();
|
||||
final Value value = process(entry.getValue());
|
||||
result.set(new StringValue(key), value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private ArrayValue process(List list) {
|
||||
final int length = list.size();
|
||||
final ArrayValue result = new ArrayValue(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
final Value value = process(list.get(i));
|
||||
result.set(i, value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.annimon.ownlang.modules.yaml;
|
||||
|
||||
import com.annimon.ownlang.lib.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
public final class yaml_encode implements Function {
|
||||
|
||||
@Override
|
||||
public Value execute(Value... args) {
|
||||
Arguments.check(1, args.length);
|
||||
try {
|
||||
final Object root = process(args[0]);
|
||||
final String yamlRaw = new Yaml().dump(root);
|
||||
return new StringValue(yamlRaw);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException("Error while creating yaml", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Object process(Value val) {
|
||||
switch (val.type()) {
|
||||
case Types.ARRAY:
|
||||
return process((ArrayValue) val);
|
||||
case Types.MAP:
|
||||
return process((MapValue) val);
|
||||
case Types.NUMBER:
|
||||
return val.raw();
|
||||
case Types.STRING:
|
||||
return val.asString();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Object process(MapValue map) {
|
||||
final Map<String, Object> result = new HashMap<>();
|
||||
for (Map.Entry<Value, Value> entry : map) {
|
||||
final String key = entry.getKey().asString();
|
||||
final Object value = process(entry.getValue());
|
||||
result.put(key, value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Object process(ArrayValue array) {
|
||||
final List<Object> result = new ArrayList<>();
|
||||
for (Value value : array) {
|
||||
result.add(process(value));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
33
src/test/resources/modules/yaml/yamldecode.own
Normal file
33
src/test/resources/modules/yaml/yamldecode.own
Normal file
@ -0,0 +1,33 @@
|
||||
use "std"
|
||||
use "yaml"
|
||||
use "ounit"
|
||||
|
||||
x = yamldecode("
|
||||
name: \"std\"
|
||||
scope: \"both\"
|
||||
desc: \"Contains common functions\"
|
||||
desc_ru: \"Ñîäåðæèò âñïîìîãàòåëüíûå ôóíêöèè îáùåãî íàçíà÷åíèÿ\"
|
||||
constants: []
|
||||
functions:
|
||||
-
|
||||
name: \"arrayCombine\"
|
||||
args: \"keys, values\"
|
||||
desc: \"creates map by combining two arrays\"
|
||||
desc_ru: \"ñîçäà¸ò îáúåêò íà îñíîâå äâóõ ìàññèâîâ\"
|
||||
-
|
||||
name: \"typeof\"
|
||||
args: \"value\"
|
||||
desc: \"returns the type of value\"
|
||||
desc_ru: \"âîçâðàùàåò òèï ïåðåäàííîãî çíà÷åíèÿ\"
|
||||
example: |-
|
||||
print typeof(1) // 1 (NUMBER)
|
||||
print typeof(\"text\") // 2 (STRING)
|
||||
print typeof([]) // 3 (ARRAY)
|
||||
")
|
||||
|
||||
assertEquals("std", x.name)
|
||||
assertEquals("both", x.scope)
|
||||
assertEquals(0, length(x.constants))
|
||||
assertEquals(2, length(x.functions))
|
||||
assertEquals("arrayCombine", x.functions[0].name)
|
||||
assertEquals("âîçâðàùàåò òèï ïåðåäàííîãî çíà÷åíèÿ", x.functions[1].desc_ru)
|
22
src/test/resources/modules/yaml/yamlencode.own
Normal file
22
src/test/resources/modules/yaml/yamlencode.own
Normal file
@ -0,0 +1,22 @@
|
||||
use "std"
|
||||
use "yaml"
|
||||
use "ounit"
|
||||
|
||||
yml = yamlencode({
|
||||
"name": "Yaml Example",
|
||||
"version": 1,
|
||||
"arrayData": [
|
||||
1, 2, 3, 4
|
||||
],
|
||||
"objectData": {
|
||||
"key": "value",
|
||||
10: "1000"
|
||||
}
|
||||
})
|
||||
obj = yamldecode(yml)
|
||||
|
||||
assertEquals("Yaml Example", obj.name)
|
||||
assertEquals(1, obj.version)
|
||||
assertEquals(4, length(obj.arrayData))
|
||||
assertEquals("value", obj.objectData.key)
|
||||
assertEquals("1000", obj.objectData["10"])
|
Loading…
Reference in New Issue
Block a user