/* * Created by PyramIDE. * User: フランスのトトロ aka (David RENÉ) * Date: 07/06/2016 * Time: 23:15 * © Calexium */ read yaml_type.anubis read tools/streams.anubis read tools/string.anubis read system/string.anubis type YAML_Parser_Info: yaml_p_info(Int parent_indent, Int context_indent, Int level). type YAML_Parser_Node_Info: none, unquoted, in_single_quote, in_double_quote. type YAML_Parser_Context_Info: none, line, block_start, block. type YAML_Parser_Node: map(List(YAML_Key_Value) kvl), list(List(YAML_Value) vl), value(YAML_Value v). define Maybe(YAML_Parser_Node) _read_node ( Stream s, YAML_Parser_Info p_info, YAML_Parser_Node_Info node_info, List(Word8) so_far ). define Bool eol(Word8 c) = if c = 10 then true // LF else if c = 13 then true // CR else false. define One skip_to_next_line ( Stream s )= if read_byte(s) is { failure then unique, success(c) then if eol(c) then unique else skip_to_next_line(s) }. define One skip_spaces ( Stream s )= if read_byte(s) is { failure then unique, success(c) then if c = ' ' then skip_spaces(s) else unput_byte(c, s); unique }. define One skip_to_next_node ( Stream s )= if read_byte(s) is { failure then unique, success(c) then if eol(c) then skip_to_next_node(s) else if c = ' ' then skip_to_next_node(s) else if c = '#' then //skip_spaces(s); skip_to_next_line(s); skip_to_next_node(s) else unput_byte(c, s); unique }. define List(Word8) trim_right ( List(Word8) char_list, Word8 token )= if char_list is { [ ] then [ ], [h . t] then if h = token then trim_right(t, token) else char_list }. define String trim_right ( String str, Word8 token )= implode(reverse(trim_right(reverse(explode(str)), token))). define YAML_Value get_yaml_value ( String str )= with str = trim_token(str, ' '), if str = "yes" then bool(var(true)) else if str = "no" then bool(var(false)) else if decimal_scan(str) is { failure then string(var(str)), success(integer) then int(var(integer)) }. define Maybe(List(YAML_Key_Value)) read_block_maps ( Stream s, YAML_Parser_Info p_info, Int block_indent, List(YAML_Key_Value) so_far )= since p_info is yaml_p_info(parent_indent, context_indent, level), skip_spaces(s); skip_to_next_node(s); with current_indent = current_column(s), //println("current_indent: " + current_indent); //println("block_indent: " + block_indent); if current_indent = block_indent then if _read_node(s, yaml_p_info(parent_indent, current_indent, level), none, []) is { failure then success([]), success(node_type) then if node_type is { map(yaml_kvl) then if yaml_kvl is { [ ] then failure, [h . _] then read_block_maps(s, p_info, block_indent, [ h . so_far ]), } list(yaml_lv) then failure, value(yaml_value) then failure } } else success(so_far). define Maybe(List(YAML_Value)) read_block_list ( Stream s, List(YAML_Value) so_far )= failure. define Maybe(YAML_Value) read_value ( Stream s, YAML_Parser_Info p_info, YAML_Parser_Context_Info ctx_info, List(Word8) so_far )= since p_info is yaml_p_info(parent_indent, context_indent, level), //skip_spaces(s); with current_indent = current_column(s), if read_byte(s) is { failure then success(null), success(c) then if eol(c) then // \n if ctx_info is { none then read_value(s, p_info, block_start, so_far), line then with value_str = implode(reverse(so_far)), //println(" value: " + value_str); success(get_yaml_value(value_str)), block_start then read_value(s, p_info, block_start, so_far), block then read_value(s, p_info, block, so_far) } else if c = '#' then skip_to_next_line(s); read_value(s, p_info, ctx_info, so_far) else if ctx_info is { none then read_value(s, p_info, line, [c . so_far]), line then //println(implode(reverse([c . so_far]))); read_value(s, p_info, line, [c . so_far]), block_start then unput_byte(c, s); //println("block_start"); skip_to_next_node(s); with current_indent = current_column(s), if current_indent =< parent_indent then success(null) else read_value(s, yaml_p_info(parent_indent, current_indent, level + 1), block, so_far), block then unput_byte(c, s); //println("block level " + level); skip_to_next_node(s); if _read_node(s, p_info, none, []) is { failure then success(null), success(node_type) then if node_type is { map(yaml_kvl) then if read_block_maps(s, p_info, context_indent, yaml_kvl) is { failure then success(map(var(yaml_kvl))), success(list_kv) then success(map(var(reverse(list_kv)))) } list(yaml_lv) then if read_block_list(s, yaml_lv) is { failure then success(list(var(yaml_lv))), success(list_v) then success(list(var(list_v))) } value(yaml_value) then success(yaml_value) } } } }. define Maybe(YAML_Parser_Node) _read_node ( Stream s, YAML_Parser_Info p_info, YAML_Parser_Node_Info node_info, List(Word8) so_far )= skip_spaces(s); if read_byte(s) is { failure then failure, success(c) then if node_info is { none then if c = '-' then todo//_read_list(s, p_info, in_double_quote, so_far) else if c = '\"' then _read_node(s, p_info, in_double_quote, so_far) else if c = '\'' then _read_node(s, p_info, in_single_quote, so_far) else _read_node(s, p_info, unquoted, [ c . so_far ]), unquoted then if c = ':' then if read_byte(s) is { failure then with key_name = implode(reverse(so_far)), success(map([key_value(key_name, var(null))])), success(next_char) then if eol(next_char) then // \n unput_byte(next_char, s); with key_name = implode(reverse(so_far)), //println("key found [LF] \n name: " + key_name); skip_spaces(s); with value = read_value(s, p_info, none, []), if value is { failure then failure, success(v) then success(map([key_value(key_name, var(v))])) } else if next_char = ' ' then with key_name = implode(reverse(so_far)), //println("key found [ ]\n name: " + key_name); skip_spaces(s); with value = read_value(s, p_info, none, []), if value is { failure then failure, success(v) then success(map([key_value(key_name, var(v))])) } else todo //_read_node(s, p_info, unquoted, [next_char . [c . so_far]]) } else if eol(c) then with str = implode(reverse(so_far)), //println("value (str): " + str); success(value(get_yaml_value(str))) else _read_node(s, p_info, unquoted, [ c . so_far ]), in_single_quote then todo, in_double_quote then todo } }. public define Maybe(YAML_Document) get_yaml_document_content ( Stream s, YAML_Document doc )= //skip all blanks of begin of line skip_spaces(s); with indent = current_column(s), if read_byte(s) is { failure then //println("skipping blank line"); //get_yaml_document_content(s, doc), //blank line success(doc) success(c) then //check for comment if eol(c) then get_yaml_document_content(s, doc) else if c = '#' then //println("skipping comment ["+line+"]"); skip_to_next_line(s); get_yaml_document_content(s, doc) //check for entry of the map else unput_byte(c, s); //println("map entry indent["+indent+"]");//["+line+"]"); with mb_node = _read_node(s, yaml_p_info(indent, indent, 0), none, /*make_stream(line)*/[]), if mb_node is { failure then println("Can't get map entries"); get_yaml_document_content(s, doc), success(node_type) then since doc is yaml_document(nodes), if node_type is { map(yaml_kv) then nodes <- [map(var(yaml_kv)) . *nodes]; get_yaml_document_content(s, yaml_document(nodes)) list(yaml_lv) then nodes <- [list(var(yaml_lv)) . *nodes]; get_yaml_document_content(s, yaml_document(nodes)) value(yaml_value) then failure } } }. //read_byte public define Maybe(YAML_Document) get_yaml_document ( Stream s, )= if read_line(s) is { failure then failure, success(line) then if start_with(line, "---") then println("Start parsing YAML document"); get_yaml_document_content(s, yaml_document(var([]))) else get_yaml_document(s) }. public define YAML parse_YAML_file ( Stream s, Var(List(YAML_Document)) docs )= if get_yaml_document(s) is { failure then yaml(var(reverse(*docs))), success(doc) then docs <- [doc . *docs]; parse_YAML_file(s, docs) }. public define YAML parse_YAML_file ( Stream s )= if read_line(s) is { failure then yaml(var([])), success(line) then if start_with(line, "%YAML 1.1") then println("%YAML 1.1 file"); parse_YAML_file(s, var([])) else yaml(var([])) }.