Skip to content

Instantly share code, notes, and snippets.

@davidar
Created September 8, 2019 09:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidar/4d2335f3764fe312500c97867e2be1c3 to your computer and use it in GitHub Desktop.
Save davidar/4d2335f3764fe312500c97867e2be1c3 to your computer and use it in GitHub Desktop.
%import common.WS
%ignore WS
ADJ: "big" | "red" | "tall" | "narrow" | "mine" | "blue" | "green" | "large" | "small" | "short" | "little" | "wide"
DET: "that" | "any" | "an" | "a" | "the"
NOUN: "block" | "pyramid" | "box" | "that" | "cube" | "table" | "thing" | "colour" | "object" | "steeple" | "superblock"
PREP: "into" | "onto" | "in" | "on top of" | "on" | "behind"
PREPT: "before" | "while"
VERB: "pick up" | "pick" | "contain" | "support" | "own" | "touch"
DIR: "left" | "right"
?start: ["will you"] ["please"] command
| question
| statement
command: verb noun
| "put" noun prep noun -> put
| "stack up" ("two" | "both of") noun ["and" noun] -> stack
| "build" noun -> build
question: "find" noun
| "is" ["there"] noun [adj]
| "do I" verb noun
| "which" noun ("is" | "are" | "were" | "does") adj
| "does" noun pred
| q
q: "what" ("does" | "did") noun verb [time] -> flipjoin
| "how many" noun ("are" | "were") adj -> count
| "how many" noun "did you" verb [time] -> count2
| ["what"] "is" noun verb "ed" ["by"] -> passive
| "what" noun "is" noun -> join
| ("had" | "have") "you" verb "ed" noun ["up"] time -> qwhen
statement: noun "is" adj
| "I" verb noun "but I do" ("not" | "n't") verb noun -> but
| "a \"" NOUN "\" is" noun -> define
| "call" noun "\"" NOUN "\""
verb: VERB
noun: [det] adj* NOUN ["s"]
| "the one you are holding" -> holding
| "the one which I told you to" verb -> commanded
| ["at least"] "one of them" -> that
| [det] adj* NOUN ["s"] ["which" | "that"] ["is" | "are"] adj ["but is" adj]
| ["either"] noun "or" noun -> disj
| "the" adj ["-"] "est" noun [adj] -> most
| noun "'s support" -> support
| "it" -> it
| "a stack which contains two" noun "and" noun -> stack
det: DET
adj: ADJ
| ADJ ["-"] "er than" noun -> join
| ADJ ["-"] "er than every" noun -> each
| "not as" ADJ "as" noun -> flipjoin2
| "not" adj -> neg
| ["sitting"] prep noun [time] -> joint
| noun verb ["s"] -> flipjoin
| pred
pred: verb ["s"] noun -> join
prep: PREP
| "to the" DIR "of"
time: PREPT event -> join
| "since we began"
event: "I told you to put" noun prep noun -> told_put
| "you were doing that" -> that
| "you started to clean" noun "off" -> cleanoff
pick up a big red block
pickup(big red block)!
pick up that pyramid
pickup(that pyramid)!
find a block which is taller than the one you are holding
block tall.holding?
put that into the box
in(that, box)!
what does the box contain
contain'.box?
what is that pyramid supported by
support[that pyramid]?
how many blocks are not in the box
#count(block ~in.box)?
is at least one of them narrower than the one which I told you to pick up
that narrow.command$pickup?
is that supported
support.that?
stack up two pyramids
stack(pyramid, pyramid)
the blue pyramid is mine
mine(blue pyramid).
I own blocks which are not red but I don't own anything which supports a pyramid
own(block ~red ~thing support.pyramid)
do I own the box
own box?
do I own anything in the box
own thing in.box?
will you please stack up both of the red blocks and either a green cube or a pyramid
stack(red block, red block, green cube | pyramid)
which cube is sitting on the table
cube on.table?
is there a large block behind a pyramid
large block behind.pyramid?
put a small block onto the green cube which supports a pyramid
on(small block, green cube support.pyramid)!
put the smallest pyramid on top of the small block
above(#most(small,pyramid), small block)!
does the shortest thing the tallest pyramid's support supports support anything green
#most(short,thing support'.support.#most(tall,pyramid)) support[thing green]?
which green thing does the shortest thing the tallest pyramid's support supports support
green thing support'[#most(short,thing support'.support.#most(tall,pyramid))]?
what colour is that
colour.that?
how many things are on top of green cubes
#count(thing above[green cube])?
had you touched any pyramid before I told you to put the green pyramid on the little cube
touch.pyramid before[goal.on(green pyramid,little cube)]?
how many objects did you touch while you were doing that
#count(touch.object while.that)?
what did the red cube support before you started to clean the red cube off
support'[red cube,before[cleanoff[red cube]]]?
which blocks were to the left of the box before you started to clean the red cube off
block left[box; before[cleanoff[red cube]]]?
put the blue pyramid on the block in the box
{'on(blue pyramid, block in.box)!', 'in(blue pyramid on.block, box)!'}
is there anything which is big-er than every pyramid but is not as wide as the thing that supports it
thing #each(big,pyramid) wide'[thing support.#it]?
a "steeple" is a stack which contains two green cubes and a pyramid
steeple(stack(green cube, green cube, pyramid)).
build a steeple
steeple!
call the big-est block "superblock"
superblock(#most(big,block)).
have you picked superblock up since we began
pick.superblock?
is there anything to the right of the red pyramid
thing right[red pyramid]?
#!/usr/bin/env python3
import lark
parser = lark.Lark(open('english.ebnf', 'r'), ambiguity='explicit')
@lark.v_args(inline=True)
class Sem(lark.Transformer):
def conj(self, *args):
return ' '.join(arg for arg in args if arg)
def disj(self, *args):
return ' | '.join(args)
def join(self, rel, *args):
if len(args) == 1 and ' ' not in args[0]:
return f"{rel}.{args[0]}"
return f"{rel}[{','.join(args)}]"
def flip(self, verb):
return f"{verb}'"
def neg(self, adj):
return f"~{adj}"
def flipjoin(self, noun, verb, *args):
return self.join(self.flip(verb), noun, *args)
def flipjoin2(self, verb, noun, *args):
return self.join(self.flip(verb), noun, *args)
def joint(self, rel, noun, time=None):
if not time: return self.join(rel, noun)
return f"{rel}[{noun}; {time}]"
def _ambig(self, args):
args = set(args)
if len(args) > 1: return args
return args.pop()
def command(self, verb, noun):
return f"{verb}({noun})!"
def put(self, noun, prep, location):
return f"{prep}({noun}, {location})!"
def stack(self, n1, n2=None):
if n2: return f"stack({n1}, {n1}, {n2})"
else: return f"stack({n1}, {n1})"
def build(self, noun):
return f"{noun}!"
def question(self, *args):
return self.conj(*args) + '?'
def passive(self, noun, verb):
return self.join(verb, noun)
def count(self, *args):
return f"#count({self.conj(*args)})"
def count2(self, noun, verb, time):
return f"#count({self.conj(self.join(verb, noun), time)})"
def qwhen(self, verb, noun, time):
return self.conj(self.join(verb, noun), time)
def statement(self, noun, adj):
return f"{adj}({noun})."
def but(self, v1, n1, v2, n2):
if v1 == v2:
return v1 + '(' + self.conj(n1, self.neg(n2)) + ')'
def define(self, noun, adj):
return f"{noun}({adj})."
def verb(self, name):
return name.replace(' ','')
def noun(self, *args):
return self.conj(*args)
def holding(self):
return 'holding'
def commanded(self, verb):
return f"command${verb}"
def that(self):
return 'that'
def most(self, adj, *args):
return f"#most({adj},{self.conj(*args)})"
def support(self, noun):
return self.join('support', noun)
def it(self):
return '#it'
def det(self, name):
if name == 'that': return name
return ''
def adj(self, name):
return name
def each(self, adj, noun):
return f"#each({adj},{noun})"
def prep(self, name):
if name.endswith('to'): name = name[:-2]
if name == 'on top of': name = 'above'
return name
def time(self):
return ''
def told_put(self, n1, p, n2):
return f"goal.{p}({n1},{n2})"
def cleanoff(self, noun):
return self.join('cleanoff', noun)
def main():
tests = [
'pick up a big red block',
'pick up that pyramid',
'find a block which is taller than the one you are holding',
'put that into the box',
'what does the box contain',
'what is that pyramid supported by',
'how many blocks are not in the box',
'is at least one of them narrower than the one which I told you to pick up',
'is that supported',
'stack up two pyramids',
'the blue pyramid is mine',
'I own blocks which are not red but I don\'t own anything which supports a pyramid',
'do I own the box',
'do I own anything in the box',
'will you please stack up both of the red blocks and either a green cube or a pyramid',
'which cube is sitting on the table',
'is there a large block behind a pyramid',
'put a small block onto the green cube which supports a pyramid',
'put the smallest pyramid on top of the small block',
'does the shortest thing the tallest pyramid\'s support supports support anything green',
'which green thing does the shortest thing the tallest pyramid\'s support supports support',
'what colour is that',
'how many things are on top of green cubes',
'had you touched any pyramid before I told you to put the green pyramid on the little cube',
'how many objects did you touch while you were doing that',
'what did the red cube support before you started to clean the red cube off',
'which blocks were to the left of the box before you started to clean the red cube off',
'put the blue pyramid on the block in the box',
'is there anything which is big-er than every pyramid but is not as wide as the thing that supports it',
'a "steeple" is a stack which contains two green cubes and a pyramid',
'build a steeple',
'call the big-est block "superblock"',
'have you picked superblock up since we began',
'is there anything to the right of the red pyramid',
]
for test in tests:
print(test)
tree = parser.parse(test)
#print(tree.pretty())
print(Sem().transform(tree))
print()
if __name__ == '__main__': main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment