parser.cxx

changeset 51
2cfa6edbf928
parent 50
2e333a3ca49a
child 52
f2596a239ea1
equal deleted inserted replaced
50:2e333a3ca49a 51:2cfa6edbf928
634 case OPER_ASSIGNADD: 634 case OPER_ASSIGNADD:
635 case OPER_ASSIGNSUB: 635 case OPER_ASSIGNSUB:
636 case OPER_ASSIGNMUL: 636 case OPER_ASSIGNMUL:
637 case OPER_ASSIGNDIV: 637 case OPER_ASSIGNDIV:
638 case OPER_ASSIGNMOD: 638 case OPER_ASSIGNMOD:
639 case OPER_ASSIGNLEFTSHIFT:
640 case OPER_ASSIGNRIGHTSHIFT:
639 case OPER_ASSIGN: 641 case OPER_ASSIGN:
640 return true; 642 return true;
641 } 643 }
642 return false; 644 return false;
643 } 645 }
648 if (IsAssignmentOperator (oper)) { 650 if (IsAssignmentOperator (oper)) {
649 if (!var) 651 if (!var)
650 error ("operator %d requires left operand to be a variable\n", oper); 652 error ("operator %d requires left operand to be a variable\n", oper);
651 653
652 // TODO: At the moment, vars only are global 654 // TODO: At the moment, vars only are global
655 // OPER_ASSIGNLEFTSHIFT and OPER_ASSIGNRIGHTSHIFT do not
656 // have data headers, instead they are expanded out in
657 // the operator parser
653 switch (oper) { 658 switch (oper) {
654 case OPER_ASSIGNADD: return DH_ADDGLOBALVAR; 659 case OPER_ASSIGNADD: return DH_ADDGLOBALVAR;
655 case OPER_ASSIGNSUB: return DH_SUBGLOBALVAR; 660 case OPER_ASSIGNSUB: return DH_SUBGLOBALVAR;
656 case OPER_ASSIGNMUL: return DH_MULGLOBALVAR; 661 case OPER_ASSIGNMUL: return DH_MULGLOBALVAR;
657 case OPER_ASSIGNDIV: return DH_DIVGLOBALVAR; 662 case OPER_ASSIGNDIV: return DH_DIVGLOBALVAR;
671 case OPER_NOTEQUALS: return DH_NOTEQUALS; 676 case OPER_NOTEQUALS: return DH_NOTEQUALS;
672 case OPER_LESSTHAN: return DH_LESSTHAN; 677 case OPER_LESSTHAN: return DH_LESSTHAN;
673 case OPER_GREATERTHAN: return DH_GREATERTHAN; 678 case OPER_GREATERTHAN: return DH_GREATERTHAN;
674 case OPER_LESSTHANEQUALS: return DH_LESSTHANEQUALS; 679 case OPER_LESSTHANEQUALS: return DH_LESSTHANEQUALS;
675 case OPER_GREATERTHANEQUALS: return DH_GREATERTHANEQUALS; 680 case OPER_GREATERTHANEQUALS: return DH_GREATERTHANEQUALS;
681 case OPER_LEFTSHIFT: return DH_LSHIFT;
682 case OPER_RIGHTSHIFT: return DH_RSHIFT;
676 } 683 }
677 684
678 error ("DataHeaderByOperator: couldn't find dataheader for operator %d!\n", oper); 685 error ("DataHeaderByOperator: couldn't find dataheader for operator %d!\n", oper);
679 return 0; 686 return 0;
680 } 687 }
693 // We peeked the operator, move forward now 700 // We peeked the operator, move forward now
694 MustNext(); 701 MustNext();
695 702
696 // Can't be an assignement operator, those belong in assignments. 703 // Can't be an assignement operator, those belong in assignments.
697 if (IsAssignmentOperator (oper)) 704 if (IsAssignmentOperator (oper))
698 ParserError ("assignment operator inside expressions"); 705 ParserError ("assignment operator inside expression");
699 706
700 // Parse the right operand, 707 // Parse the right operand,
701 MustNext (); 708 MustNext ();
702 DataBuffer* rb = ParseExprValue (reqtype); 709 DataBuffer* rb = ParseExprValue (reqtype);
703 710
710 return retbuf; 717 return retbuf;
711 } 718 }
712 719
713 // ============================================================================ 720 // ============================================================================
714 // Parses an operator string. Returns the operator number code. 721 // Parses an operator string. Returns the operator number code.
722 #define ISNEXT(char) !PeekNext (peek ? 1 : 0).compare (char)
715 int ScriptReader::ParseOperator (bool peek) { 723 int ScriptReader::ParseOperator (bool peek) {
716 str oper; 724 str oper;
717 if (peek) 725 if (peek)
718 oper += PeekNext (); 726 oper += PeekNext ();
719 else 727 else
720 oper += token; 728 oper += token;
721 729
722 // Check one-char operators 730 // Check one-char operators
723 bool equalsnext = !PeekNext (peek ? 1 : 0).compare ("="); 731 bool equalsnext = ISNEXT ("=");
732 bool morenext = ISNEXT (">");
733 bool lessnext = ISNEXT ("<");
734
724 int o = (!oper.compare ("=") && !equalsnext) ? OPER_ASSIGN : 735 int o = (!oper.compare ("=") && !equalsnext) ? OPER_ASSIGN :
725 (!oper.compare (">") && !equalsnext) ? OPER_GREATERTHAN : 736 (!oper.compare (">") && !equalsnext && !morenext) ? OPER_GREATERTHAN :
726 (!oper.compare ("<") && !equalsnext) ? OPER_LESSTHAN : 737 (!oper.compare ("<") && !equalsnext && !lessnext) ? OPER_LESSTHAN :
727 !oper.compare ("+") ? OPER_ADD : 738 !oper.compare ("+") ? OPER_ADD :
728 !oper.compare ("-") ? OPER_SUBTRACT : 739 !oper.compare ("-") ? OPER_SUBTRACT :
729 !oper.compare ("*") ? OPER_MULTIPLY : 740 !oper.compare ("*") ? OPER_MULTIPLY :
730 !oper.compare ("/") ? OPER_DIVIDE : 741 !oper.compare ("/") ? OPER_DIVIDE :
731 !oper.compare ("%") ? OPER_MODULUS : 742 !oper.compare ("%") ? OPER_MODULUS :
735 return o; 746 return o;
736 } 747 }
737 748
738 // Two-char operators 749 // Two-char operators
739 oper += PeekNext (peek ? 1 : 0); 750 oper += PeekNext (peek ? 1 : 0);
751 equalsnext = !PeekNext (peek ? 2 : 1).compare ("=");
740 752
741 o = !oper.compare ("+=") ? OPER_ASSIGNADD : 753 o = !oper.compare ("+=") ? OPER_ASSIGNADD :
742 !oper.compare ("-=") ? OPER_ASSIGNSUB : 754 !oper.compare ("-=") ? OPER_ASSIGNSUB :
743 !oper.compare ("*=") ? OPER_ASSIGNMUL : 755 !oper.compare ("*=") ? OPER_ASSIGNMUL :
744 !oper.compare ("/=") ? OPER_ASSIGNDIV : 756 !oper.compare ("/=") ? OPER_ASSIGNDIV :
745 !oper.compare ("%=") ? OPER_ASSIGNMOD : 757 !oper.compare ("%=") ? OPER_ASSIGNMOD :
746 !oper.compare ("==") ? OPER_EQUALS : 758 !oper.compare ("==") ? OPER_EQUALS :
747 !oper.compare ("!=") ? OPER_NOTEQUALS : 759 !oper.compare ("!=") ? OPER_NOTEQUALS :
748 !oper.compare (">=") ? OPER_GREATERTHANEQUALS : 760 !oper.compare (">=") ? OPER_GREATERTHANEQUALS :
749 !oper.compare ("<=") ? OPER_LESSTHANEQUALS : 761 !oper.compare ("<=") ? OPER_LESSTHANEQUALS :
762 (!oper.compare ("<<") && !equalsnext) ? OPER_LEFTSHIFT :
763 (!oper.compare (">>") && !equalsnext) ? OPER_RIGHTSHIFT :
750 -1; 764 -1;
751 765
752 if (o != -1) 766 if (o != -1) {
753 MustNext (); 767 MustNext ();
768 return o;
769 }
770
771 // Three-char opers
772 oper += PeekNext (peek ? 2 : 1);
773 o = !oper.compare ("<<=") ? OPER_ASSIGNLEFTSHIFT :
774 !oper.compare (">>=") ? OPER_ASSIGNRIGHTSHIFT :
775 -1;
776
777 if (o != -1) {
778 MustNext ();
779 MustNext ();
780 }
754 781
755 return o; 782 return o;
756 } 783 }
757 784
758 // ============================================================================ 785 // ============================================================================
817 // ============================================================================ 844 // ============================================================================
818 // Parses an assignment. An assignment starts with a variable name, followed 845 // Parses an assignment. An assignment starts with a variable name, followed
819 // by an assignment operator, followed by an expression value. Expects current 846 // by an assignment operator, followed by an expression value. Expects current
820 // token to be the name of the variable, and expects the variable to be given. 847 // token to be the name of the variable, and expects the variable to be given.
821 DataBuffer* ScriptReader::ParseAssignment (ScriptVar* var) { 848 DataBuffer* ScriptReader::ParseAssignment (ScriptVar* var) {
849 bool global = !var->statename.len ();
850
822 // Get an operator 851 // Get an operator
823 MustNext (); 852 MustNext ();
824 int oper = ParseOperator (); 853 int oper = ParseOperator ();
825 if (!IsAssignmentOperator (oper)) 854 if (!IsAssignmentOperator (oper))
826 ParserError ("expected assignment operator"); 855 ParserError ("expected assignment operator");
827 856
828 if (g_CurMode == MODE_TOPLEVEL) // TODO: lift this restriction 857 if (g_CurMode == MODE_TOPLEVEL) // TODO: lift this restriction
829 ParserError ("can't alter variables at top level"); 858 ParserError ("can't alter variables at top level");
830 859
831 // Parse the right operand, 860 // Parse the right operand
832 MustNext (); 861 MustNext ();
833 DataBuffer* retbuf = ParseExpression (TYPE_INT); 862 DataBuffer* retbuf = new DataBuffer;
834 863 DataBuffer* expr = ParseExpression (TYPE_INT);
835 long dh = DataHeaderByOperator (var, oper); 864
836 retbuf->Write<word> (dh); 865 // <<= and >>= do not have data headers. Solution: expand them.
837 retbuf->Write<word> (var->index); 866 // a <<= b -> a = a << b
867 // a >>= b -> a = a >> b
868 if (oper == OPER_ASSIGNLEFTSHIFT || oper == OPER_ASSIGNRIGHTSHIFT) {
869 retbuf->Write<word> (global ? DH_PUSHGLOBALVAR : DH_PUSHLOCALVAR);
870 retbuf->Write<word> (var->index);
871 retbuf->Merge (expr);
872 retbuf->Write<word> ((oper == OPER_ASSIGNLEFTSHIFT) ? DH_LSHIFT : DH_RSHIFT);
873 retbuf->Write<word> (global ? DH_ASSIGNGLOBALVAR : DH_ASSIGNLOCALVAR);
874 retbuf->Write<word> (var->index);
875 } else {
876 retbuf->Merge (expr);
877 long dh = DataHeaderByOperator (var, oper);
878 retbuf->Write<word> (dh);
879 retbuf->Write<word> (var->index);
880 }
838 881
839 return retbuf; 882 return retbuf;
840 } 883 }
841 884
842 void ScriptReader::PushBlockStack () { 885 void ScriptReader::PushBlockStack () {

mercurial