Ejemplo n.º 1
0
        private static void EmitShowMessage(Token[] smt)
        {
            //ShowMessage DoorOpenedScienceMsg passSkill
            //59 10 0E 00 01 00 72 02 00 01 00 73 01 00 00 00 00 00
            Emit(0x1059);
            if(smt.Length==1) {
                AddError("Not enough arguments to ShowMessage");
                return;
            }
            long pos=bw.BaseStream.Length;
            Emit(0);
            Emit(1);

            switch(smt[1].type) {
            case TokenType.edid:
                if(edidList[smt[1].token].Value!="MESG") goto default;
                else EmitRefLabel(smt[1], RefType.Expression);
                break;
            case TokenType.Local:
                LocalVar vt=locals[smt[1].token];
                if(vt.type!=VarType.Ref) goto default;
                EmitRefLabel(smt[1], RefType.Expression);
                break;
            default:
                AddError("First argument to ShowMessage must be an MESG record");
                return;
            }

            if(smt.Length==2) {
                Emit(0);
            } else {
                bool lastwasref=false;
                Emit((ushort)(smt.Length-2));
                for(int i=2;i<smt.Length;i++) {
                    if(smt[i].type==TokenType.Symbol) {
                        if(smt[i].IsSymbol(".")&&lastwasref) {
                            if(i<smt.Length-1&&farVars.ContainsKey(smt[i-1].token)) {
                                i++;
                                EmitByte(0x73);
                                Dictionary<string, ushort> vars=farVars[smt[i-2].token];
                                if(!vars.ContainsKey(smt[i].token)) AddError("Reference '"+smt[i-2].utoken+"' has no variable called '"+smt[i].utoken+"'");
                                else Emit(vars[smt[i].token]);
                                continue;
                            }
                        } else if(smt[i].IsSymbol("-")) {
                            if(i<smt.Length-1&&(smt[i+1].type==TokenType.Integer||smt[i+1].type==TokenType.Float)) {
                                smt[i+1]=new Token(smt[i+1].type, "-"+smt[i+1].token);
                                continue;
                            }
                        }
                        AddError("Unexpected symbol '"+smt[i].token+"' in ShowMessage arguments");
                    }
                    lastwasref=false;
                    switch(smt[i].type) {
                    case TokenType.edid:
                        EmitRefLabel(smt[i], RefType.Expression);
                        lastwasref=true;
                        break;
                    case TokenType.Local:
                        LocalVar vt=locals[smt[i].token];
                        switch(vt.type) {
                        case VarType.Int:
                            EmitByte(0x73);
                            Emit((ushort)locals[smt[i].token].index);
                            break;
                        case VarType.Float:
                            EmitByte(0x66);
                            Emit((ushort)locals[smt[i].token].index);
                            break;
                        case VarType.Ref:
                            EmitRefLabel(smt[i], RefType.Expression);
                            break;
                        }
                        break;
                    case TokenType.Global:
                        EmitRefLabel(smt[i], RefType.Expression);
                        break;
                    case TokenType.Integer:
                        EmitByte(0x6e);
                        bw.Write(int.Parse(smt[i].token));
                        break;
                    case TokenType.Float:
                        EmitByte(0x7a);
                        bw.Write(double.Parse(smt[i].token));
                        break;
                    default:
                        AddError("Expected <global>|<local>|<constant>");
                        return;
                    }
                }
            }
            Emit(0);
            Emit(0);
            bw.BaseStream.Position=pos;
            Emit((ushort)(bw.BaseStream.Length-(pos+2)));
            bw.BaseStream.Position=bw.BaseStream.Length;
        }
