Tuesday, May 26, 2009

My First Oslo MGrammar

Ever since working with FORTH, I’ve been a big fan of languages and understanding how they work.  FORTH did a great job of extending FORTH using FORTH, very cool.  Last fall I was introduced to Oslo, and was very impressed.  At the time, it looked like a pre-bleeding edge CTP, so I didn’t spend too much time with it.  Today (May 26, 2009) Microsoft released the May CTP of Oslo.  Although I’m sure the standards aren’t 100% baked, if you are interested, now is the time to start playing with it.  I have good intentions of publishing a better description of how this grammar was built, but with the limited time I have, I wanted to at least get my first grammar on my site.  There will be three components you need to know about when using Intellipad, the first is the development of the grammar, the second is where you enter your sample grammar and the third is the output.  The output is in the form of MGraph which you can use in your application.

 

Intellipad (better detail on the content below)

image

Here’s my very first MGrammar

module Pets
{
    @{CaseSensitive[false]}
    language MyPets
    {
        syntax Main = i:InitialStatement
          additional:(ThePet)+
          friends:(Friends)+        
          foes:(Foes)+
          => MyPets {
                     valuesof(additional),
                     Friends [valuesof(friends)],
                     Foes [valuesof(foes)]
                     } ;
       syntax ThePet = t:Pet w:Activity+ h:HowMuchTheyEat+
            => {t, Activities [valuesof(w)], Meals [valuesof(h)]} ;
       syntax Friends = f:PetsFriends => {valuesof(f)};
       syntax Foes = f:PetsFoes => {valuesof(f)};
        token Upper = 'A'..'Z';
        token Lower = 'a'..'z';
        token Digit = '0'..'9';
        token Name = Upper Lower*;
        token Time = '0'..'9' Digit?;
        token Age = '0'..'9' Digit?;
        token Cups = '0'..'9' Digit?;
        token Type = Upper Lower*;
        syntax Action = 'run' | 'jump' | 'play' | 'bark' | 'fetch'
                              | 'hunt' | 'whine';
        syntax Sex = 'male' | 'female';
        syntax Color = 'white' | 'black' | 'brown';
        syntax MealTime = 'breakfast' | 'lunch' | 'dinner';
        syntax AnimalTypes = 'Rat Terrier' | 'Terrier' | 'dog' | 'cat'
                             
| 'fish' | 'bird' | 'pig' | 'Poodle';       
        syntax Pronoun = "he" | "He" | "she" | "She" | "Her" 
                              | "His" | "her";
        @{Classification["Keyword"]} token AnimalColor = "color is";
        @{Classification["Keyword"]} token Will = "will" | "will also";
        @{Classification["Keyword"]} token Eats = "eat" | "eats";
        @{Classification["Keyword"]} token CupsOfFood = "cups of food for"
                             
| "cup of food for";
        @{Classification["Keyword"]} token For = "for";
        @{Classification["Keyword"]} token IsFriends = "is friends with";
        @{Classification["Keyword"]} token DoesntLike = "does not like";
        @{Classification["Keyword"]} token IsA= "is a";
        @{Classification["Keyword"]} token Minutes = "minutes" 
                              | "minute";
        @{Classification["Keyword"]} token Seconds = "seconds"
                              | "second";
        @{Classification["Keyword"]} token And = "and";
        @{Classification["Keyword"]} token YearOld = "year old";
        syntax InitialStatement = "About my pets";

        syntax Pet = n:Name IsA t:AnimalTypes IsA a:Age YearOld s:Sex 
                
Pronoun AnimalColor c:Color 
                
=> Profile {Name=>n, AnimalType=>t, Sex=>s, Color=>c};               
        syntax Activity = Pronoun? Will? a:Action For? m:Time? Minutes?
                 s:Time? Seconds?
                 => Activity {Type=>a, Minutes => m, Seconds => s };
        syntax HowMuchTheyEat = Pronoun? Eats q:Cups CupsOfFood m:MealTime
                 => HowMuchTheyEat {Cups=>q, MealTime=>m};
        syntax PetsFriends = n:Name IsFriends f:Name
                 => Friends {Name=>n, Friend=>f};
        syntax PetsFoes = n:Name DoesntLike f:Name => Foes {Name=>n, Foe=>f};
        interleave whitespace = ("and" | "," | " " | "\r"
                  | "\n" | "\t" | "." | "that")+;
    }       
}

Sample Text

What you see in bold is the tokens that make up my grammar, the plain text are the values I want to extract as data.

 

About my pets

About my pets

Razor is a Terrier that is a 9 year old male, and
her color is
white.  She will jump for 15 seconds
and bark for
2 minutesShe eats 1 cup of food for
breakfast and eats
2 cups of food for dinner.

Razor is friends with Rocket

Rocket does not like Rascal

MGraph

MyPets{
  [
    {
      Profile{
        Name => "Razor",
        AnimalType => AnimalTypes[
          "Terrier"
        ],
        Age => "9",
        Sex => Sex[
          "male"
        ],
        Color => Color[
          "white"
        ]
      },
      Activities[
        Activity{
          Type => Action[
            "jump"
          ],
          Minutes => null,
          Seconds => "15"
        },
        Activity{
          Type => Action[
            "bark"
          ],
          Minutes => "2",
          Seconds => null
        }
      ],
      Meals[
        HowMuchTheyEat{
          Cups => "1",
          MealTime => MealTime[
            "breakfast"
          ]
        },
        HowMuchTheyEat{
          Cups => "2",
          MealTime => MealTime[
            "dinner"
          ]
        }
      ]
    }
  ],
  Friends[
    [
      {
        Name => "Razor",
        Friend => "Rocket"
      }
    ]
  ],
  Foes[
    [
      {
        Name => "Rocket",
        Foe => "Rascal"
      }
    ]
  ]
}

 

More to come, I’m really excited about this technology!

 

Updated 6/12/2009 – Added Friends and Foes grammar and changed MGraph Structure

-ec

1 comment:

  1. Very cool Kevin. Where do you think Microsoft is taking this technology?

    Mitch

    ReplyDelete