Extending Grammar for LR Parser - parsing

I have the following grammar for basic arithmetic expressions
E -> E + T
E -> T
T -> T * F
T -> F
F -> (E)
F -> id
Where E is expression, T is term, F is factor. I'm wondering how I can extend this grammar to support further arithmetic operations such exponents possibly represented with ^ or logarithm.
Thanks

Since exponentation has higher precedence you could use the following grammar:
E -> E + T
E -> T
T -> T * F
T -> F
F -> G ^ F
F -> G
G -> log(E)
G -> (E)
G -> id

Related

How to handle operator precedence in LALR(1) parser

I was writing an LALR(1) parser for a simple arithmetic grammar
E -> E ('+' | '-') T
E -> T
T -> T ('*' | '/') F
T -> F
F -> '( E ')'
F -> int
How would I handle operator precedence for an expression such as 1 * 1 + 2 so that the 1+2 is evaluated before the multiplication?

How to handle operator precedence in an LL(1) parser

I was writing an LL(1) parser for an expression grammar. I had the following grammar:
E -> E + E
E -> E - E
E -> E * E
E -> E / E
E -> INT
However, this is left recursive and I removed the left recursion with the following grammar:
E -> INT E'
E' -> + INT E'
E' -> - INT E'
E' -> * INT E'
E' -> / INT E'
E' -> ε
If I was to have the expression 1 + 2 * 3, how would the parser know to evaluate the multiplication before the addition?
Try this:
; an expression is an addition
E -> ADD
; an addition is a multiplication that is optionally followed
; by +- and another addition
ADD -> MUL T
T -> PM ADD
T -> ε
PM -> +
PM -> -
; a multiplication is an integer that is optionally followed
; by */ and another multiplication
MUL -> INT G
G -> MD MUL
G -> ε
MD -> *
MD -> /
; an integer is a digit that is optionally followed by an integer
INT -> DIGIT J
J -> INT
J -> ε
; digits
DIGIT -> 0
DIGIT -> 1
DIGIT -> 2
DIGIT -> 3
DIGIT -> 4
DIGIT -> 5
DIGIT -> 6
DIGIT -> 7
DIGIT -> 8
DIGIT -> 9

How to solve shift/reduce conflict using operator precedence?

So I have this grammar I'm trying to build an LR(1) table for
E' -> E
E -> E + E
E -> E * E
E -> ( E )
E -> a
So far, this my table
I'm trying to solve the conflicts here. I thought about changing the grammar to postfix instead of infix but I'm not really sure if I can do that. Any ideas?
Here is your grammar, with precedence:
E' -> E
E -> E + T
E -> T
T -> T * F
T -> F
F -> ( E )
F -> a
Don't forget the extra E -> T, and T -> F, as without it the grammar will be useless.
Note: This will not work with LR(0), because you'll get a conflict.

F#, concise way to define map4 using map2 and map3

