Пример #1
0
    /// <summary>A somewhat high-level function to parse (only) a single indeterminate noun phrase like "a numeric entry", "a number",
    /// "a car", "a vertical percentage", "several cars", "anything", "the manager" (if the NP is the subject of its
    /// sentence), "many gadgets" (when gadget itself hasn't been established yet), or a number of specifically invalid
    /// combinations, that describes a typed parameter in the definition of a multimethod's signature.
    /// Will soon need ability to parse -ing phrases and sub-predicates as in "To learn (repairing a car with a tool)".
    /// Uses ParseArticle, ParseNewIdentifier, ParseAdjectiveType, Parse enum, ParseAnyType, and multiple NameOfType.
    /// Finally calls CreateParameterObject after all but the worst parses.
    /// </summary>
    static parameter ParseNounPhraseForParameter(string[] words, bool isSubject = false)
    {
        StandardType?type       = null;
        string       ident      = "";
        int          savedIndex = index;
        bool         identIsAdjectiveTypeIsNoun = false;
        // usually if the type is the noun, there is no adjective: "the task"
        // and usually if both adj & noun are present, the type is the adjective: "the numeric virtue"
        // this is for constructions like "the horizontal percent, the vertical percent"

        // step 1: try parsing "something", "an adjective-type noun" "nountype", etc., or as a last resort, just a new identifier
        Article?              mode    = ParseArticle(words) ?? ((isQuestion && isSubject) ? Article.a : (Article?)null);
        OtherParameterTypes?  opt     = Parse <OtherParameterTypes>(words[index]);
        StandardTypeAdjective?adjtype = ParseAdjectiveType(words);

        if (adjtype != null)
        {
            ident = ParseNewIdentifier(words, ref type);
            if (type != null && type != (StandardType)adjtype)
            {
                Console.WriteLine("ERROR: I'm unsure whether '{0} {1}' is a {1} nicknamed {0} or is something {0} nicknamed {1}.", adjtype, type);
                method_being_constructed.problems++;
                return(null);
            }
            type = (StandardType)adjtype;
            if (ident == "")
            {
                Console.WriteLine("ERROR: must provide a name after the adjective '{0}' or use its noun form instead, '{1}'.", adjtype, (StandardType)adjtype);
                method_being_constructed.problems++;
                return(null);
            }
        }
        else if (opt != null)
        {
            type = (StandardType)opt;
        }
        else
        {
            fiveforms ing = PresentParticiple(words[index]);
            if (ing != null)
            {
                return(CreateFunctionParameterObject(words, ing, isSubject));
            }
            type  = ParseAnyType(words);
            ident = (type == null) ? "" : NameOfType(type.Value);
        }
        if (ident == "" && type == null /*&& isSubject*/) // then we have no type info whatsoever. Just get a new ident
        {
            ident = ParseNewIdentifier(words, ref type);
            identIsAdjectiveTypeIsNoun = (type != null);
        }

        if (type == null && mode == null)
        {   // if we know nothing, abort
            index = savedIndex;
            return(null);
        }
        return(CreateParameterObject(words, mode, type, adjtype, ident, identIsAdjectiveTypeIsNoun, isSubject));
    }
Пример #2
0
    /// <summary>This is used while defining a higher-order function, tipped off by the -ing verb form that leads.</summary>
    static parameter CreateFunctionParameterObject(string[] words, fiveforms ing, bool isSubject = false)
    {
        long        savedIndex       = index;
        multimethod outerMethod      = method_being_constructed;
        string      savedDefinedVerb = definedVerb;

        method_being_constructed = new multimethod()
        {
            prompt = -outerMethod.prompt, question = ""
        };
        multimethod innerMethod = PredicateDefinition2(words, ing, isSubject); // returns method_being_constructed

        method_being_constructed = outerMethod;
        definedVerb = savedDefinedVerb;
        return(new parameter(innerMethod));
    }
