Ejemplo n.º 1
0
        // Create piece index from array of section nodes
        // Note: Also does sanity check (first peek inside game/variant definition)
        // The passed in parser is used to generate meaningful errors
        Dictionary <string, Node> CreatePieceLookup(NodeListParser nlp)
        {
            Dictionary <string, Node> lookup = new Dictionary <string, Node>();

            while (!nlp.Done)
            {
                var pnode = nlp.Current; // could be a piece section
                var nlp2  = nlp.GetParser();
                // note: cannot use anything that relies on CheckedIdent
                nlp.Expect(nlp2.IsIdent, "section identifier");
                if (nlp2.GetNode().AsIdent.Name == "piece")
                {
                    while (true)
                    {
                        nlp2.Expect(nlp2.IsList, "piece name");
                        var nlp3 = nlp2.GetParser();
                        if (nlp3.IsIdent && nlp3.GetNode().AsIdent.Name == "name")
                        {
                            if (nlp3.IsIdent)
                            {
                                lookup[nlp3.GetNode().AsIdent.Name] = pnode;
                                break;
                            }
                        }
                    }
                }
            }
            return(lookup);
        }
Ejemplo n.º 2
0
        //: ( BOARD-SETUP ( player placement+ )+ )?
        //: placement := (piece-type { off <int> | position }+ )
        IList <PlacementDef> ParsePlacements(NodeListParser nlp)
        {
            Logger.WriteLine(4, "ParsePlacements <{0}>", nlp);
            var list = new List <PlacementDef>();

            while (!nlp.Done)
            {
                list.Add(ParsePlacement(nlp.GetParser()));
            }
            return(list);
        }
Ejemplo n.º 3
0
        // Compile a literal, symbol or expression that returns a typed value
        // Return datatype to caller for type checking
        DataTypes CompileValue(Type type, NodeListParser nlp)
        {
            Logger.WriteLine(4, "CompileValue {0} <{1}>", type, nlp);

            // bracketed expression with arguments
            if (nlp.IsSexpr)
            {
                var sexpr = nlp.GetSexprNode();
                CompileSexpr(sexpr, nlp);
                return(sexpr.DataType);
            }
            if (nlp.IsFunc)
            {
                // bare function no arguments
                var sym = nlp.GetIdent().Sym as BuiltinSymbol;
                CompileBuiltin(sym, NodeListParser.Null);
                return(sym.DataType);
            }
            if (nlp.IsVariable)
            {
                var sym = nlp.GetIdent().Sym;
                _gen.EmitLoadVar(sym);
                return(sym.DataType);
            }
            if (nlp.IsAttribute || (nlp.IsList && nlp.CheckedHead.IsAttribute))
            {
                var handler = Symbols.Find("--attribute") as BuiltinSymbol;
                if (handler != null)
                {
                    CompileBuiltin(handler, nlp.GetParser());
                }
                else
                {
                    nlp.Syntax("attribute not allowed here");
                }
                return(handler.DataType);
            }
            var func = _typeactiondict.SafeLookup(type);

            if (func != null)
            {
                // direct lookup to get constant value
                var value = func(type, nlp, this) as TypedValue;
                _gen.EmitLoadValue(value);
                return(value.DataType);
            }
            nlp.Unexpected("unknown type {0}", type);
            return(DataTypes.Unknown);
        }
Ejemplo n.º 4
0
        // compile a prog block inside an existing scope
        internal void CompileProg(NodeListParser nlp)
        {
            Logger.WriteLine(2, "CompileProg <{0}>", nlp);
            // iterate over the action items in the prog block
            while (!nlp.Done)
            {
                // value -- special handler
                if (nlp.IsValue || nlp.IsValueCallable)
                {
                    if (!CompileHandler("--value", nlp))
                    {
                        nlp.Syntax("bare value not allowed");
                    }

                    // callable function, call it
                }
                else if (nlp.IsCallable)
                {
                    if (nlp.IsFunc && nlp.CurrentIdent.Sym.Keyword == Keywords.ELSE)
                    {
                        return;                                                    // sneaky!
                    }
                    var sexpr = nlp.GetSexprNode();
                    nlp.Expect(sexpr.DataType == DataTypes.Void, "void function");
                    CompileSexpr(sexpr, nlp);

                    // list -- special handler
                }
                else if (nlp.IsList)
                {
                    var handler = Symbols.Find("--list") as BuiltinSymbol;
                    if (handler != null)
                    {
                        CompileBuiltin(handler, nlp.GetParser());
                    }
                    else
                    {
                        nlp.Unexpected("unknown function");
                    }
                }
                else
                {
                    nlp.Expected("function call");
                }
            }
        }