Ejemplo n.º 2
0
 private static void HandleStatement(Token[] smt)
 {
     if(smt[0].type==TokenType.Function) {
         EmitFunctionCall(ref smt, false, false, false);
     } else if(smt[0].IsKeyword(Keywords.ShowMessage)) {
         EmitShowMessage(smt); ;
     } else if(smt[0].IsKeyword(Keywords.Set)) {
         if(smt.Length<4||!(smt[2].IsKeyword(Keywords.To)||smt[2].IsSymbol("."))) {
             AddError("Expected 'set <var> to <expression>'");
             return;
         }
         Emit(0x15);
         long pos=bw.BaseStream.Length;
         Emit(0);
         if(smt[1].type==TokenType.Local) {
             LocalVar lv=locals[smt[1].token];
             if(lv.type==VarType.Int) EmitByte(0x73);
             else EmitByte(0x66);
             Emit((ushort)lv.index);
             EmitExpression(TrimStatement(smt, 3), (lv.type==VarType.Ref)?ExpressionType.Ref:ExpressionType.Numeric);
         } else if(smt[1].type==TokenType.Global) {
             EmitRefLabel(smt[1], RefType.Expression);
             EmitExpression(TrimStatement(smt, 3), ExpressionType.Numeric);
         } else if(smt[1].type==TokenType.edid&&farVars.ContainsKey(smt[1].token)&&smt[2].IsSymbol(".")) {
             if(smt.Length<6||!smt[4].IsKeyword(Keywords.To)) {
                 AddError("Expected 'set <var> to <expression>'");
                 return;
             }
             EmitRefLabel(smt[1], RefType.Expression);
             EmitByte(0x73);
             if(!farVars[smt[1].token].ContainsKey(smt[3].token)) {
                 AddError("Local variable '"+smt[3].token+" does not exist in quest "+smt[1].token);
             } else {
                 Emit(farVars[smt[1].token][smt[3].token]);
             }
             EmitExpression(TrimStatement(smt, 5), ExpressionType.If);
         } else {
             AddError("Expected set <local>|<global> to <expression>");
         }
         bw.BaseStream.Position=pos;
         Emit((ushort)(bw.BaseStream.Length-(pos+2)));
         bw.BaseStream.Position=bw.BaseStream.Length;
     } else if(smt[0].type==TokenType.edid) {
         if(smt.Length<3||!smt[1].IsSymbol(".")||smt[2].type!=TokenType.Function) {
             AddError("Expected ref.function");
             return;
         }
         EmitRefLabel(smt[0], RefType.Standard);
         smt=TrimStatement(smt, 2);
         EmitFunctionCall(ref smt, false, true, false);
     } else if(smt[0].type==TokenType.Local) {
         LocalVar lv=locals[smt[0].token];
         if(lv.type!=VarType.Ref) {
             AddError("Expected 'Set', <function> or <ref>.<function>");
             return;
         }
         if(smt.Length<3||!smt[1].IsSymbol(".")||smt[2].type!=TokenType.Function) {
             AddError("Expected ref.function");
             return;
         }
         EmitRefLabel(smt[0], RefType.Standard);
         smt=TrimStatement(smt, 2);
         EmitFunctionCall(ref smt, false, true, false);
     } else {
         AddError("Expected 'Set', <function> or <ref>.<function>");
     }
 }
