So I'm taking a class in Programming Languages and we are going over the BNG (Backus Naur Grammar) and Grammar Tree Syntax. The problem is that the professor just mumbles and really can't explain anything well. If you guy can help make sure that I've got this right, I would greatly appreciate it!
Here's what I'm trying to understand.
Given The BNG Grammar
< S > ::= < X > < Y > < Z > | < Y > < Z >
< X > ::= < X > < T > | < T > < W >
< Y > ::= run | throw | jump
< Z > ::= < Z > < K > | < K >
< T > ::= mike | sue | ted
< W > ::= smith | jones | miller
< K > ::= fence | rope | ball
a) Draw a grammar tree with all tip node terminals.
My understanding here is that "tip nodes" means the part of the branch before the "leaf nodes" (so s, x, y, z, t, w, and k). So I got something like this... Using all the "tip nodes".
b) Draw another grammar tree using at least three different rules.
My understanding here is that for each "rule" of S, X, Y ..etc I have to choose a different terminal and non terminal. This is what I got.
I appreciate anyone trying to help explain this to me, I've spent too long trying to read though my book and notes to understand this, but unfortunately the words and descriptions that my professor uses does not correlate to anything in my book or online.
Thank you!
Related
I am looking at the source code for L2 Syntactic Complexity Analyzer
and it had a tregex expression for clause as:
S|SINV|SQ [> ROOT <, (VP <# VB) | <# MD|VBZ|VBP|VBD | < (VP [<#
MD|VBP|VBZ|VBD | < CC < (VP <# MD|VBP|VBZ|VBD)])]
I am reading tregex syntax from this link but am not confident that I understood the Boolean relational operators correctly, specifically does the second part of this tregex:
VP [<# MD|VBP|VBZ|VBD | < CC < (VP <# MD|VBP|VBZ|VBD)]
mean
(VP <# MD|VBP|VBZ|VBD) OR ((VP < CC) AND (VP < (VP <# MD|VBP|VBZ|VBD)))
verb phrase that contains both a cc and vp (with md vbp vbz vbd)
Or
(VP <# MD|VBP|VBZ|VBD) OR (VP < (CC < (VP <# MD|VBP|VBZ|VBD)))
verb phrase that contains a cc that contains a vp
In tregex (following earlier tgrep languages) a clause A op B op C op D always means A op B AND A op C AND A op D. If you want the opposite, you need to use parentheses as in Example 1: A op (B op (C op D)). So in the second disjunct of the original message, the VP has to contain a CC and another VP headed by a word of the indicated part-of-speech (<# is the "headed by" relation). So the answer is basically the former interpretation, with the one added constraint that the first VP in each conjunct of the second disjunct has to be the same VP node.
Chris's answer is correct...
Full slides here:
https://nlp.stanford.edu/software/tregex/The_Wonderful_World_of_Tregex.ppt
How might one recurse over a set, S, in Dafny when writing pure functional code? I can use :| in imperative code, having checked for non-emptiness, to select an element, s, then recurse on S - {s}. Not quite sure how to make :| deterministic and use it in functional code.
Good question! (I wish downvoters would have the courage to leave a comment...)
This is addressed in depth in Rustan's paper "Compiling Hilbert's Epsilon Operator".
In particular, see section 3.2, which describes how to write a deterministic function by recursion over sets. For reasons not entirely clear to me, the paper's Dafny code proving lemma ThereIsASmallest doesn't work for me in modern Dafny. Here is a version that works (but is ugly):
lemma ThereIsASmallest(S: set<int>)
requires S != {}
ensures exists x :: x in S && forall y | y in S :: x <= y
{
var y :| y in S;
if S != {y} {
var S' := S - {y};
assert forall z | z in S :: z in S' || z == y;
ThereIsASmallest(S');
var x' :| x' in S' && forall y | y in S' :: x' <= y;
var x := min2(y, x');
assert x in S;
}
}
Finally, as an aside, note that the technique of section 3.2 relies on having a total order on the type. If you are trying to do something fully polymorphic, then as far as I know it isn't possible.
I'm having problems understanding an online explanation of how to remove the left recursion in this grammar. I know how to remove direct recursion, but I'm not clear how to handle the indirect. Could anyone explain it?
A --> B x y | x
B --> C D
C --> A | c
D --> d
The way I learned to do this is to replace one of the offending non-terminal symbols with each of its expansions. In this case, we first replace B with its expansions:
A --> B x y | x
B --> C D
becomes
A --> C x y | D x y | x
Now, we do the same for non-terminal symbol C:
A --> C x y | D x y | x
C --> A | c
becomes
A --> A x y | c x y | D x y | x
The only other remaining grammar rule is
D --> d
so you can also make that replacement, leaving your entire grammar as
A --> A x y | c x y | d x y | x
There is no indirect left recursion now, since there is nothing indirect at all.
Also see here.
To eliminate left recursion altogether (not merely indirect left recursion), introduce the A' symbol from your own materials (credit to OP for this clarification and completion):
A -> x A'
A' -> xyA' | cxyA' | dxyA' | epsilon
Response to naomik's comments
Yes, grammars have interesting properties, and you can characterize certain semantic capabilities in terms of constraints on grammar rules. There are transformation algorithms to handle certain types of parsing problems.
In this case, we want to remove left-recursion: one desirable property of a grammar is that the use of any rule must consume at least one input token (terminal symbol). Left-recursion opens a door to infinite recursion in the parser.
I learned these things in my "Foundations of Computing" and "Compiler Construction" classes many years ago. Instead of writing a parser to adapt to a particular grammar, we'd transform the grammar to fit the parser style we wanted.
I have this simple F# function:
let compareNum x =
let y = 10
match x with
| _ when x = y -> 0
| _ when x > y -> 1
| _ when x < y -> -1
However, F# compiler gives me "Incomplete pattern matches on this expression" warning. In this case, all cases should cover every pattern.
I also see a similar example in "Pattern Matching" section in the 1st edition of Programming F# book by Chris Smith. So something might be changed in the later version of F#?
I think the answer to the previous question (and the comments -- "In general, it is an anti-pattern to have a when guard in the last pattern" -- by kimsk) explain the situation.
However, I would not say that having a guard in the last pattern is an anti-pattern - it is the easiest workaround, but I find this somewhat unfortunate, because the when pattern gives you useful information about the values you can expect - and that makes understanding the program easier. Last time I had this problem, I left it there, at least as a comment:
let compareNum x =
let y = 10
match x with
| _ when x = y -> 0
| _ when x > y -> 1
| _ (*when x < y*) -> -1
I was assigned a task for creating a parser for Arithmetic Expressions (with parenthesis and unary operators). So I just wanna know if this grammar correct or not and is it in LL(1) form and having real problems constructing the parse table for this
S -> TS'
S' -> +TS' | -TS' | epsilon
T -> UT'
T' -> *UT' | /UT' | epsilon
U -> VX
X -> ^U | epsilon
V -> (W) | -W | W | epsilon
W -> S | number
Precedence (high to low)
(), unary –
^
*, /
+, -
Associativity for binary operators
^ = right
+, -, *, / = left
Is it in LL(1) form?
To tell if the grammar is LL(1) or not, you need to expand the production rules out. If you can generate any sequence of productions which results in the left-hand-side appearing as the first thing on the right-hand-side, the grammar is not LL(1).
For example, consider this rule:
X --> X | x | epsilon
This clearly can't be part of an LL(1) grammar, since it's left-recursive if you apply the leftmost production. But what about this?
X --> Y | x
Y --> X + X
This isn't an LL(1) grammar either, but it's more subtle: first you have to apply X --> Y, then apply Y --> X + X to see that you now have X --> X + X, which is left-recursive.
You seem to be missing anything for unary plus operator. Try this instead...
V -> (W) | -W | +W | epsilon