Ejemplo n.º 5
0
        OccupierDef ParseOccupier(NodeListParser nlp)
        {
            //NOTE: this change allows dropping parens, but breaks order dependence
            //if (nlp.IsIdent && (nlp.CurrentIdent.IsPiece || nlp.CurrentIdent.IsDirection)) {

            // take ident; define as piece if not direction
            if (nlp.IsIdent)
            {
                var ident = nlp.GetIdent();
                if (ident.IsDirection) // only used by relative-config
                {
                    return(OccupierDef.Create(ident.AsValue as DirectionValue));
                }
                else
                {
                    return(OccupierDef.Create(PlayerKinds.Friend, DefPiece(ident)));
                }
            }
            // note: relies on dummy functions defined in scope
            if (nlp.IsList && nlp.IsCallable)
            {
                var nlp2  = nlp.GetParser();
                var ident = nlp2.GetIdent();
                if (ident.Sym.Name == "not")
                {
                    return(ParseOccupier(nlp2).SetNot());
                }
                else
                {
                    var piece = DefPiece(nlp2.GetIdent());
                    nlp2.CheckDone();
                    if (ident.Sym.Name == "opponent")
                    {
                        return(OccupierDef.Create(PlayerKinds.Enemy, piece));
                    }
                    if (ident.Sym.Name == "any-owner")
                    {
                        return(OccupierDef.Create(PlayerKinds.Any, piece));
                    }
                }
            }
            return(null);
        }
Ejemplo n.º 6
0
        //--------------------------------------------------------------------------
        // Parsers for individual productions that return a data structure

        //: (TURN-ORDER { player | ( player move-type ) | ( player player ) | ( player player move-type ) | REPEAT }+ )?
        TurnDef ParseTurnDef(NodeListParser nlparg)
        {
            Logger.WriteLine(4, "ParseTurnDef <{0}>", nlparg);
            nlparg.Expect(nlparg.IsIdent || nlparg.IsList, "player or list");

            var nlp   = nlparg.GetParser();
            var ident = nlp.GetIdent();

            if (ident.Name == "repeat")
            {
                nlp.CheckDone();
                return(TurnDef.Repeat);
            }
            var player = DefPlayer(ident);
            // default is to play as self
            var playeras = nlp.IsIdent && nlp.Current.IsPlayer ? DefPlayer(nlp.GetIdent()) : player;
            var movetype = nlp.IsIdent ? DefMoveType(nlp.GetIdent()) : MoveTypeValue.Any;

            nlp.CheckDone();
            return(new TurnDef {
                TurnPlayer = player, MovePlayer = playeras, MoveType = movetype
            });
        }