Ejemplo n.º 3
0
 private static void EmitFunctionCall(ref Token[] smt, bool expression, bool hadref, bool requiresRef)
 {
     FunctionSig fs=functionList[smt[0].token];
     if(hadref&&!fs.allowref) AddError("Object reference not valid on this function");
     if(expression) {
         EmitByte(0x58);
         //if(fs.ret==VarType.None) AddError("Functions with no return type cannot be used in expressions");
     }
     //if(requiresRef&&fs.ret!=VarType.Ref) AddError("Function does not return a reference");
     Emit(fs.opcode);
     if(fs.skipArgs) {
         if(expression) AddError("SkipArgs is not valid on functions used in expressions");
         //for(int j=1;j<smt.Length;j++) smt[j-1]=smt[j];
         //Array.Resize<Token>(ref smt, smt.Length-1);
         smt=new Token[0];
         Emit(0);
         return;
     }
     if(smt.Length==1) {
         if(fs.requiredArgs>0) AddError("Not enough arguments to function");
         if(fs.args.Length>0) Emit(2);
         Emit(0);
         smt=new Token[0];
         return;
     }
     if(fs.args.Length==0) {
         Emit(0);
         for(int j=1;j<smt.Length;j++) smt[j-1]=smt[j];
         Array.Resize<Token>(ref smt, smt.Length-1);
         return;
     }
     long pos=bw.BaseStream.Length;
     ushort argcount=0;
     Emit(0);
     Emit(0);
     int i=0;
     bool lastwasref=false;
     while(true) {
         i++;
         if(i==smt.Length) {
             if(argcount<fs.requiredArgs) AddError("Not enough arguments to function. Expected "+fs.requiredArgs);
             smt=new Token[0];
             break;
         }
         if(smt[i].type==TokenType.Symbol) {
             if(smt[i].IsSymbol(".")&&lastwasref) {
                 if(i<smt.Length-1&&farVars.ContainsKey(smt[i-1].token)) {
                     i++;
                     EmitByte(0x73);
                     Dictionary<string, ushort> vars=farVars[smt[i-2].token];
                     if(!vars.ContainsKey(smt[i].token)) AddError("Reference '"+smt[i-2].utoken+"' has no variable called '"+smt[i].utoken+"'");
                     else Emit(vars[smt[i].token]);
                     continue;
                 }
             } else if(smt[i].IsSymbol("-")&&(!expression||(argcount<fs.requiredArgs))) {
                 if(i<smt.Length-1&&(smt[i+1].type==TokenType.Integer||smt[i+1].type==TokenType.Float)) {
                     smt[i+1]=new Token(smt[i+1].type, "-"+smt[i+1].token);
                     continue;
                 }
             }
             if(expression) {
                 if(argcount<fs.requiredArgs) AddError("Not enough arguments to function. Expected "+fs.requiredArgs);
                 for(int j=i;j<smt.Length;j++) smt[j-i]=smt[j];
                 Array.Resize<Token>(ref smt, smt.Length-i);
                 break;
             } else AddError("Unexpected symbol '"+smt[i].token+"' in function arguments");
         }
         if(argcount==fs.args.Length) AddError("Too many arguments given to function. Expected "+fs.args.Length);
         argcount++;
         lastwasref=false;
         switch(fs.args[argcount-1]) {
         case VarType.Axis:
             switch(smt[i].token) {
             case "x":
                 EmitByte((byte)'X');
                 continue;
             case "y":
                 EmitByte((byte)'Y');
                 continue;
             case "z":
                 EmitByte((byte)'Z');
                 continue;
             default:
                 AddError("Expected 'x', 'y' or 'z'");
                 continue;
             }
         case VarType.Enum:
             if(smt[i].type==TokenType.Integer) {
                 Emit(ushort.Parse(smt[i].token));
             } else {
                 Dictionary<string, ushort> Enum=enumList[fs.reftypes[argcount-1]];
                 if(!Enum.ContainsKey(smt[i].token)) {
                     AddError("'"+smt[i].token+"' is not a valid entry of the enum '"+fs.reftypes[argcount-1]+"'");
                 } else {
                     Emit(Enum[smt[i].token]);
                 }
             }
             continue;
         case VarType.Short:
             if(smt[i].type!=TokenType.Integer) {
                 AddError("Expected integer argument");
             } else {
                 Emit(ushort.Parse(smt[i].token));
             }
             continue;
         case VarType.String:
             Emit((ushort)smt[i].token.Length);
             bw.Write(System.Text.Encoding.Default.GetBytes(smt[i].token));
             continue;
         }
         switch(smt[i].type) {
         case TokenType.edid:
             if(i==smt.Length-1||!smt[i+1].IsSymbol(".")) {
                 if(fs.args[argcount-1]!=VarType.Ref) AddError("Invalid argument "+i+" to function. Expected "+fs.args[argcount-1].ToString());
                 if(fs.reftypes[argcount-1]!=null&&fs.reftypes[argcount-1]!=edidList[smt[i].token].Value) {
                     AddError("Invalid record type at argument "+i+" of function. Expected "+fs.reftypes[argcount-1]);
                 }
             }
             EmitRefLabel(smt[i], RefType.Expression);
             lastwasref=true;
             break;
         case TokenType.Local:
             LocalVar vt=locals[smt[i].token];
             switch(vt.type) {
             case VarType.Int:
                 if(fs.args[argcount-1]!=VarType.Float&&fs.args[argcount-1]!=VarType.Int) AddError("Invalid argument "+i+" to function. Expected "+fs.args[argcount-1].ToString());
                 EmitByte(0x73);
                 Emit((ushort)locals[smt[i].token].index);
                 break;
             case VarType.Float:
                 if(fs.args[argcount-1]!=VarType.Float&&fs.args[argcount-1]!=VarType.Int) AddError("Invalid argument "+i+" to function. Expected "+fs.args[argcount-1].ToString());
                 EmitByte(0x66);
                 Emit((ushort)locals[smt[i].token].index);
                 break;
             case VarType.Ref:
                 if(fs.args[argcount-1]!=VarType.Ref) AddError("Invalid argument "+i+" to function. Expected "+fs.args[argcount-1].ToString());
                 EmitRefLabel(smt[i], RefType.Expression);
                 break;
             }
             break;
         case TokenType.Global:
             if(fs.args[argcount-1]!=VarType.Float&&fs.args[argcount-1]!=VarType.Int) AddError("Invalid argument "+i+" to function. Expected "+fs.args[argcount-1].ToString());
             EmitRefLabel(smt[i], RefType.Expression);
             break;
         case TokenType.Integer:
             if(fs.args[argcount-1]==VarType.Float) goto case TokenType.Float;
             if(fs.args[argcount-1]!=VarType.Int) AddError("Invalid argument "+i+" to function. Expected "+fs.args[argcount-1].ToString());
             EmitByte(0x6e);
             bw.Write(int.Parse(smt[i].token));
             break;
         case TokenType.Float:
             if(fs.args[argcount-1]!=VarType.Float&&fs.args[argcount-1]!=VarType.Int) AddError("Invalid argument "+i+" to function. Expected "+fs.args[argcount-1].ToString());
             EmitByte(0x7a);
             bw.Write(double.Parse(smt[i].token));
             break;
         default:
             AddError("Expected <global>|<local>|<constant>");
             return;
         }
     }
     for(int j=0;j<fs.paddingbytes;j++) EmitByte(0);
     bw.BaseStream.Position=pos;
     Emit((ushort)(bw.BaseStream.Length-(pos+2)));
     Emit(argcount);
     bw.BaseStream.Position=bw.BaseStream.Length;
 }
Ejemplo n.º 4
0
 private static void EmitRefLabel(Token t, RefType type)
 {
     if(t.type==TokenType.Global) {
         EmitByte(0x47);
     } else {
         switch(type) {
         case RefType.Standard: Emit(0x1c); break;
         case RefType.Expression: EmitByte(0x72); break;
         case RefType.Standalone: EmitByte(0x5a); break;
         }
     }
     if(t.type==TokenType.Local) {
         LocalVar var=locals[t.token];
         if(var.refid==0) AddError("Variable was not of type ref");
         else Emit((ushort)var.refid);
     } else if(t.type==TokenType.edid||t.type==TokenType.Global) {
         if(!edidRefs.ContainsKey(t.token)) {
             SubRecord sr=new SubRecord();
             sr.Name="SCRO";
             if(t.type==TokenType.edid) sr.SetData(TypeConverter.i2h(edidList[t.token].Key));
             else sr.SetData(TypeConverter.i2h(globals[t.token]));
             r.AddRecord(sr);
             refcount++;
             edidRefs[t.token]=(ushort)refcount;
         }
         Emit(edidRefs[t.token]);
     } else {
         AddError("Expected ref variable or edid");
     }
 }
Ejemplo n.º 5
0
 private static void EmitExpressionValue(Token t, Queue<Token> smt, ExpressionType type)
 {
     EmitByte(0x20);
     bool hadRef=false;
     switch(t.type) {
     case TokenType.edid:
         if(smt.Count>0&&smt.Peek().IsSymbol(".")) {
             EmitRefLabel(t, RefType.Expression);
             smt.Dequeue();
             if(smt.Count==0) throw new ExpressionParseException("Unexpected end of line");
             if(farVars.ContainsKey(t.token)) {
                 Dictionary<string, ushort> fars=farVars[t.token];
                 t=smt.Dequeue();
                 if(fars.ContainsKey(t.token)) {
                     EmitByte(0x73);
                     Emit(fars[t.token]);
                     break;
                 }
             } else t=smt.Dequeue();
             hadRef=true;
             goto case TokenType.Function;
         } else {
             if(type==ExpressionType.Numeric) AddError("Reference type not valid here");
             EmitRefLabel(t, RefType.Standalone);
         }
         break;
     case TokenType.Local:
         LocalVar lv=locals[t.token];
         if(lv.type==VarType.Ref&&smt.Count>0&&smt.Peek().IsSymbol(".")) goto case TokenType.edid;
         if(lv.type==VarType.Ref&&type==ExpressionType.Numeric) AddError("Reference type not valid here");
         if(lv.type!=VarType.Ref&&type==ExpressionType.Ref) AddError("A reference assignment must consist of a single edid or function");
         if(lv.type==VarType.Int) {
             EmitByte(0x73);
         } else {
             EmitByte(0x66);
         }
         Emit((ushort)lv.index);
         break;
     case TokenType.Global:
         if(type==ExpressionType.Ref) AddError("A reference assignment must consist of a single edid or function");
         EmitRefLabel(t, RefType.Expression);
         break;
     case TokenType.Float:
     case TokenType.Integer:
         if(type==ExpressionType.Ref&&t.token!="0") AddError("A reference assignment must consist of a single edid or function");
         bw.Write(System.Text.Encoding.ASCII.GetBytes(t.token));
         break;
     case TokenType.Function:
         //FunctionSig fs=functionList[t.token];
         //if(fs.requiredArgs!=fs.args.Length) throw new ExpressionParseException("functions with variable argument count cannot be used in expressions");
         //if(fs.ret==VarType.None) throw new ExpressionParseException("Functions with no return type cannot be used in expressions");
         //if(smt.Count<fs.args.Length) throw new ExpressionParseException("Not enough parameters to function");
         Token[] args=new Token[smt.Count+1];
         args[0]=t;
         for(int i=1;i<args.Length;i++) args[i]=smt.Dequeue();
         EmitFunctionCall(ref args, true, hadRef, type==ExpressionType.Ref);
         for(int i=0;i<args.Length;i++) smt.Enqueue(args[i]);
         break;
     default:
         AddError("Expected <local>|<global>|<number>|<function>");
         break;
     }
 }