This question is for amusement only. Please don't take this question too seriously.
I am currently learning F#, and I am interested to see if there is a concise way to define map4, using existing functions List.map2, List.map3, pipe forward/backward, forward/backward composition, etc.
i.e.
let map4 f a b c d = ......
map4 f [a1;a2] [b1;b2] [c1;c2] [d1;d2]
// output: [f(a1,b1,c1,d1); f(a2,b2,c2,d2)]
I can solve this recursively, or by defining a new operator (see the following URL)
http://www.fssnip.net/9W/title/nary-Seqmap-
http://call-with-cc-en.blogspot.sg/2009/04/applicative-functors-mapping-function.html
I can also solve this by combining List.map2 and List.map3, using partially applied functions f(a,b,?,?)
let map4 f a b c d =
List.map3 (fun g y -> g y) (List.map2 f a b) c d
I can try to shorten my code above using forward composition (and make it as abstract/confusing as possible)
let map4 f a =
List.map2 f a >> List.map3 id;;
// Output type: f:('a -> 'b -> 'c -> 'd -> 'e) ->
// a:'a list -> ('b list -> 'c list -> 'd list -> 'e list)
I would like to know if I can shorten it even further by getting rid of the "f" and "a", resulting in:
let map4 = ...... (* Use only List.map2, List.map3, |>, |<, >>, <<, etc.*) ..........
It will probably make it unnecessarily confusing, but it will be pretty cool. Thank you.
EDIT:
Adapting TheInnerLight's answer:
let inline (<!>) f xList = List.map f xList
let inline (<*>) gList xList = List.map2 (id) gList xList
let map4 f w x y z = f <!> w <*> x <*> y <*> z
let map5 f v w x y z = f <!> v <*> w <*> x <*> y <*> z
let map6 f u v w x y z = f <!> u <*> v <*> w <*> x <*> y <*> z
This is a good use for the applicative style of programming, i.e. using applicative functors.
Just define the apply function and some helper operators:
module List =
// val apply : f:('a -> 'b) list -> x:'a list -> 'b list
let apply f x = List.map2 (fun f x -> f x) f x
// val inline ( <!> ) : f:('a -> 'b) -> x:'a list -> 'b list
let inline (<!>) f x = List.map f x
// val inline ( <*> ) : f:('a -> 'b) list -> x:'a list -> 'b list
let inline (<*>) f x = apply f x
Then use map and apply to define mapN functions.
// val map2 : f:('a -> 'b -> 'c) -> x:'a list -> y:'b list -> 'c list
let map2 f x y = f <!> x <*> y
// val map3 : f:('a -> 'b -> 'c -> 'd) -> x:'a list -> y:'b list -> z:'c list -> 'd list
let map3 f x y z = f <!> x <*> y <*> z
// val map4 : f:('a -> 'b -> 'c -> 'd -> 'e) -> x:'a list -> y:'b list -> z:'c list -> a:'d list -> 'e list
let map4 f x y z a = f <!> x <*> y <*> z <*> a
// val map8 : f:('a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> 'h -> 'i) -> x:'a list -> y:'b list -> z:'c list -> a:'d list -> b:'e list -> c:'f list -> d:'g list -> e:'h list -> 'i list
let map8 f x y z a b c d e = f <!> x <*> y <*> z <*> a <*> b <*> c <*> d <*> e
As you can see, you can keep adding arguments to define arbitrary mapNs to your heart's content.
Since the question specifically asks about using map2 or map3, you can do this in the same style although it's a little less concise, e.g:
let map4_2 f x y z a = List.map2 f x y <*> z <*> a
let map4_3 f x y z a = List.map3 f x y z <*> a
Hopefully you get the idea.
As a small aside, I think it's worth noting that any monad is automatically an applicative functor, so there is a wide array of types you could use this pattern with, here is an Async example.
module Async =
// val map : f:('a -> 'b) -> x:Async<'a> -> Async<'b>
let map f x = async.Bind(x, async.Return << f)
// val apply : f:Async<('a -> 'b)> -> x:Async<'a> -> Async<'b>
let apply f x = async.Bind(f, fun fe -> map fe x)
// val inline ( <!> ) : f:('a -> 'b) -> x:Async<'a> -> Async<'b>
let inline (<!>) f x = map f x
// val inline ( <*> ) : f:Async<('a -> 'b)> -> x:Async<'a> -> Async<'b>
let inline (<*>) f x = apply f x
// val map4 : f:('a -> 'b -> 'c -> 'd -> 'e) -> x:Async<'a> -> y:Async<'b> -> z:Async<'c> -> a:Async<'d> -> Async<'e>
let map4 f x y z a = f <!> x <*> y <*> z <*> a
After lots of experimenting, I come up with the following "point-free" style answer:
// Warning: still have "Value Restriction" error
let map4 = List.map2 >> (>>) >> (|>) ((>>) >> (|>) (List.map3 id))
Unfortunately, the F# compiler will produce a "Value restriction" error, see:
https://blogs.msdn.microsoft.com/mulambda/2010/05/01/finer-points-of-f-value-restriction/
And so, I will settle with:
let map4 f =
f
|> ( List.map2 >> (>>) >> (|>) ((>>) >> (|>) (List.map3 id)) )
// val map4: f:('a->'b->'c->'d->'e) -> ('a list -> 'b list -> 'c list -> 'd list -> 'e list)

Grammar Precedence and associativity

if i am given following grammar
E->E W T|T
T->L S T|L
L->a|b|c
W->*
S->+|-
From following grammar i see that since + and - are deeper down the tree they have higher precedence then *, am i correct on that?
Also since this is left recursion i can assume left associativity?
Since operators can have different associativity i a confused how to tell which one has which one.
I guess what i am asking is how can i tell operator associativity based on grammar?
Start with
T->L S T|L
and consider a+b+c, which can be produced from T as follows:
T -> L S T
-> L S (L S T)
-> L S (L S (L))
-> L S (L S (c))
-> L S (b + (c))
-> L + (b + (c))
-> a + (b + (c))
(The parentheses are only there as a shorthand for the parse tree.)
That rightmost derivation is unique; T cannot match (a + b) + c because a + b is not an L.
Consequently, + and - are "right-associative".
By contrast, we have
E->E W T|T
so a*b*c will be produced as follows:
E -> E W T
-> E W L
-> E W c
-> E * c
-> (E W T) * c
-> (E W L) * c
-> (E W b) * c
-> (E * b) * c
-> ((T) * b) * c
-> ((L) * b) * c
-> ((a) * b) * c
Again, that parse is unambiguous.
I didn't do a+b*c, so it would be a good exercise.

Resources