Ejemplo n.º 7
0
        // Compile an argument of given type
        void CompileArg(Type type, NodeListParser nlp)
        {
            Logger.WriteLine(4, "CompileArg {0} <{1}>", type, nlp);

            var func = _typeactiondict.SafeLookup(type);

            // special for variable assignment and implicit definition
            if (type == typeof(Variable))
            {
                var ident    = nlp.GetIdent();
                var datatype = DataTypes.Bool; // TODO: handle other types
                if (ident.Sym.IsVariable)
                {
                    nlp.Expect(ident.Sym.DataType == datatype, "variable of type {0}", datatype);
                }
                else if (ident.Sym.IsUndef)
                {
                    Symbols.DefineVariable(ident.Name, datatype, BoolValue.False);
                }
                else
                {
                    nlp.Expected("defined variable");
                }
                _gen.EmitRefVar(ident.Sym);

                // handle these separately, could be variable or function
            }
            else if (type.IsSubclassOf(typeof(TypedValue)))
            {
                // TODO: type checking
                CompileValue(type, nlp);
                //var exptype = TypedValue.DataTypeDict.SafeLookup(type);
                //var rettype = CompileValue(type, nlp);
                //nlp.Expect(rettype == exptype, "value of type {0}", exptype);

                // direct lookup gets special cases; else continue
            }
            else if (func != null)
            {
                var value = func(type, nlp, this);
                _gen.EmitLoadValue(value);

                // Array means parse a list of this type
            }
            else if (type.IsArray)
            {
                var nargs = 0;
                for (var nlp2 = nlp.GetParser(); !nlp2.Done; nargs++)
                {
                    CompileArg(type.GetElementType(), nlp2);
                }
                _gen.EmitToArray(type, nargs);

                // List<> means parse a tail of this type
            }
            else if (type.IsGenericType && type.Name.StartsWith("List"))
            {
                var nargs = 0;
                for (; !nlp.Done; ++nargs)
                {
                    CompileArg(type.GetGenericArguments()[0], nlp);
                }
                _gen.EmitToList(type, nargs);

                // Pair<> means parse a pair of arbitrary types
            }
            else if (type.IsGenericType && type.Name.StartsWith("Pair"))
            {
                var nlp2 = nlp.GetParser();
                foreach (var subtype in type.GetGenericArguments())
                {
                    CompileArg(subtype, nlp2);
                }
                _gen.EmitToPair(type);

                // nested prog block
            }
            else if (type.IsSubclassOf(typeof(CodeBase)))
            {
                var info = Symbols.PredefScopeDict.First(kv => kv.Value.CodeType == type).Value;
                CompileProg(info, nlp);
            }
            else if (type == typeof(PositionOrDirection))
            {
                CompilePositionOrDirection(nlp);

                // function call on built in
            }
            else if (nlp.IsSexpr)
            {
                var sexpr    = nlp.GetSexprNode();
                var datatype = TypedValue.DataTypeDict.SafeLookup(type);
                nlp.Expect(sexpr.DataType == datatype, "value of type {0}", datatype);
                CompileBuiltin(sexpr.Sym as BuiltinSymbol, NodeListParser.Create(sexpr.Args, Symbols));
            }
            else
            {
                nlp.Syntax("unknown type {0}", type);
            }
        }
Ejemplo n.º 8
0
        Maybe <PositionOrZone> ParseMaybePositionOrZone(NodeListParser nlp)
        {
            if (nlp.IsConstant)
            {
                var value = nlp.Current.AsValue;
                if (value is PositionValue || value is ZoneValue)
                {
                    return new Maybe <PositionOrZone> {
                               Value = ParsePositionOrZone(nlp)
                    }
                }
                ;
            }
            return(new Maybe <PositionOrZone> {
            });
        }

        // parse a term which may be a position, direction or opposite
        void CompilePositionOrDirection(NodeListParser nlp)
        {
            var rettype = CompileValue(typeof(TypedValue), nlp);

            nlp.Expect(rettype == DataTypes.Position || rettype == DataTypes.Direction, "position or direction");
            var funcsym = Symbols.Find("--pos-or-dir");

            _gen.EmitCall(funcsym as BuiltinSymbol);
        }

        //protected PositionOrDirection ParsePositionOrDirection(NodeListParser nlp) {
        //  if (nlp.IsValue) {
        //    var value = nlp.GetValue();
        //    if (value is PositionValue || value is DirectionValue)
        //      return new PositionOrDirection { Value = value };
        //  }
        //  nlp.Expected("position or direction");
        //  return null;
        //}

        GoKinds ParseGoKind(NodeListParser nlp)
        {
            var ident = nlp.GetIdent();
            var gosym = Symbols.Find(ident.Name, PredefKinds.GO);

            nlp.Expect(gosym != null, "valid go target");
            return(gosym.GoKind);
        }

        Maybe <PlayerValue[]> ParseMaybePlayers(NodeListParser nlp)
        {
            if (!(nlp.IsList && nlp.CheckedHead.IsPlayer))
            {
                return(Maybe <PlayerValue[]> .Null);
            }
            return(Maybe <PlayerValue[]> .Create(nlp.GetParser().UntilDone(n => DefPlayer(n.GetIdent())).ToArray()));
        }

        Maybe <PieceValue> ParseMaybePiece(NodeListParser nlp)
        {
            return((nlp.IsIdent && nlp.Current.IsPiece)
        ? Maybe <PieceValue> .Create(DefPiece(nlp.GetIdent()))
        : Maybe <PieceValue> .Null);
        }

        Maybe <PlayerValue> ParseMaybePlayer(NodeListParser nlp)
        {
            return((nlp.IsIdent && nlp.Current.IsPlayer)
        ? Maybe <PlayerValue> .Create(DefPlayer(nlp.GetIdent()))
        : Maybe <PlayerValue> .Null);
        }
    }