Пример #3
0
    /// <summary> Creates a parameter name for use in the function body like "the thing given" or "the person given to" </summary>
    static parameter NamedParameter(parameter noun_phrase_being_constructed, fiveforms verb, bool isSubject = false)
    {
        //parameter noun_phrase = noun_phrase_being_constructed;
        if (noun_phrase_being_constructed.preposition == "" && !isSubject)
        {
            HandleSwappedDirectandIndirectObjects(method_being_constructed, "to", verb, isSubject);
        }

        foreach (term part_of_speech in method_being_constructed.signature)
        {
            if (part_of_speech.which != PartsOfSpeech.noun)
            {
                continue;
            }
            if (part_of_speech.noun == noun_phrase_being_constructed)
            {
                break;
            }
            if (part_of_speech.noun.type == noun_phrase_being_constructed.type) // is the noun a Integer? Percentage? Ranking?
            {
                noun_phrase_being_constructed.position++;                       // then it shall be the first/second/third integer/task/customer
            }
        }
        if (noun_phrase_being_constructed.position == 2) // then find the first "the TYPE" and change it to "the first TYPE"
        {
            foreach (term np in method_being_constructed.signature)
            {
                if (np.which != PartsOfSpeech.noun)
                {
                    continue;
                }
                if (np.noun.type == noun_phrase_being_constructed.type)
                {
                    np.noun.fullname2 = "first " + np.noun.fullname2;
                    break;
                }
            }
        }

        CreateFullNames(noun_phrase_being_constructed, verb, isSubject);

        return(noun_phrase_being_constructed);
    }
Пример #4
0
    /// <summary>Creates the names by which the given parameter will be invoked:  the thing given, the person given to, etc.</summary>
    static void CreateFullNames(parameter noun_phrase, fiveforms verb, bool isSubject = false)
    {
        if (noun_phrase.isAggregate) // it's a gerund, or participial phrase, etc.
        {
            return;
        }

        noun_phrase.fullname1 = noun_phrase.name + ((verb == TheVerbIs) ? "" : " " + ((isSubject) ? verb._ing : verb._en));
        if (noun_phrase.preposition != "")
        {
            noun_phrase.fullname1 += " " + noun_phrase.preposition;
        }

        noun_phrase.fullname2 = noun_phrase.name; // given name.  But, if the name is just the type, then..
        if (noun_phrase.position > 1)
        {
            if (Contains <StandardType>(noun_phrase.name) || Contains <StandardTypePlural>(noun_phrase.name))
            {
                noun_phrase.fullname2 = NumberToSpelledOutOrdinal(noun_phrase.position) + " " + noun_phrase.name; // TODO translate int to ordinal
            }
        }
    }
Пример #5
0
    static void VerifyAbstractSyntaxTree()
    {
        // now check the whole abstract syntax tree

        // First, is there one and only one root?  "To do:"
        fiveforms   rootverb = FindVerb("do");
        multimethod main     = null;

        if (mms.ContainsKey(rootverb))
        {
            foreach (multimethod possibleRoot in mms[rootverb])
            {
                if (possibleRoot.signature.Count == 1)
                {
                    if (main == null)
                    {
                        main = possibleRoot;
                    }
                    else
                    {
                        Console.WriteLine("  ERROR:  I have too many definitions for \"To do:\", like #{0} and #{1}", main.prompt, possibleRoot.prompt);
                    }
                }
            }
        }
        if (main == null)
        {
            Console.WriteLine("  ERROR:  Where does the whole thing start?  I need a sentence which begins, \"To do:\"");
        }
        else
        {
            main.called++;
        }

        // dead code elimination?  unused structs elimination?
    }
Пример #6
0
    /// <summary> Once a string has been converted to a verb (fiveforms), this parses the parameter list via multiple calls to
    /// ParseNounPhraseForParameter and its own list delimiter parsing. Returns the defined verb as a convenience, but the real
    /// result is added to the global multimethods collection. </summary>
    static multimethod PredicateDefinition2(string[] words, fiveforms incarnations, bool isSubject = false)
    {
        method_being_constructed.signature.Add(new term(incarnations));
        definedVerb = words[index];
        string preposition = "";
        bool   found_official_preposition = false;

        TheGiveSomebodyItException = DirectObjectPlacement.not_there_yet;
        do
        {
            index++;
            while (!stringnums.EndsInfinitiveDefinition.Contains(words[index]))
            {
                if (stringnums.EOL.Contains(words[index]))
                {
                    goto doublebreak;
                }
                parameter noun_phrase = ParseNounPhraseForParameter(words);
                if (noun_phrase == null)
                {
                    if (!stringnums.ListSeparators.Contains(words[index]))
                    {
                        if (!found_official_preposition) // after a preposition, there shouldn't be any words related to the verb.
                        {
                            if (isSubject && FindMainVerb(words[index]).HasValue())
                            {
                                goto doublebreak;
                            }
                            if (preposition != "")
                            {
                                preposition += " ";
                            }
                            preposition += words[index]; // so, "the person given to", not, "the person given to just"
                        }
                        if (stringnums.prepositions.Contains(words[index]))
                        {
                            found_official_preposition = true;
                        }
                    }
                    index++;
                }
                else
                {
                    if (preposition != "")
                    {
                        method_being_constructed.signature.Add(new term(preposition));
                    }
                    method_being_constructed.signature.Add(new term(noun_phrase, preposition));
                    preposition = "";
                    found_official_preposition = false;
                }
            }
            // if the next word is "a/an/another", then we are probably in a list.
            // if it were a function body starting, it would likely be "the"
        } while (stringnums.IndefiniteArticles.Contains(words[index + 1]) || stringnums.ListDeterminers.Contains(words[index + 1]) || stringnums.ListSeparators.Contains(words[index + 1]));
doublebreak:
        if (preposition != "")
        {
            method_being_constructed.signature.Add(new term(preposition));
        }
        return(method_being_constructed);
    }
Пример #7
0
    /// <summary>For cases of "give someone the thing", we must back up and add "to" to the "someone"</summary>
    static void HandleSwappedDirectandIndirectObjects(multimethod method_being_constructed, string prep, fiveforms verb, bool isSubject)
    {
        if (isSubject)
        {
            return;
        }
        if (listType != null)
        {
            return;
        }
        switch (TheGiveSomebodyItException)
        {
        case DirectObjectPlacement.not_there_yet:
            TheGiveSomebodyItException = DirectObjectPlacement.normal;
            break;

        case DirectObjectPlacement.normal:
            // then the previous parameter is the indirect, not direct, object, and needs "to" prepended
            for (int i = 0; method_being_constructed.signature.Count > i; i++)
            {
                if (method_being_constructed.signature[i].which == PartsOfSpeech.noun)
                {
                    term newterm = method_being_constructed.signature[i];
                    newterm.noun.preposition = prep;
                    method_being_constructed.signature[i] = newterm;
                    CreateFullNames(method_being_constructed.signature[i].noun, verb);    //not sure why this is still needed
                    break;
                }
            }
            TheGiveSomebodyItException = DirectObjectPlacement.after_the_indirect_object;
            break;

        case DirectObjectPlacement.after_the_indirect_object:
        case DirectObjectPlacement.error:
            TheGiveSomebodyItException = DirectObjectPlacement.error;
            Console.WriteLine("  ERROR: I require those parameters to be separated by prepositions or commas.");
            method_being_constructed.problems++;
            break;
        }
    }
Пример #8
0
 public term(fiveforms v)
 {
     which = PartsOfSpeech.verb; verb = v;
 }
