json モジュールについて (2)

数式処理 json5 parser コマンド

  • json5にて、 数式処理 をできるようにしたpython json5 parser.


ルール

  • 文字列を与えた際は、常に、try する.

    • 一方で、普通の文字列との区別がつかないので、エラーはでない.

    • エラーをだすには オプショナル引数として、"verbose=True" を与える.

  • または、数式は文字式で与え、文字式内にバッククォートで囲まれた領域を持つものとする

    • formula_mark=" ` "として与える.

    • " ` (数式) ` " という構成.

    • バッククォート前後の空白は許すが、空白以外があると感知されない.

    • 正規表現的には、 r"\s*`([\s\S]+)`\s*"

    • 引数のexpr_fmlで正規表現を与えれば、 変更も可能

  • 変数は"変数マークをつけた語"で記載.(e.g. ${...} :ShellScript 環境変数 -like)

    • 前後での空白は許すが、括弧内や$マークとの間の空白は許さない

    • {}はあってもなくてもよい.

    • 正規表現例(@のとき): "@\{*[varname]\}*\s*" ( [varname] は登録変数名、総当りで検索. )

  • その他、空白は許されるはず.

  • 変数名に 正規表現でエスケープが必要となる文字 を使用する際は注意( "."など.)


parser 関数( コード )

import json5, re, math, sys
import numpy as np

# ========================================================= #
# ===  json__formulaParser.py                           === #
# ========================================================= #

def json__formulaParser( inpFile=None, stop__error=False, verbose=False, table=None, \
                         expr_fml=None, formula_mark="", variable_mark="$" ):
    
    if ( expr_fml is None ):
        if   ( formula_mark == "`" ):
            expr_fml = r"\s*`([\s\S]+)`\s*"
        elif ( formula_mark == "" ):
            expr_fml = r"([\s\S]+)"
        else:
            print( "[json__formulaParser.py] formula_mark == {} ??? ".format( variable_mark ) )
            sys.exit()

    if ( variable_mark in [ "$" ] ):
        variable_mark = "\{}".format( variable_mark )
            
    # ------------------------------------------------- #
    # --- [1] load json file as json5               --- #
    # ------------------------------------------------- #
    with open( inpFile, "r" ) as f:
        varDict = json5.load( f )
    if ( table is not None ):
        varDict = { **table, **varDict }

    # ------------------------------------------------- #
    # --- [2] convert formula string into value     --- #
    # ------------------------------------------------- #
    for key,val in varDict.items():
        if ( type(val) is str ):
            match_fml = re.match( expr_fml, val )
            if ( match_fml ):
                formula   = match_fml.group(1)
                for var_,val_ in varDict.items():
                    expr_from = variable_mark+"\{*"+var_+"\}*\s*"
                    expr_into = "{}".format( val_ )
                    formula = re.sub( expr_from, expr_into, formula )
                try:
                    varDict[key] = eval( formula )
                except SyntaxError:
                    if ( verbose ):
                        print()
                        print( "[json__wformula.py] Cannot evaluate [ERROR]" )
                        print( "[json__wformula.py] key     :: {}".format( key     ) )
                        print( "[json__wformula.py] formula :: {}".format( val     ) )
                        print( "[json__wformula.py]         :: {}".format( formula ) )
                        print()
                except:
                    if ( verbose ):
                        print()
                        print( "[json__wformula.py] Cannot evaluate [ERROR]" )
                        print( "[json__wformula.py] key     :: {}".format( key     ) )
                        print( "[json__wformula.py] formula :: {}".format( val     ) )
                        print( "[json__wformula.py]         :: {}".format( formula ) )
                        print()
                        raise
                
    # ------------------------------------------------- #
    # --- [4] print parsed items                    --- #
    # ------------------------------------------------- #
    return( varDict )

# ========================================================= #
# ===   Execution of Pragram                            === #
# ========================================================= #

if ( __name__=="__main__" ):
    
    # ------------------------------------------------- #
    # --- [1] declare regexp and file name          --- #
    # ------------------------------------------------- #
    inpFile  = "test/json__formulaParser/sample1.json"
    ret      = json__formulaParser( inpFile=inpFile, variable_mark="$" )
    print( ret )

    # ------------------------------------------------- #
    # --- [2] variable mark is "@" case             --- #
    # ------------------------------------------------- #
    inpFile  = "test/json__formulaParser/sample2.json"
    ret      = json__formulaParser( inpFile=inpFile, variable_mark="@" )
    print( ret )


{'string': 'This is a pen', 'val1': 30.0, 'val2': 2, 'arr1': [1.0, 2.0, 3.0], 'sw1': True, 'sw2': False, 'item': None, 'fml': 1.7320508075688774, 'fml2': 1.0000000000000002, 'val3': 60.0}

json サンプル

{
    // This is a sample of json file
    "string" :"This is a pen", 
    "val1"   : 30.0,
    "val2"   : 2,
    "arr1"   : [1.0,2.0,3.0,],
    "sw1"    :true, 
    "sw2"    :false,
    "item"   :null,
    "fml"    : " ` np.cos(${val1}/180.0*np.pi) * ${val2} ` ",
    "fml2"   : " ` np.cos(${val3}/180.0*np.pi) * ${val2} ` ",
    "val3"   : 60.0,
    "val4"   : " ` ${val1} + ${val2} ` ",
    "val5"   : " ` ${val3} * ${val4} ` ",
    "val6"   : " ` ${val5} / ${val1} ` ",
    
    /* comment line */
}