/* parse.rex * * Homework 4, problem 3 - starter file * * Name: * * Comments to the graders: * */ // tokenize // in: a string to be broken into STRING tokens (not chars) // out: a list of strings, the tokens // // NOT YET DONE: handling whitespace, handling multi-digit integers // the implode changes chars to strings tokenize( s ) => map( (c)=>implode([c]), explode( s ) ); test( tokenize( "1+2" ), [ "1", "+", "2" ] ); // parse // in: a list of tokens (from tokenize, perhaps) // out: a two-element list // first: the resulting parse tree, as covered in class // second: the residue list of unhandled tokens // // NOT YET DONE: all the rules other than addition! parse( TL ) => S( TL ); // starting rule // S // a rule in the grammar handling + and - // in: a token list // out: its parse tree and Residue list - according to S S( TL ) => [ PT, [op|R] ] = P(TL), // get result from P, nonempty Residue (op == "+" || op == "-") // is the next token a + or - ? [ RightPT, Res ] = S(R), // if so, call S [ [op, PT, RightPT], Res ] // and assemble the result : [ PT, [op|R] ]; // otherwise send back just P(TL) S( TL ) => [ PT, [] ] = P(TL), // handles the empty Residue case [ PT, [] ]; // P // a rule in the grammar handling * and / // in: a token list // out: its parse tree and Residue list - according to P // // NOT YET DONE: needs to be modeled from the S rule, above P( TL ) => V( TL ); // delegates to V for now // V // a rule in the grammar handling the values (ints) // in: a token list // out: its parse tree and Residue list - according to V // // NOT YET DONE: handling longer strings of digits V( [] ) => [ "Error", ["missing_V"] ]; // there were no more tokens! DIGITS = ["0","1","2","3","4","5","6","7","8","9"]; // is it a single digit V( [f|R] ) => member( f, DIGITS ) ? [ f, R ]; // if so, it's OK V( [f|R] ) => [ "Error", [ concat("Bad_V_token |->",f,"<-|") | R] ]; // else, // this rule returns an "Error" parse tree and a message // in the Residue list // tests of the parse function // addition and subtraction test( parse( [ "1" ] ), [ "1", [] ] ); test( parse( [ "1", "+", "2" ] ), [ ["+", "1", "2"], [] ] ); test( parse( [ "1", "+", "2", "+", "3" ] ), [ ["+", "1", ["+", "2", "3"]], [] ] ); test( parse( [ "1", "-", "2" ] ), [ ["-", "1", "2"], [] ] ); test( parse( [ "1", "-", "2", "-", "3" ] ), [ ["-", "1", ["-", "2", "3"]], [] ] ); // Evaluate // in: a well-formed parse tree // out: its value! // // NOT DONE YET: everything except addition and subtraction! Evaluate( ["+", L, R] ) => Evaluate( L ) + Evaluate( R ); // addition Evaluate( ["-", L, R] ) => Evaluate( L ) - Evaluate( R ); // subtraction // here, we assume that if it's not an operator, its a number Evaluate( x ) => is_string(x) ? make_number(x); // change to an int // This catches everything else as an error Evaluate( AnythingElse ) => x = print("I don't understand", AnythingElse, "\n\n"), AnythingElse; // tests of Evaluate // addition and subtraction test( Evaluate( "1" ), 1 ); test( Evaluate( ["+", "1", "2"] ), 3 ); test( Evaluate( ["+", "1", ["+", "2", "3"]] ), 6 ); test( Evaluate( ["-", "1", "2"] ), -1 ); test( Evaluate( ["-", "1", ["-", "2", "3"]] ), 2 );