문제

C- (실제 C- 언어가 아님)라는 가상의 프로그래밍 언어를위한 파서를 구축하고 있습니다. 나는 언어의 문법을 pyparsing이 받아 들일 수있는 것으로 번역 해야하는 무대에 도착했습니다. 불행히도 입력 문자열 (정확하고 오류가 발생하지 않아야 함)을 구문 분석 할 때 올바르게 구문 분석하지 않습니다. 나는 이것이 내 문법의 오류 때문이라고 걱정하지만, 처음으로 pyparsing을 시작할 때 내가 어디에서 잘못 될지 알 수없는 것 같습니다.

나는 내가 번역하는 문법을 업로드했다 여기 사람들이 읽을 수 있습니다.

편집하다: Paul의 조언으로 업데이트되었습니다.

이것은 내가 현재 가지고있는 그레이머입니다 (구문 정의의 두 줄은 내가 아는 나에게 끔찍한 나쁘다).

# Lexical structure definition
ifS = Keyword('if')
elseS = Keyword('else')
whileS = Keyword('while')
returnS = Keyword('return')
intVar = Keyword('int')
voidKeyword = Keyword('void')
sumdiff = Literal('+') | Literal('-')
prodquot = Literal('*') | Literal('/')
relation = Literal('<=') | Literal('<') | Literal('==') | \
           Literal('!=') | Literal('>') | Literal('=>')
lbrace = Literal('{')
rbrace = Literal('}')
lparn = Literal('(')
rparn = Literal(')')
semi = Literal(';')
comma = Literal(',')
number = Word(nums)
identifier = Word(alphas, alphanums)

# Syntax definition
term = ''
statement = ''
variable    =   intVar + identifier + semi
locals      =   ZeroOrMore(variable)
expr        =   term | OneOrMore(Group(sumdiff + term))
args        =   ZeroOrMore(OneOrMore(Group(expr + comma)) | expr)
funccall    =   Group(identifier + lparn + args + rparn)
factor      =   Group(lparn + expr + rparn) | identifier | funccall | number
term        =   factor | OneOrMore(prodquot + factor)
cond        =   Group(lparn + expr + relation + expr + rparn)
returnState =   Group(returnS + semi) | Combine(returnS + expr + semi)
assignment  =   Group(identifier + '=' + expr + semi)
proccall    =   Group(identifier + lparn + args + rparn + semi)
block       =   Group(lbrace + locals + statement + rbrace)
iteration   =   Group(whileS + cond + block)
selection   =   Group(ifS + cond + block) | Group(ifS + cond + block + elseS + block)
statement   =   OneOrMore(proccall | assignment | selection | iteration | returnState)
param       =   Group(intVar + identifier)
paramlist   =   OneOrMore(Combine(param + comma)) | param
params      =   paramlist | voidKeyword
procedure   =   Group(voidKeyword + identifier + lparn + params + rparn + block)
function    =   Group(intVar + identifier + lparn + params + rparn + block)
declaration =   variable | function | procedure
program     =   OneOrMore(declaration)

문법을 번역하는 데 실수가 있었는지, 내가 준 문법을 준수하면서 단순화하기 위해 어떤 개선을 할 수 있는지 알고 싶습니다.

편집 2 : 새로운 오류를 포함하도록 업데이트되었습니다.

내가 구문 분석하는 입력 문자열은 다음과 같습니다.

int larger ( int first , int second ) { 
if ( first > second ) { 
return first ; 
} else { 
return second ; 
} 
} 

void main ( void ) { 
int count ; 
int sum ; 
int max ; 
int x ; 

x = input ( ) ; 
max = x ; 
sum = 0 ; 
count = 0 ; 

while ( x != 0 ) { 
count = count + 1 ; 
sum = sum + x ; 
max = larger ( max , x ) ; 
x = input ( ) ; 
} 

output ( count ) ; 
output ( sum ) ; 
output ( max ) ; 
} 

그리고 이것은 터미널에서 내 프로그램을 실행할 때 얻는 오류 메시지입니다.

/Users/Joe/Documents/Eclipse Projects/Parser/src/pyparsing.py:1156: SyntaxWarning: null string passed to Literal; use Empty() instead
other = Literal( other )
/Users/Joe/Documents/Eclipse Projects/Parser/src/pyparsing.py:1258: SyntaxWarning: null string passed to Literal; use Empty() instead
other = Literal( other )
Expected ")" (at char 30), (line:6, col:26)
None
도움이 되었습니까?

해결책

1) 변경 Literal("if") 에게 Keyword("if") (그리고 아래로 Literal("void")), 이름이 지정된 변수의 선행 "if"와 일치하지 않도록 "ifactor".

2) nums, alphas, 그리고 alphanums 표현이 아니며 문자열이며, "숫자"와 같은 "단어"를 정의 할 때 일부 일반적인 문자 세트를 정의하기 위해 단어 클래스와 함께 사용될 수있는 문자열입니다. 알파가있는 다음 0 개 이상의 알파늄이 뒤 따릅니다. " 그래서 대신 :

number = nums
identifier = alphas + OneOrMore(alphanums)

당신은 원합니다

number = Word(nums)
identifier = Word(alphas, alphanums)

3) 대신 Combine, 나는 당신이 원한다고 생각합니다 Group. 사용 Combine 일치하는 토큰이 중간 공백없이 인접 해지기를 원할 때, 토큰을 연결하고 단일 문자열로 반환합니다. Combine 다음과 같은 경우에 종종 사용됩니다.

realnum = Combine(Word(nums) + "." + Word(nums))

없이 Combine, 구문 분석 "3.14" 문자열 목록을 반환합니다 ['3', '.', '14'], 그래서 우리는 추가합니다 Combine 따라서 Realnum의 구문 분석 결과 '3.14' (그런 다음 실제 부동 값으로 변환하기 위해 구문 분석 조치로 전달할 수 있습니다. 3.14). Combine중재 공백이없는 S 시행도 실수로 구문 분석하지 못하게합니다. 'The answer is 3. 10 is too much.' 그리고 생각 "3. 10" 실수를 나타냅니다.

4) 이것은 오류를 일으키지 않아야하지만 입력 문자열은 많이 여분의 공간. 문법이 작동하면 구문 분석 할 수 있어야합니다. "int x;" 마찬가지로 "int x ;".

이 힌트 중 일부가 당신을 갈 수 있기를 바랍니다. 온라인 pyparsing 기사 나 튜토리얼을 읽었습니까? 온라인 예제를 살펴보십시오. 방법을 잘 이해해야합니다 Word, Literal, Combine, 등. 개별 구문 분석 작업을 수행합니다.

5) 당신은 용어와 진술에 대한 재귀 적 정의를 잘못 구현했습니다. 할당하는 대신 '' 그들에게 다음과 같이 씁니다.

term = Forward()
statement = Forward()

그런 다음 실제로 재귀 적 정의로 그들을 정의 할 때 << 연산자 (그리고 RHS를 동봉하십시오. ()'에스).

term << (... term definition ...)
statement << (... statement definition ...)

재귀 파서의 예를 찾을 수 있습니다 여기, 및 기본 파파 싱 사용법에 대한 프레젠테이션 여기 -재귀 처리 방법에 대한 더 많은 단계별로 "구문 분석 목록"이라는 섹션을 참조하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top