如何实现具有优先级和关联性的中缀计算器

时间:2016-10-17 08:59:16

标签: c bison flex-lexer

我正在测试使用bison flex编写中缀计算器的示例。我发现除了括号“()”之外,一切都是正确的。我发现当我用括号输入计算时,计算结果不正确。这是文件“infix-calc.y”的代码

/* bison grammar file for infix notation calculator */
%{
#define YYSTYPE double
#include <math.h>
#include <stdio.h>


int yyerror(const char *s);
int yylex(void);


%}

%token NUM
%left '-' '+'
%left '*' '/'
%left NEG
%right '^'

%% /* Grammer rules and actions follow */

input: /* empty */
     | input line
     ;

line: '\n'
    | exp '\n' { printf("\t%.10g\n", $1); }
    ;

exp: NUM { $$ = $1; }
   | exp '+' exp { $$ = $1 + $3; }
   | exp '-' exp { $$ = $1 - $3; }
   | exp '*' exp { $$ = $1 * $3; }
   | exp '/' exp { $$ = $1 / $3; }
   | '-' exp %prec NEG { $$ = -$2; }
   | exp '^' exp { $$ = pow($1, $3); }
   | '(' exp ')' { $$ = $2; }
   ;

%%

/* Additional C code */

int main() { return yyparse(); }

int yyerror(const char* s)
{
    printf("%s\n", s);
    return 0;
}

这是文件“infix-calc.lex”的代码

/* lex file for infix notation calculator */
%option noyywrap

%{
#define YYSTYPE double     /* type for bison's var: yylval */
#include <stdlib.h>        /* for atof(const char*) */
#include "infix-calc.tab.h"
%}


digits [0-9]
rn     (0|[1-9]+{digits}*)\.?{digits}*
op     [+*^/\-]
ws     [ \t]+  


%%

{rn}   yylval = atof(yytext); return NUM;
{op}   |
\n     return *yytext;
{ws}   /* eats up white spaces */

%%

问题在于,当我输入时,说“2 *(3 + 4)”,我应该接收输出“14”。但输入是“()10”。在这种情况下,括号似乎不起作用。这些代码有什么问题? 非常感谢你帮助我!!!!

1 个答案:

答案 0 :(得分:0)

看起来您必须将class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate { var window: UIWindow? func applicationDidBecomeActive(_ application: UIApplication) { let locationManager = CLLocationManager() locationManager.requestAlwaysAuthorization() locationManager.requestWhenInUseAuthorization() if CLLocationManager.locationServicesEnabled() { locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters locationManager.startUpdatingLocation() if ((locationManager.location?.coordinate) != nil) { let locValue:CLLocationCoordinate2D = (locationManager.location?.coordinate)! let geoCoder = CLGeocoder() let location = CLLocation(latitude: locValue.latitude, longitude: locValue.longitude) geoCoder.reverseGeocodeLocation(location) { (placemarks, error) -> Void in let placeArray = placemarks as [CLPlacemark]! // Place details var placeMark: CLPlacemark! placeMark = placeArray?[0] if let state = placeMark.addressDictionary?["State"] as? NSString { let parameters: Parameters = ["Location": state] Alamofire.request(GlobalValues.APIUrl, method: .post, parameters: parameters).validate().responseJSON{ response in if let result = response.result.value { let JSON = result as! NSDictionary let items = JSON.object(forKey: "Items") as! NSDictionary userData.set(items.object(forKey: "fajr") as! String, forKey: "sabahNamazi") userData.set(items.object(forKey: "dhuhr") as! String, forKey: "ogleNamazi") userData.set(items.object(forKey: "asr") as! String, forKey: "ikindiNamazi") userData.set(items.object(forKey: "maghrib") as! String, forKey: "aksamNamazi") userData.set(items.object(forKey: "isha") as! String, forKey: "yatsiNamazi") } } } } } else { // create the alert let alert = UIAlertController(title: "Konum Alınamıyor", message: "Telefonunuzun konum ayarlarını kontrol edip tekrar deneyin!", preferredStyle: UIAlertControllerStyle.alert) // add the actions (buttons) alert.addAction(UIAlertAction(title: "Tamam", style: UIAlertActionStyle.default, handler: nil)) // show the alert self.window?.rootViewController?.present(alert, animated: true, completion: nil) } } else { // create the alert let alert = UIAlertController(title: "Konum Ayarını Açın", message: "Bu uygulama bulunduğunuz şehrin 'EZAN VAKİTLERİNİ' tespit edebilmek için konum bilginize ihtiyaç duyuyor.", preferredStyle: UIAlertControllerStyle.alert) // add the actions (buttons) alert.addAction(UIAlertAction(title: "Ayarlar", style: UIAlertActionStyle.default, handler: {( action:UIAlertAction!) -> Void in UIApplication.shared.openURL(URL(string: "prefs:root=LOCATION_SERVICES")!) })) alert.addAction(UIAlertAction(title: "İptal", style: UIAlertActionStyle.cancel, handler: nil)) // show the alert self.window?.rootViewController?.present(alert, animated: true, completion: nil) } } func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } } (声明为令牌才能生效。

在你的lex文件中的最后)之前添加以下两行:

%%

然后添加

"("    return LEFT;
")"    return RIGHT;

到infix-calc.y的顶部,并替换

%token LEFT RIGHT

   | '(' exp ')' { $$ = $2; }