2017-04-06 8 views
1

심지어 성능을 크게 향상 enablePackrat을, 사용 후 원하는 것보다 infixNotation의 내 구현이 느리게 실행됩니다.대한 파싱의 infixNotation 최적화

구문 분석 인식하고 문자열의 다음과 같은 유형의 구문 분석에 필요한 :

  • 기본 산술 연산, 숫자, 부정, 그리고 괄호 형식으로
  • 그룹화 함수 호출과 같이 prefix::dotted.alphanum.string -> [prefix::dotted.alphanum.string]
  • 문자열을 그룹 예 pow(some::var + 2.3, 5) -> [pow, [[some::var, +, 2.3], 5]]

내가 사용하고 코드 :

def parse_expression(expr_str): 

    fraction = Combine("." + Word(nums)) 
    number = Combine(Word(nums) + Optional(fraction)).setParseAction(str_to_num) 

    event_id_expr = Word(alphanums + "_") + "::" 
    dotted_columns = Combine(Word(alphanums + "_") + Optional(".")) 

    column_expr = Combine(event_id_expr + OneOrMore(dotted_columns)) 

    arith_expr = infixNotation(column_expr | number, [ 
     (Word(alphanums + "_"), 1, opAssoc.RIGHT), 
     ("-", 1, opAssoc.RIGHT), 
     (oneOf("* /"), 2, opAssoc.LEFT), 
     (oneOf("+ -"), 2, opAssoc.LEFT), 
     (Literal(","), 2, opAssoc.LEFT) 
    ]) 

    parsed_expr = arith_expr.parseString(expr_str).asList()[0] 

    return parsed_expr 

def str_to_num(t): 
     num_str = t[0] 
     try: 
      return int(num_str) 
     except ValueError: 
      return float(num_str) 

내가 그 실질적인 성능 향상을 초래 할 수 있습니다 어떤 변화가 있습니까? 구문 분석하는 구조는 매우 간단하지만 일괄 처리됩니다. 평균적으로 각 문자열은 ~ 5.3ms를 사용합니다. 나는 또한 당신의 식별자의 대부분을 수정

def parse_expression(expr_str): 

    number = pyparsing_common.number() 

    event_id_expr = Word(alphas+"_", alphanums + "_") + "::" 
    dotted_columns = Combine(Word(alphas+"_", alphanums + "_") + Optional(".")) 

    column_expr = Combine(event_id_expr + OneOrMore(dotted_columns)) 

    func_name = Word(alphas+"_", alphanums+'_') 
    LPAR, RPAR = map(Suppress, "()") 
    arith_expr = Forward() 
    func_call = Group(func_name('name') 
         + LPAR 
         + Group(Optional(delimitedList(arith_expr)))("args") 
         + RPAR) 

    arith_expr <<= infixNotation(number | func_call | column_expr, [ 
     ("-", 1, opAssoc.RIGHT), 
     (oneOf("* /"), 2, opAssoc.LEFT), 
     (oneOf("+ -"), 2, opAssoc.LEFT), 
    ]) 

    parsed_expr = arith_expr.parseString(expr_str)[0] 

    return parsed_expr 

: 그들은 운영자가, 당신이 이동 기능은 infixNotation에 대한 피연산자 식으로 호출하는 것이 더 낫다 생각하는 것처럼 당신이 "fudging"기능이있는 것처럼

+0

'number'를'pyparsing_common.number'로 대체하십시오. 그것은 당신의'str_to_num' 구문 분석 액션처럼 int 나 float로 변환 될 것입니다. 그러나 더 중요한 것은, 하나의 Regex를 사용하여 Combine으로 싸여진 더 작은 표현식 대신에 구문 분석을하는 것입니다. 나는이 간단한 변화가 측정 가능한 성능 차이를 만들 수 있음을 발견했다. – PaulMcG

+0

좋습니다. 그 혼자서 ~ .5ms를 깎아 내었습니다. – user3747260

+0

한계에 다다 렸을 수 있습니다. - 깎아 지른듯한 미덕은 런타임 속도가 아닙니다. – PaulMcG

답변

1

같습니다 단지 또한 내가 는 의도라고 생각하지 않습니다 보통의 정수를 일치합니다 Word(alphanums+"_")를 사용하여 - 워드의 2 인자 양식을 사용하세요. 내가 잘못했다면, 네가 가진대로 돌려 놓으 라.

+0

도움 주셔서 감사합니다. 이것은 약 3.8ms로 ​​내려 갔고 또한 토큰 처리에 대한 논리를 더 간단하게 만들었습니다. – user3747260