Пример #9
0
    /// <summary>Once the magic words that begin a relative clause are found ("the TYPE which..") by ParseInvokedNoun,
    /// this parses the rest of the invocation.  Relative clauses invoke phrases or data structures and play a matching game with
    /// them. This is straightforward with data, but with imperative code we have to "go Prolog" for it to make sense
    /// even conceptually. </summary>
    static invocation ParseARelativeInvocation(theTypeWhich theTypeWhich, List <string> words)
    {
        subsubprompt++;

        // Handle passive voice constructions like "the type1 to which the type2 WAS GIVEN".
        string    theIsUsed    = "";
        fiveforms relativeVerb = null;
        bool      passiveVoice = (words[index] == "was" || words[index] == "were" || words[index] == "is" || words[index] == "are");

        if (passiveVoice)
        {
            theIsUsed    = words[index++];
            relativeVerb = mms.SingleOrDefault(item => item.Key._en == words[index]).Key;
            if (relativeVerb == null)
            {
                passiveVoice = false;
                relativeVerb = TheVerbIs;
                index--;
            }
        }
        else
        {
            relativeVerb = mms.SingleOrDefault(item => item.Key.singular == words[index] || item.Key.plural == words[index] || item.Key.past == words[index]).Key;
        }

        /*if (relativeVerb != null)
         * {
         *  bool pastTense = (words[index++] == relativeVerb.past);
         *
         *  // now search all possible keywords & prepositions for all possible methods to see if the next word matches one of them
         *  List<multimethod> submatches = new List<multimethod>();
         *  int invocationBeginsAt = index;
         *  foreach (multimethod mm in mms[relativeVerb])
         *  {
         *      index = invocationBeginsAt;
         *      foreach (term t in mm.signature)
         *          if (t.which == PartsOfSpeech.noun && Match(words, t.noun.preposition))
         *              if (IsA(theTypeWhich.type.typeid, t.noun.type))
         *                  // "which gave" (imperative)  vs.  "which knows" (relation)
         *                  if ((pastTense && !mm.fully_parsed) || (!pastTense && mm.fully_parsed))
         *                  {
         *                      submatches.Add(mm);
         *                      break;
         *                  }
         *  }
         *  if (submatches.Count == 0)
         *  {
         *      Console.WriteLine("  ERROR: In the relative clause 'which {0}{1}' I couldn't find any defined method for {2} which matched it", passiveVoice ? theIsUsed + " " : "", passiveVoice ? relativeVerb._en : pastTense ? relativeVerb.past : relativeVerb.singular, relativeVerb.singular);
         *      index = savedIndex;
         *      return null;
         *  }
         *  if (submatches.Count > 1)
         *  {
         *      Console.WriteLine("  ERROR: In the relative clause 'which {0}{1}' I found too many defined methods for {2}", passiveVoice ? theIsUsed + " " : "", passiveVoice ? relativeVerb._en : pastTense ? relativeVerb.past : relativeVerb.singular, relativeVerb.singular);
         *      index = savedIndex;
         *      return null;
         *  }
         *  Console.WriteLine("  relative clause matches #{0}", submatches[0].prompt);
         * }*/


        // now parse the argument(s) being fed to it
        int savedIndex            = index;
        List <multimethod> likely = passiveVoice ? mms[relativeVerb] : ParseInvocationByFirstWord(words);

        if (likely == null || likely.Count == 0)
        {
            Console.WriteLine("Cannot find any multimethod which fits this part of the relative clause: '{0}...'", words[index]);
            return(null);
        }

        List <invocation> matching = ParseAnInvocation2(words, likely, true, theTypeWhich);

        return(InvocationProblems(words, matching, likely, savedIndex, theTypeWhich));
    }
Пример #10
0
    /// <summary>
    /// This does a quick 'n shallow look through all the signatures to see which ones match the opening word of the
    /// invocation-to-be-parsed.  Academically speaking, it's unnecessary.  Practically speaking, it's better than nothing.
    /// </summary>
    public static List <multimethod> ParseInvocationByFirstWord(List <string> words)
    {
        var    likely    = new List <multimethod>();
        string firstWord = words[index];

        if (stringnums.DefiniteArticles.Contains(firstWord) || stringnums.IndefiniteArticles.Contains(firstWord) || stringnums.ListDeterminers.Contains(firstWord))
        {
            firstWord = words[++index];
        }
        int  savedIndex = index;
        bool startsThe  = (words[index] == "the");

        while (words[index] == "the")
        {
            index++;
        }
        theTypeWhich theTypeWhich = IsNameOfTypeWhich(words);

        index = savedIndex;
        long?number = ParseNumberOrdinalPercent(words);

        index = savedIndex;
        bool TextLit = words[index].StartsWith("__litstring");

        index = savedIndex;
        fiveforms aVerb = PresentParticiple(words[index]) ?? FindMainVerb(firstWord);

        index = savedIndex;
        bool IsPrep    = stringnums.prepositions.Contains(firstWord);
        bool IsVerb    = aVerb != null;
        bool IsNoun    = startsThe || theTypeWhich != null || number != null || TextLit;
        bool CanBeNoun = !IsVerb && !IsPrep;

        foreach (var mm in multimethods)
        {
            switch (mm.signature[0].which)
            {
            case PartsOfSpeech.verb:
                if (IsVerb && mm.signature[0].verb.Contains(firstWord))
                {
                    likely.Add(mm);
                }
                break;

            case PartsOfSpeech.noun:
                if (mm.signature[0].noun.isAggregate)
                {
                    likely.Add(mm);
                }
                if (CanBeNoun)
                {
                    likely.Add(mm);
                }
                break;

            case PartsOfSpeech.preposition:
                if (IsPrep && firstWord == mm.signature[0].preposition)
                {
                    likely.Add(mm);
                }
                break;
            }
        }
        return(likely);
    }
