/* * Integer calculator * You can compile "Calc.as" by "mxmlc Calc.as" with Flex2 SDK. */ %{ package { import flash.display.*; import flash.text.*; public class Calc extends MovieClip { public static var _i:Calc; // main instance public function Calc() { _i = this; var cp:CalcParser = new CalcParser(); cp.inputString = "> 30 * 2\n" + "hoge = 3\n" + "> hoge\n" + "> (hoge * 2)\n"; CalcParser.yydebug = true; cp.yyparse(); } // output command // output command private static var output_y:Number = 0; public static function output(v:int):void { var t:TextField = new TextField(); t.autoSize = TextFieldAutoSize.LEFT; t.x = 10; t.y = output_y; t.text = "> " + v; output_y += t.height; _i.addChild(t); } } } %} %token NUMBER %token WORD %left '+' '-' %left '*' '/' '%' %% start: lines; lines: /* empty */ | lines line { yylrec++; } ; line : expr '\n' { trace("result = " + $1); } | '>' expr '\n' { Calc.output( $2 ); } | '\n' { trace("(empty line ignored)"); } | WORD '=' expr { calc_vars[$1] = $3; } | error '\n' ; expr : expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { $$ = $1 / $3; } | expr '%' expr { $$ = ($1) % ($3); } | '(' expr ')' { $$ = $2; } | NUMBER { $$ = $1; } | WORD { $$ = calc_vars[$1]; } ; %% /* Lexical analyzer */ private var ch:String = null; public var inputString:String; private var inputPos:int=0; private var calc_vars:Object = {}; private function getch():String { var c:String = ch; if (c != null) { ch = null; return c; } if(inputPos >= inputString.length) { return null; } return inputString.charAt(inputPos++); } private function ungetch(c:String):void { ch = c; } private function isDigit(s:String):Boolean { s = s.charAt(0); return ("0" <= s && s <= "9"); } private function isAlpha(s:String):Boolean { s = s.charAt(0); return ("a" <= s && s <= "z" || s == "_" || "A" <= s && s <= "Z"); } private function yylex():int { yylval = null; for (;;) { var c:String = getch(); if (c == null) { return 0; } else if (c == ' ' || c == '\t') { // skip } else if (isDigit(c)) { var n:String = ""; while (c != null && isDigit(c)) { n += c; c = getch(); } ungetch(c); yylval = parseInt(n); return NUMBER; } else if (isAlpha(c)) { var id:String = ""; while (c != null && isAlpha(c)) { id += c; c = getch(); } ungetch(c); yylval = id; return WORD; } else { return c.charCodeAt(0); } } throw "Doesn't come here"; } private function yyerror(msg:String):void { trace(msg); }