数式を構文解析した話
TRANSCRIPT
calc.py
• #!/usr/bin/env python# -*- coding: utf-8 -*-exp = raw_input( “input:” )print "ans:" + str(eval( exp ))
9
#include <iostream> #include <string> #include <cstdlib> using namespace std; !double calc( string exp ); int main( void ){ string exp; ! cin >> exp; ! cout << calc( exp ); ! return 0; } double calc( string exp ){ int mulPos; int divPos; ! mulPos = exp.find( '*' ); divPos = exp.find( '/' ); if( mulPos == string::npos && divPos == string::npos ){ int addPos; int subPos; addPos = exp.find( '+' ); subPos = exp.find( '-' ); if( addPos == string::npos && subPos == string::npos ) return atof( exp.c_str() ); if( addPos == string::npos && subPos != string::npos ) return calc( exp.substr( 0, subPos ) ) - calc( exp.substr( subPos + 1 ) ); if( addPos != string::npos && subPos == string::npos ) return calc( exp.substr( 0, addPos ) ) + calc( exp.substr( addPos + 1 ) ); if( addPos != string::npos && subPos != string::npos ){ if( addPos < subPos ) return calc( exp.substr( 0, addPos ) ) + calc( exp.substr( addPos + 1 ) ); else return calc( exp.substr( 0, subPos ) ) - calc( exp.substr( subPos + 1 ) ); } } if( mulPos == string::npos && divPos != string::npos ) return calc( exp.substr( 0, divPos ) ) / calc( exp.substr( divPos + 1 ) ); if( mulPos != string::npos && divPos == string::npos ) return calc( exp.substr( 0, mulPos ) ) * calc( exp.substr( mulPos + 1 ) ); ! if( mulPos != string::npos && divPos != string::npos ){ if( mulPos < divPos ) return calc( exp.substr( 0, mulPos ) ) * calc( exp.substr( mulPos + 1 ) ); else return calc( exp.substr( 0, divPos ) ) / calc( exp.substr( divPos + 1 ) ); } } 12
うごかしてみよう• ➜ calc git:(master) ✗ ./a.out ./a.out3+25 ➜ calc git:(master) ✗ ./a.out 3+2+16 ➜ calc git:(master) ✗ ./a.out 2*24 ➜ calc git:(master) ✗ ./a.out 2*3/32 ➜ calc git:(master) ✗ ./a.out 1+2*39 ???????????????
13
#include <iostream> #include <string> #include <cstdlib> using namespace std; !double calc( string exp ); int main( void ){ string exp; ! cin >> exp; ! cout << calc( exp ); ! return 0; } double calc( string exp ){ int mulPos; int divPos; ! mulPos = exp.find( '*' ); divPos = exp.find( '/' ); if( mulPos == string::npos && divPos == string::npos ){ int addPos; int subPos; addPos = exp.find( '+' ); subPos = exp.find( '-' ); if( addPos == string::npos && subPos == string::npos ) return atof( exp.c_str() ); if( addPos == string::npos && subPos != string::npos ) return calc( exp.substr( 0, subPos ) ) - calc( exp.substr( subPos + 1 ) ); if( addPos != string::npos && subPos == string::npos ) return calc( exp.substr( 0, addPos ) ) + calc( exp.substr( addPos + 1 ) ); if( addPos != string::npos && subPos != string::npos ){ if( addPos < subPos ) return calc( exp.substr( 0, addPos ) ) + calc( exp.substr( addPos + 1 ) ); else return calc( exp.substr( 0, subPos ) ) - calc( exp.substr( subPos + 1 ) ); } } if( mulPos == string::npos && divPos != string::npos ) return calc( exp.substr( 0, divPos ) ) / calc( exp.substr( divPos + 1 ) ); if( mulPos != string::npos && divPos == string::npos ) return calc( exp.substr( 0, mulPos ) ) * calc( exp.substr( mulPos + 1 ) ); ! if( mulPos != string::npos && divPos != string::npos ){ if( mulPos < divPos ) return calc( exp.substr( 0, mulPos ) ) * calc( exp.substr( mulPos + 1 ) ); else return calc( exp.substr( 0, divPos ) ) / calc( exp.substr( divPos + 1 ) ); } } 14
私が実装した演算規則
• hoge+foo-bar = hoge + calc( foo - bar )= hoge + foo - bar // 動作かくにん! よかった
• hoge*foo/bar = hoge * calc( foo / bar )= hoge * foo / bar // 動作かくにん! よかった
15
#include <iostream> #include <string> #include <cstdlib> using namespace std; !double calc( string exp ); int main( void ){ string exp; ! cin >> exp; ! cout << calc( exp ); ! return 0; } double calc( string exp ){ int addPos; int subPos; ! addPos = exp.find( '+' ); subPos = exp.find( '-' ); if( addPos == string::npos && subPos == string::npos ){ int mulPos; int divPos; mulPos = exp.find( '*' ); divPos = exp.find( '/' ); if( mulPos == string::npos && divPos == string::npos ) return atof( exp.c_str() ); if( mulPos == string::npos && divPos != string::npos ) return calc( exp.substr( 0, divPos ) ) / calc( exp.substr( divPos + 1 ) ); if( mulPos != string::npos && divPos == string::npos ) return calc( exp.substr( 0, mulPos ) ) * calc( exp.substr( mulPos + 1 ) ); if( mulPos != string::npos && divPos != string::npos ){ if( mulPos < divPos ) return calc( exp.substr( 0, mulPos ) ) * calc( exp.substr( mulPos + 1 ) ); else return calc( exp.substr( 0, divPos ) ) / calc( exp.substr( divPos + 1 ) ); } } if( addPos == string::npos && subPos != string::npos ) return calc( exp.substr( 0, subPos ) ) - calc( exp.substr( subPos + 1 ) ); if( addPos != string::npos && subPos == string::npos ) return calc( exp.substr( 0, addPos ) ) + calc( exp.substr( addPos + 1 ) ); ! if( addPos != string::npos && subPos != string::npos ){ if( addPos < subPos ) return calc( exp.substr( 0, addPos ) ) + calc( exp.substr( addPos + 1 ) ); else return calc( exp.substr( 0, subPos ) ) - calc( exp.substr( subPos + 1 ) ); } !} 17
うごかしてみよう• ➜ calc git:(master) ✗ ./a.out ./a.out3+25 ➜ calc git:(master) ✗ ./a.out 3+2+16 ➜ calc git:(master) ✗ ./a.out 2*24 ➜ calc git:(master) ✗ ./a.out 2*3/32 ➜ calc git:(master) ✗ ./a.out 1+2*37 // 動作かくにん!よかった
18
動きの流れ
• Input: a+b*c+d = calc(a) + calc( b*c + d ) // +で分割= a + calc( b*c ) + calc( d ) // +で分割 & atof= a + calc(b) * calc(c) + d // atof & *で分割= a + b * c + d // atof