Пример #11
0
    static void CodeGeneration()
    {
        // create file
        CodeGen codegen = new Flash();

        codegen.Begin("complish");
        codegen.WriteStringTable(literalStrings);

        foreach (multimethod method in multimethods)
        {
            if (method.parsed_body == null || method.parsed_body.Count == 0)
            {   // it's data not code
                parameter subject = null;
                fiveforms verb    = null;
                foreach (term term in method.signature)
                {
                    if (term.which == PartsOfSpeech.verb)
                    {
                        verb = term.verb;
                        break;
                    }
                    else if (term.which == PartsOfSpeech.noun)
                    {
                        subject = term.noun;
                    }
                }
                if (verb == null)
                {
                    continue;
                }
                bool subjectNamesStruct = (verb == TheVerbIs);
                if (subjectNamesStruct && subject == null)
                {
                    continue;//compiler error? named instance? global var?
                }
                //Console.WriteLine("struct {0} {1}  // #{2}{3}", subjectNamesStruct ? subject.fullname1.Replace(' ', '_') : verb.singular + "_relation", "{", method.prompt, method.problems > 0 ? " ?" : "");
                foreach (term term in method.signature)
                {
                    if (term.which != PartsOfSpeech.noun)
                    {
                        continue;
                    }
                    if (subjectNamesStruct && term.noun == subject)
                    {
                        continue;
                    }

                    /*if (term.noun.art != Article.many)
                     *  Console.WriteLine("\t{0} {1};", NameOfType(term.noun.type), term.noun.fullname1.Replace(' ', '_'));
                     * else
                     *  Console.WriteLine("\tList<{0}> {1};", NameOfType(term.noun.type), term.noun.fullname1.Replace(' ', '_'));*/
                }
                //Console.WriteLine("}");
                //Console.WriteLine();
            }
            else // it's code not data
            {
                ;// Console.WriteLine("#{0} called from {1} places", method.prompt, method.called);
            }
        }

        codegen.WriteInt(10);
        codegen.Finish();

        Console.Write("---- press enter ----");
        Console.ReadLine();
    }