Ejemplo n.º 6
0
        private static void EmitExpression(Token[] smt, ExpressionType type)
        {
            long pos=bw.BaseStream.Length;
            Emit(0);
            try {
                EmitExpression2(new Queue<Token>(smt), int.MaxValue, false, type);
            } catch(ExpressionParseException ex) {
                AddError(ex.Message);
            }

            bw.BaseStream.Position=pos;
            Emit((ushort)(bw.BaseStream.Length-(pos+2)));
            bw.BaseStream.Position=bw.BaseStream.Length;
        }
Ejemplo n.º 7
0
 private static void EmitBegin(Token[] smt)
 {
     Emit(0x10);
     if(!blockList.ContainsKey(smt[1].token)) {
         AddError("Unknown block type");
         EmitLong(0);
         EmitLong(0);
         return;
     }
     FunctionSig fs=blockList[smt[1].token];
     long pos=bw.BaseStream.Length;
     Emit(0);
     Emit(fs.opcode);
     EmitLong(0);
     if(smt.Length>fs.args.Length+2) AddError("Too many arguments to 'begin' block");
     //for(int i=0;i<fs.paddingbytes;i++) EmitByte(0);
     if(fs.args.Length>0) {
         Emit((ushort)(smt.Length-2));
         for(int i=2;i<smt.Length;i++) {
             switch(fs.args[i-2]) {
             case VarType.Short:
                 if(smt[i].type!=TokenType.Integer) AddError("Block argument: Expected short");
                 else Emit(ushort.Parse(smt[i].token));
                 break;
             case VarType.Int:
                 if(smt[i].type!=TokenType.Integer) AddError("Block argument: Expected integer");
                 else {
                     EmitByte(0x73);
                     EmitLong(uint.Parse(smt[i].token));
                 }
                 break;
             case VarType.Ref:
                 if(smt[i].type!=TokenType.edid) AddError("Block argument: Expected edid");
                 else {
                     EmitRefLabel(smt[i], RefType.Expression);
                 }
                 break;
             default:
                 AddError("Sanity check failed. VarType of block argument was invalid");
                 break;
             }
         }
     }
     bw.BaseStream.Position=pos;
     Emit((ushort)(bw.BaseStream.Length-(pos+2)));
     bw.BaseStream.Position=bw.BaseStream.Length;
 }
Ejemplo n.º 8
0
 public LocalVar(int index, Token t)
 {
     this.index=index;
     switch(t.keyword) {
     case Keywords.Int:
         type=VarType.Int;
         break;
     case Keywords.Float:
         type=VarType.Float;
         break;
     case Keywords.Ref:
         type=VarType.Ref;
         break;
     default:
         throw new Exception("Should never happen: Invalid type passed to local variable constructor");
     }
 }
Ejemplo n.º 9
0
 private static Token[] TrimStatement(Token[] smt, int size)
 {
     Token[] smt2=new Token[smt.Length-size];
     for(int i=0;i<smt2.Length;i++) smt2[i]=smt[i+size];
     return smt2;
 }