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)
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 minutes. She 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
When I got home last night, I tried to boot my new
the points that Joel made really struck home. At about 32 minutes into the podcast Joel made a point about Taxi Drivers trying to run him over in NYC. I encourage you to listen to this chunk of the podcast, but let me attempt to summarize. With the significant number of cab drivers and with an average turn over of 3 weeks, it’s futile to get upset and slap the hood of the cab that just about ran you over. This goes along with one of my favorite sayings “Never try to teach a pig to sing, it just annoys the pig”.
selfish developer is so focused on cutting code he doesn’t realize he is always drinking the last cup of coffee. The team that doesn’t think they need source control…wait, no sorry, no empathy there. Anyway dealing with these sorts of issues might be considered as a change requests, not really bugs. Does this work for me? I wish I could say that yes, I’ve got it all figured out, but I can’t. Managing hundreds of thousands of details and fixing bugs in our software is not even a fraction as complicated as being obsessed with trying to fix bugs in the real world.
something new and with so many people talking about elegance of the language I was extremely excited to spend a full eight hours focused on getting a crash course in Ruby. I was not disappointed. After attending the overview, here’s my summary: