python 에서 protobuf 파일 을 분석 하 는 간단 한 컴 파일 러 를 개발 합 니 다.
최근 에 python 으로 protobuf 파일 을 분석 하 는 간단 한 컴 파일 러 를 썼 습 니 다.ply 는 품사 분석 과 문법 분석 을 간결 하고 편리 하 게 실현 하 는 것 을 느 꼈 습 니 다.여열 이 지나 지 않 은 틈 을 타서 머리 가 맑 고 정리 와 소감 을 적어 서 여러분 의 pythoner 가 참고 하여 사용 하기에 편리 합 니 다.
ply 사용
간단 한 소개
컴 파일 러 나 해석 기 개발 에 종사 하지 않 았 다 면 ply 를 들 어 본 적 이 없 었 을 것 이다.ply 는 python 의 lex 와 Ycc 를 기반 으로 하 며,그 작 가 는 유명한 Python Cookbook,3rd Edition 의 작가 입 니 다.어떤 친구 들 은 궁금 해 할 것 이다.내 업무 개발 에 어떻게 스스로 컴 파일 러 를 써 야 하 는 지,여러분 의 프로 그래 밍 소 들 은 중앙 에서 결정 하고 새로운 것 을 많이 시도 해 야 한다 고 말 했다.그리고 문법 해석 자 세 를 알 아 보고 복잡 한 로그 나 수학 공식 을 스스로 해석 하 는 것 도 도움 이 된다.
컴 파일 기반 이 없 는 어린이 신발 에 대해 문법 과 관련 된 기본 개념 을 알 아 보 는 것 을 강력 히 권장 합 니 다.바퀴 형 이 강력 히 추천 하 는 parsing techniques 와 용 호 고래 책 을 번역 하 는 것 은 개인 적 으로 입문 학습 에 적합 하지 않다 고 생각 합 니 다.여기 서 후 룬 준 의 컴 파일 원리(전자 공업 출판사)를 추천 합 니 다.개념 에 대한 예 를 많이 설명 하여 입문 학습 에 적합 합 니 다.물론 특별히 깊이 연구 할 필요 도 없고 문법 분석 과 문법 분석의 관련 개념 과 방법 을 알 면 ply 를 즐겁게 사용 할 수 있다.문서 링크:http://www.pchou.info/open-source/2014/01/18/52da47204d4cb.html
여러분 의 편 의 를 위해 다 원 화 된 방정식 팀 을 예 로 들 어 ply 의 사용 을 설명 합 니 다.
예 설명
입력 은 여러 형식 이 x+4y-3.2z=7 인 일차 방정식 입 니 다.예 를 가능 한 한 간단하게 하기 위해 다음 과 같은 제한 을 합 니 다.
어법 해석
ply 에서 lex 는 품사 해석 을 하 는데 품사 해석 이론 이 많 지만 lex 는 사용 하기에 매우 직관 적 입 니 다.바로 정규 표현 식 으로 텍스트 문자열 을 하나의 token 으로 해석 하 는 것 입 니 다.아래 코드 는 lex 로 품사 해석 을 실현 하 는 것 입 니 다.
from ply import lex
#
t_ignore = ' \t\r'
#
def t_error(t):
raise Exception('error {} at line {}'.format(t.value[0], t.lineno))
# ,
def t_newline(t):
r'
+'
t.lexer.lineno += len(t.value)
# c++ \\
def t_ignore_COMMENT(t):
r'\/\/[^
]*'
#
def t_VARIABLE(t):
r'[a-z]+'
return t
#
def t_CONSTANT(t):
r'\d+(\.\d+)?'
t.value = float(t.value)
return t
# token, t_PLUS = r'\+' token
literals = '+-,;='
tokens = ('VARIABLE', 'CONSTANT')
if __name__ == '__main__':
data = '''
-x + 2.4y + z = 0; //this is a comment
9y - z + 7.2x = -1;
y - z + x = 8
'''
lexer = lex.lex()
lexer.input(data)
while True:
tok = lexer.token()
if not tok:
break
print tok
파일 을 직접 실행 하면 해 석 된 token 문자열 을 인쇄 할 수 있 습 니 다.아래 와 같이 상세 한 사용 문 서 는 ply 문 서 를 참고 할 수 있 습 니 다.
LexToken(-,'-',2,5)
LexToken(VARIABLE,'x',2,6)
LexToken(+,'+',2,8)
LexToken(CONSTANT,2.4,2,10)
LexToken(VARIABLE,'y',2,13)
LexToken(+,'+',2,15)
LexToken(VARIABLE,'z',2,17)
LexToken(=,'=',2,19)
LexToken(CONSTANT,0.0,2,21)
LexToken(;,';',2,22)```
###
ply yacc , , 。 yacc , , , , 。
, 。 , , , , , 。 LL(1), , , 。 , , , , , 。 SLR、LRLR,ply LRLR。
, 。
```python
# -*- coding=utf8 -*-
from ply import (
lex,
yacc
)
#
t_ignore = ' \t\r'
#
def t_error(t):
raise Exception('error {} at line {}'.format(t.value[0], t.lineno))
# ,
def t_newline(t):
r'
+'
t.lexer.lineno += len(t.value)
# c++ \\
def t_ignore_COMMENT(t):
r'\/\/[^
]*'
#
def t_VARIABLE(t):
r'[a-z]+'
return t
#
def t_CONSTANT(t):
r'\d+(\.\d+)?'
t.value = float(t.value)
return t
# token, t_PLUS = r'\+' token
literals = '+-,;='
tokens = ('VARIABLE', 'CONSTANT')
# , equations p[1] ,
def p_start(p):
"""start : equations"""
var_count, var_list = 0, []
for left, _ in p[1]:
for con, var_name in left:
if var_name in var_list:
continue
var_list.append(var_name)
var_count += 1
matrix = [[0] * (var_count + 1) for _ in xrange(len(p[1]))]
for counter, eq in enumerate(p[1]):
left, right = eq
for con, var_name in left:
matrix[counter][var_list.index(var_name)] = con
matrix[counter][-1] = -right
var_list.append(1)
p[0] = matrix, var_list
# , , ;
def p_equations(p):
"""equations : equation ',' equations
| equation ';' equations
| equation"""
if len(p) == 2:
p[0] = [p[1]]
else:
p[0] = [p[1]] + p[3]
#
def p_equation(p):
"""equation : eq_left '=' eq_right"""
p[0] = (p[1], p[3])
#
def p_eq_left(p):
"""eq_left : var_unit eq_left
|"""
if len(p) == 1:
p[0] = []
else:
p[0] = [p[1]] + p[2]
# : x, 5x, +x, -x, +4x, -4y
# , : (5, 'x')
def p_var_unit(p):
"""var_unit : VARIABLE
| CONSTANT VARIABLE
| '+' VARIABLE
| '-' VARIABLE
| '+' CONSTANT VARIABLE
| '-' CONSTANT VARIABLE"""
len_p = len(p)
if len_p == 2:
p[0] = (1.0, p[1])
elif len_p == 3:
if p[1] == '+':
p[0] = (1.0, p[2])
elif p[1] == '-':
p[0] = (-1.0, p[2])
else:
p[0] = (p[1], p[2])
else:
if p[1] == '+':
p[0] = (p[2], p[3])
else:
p[0] = (-p[2], p[3])
# , :1.2, +1.2, -1.2
def p_eq_right(p):
"""eq_right : CONSTANT
| '+' CONSTANT
| '-' CONSTANT"""
if len(p) == 3:
if p[1] == '-':
p[0] = -p[2]
else:
p[0] = p[2]
else:
p[0] = p[1]
if __name__ == '__main__':
data = '''
-x + 2.4y + z = 0; //this is a comment
9y - z + 7.2x = -1;
y - z + x = 8
'''
lexer = lex.lex()
parser = yacc.yacc(debug=True)
lexer.lineno = 1
s = parser.parse(data)
print s
파일 을 직접 실행 하면 됩 니 다.출력 은 다음 과 같 습 니 다.그 다음 에 선형 대수 방법 에 따라 각 변수의 값 을 구 할 수 있 습 니 다.([[-1.0, 2.4, 1.0, -0.0], [7.2, 9.0, -1.0, 1.0], [1.0, 1.0, -1.0, -8.0]], ['x', 'y', 'z', 1])
총결산
python 의 간결 한 문법 을 바탕 으로 ply 는 우리 에 게 강력 한 문법 분석 도 구 를 제공 합 니 다.더욱 복잡 한 예 는 참고 할 수 있 습 니 다https://github.com/LiuRoy/proto_parser.이것 은 제 가 ply 로 실현 한 간단 한 protobuf 해석 기 입 니 다.빈번 한 중간 파일 생 성 을 줄 이 는 데 사 용 됩 니 다.이런 신기 가 있 습 니 다.조정 하나!
이상 은 python 이 protobuf 파일 을 분석 하 는 간단 한 컴 파일 러 를 개발 하 는 상세 한 내용 입 니 다.python 개발 컴 파일 러 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
로마 숫자를 정수로 또는 그 반대로 변환그 중 하나는 로마 숫자를 정수로 변환하는 함수를 만드는 것이었고 두 번째는 그 반대를 수행하는 함수를 만드는 것이었습니다. 문자만 포함합니다'I', 'V', 'X', 'L', 'C', 'D', 'M' ; 문자열이 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.