nim 语言实现INI解析

在 http://code.taobao.org/p/parseIni/src/ 有代码,可以用svn下载

因为INI语法比较简单

[section1]

key1= xxx

key2 = xxx

key3 =xxx

...

[section2]

key21=xxx

key22=xxx

...

扫描二维码关注公众号,回复: 2749445 查看本文章

...

解析这个的目的:

1 练习一下nim语言。很久的代码了,从0.12的时候,现在已经0.15了。声援一下Nim,盼着快出1.0

2 练习一下编译原理

包含词法分析,语法分析(特别的简单)。

最后声称一个 section的table(和 c++中的map类似)

这个table 又包含一个table 这个table ,是 key-value 的一个 table

代码:

#
#
#            ParseIni
#        (c) Copyright 2015 bkdrong
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

## scan.nim 实现词法分析
## 
import
    windows,tables,os
proc printf(formatstr: cstring) {.importc: "printf", varargs,
header: "<stdio.h>".}
type 
    TOKEN_KIND = enum
        TK_NONE,    #如果是TK_NONE,则出错了
        TK_ID,      #标识符
        TK_EQU,     #等号
        TK_STR,     #字符串
        TK_INT,     #整数类型
        TK_SECTION  #区域

    SCAN_STATE = enum
        SS_START,
        SS_INID,
        SS_INSTR,
        SS_ININT,
        SS_INSECTION,
        SS_END
    TTOKEN = object
        kind:TOKEN_KIND
        value:string
    TSymbolList = Table[string,string]
    TSection = Table[string,TSymbolList]

const 
    END_CHAR = '\0'        
#全局变量区
var 
    g_buffer : string  = """
    [bkdrong]
        name  = "ronggf"
        scope = 90
        age   = 41
        num   = 20
        nation = "china"
    [xieglt]
        name  = "xielt"
        scope = 80
        age   = 37
        num   = 16
        nation = "japen"    
    """
    g_buffer_pos : int = 0
    g_curr_token : TTOKEN
    g_section_lst:TSection = initTable[string,TSymbolList]()
#获得下一个字符
proc getCharFormBuffer():char = 
    if g_buffer_pos < g_buffer.len :        
        result = g_buffer[g_buffer_pos]
    else: 
        result = '\0'
    g_buffer_pos+=1

proc backBuffer() =
    g_buffer_pos-=1   
#get a token from g_buffer
proc getTok():TTOKEN = 
    var 
        state = SS_START
        token_value :string =""
        ret_val:TTOKEN
    while true:        
        var c = getCharFormBuffer()
        #printf("get char 0x%x\n",c)
        case state :
        of SS_START:
            if c in {'a'..'z','A'..'Z'} :
                state = SS_INID
                token_value =token_value & c
            elif c =='"':
                state = SS_INSTR                
            elif c=='=':
                state = SS_END
                ret_val.kind = TK_EQU
                ret_val.value="="
            elif c in {'0'..'9'}:
                state = SS_ININT
                token_value = token_value & c
            elif c == '[':
                state = SS_INSECTION
            elif c == END_CHAR:
                state = SS_END
                ret_val.kind = TK_NONE
        of SS_INID:
            if c notin {'a'..'z','A'..'Z','0'..'9','_'}:
                backBuffer()
                ret_val.kind =TK_ID
                ret_val.value = token_value
                state = SS_END
            else:
                token_value = token_value & c
        of SS_ININT:
            if c notin {'0'..'9'} :
                backBuffer()
                ret_val.kind =TK_INT
                ret_val.value = token_value
                state = SS_END
            else:
                token_value = token_value & c
        of SS_INSTR:
            if c!='"':
                token_value = token_value &c
            else :
                ret_val.kind = TK_STR
                ret_val.value = token_value
                state = SS_END
        of SS_INSECTION:
            if c!=']':
                token_value = token_value &c
            else :
                ret_val.kind = TK_SECTION
                ret_val.value = token_value
                state = SS_END
        else:discard
        if state == SS_END:
            return ret_val
proc match(kind:TOKEN_KIND) =
    if g_curr_token.kind == kind :
        g_curr_token = getTok()
    else :
        echo "expected :",kind," but got ",g_curr_token.kind
        quit(1)
proc test_gettoken() =
    while true:
        var tok :TTOKEN
        tok = getTok()
        if tok.kind == TK_NONE:
            break
        else :
            echo tok
proc assignStmt(symlst:var TSymbolList):bool =
        if g_curr_token.kind == TK_ID :
            var 
                sym_name:string
                sym_value:string
            sym_name = g_curr_token.value
            match(TK_ID)
            match(TK_EQU)            

            if g_curr_token.kind == TK_STR:
                sym_value = g_curr_token.value
                match(TK_STR)                
            elif g_curr_token.kind == TK_INT:
                sym_value = g_curr_token.value
                match(TK_INT)
            else:
                sym_value ="no value"
            symlst.add(sym_name,sym_value)
            result = true
        elif g_curr_token.kind == TK_NONE or g_curr_token.kind == TK_SECTION:
            result = false
        else:
            echo "assignListStmt failed"
            quit(1)

proc assignListStmt(symlst: var TSymbolList) =
    while true :
        if not assignStmt(symlst) :
            break
proc stmt() =      
    g_curr_token = getTok()
    while true:
        if g_curr_token.kind == TK_SECTION:
            var section_name = g_curr_token.value
            match(TK_SECTION)
            var sym_list : TSymbolList = initTable[string,string]()
            assignListStmt(sym_list)
            #echo "section_name ",section_name
            g_section_lst.add(section_name,sym_list)
            #echo "item:",g_section_lst[section_name]
            #echo "sym_list",sym_list
        elif g_curr_token.kind==TK_NONE :
            break
        else:
            echo "tk is = ",g_curr_token
            quit(1)
proc readINI(filename:string,section_name:string,key_name:string):string =
    result=""
    var 
        file = open(filename)
        content : string = ""
    if file!=nil :
        for str in lines(file) :
            content &= str & "\n"
        g_buffer = content
        stmt()
        try:
            let symlst = g_section_lst[section_name]
            result = symlst[key_name]
        except:
            echo "except:",repr(getCurrentExceptionMsg())
            #echo "can not find the key_name:",key_name," in section_name:",section_name
    else:
        echo "open file:",filename," failed"
proc main() =
    echo "CPU:",hostCPU," OS:",hostOS
    if paramCount() < 1:
        echo ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
        echo "scan inifile"
        echo "example:scan\x0a\x09 c:\\test\\haha.ini"
        echo ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
        return

    let filename = commandLineParams()[0]
    if not existsFile(filename):
        echo "file " & filename & " not exist"
        return
    stdout.write("input a section string:")
    let section_name = readline(stdin)
    stdout.write("input a key string:")
    let key_name = readline(stdin)
    echo "result = " , readINI(filename,section_name,key_name)
main()
#test_gettoken()            
#stmt()
#echo repr(g_symbol_lst)
#echo g_section_lst








猜你喜欢

转载自blog.csdn.net/justin_bkdrong/article/details/53143556
Nim