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 () { |