Пример #12
0
    static int prompt = 1, subprompt, subsubprompt; // the sentence#, invocation#, and relative clause #

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static void Main(string[] args)
    {
        ReadForms();
        TheVerbIs = FindVerb("is");
        InitNumberUnitSystem();
        InitInheritanceTree();

        string input = null;

        string[] words = null;
        int      maxWords;

        TestHarness.loadTestScript("me");
        for (Console.Write("{0}: ", prompt); (input = TestHarness.LineFeeder()) != null; TestHarness.EndTurn(2), Console.Write("{0}: ", ++prompt))
        {
            TestHarness.BeginTurn();

            // Move string literals into the string table, leaving placeholders behind.
            while (input.Contains('"'))
            {
                int from  = input.IndexOf('"');
                int endAt = from + 1;
loopPastDquoteLiteral:
                endAt += input.Substring(endAt).IndexOf('"');
                if (input.Length > endAt + 1 && input.ElementAt(endAt + 1) == '"')
                {
                    endAt += 2;
                    goto loopPastDquoteLiteral;
                }
                int    len     = endAt - (from + 1);
                string literal = input.Substring(from + 1, len);
                input = input.Substring(0, from - 1) + String.Format(" __litstring{0}__ ", literalStrings.Count) + input.Substring(endAt + 1);
                literalStrings.Add(literal.Replace("\"\"", "\""));
            }

            // cleanse the input
            input    = input.ToLowerInvariant() + " ";
            input    = input.Replace(", ", " , ").Replace(". ", " . ").Replace(": ", " : ").Replace("? ", " ? ");
            input    = input + " " + stringnums.EOL[0];
            words    = input.Split(new[] { ' ', '\t', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            maxWords = (int)words.Count();
            if (maxWords < 2)
            {
                break;               // EOL is always appended
            }
            // debugging / testharness feature: input a line number
            if (maxWords == 2 && Int32.TryParse(words[0], out subjectAt))
            {
                Console.WriteLine(TestHarness.testlines[--subjectAt * 3]);
                Console.WriteLine(TestHarness.testlines[subjectAt * 3 + 1]);
                Console.WriteLine(TestHarness.testlines[subjectAt * 3 + 2]);
                continue;
            }

            // meta / macro command: tell the compiler to run another file.
            if (maxWords == 3 && words[0] == "regard" && words[1].StartsWith("__litstring"))
            {
                TestHarness.loadTestScript(Say(words[1]));
                continue;
            }

            // initialize vars
            index       = 0;
            definedVerb = "";
            preposition = "";
            method_being_constructed = new multimethod()
            {
                prompt = prompt, question = ""
            };
            //method_being_constructed.prompt = prompt;
            subjectAt              = -1;
            isQuestion             = false;
            incarnations           = null;
            listType               = null;
            IdentEndsAt            = maxWords;
            just_declared_new_type = false;

            // Absorb any prepositions at the beginning, as in "To give..." or "To boldly go..." or "To a person give...", etc.
            while (stringnums.prepositions.Contains(words[index]))
            {
                if (preposition != "")
                {
                    preposition += " ";
                }
                preposition += words[index++];
            }

            // if the first word(s) indicate a question, read it.
            //method_being_constructed.question = "";

            /*if (stringnums.QuestionWords.Contains(words[index]))
             * {
             *  string question = "";
             *  while (stringnums.QuestionWords.Contains(words[index]))
             *  {
             *      if (question != "") question += " ";
             *      question += words[index++];
             *  }
             *  incarnations = FindVerb(words[index]); // Catches "What is.." but not "Which car is..."
             *  method_being_constructed.question = question;
             *  isQuestion = true;
             * }*/

            // if first word(s) indicated a subject, read it
            if (stringnums.DefiniteArticles.Contains(words[index]) || stringnums.IndefiniteArticles.Contains(words[index]) || stringnums.ListDeterminers.Contains(words[index]) || words[index].EndsWith("ing") || (method_being_constructed.question != "" && incarnations == null))
            {
                ParseSubject(words);
            }

            if (prompt >= 37)
            {
                Console.WriteLine();
            }

            // Regardless, parse the predicate:  a verb and the nouns that go with.
            incarnations = PredicateDefinition(words);

            // If we haven't found a verb yet, but we do have a subject, look for the verb in the subject's name.
            if (incarnations == null && subjectAt >= 0)
            {
                string[] subnames = method_being_constructed.signature[subjectAt].noun.name.Split(' ');
                for (int i = subnames.Count() - 1; i >= 0; i--)
                {
                    index--;
                    incarnations = FindMainVerb(subnames[i]);
                    if (incarnations == null)
                    {
                        continue;
                    }

                    // Ah, there's the verb. Shorten the subject's name, and try parsing the predicate again from this index position.
                    definedVerb = subnames[i];
                    string newname = subnames[0];
                    for (int j = 1; j < i; j++)
                    {
                        newname += " " + subnames[j];
                    }
                    method_being_constructed.signature[subjectAt].noun.name = newname;
                    Console.WriteLine("  oops; verb is '{1}' and subject is '{0}'", newname, definedVerb);
                    incarnations = PredicateDefinition(words);
                    break;
                }
            }

            // If we still don't have a verb, we're going to have to search for it the long way.
            if (incarnations == null)
            {
                int savedIndex = index;
                while (incarnations == null && index < maxWords - 1 && !stringnums.EndsInfinitiveDefinition.Contains(words[index]))
                {
                    incarnations = FindMainVerb(words[++index]); // this is an expensive loop
                }
                if (incarnations != null)
                {
                    // ah, found it. There must be a subject in front of it...
                    definedVerb = words[index];
                    IdentEndsAt = index;
                    index       = 0; // back to first word of sentence
                    if (ParseSubject(words) == null)
                    {
                        method_being_constructed.signature.Add(new term(incarnations));
                        Console.Write("ERROR: verb is '{0}' but I don't know what to do with the subject: ", definedVerb);
                        for (int i = savedIndex; i < IdentEndsAt; i++)
                        {
                            Console.Write("{0} ", words[i]);
                        }
                        Console.WriteLine();
                        method_being_constructed.problems++;
                        multimethods.Add(method_being_constructed);
                        continue;
                    }
                    index++;                                            // advance past verb
                    IdentEndsAt = (int)words.Count();                   // un-set the hint
                    var mm = PredicateDefinition2(words, incarnations); // and finish the predicate as normal
                    multimethods.Add(mm);
                }
            }

            // If we STILL don't have a verb, abort this sentence.
            if (incarnations == null)
            {
                method_being_constructed.signature.Add(new term("..."));
                Console.Write("ERROR: I couldn't find a verb in: ");
                for (int i = 0; i < index; i++)
                {
                    Console.Write("{0} ", words[i]);
                }
                Console.WriteLine();
                method_being_constructed.problems++;
                multimethods.Add(method_being_constructed);
                continue;
            }

            //if (prompt == 32)
            //    Console.WriteLine("debug");

            // OK, we have a verb, and processed the rest of the definition with it.  We should be at a marker separating
            // the function head from the function body.  Or if it's a type/struct/object definition, we're at the end of
            // the sentence entirely.
            method_being_constructed.fully_parsed = stringnums.EOL.Contains(words[index]);
            if (stringnums.EndsInfinitiveDefinition.Contains(words[index]))
            {
                index++; // advance past the comma, colon, BY, VIA, MEANS, or whatever separates head from body
            }
            else if (words[index] != ".")
            {
                Console.WriteLine("I didn't expect this definition of '{1}' end with a '{0}'", words[index], definedVerb);
                method_being_constructed.problems++;
                continue;
            }

            // If we had a valid definition, save away its body. We can't parse the bodies until we read all the heads.
            // That's because what names, esp. parameter names and other function invocations, that appear in the bodies
            // aren't even known yet.
            if (!method_being_constructed.fully_parsed)
            {
                method_being_constructed.body = new List <string>();
                while (index < maxWords - 1 && !stringnums.EOL.Contains(words[index]))
                {
                    method_being_constructed.body.Add(words[index++]);  //ParseParameterInvocation(words);
                }
            }


            // for case of "X is Y..."
            // if the subject is already a type, and is now being used with "IS" again,
            // Ensure we don't use a known type with "is" unless
            // 1) there's a "when", or
            // 2) the subject is "the" instance of the type, or
            // 3) the subject is a gerund phrase (function type), so the predicate is a categorical name, a "class" or "name of enum" for signatures
            if (subjectAt != -1 && incarnations._en == "been" && method_being_constructed.fully_parsed)
            {
                parameter theSubject = method_being_constructed.signature[subjectAt].noun;
                if (just_declared_new_type && theSubject.art == Article.the)
                {
                    Console.WriteLine("  global variable or singleton instance '{0}' created", theSubject.name);
                    PermanentDataSegment.Add(theSubject);
                }
                else if (theSubject.isAggregate && method_being_constructed.signature.Count == 3)
                {   // "Xing... is Y." so define Y as a category for verbs
                    var ident   = method_being_constructed.signature[2].which == PartsOfSpeech.noun ? method_being_constructed.signature[2].noun.name : method_being_constructed.signature[2].preposition;
                    var newType = CreateNewType(ident, StandardType.homogene);
                    Console.WriteLine("  assuming '{0}' categorizes verbs", ident);
                }
                else if (!just_declared_new_type)
                {
                    if (theSubject.type == StandardType.anything)
                    {
                        Console.WriteLine("  ERROR: I have no idea what a '{0}' is. It could be anything.", theSubject.name);
                    }
                    else
                    {
                        Console.WriteLine("  ERROR: trying to re-define the type '{0}'", NameOfType(theSubject.type));
                    }
                    method_being_constructed.problems++;
                }
            }

            // Create the various names for each parameter in the new method.
            // This isn't perfect because we don't know where a noun phrase ends and where adverbs and verbs begin.
            // We'll keep it all as the possible noun phrase, but when we start parsing the body, we'll look at
            // what the parameters are actually called in there. Then we can shorten our parameter names to match
            // sensibly.
            TheGiveSomebodyItException = DirectObjectPlacement.not_there_yet;
            for (int i = 0; i < method_being_constructed.signature.Count; i++)
            {
                if (method_being_constructed.signature[i].which == PartsOfSpeech.noun)
                {
                    term      newterm  = method_being_constructed.signature[i];
                    parameter oldparam = newterm.noun;
                    newterm.noun = NamedParameter(oldparam, incarnations, (i == subjectAt));
                    method_being_constructed.signature[i] = newterm;
                }
                else if (method_being_constructed.signature[i].which == PartsOfSpeech.verb)
                {
                    TheGiveSomebodyItException = DirectObjectPlacement.not_there_yet;
                }
            }

            // Now we should be at the end of line: a period, question mark, or exclamation mark
            // If not, throw a helpful error.
            method_being_constructed.problems++;
            if (index >= words.Count())
            {
                Console.WriteLine("COMPILER ERROR: EOL eaten: index too high");
            }
            else if (words[index] != "ENDOFINPUT" && words[index] != ".")
            {
                if (index < words.Count())
                {
                    Console.WriteLine("  ERROR: I wasn't expecting '{0}' there, but rather, the end of the sentence.", words[index]);
                }
                else
                {
                    Console.WriteLine("COMPILER ERROR: EOL eaten");
                }
            }
            else
            {
                method_being_constructed.problems--;
            }


            // Sentence processed. Get next sentence
        }

        TestSignatures();
        Pass2ResolveImplicitTypesAndCreateMultimethodDictionary();
        Pass3MethodBodies();
        VerifyAbstractSyntaxTree();
        CodeGeneration();
    }
Пример #13
0
    /// <summary>Stub. Get the proper inflection for the passed-in verb, which is presumably in its root form.</summary>
    static string FormOf(Inflections inflection, string verb)
    {
        // first of all, for the verb "is", handle it separately
        // (note that "is" does exist in the FindVerb list as the first element, but it's obviously missing a few forms)
        if (stringnums.InflectionsOfIs.Contains(verb))
        {
            switch (inflection)
            {
            case Inflections.root: return("were");            // whatever

            case Inflections.infinitive: return("to be");

            case Inflections.singular: return("is");

            case Inflections.plural: return("are");

            case Inflections.past: return("was");    // one of them, anyway

            case Inflections.present_participal: return("being");

            case Inflections.past_participal: return("been");

            default: return("am");
            }
        }

        // second, is it one of the irregular ones that have all five forms?
        fiveforms f5 = FindVerb(verb);

        if (f5 != null)
        {
            switch (inflection)
            {
            case Inflections.singular: return(f5.singular);

            case Inflections.plural: return(f5.plural);

            case Inflections.past: return(f5.past);

            case Inflections.present_participal: return(f5._ing);

            case Inflections.past_participal: return(f5._en);
            }
        }

        // for now, make stuff up
        switch (inflection)
        {
        case Inflections.root: return(verb);                    // used for the imperative invocation

        case Inflections.infinitive: return("to " + verb);      // used for the infinitive definition

        case Inflections.singular: return(verb + "s");          // used for relations

        case Inflections.plural: return(verb);                  // used for relations

        case Inflections.past: return(verb + "ed");

        case Inflections.present_participal: return(verb + "ing");   // used for continuous tense & for gerund (noun phrase)

        case Inflections.past_participal: return(verb + "n");        // used for perfect tense & for adjective
        }
        return(verb);
    }