Dart => expr syntax notes:
Only an expression—not a statement—can appear between the arrow (=>) and the semicolon (;).
case:
sayHello(String name) => print("Hello, $name");
Here I think print is a statement.
Generally we agree:
Expression: which can be calculated as a value.
Statement: a piece of code which can do logic processing.
=> can be understood as a single-line function, a expression or a single-line statement(Function Expression).
if ..., for ..., switch ..., would be statements. print() is a function call that evaluates to void and is an expression as a + b which is also a function call like a.operator+(b) just with a different syntax.
Summary => expr:
Arithmetic Expression: a + b
Assignment Expression: a = b
Relational Expression: a > b
Logical Expression: a && b
Conditional Expression: expr1 ? expr2 : expr3
Function Expression: print()
Related
So I am trying to take a user input and then parse it into an expression that I have set up an expression tree for. The expression tree that I have is:
data Expression = State [Float] Float
| Const Float
| Plus Expression Expression
| Times Expression Expression
| Minus Expression Expression
| Divide Expression Expression
| Uminus Expression
deriving(Show, Read)
And then I am trying to take the input and then parse it using the following two lines.
expression <- getLine
read expression
Is there something that I am missing regarding either getting the input or in my use of read? The error that it is giving me is:
Main.hs:94:3: error:
• No instance for (Read (IO a0)) arising from a use of ‘read’
• In a stmt of a 'do' block: read expression
In the expression:
do putStrLn "Input an expression to evaluate"
expression <- getLine
read expression
print ("Hello World")
....
In an equation for ‘main’:
main
= do putStrLn "Input an expression to evaluate"
expression <- getLine
read expression
....
If you use something inside a do-notation, it is in the Monad (or Applicative, if you turn on some language pragmas).
So, your code
expression <- getLine
read expression
is written inside a monad. Then read expression is expected to have a type m a for some monad m and some type a. Compiler can infer m from the type of getLine :: IO String, so m is IO.
But read has type read :: Read b => String -> b. Therefore, b should be IO a. But there is no instance of Read for IO a, you can't convert a string into an IO action returning something.
The problem is that you want to perform pure computation. To do so you have to use let:
expression <- getLine
let parsed = read expression :: Expression
print parsed
Here I use let to bind a name parsed to the result of read expression. Then you have to do something with a value parsed, for example, you can print it.
I have to specify the type because print can work with anything that has Show instance, and the compiler can't select the specific type of parsed. If I write something more specific, like performOperation :: Expression -> IO (), then the type declaration can be omitted.
I'm currently writing a parser for ECMAScript 5 (as a toy). The standard dictates how logical or expressions should be parsed:
<LogicalORExpression> :
<LogicalANDExpression>
<LogicalORExpression> || <LogicalANDExpression>
basicly this is equivalent to
<logicalOrExpression> = [<logicalOrExpression> ||] <LogicalAndExpression>
but how should I parse this without running into an infite loop? My current parser obviously does:
logicalOrExpression :: Parser LogicalOrExpression
logicalOrExpression = do
orExpr <- optional $ do
e <- logicalOrExpression
_ <- symbol "||"
return e
andExpr <- logicalAndExpression
case orExpr of
Just e -> return $ LogicalOrExpression (e, andExpr)
Nothing -> return $ AndExpression andExpr
Thanks
It's easiest to use megaparsec's built-in tools if you need to parse a grammar of operators with precedence and associativity.
expr = makeExprParser term table
where
term = literal <|> parenthesised expr
table = [[InfixL (string "&&" $> And)], [InfixL (string "||" $> Or)]]
For suitable definitions of literal and parenthesised, this'll parse a grammar of literal expressions composed with left-associative infix && and || operators, with && having greater precedence than ||. Megaparsec takes care of the tedious work of generating an LL(k) parser, and produces correct (left-associative, in this instance) parse trees.
Of course JavaScript's expression grammar is much larger than two operators. This example can be straightforwardly extended to include (eg) unary prefix operators like !, postfix function calls, etc. See the module's documentation.
That grammar looks equivalent to
<LogicalORExpression> :
<LogicalANDExpression>
<LogicalANDExpression> || <LogicalORExpression>
which becomes
<LogicalORExpression> :
<LogicalANDExpression> [|| <LogicalORExpression>]
In general, you need to rewrite the grammar in (roughly) LL(1) form, if possible.
The empty string matches this parser, which I believe, causes infinite recursion in Magaparsec. I think you are missing a "term" or "boolean" somewhere in your function. If I wrote True || False what would capture the first "True"
As I want to stay true to the spec in terms of the AST produced, I decided to switch to an Earley based parser and not parser combinators, as Earley's algorithm can handle left recursion.
If I would be OK with flattening the grammar, I would use the answer of Benjamin Hodgson
I am working on building a parser in Haskell using parser combinators. I have an issue with parsing keywords such as "while", "true", "if" etc
So the issue I am facing is that after a keyword there is a requirement that there is a separator or whitespace, for example in the statement
if cond then stat1 else stat2 fi;x = 1
with this statement all keywords have either a space in front of them or a semi colon. However in different situations there can be different separators.
Currently I have implemented it as follows:
keyword :: String -> Parser String
keyword k = do
kword <- leadingWS (string k)
check (== ';') <|> check isSpace <|> check (== ',') <|> check (== ']')
junk
return word
however the problem with this keyword parser is that it will allow programs which have statements like if; cond then stat1 else stat2 fi
We tried passing in a (Char -> Bool) to keyword, which would then be passed to check. But this wouldn’t work because where we parse the keyword we don’t know what kind of separator is allowed.
I was wondering if I could have some help with this issue?
Don't try to handle the separators in keyword but you need to ensure that keyword "if" will not be confused with an identifier "iffy" (see comment by sepp2k).
keyword :: String -> Parser String
keyword k = leadingWS $ try (do string k
notFollowedBy alphanum)
Handling separators for statements would go like this:
statements = statement `sepBy` semi
statement = ifStatement <|> assignmentStatement <|> ...
I am trying to write if syntax by using flex bison and in parser I have a problem
here is a grammar for if syntax in cpp
program : //start rule
|statements;
block:
TOKEN_BEGIN statements ';'TOKEN_END;
reexpression:
| TOKEN_OPERATOR expression;
expression: //x+2*a*3
TOKEN_ID reexpression
| TOKEN_NUMBER reexpression;
assignment:
TOKEN_ID'='expression
statement:
assignment;
statements:
statement';'
| block
| if_statement;
else_statement:
TOKEN_ELSE statements ;
else_if_statement:
TOKEN_ELSE_IF '(' expression ')' statements;
if_statement:
TOKEN_IF '(' expression ')' statements else_if_statement else_statement;
I can't understand why if I replace these three rules , left recursion happen I just add lambda to These rules
else_statement:
|TOKEN_ELSE statements ;
else_if_statement:
|TOKEN_ELSE_IF '(' expression ')' statements;
if_statement:
TOKEN_IF '(' expression ')' statements else_if_statement else_statement;
please help me understand.
There's no lambda or left-recursion involved.
When you add epsilon to the if rules (making the else optional), you get conflicts, because the resulting grammar is ambiguous. This is the classic dangling else ambiguity where when you have TWO ifs with a single else, the else can bind to either if.
IF ( expr1 ) IF ( expr2 ) block1 ELSE block2
How can I write a no-op statement in F#?
Specifically, how can I improve the second clause of the following match statement:
match list with
| [] -> printfn "Empty!"
| _ -> ignore 0
Use unit for empty side effect:
match list with
| [] -> printfn "Empty!"
| _ -> ()
The answer from Stringer is, of course, correct. I thought it may be useful to clarify how this works, because "()" insn't really an empty statement or empty side effect...
In F#, every valid piece of code is an expression. Constructs like let and match consist of some keywords, patterns and several sub-expressions. The F# grammar for let and match looks like this:
<expr> ::= let <pattern> = <expr>
<expr>
::= match <expr> with
| <pat> -> <expr>
This means that the body of let or the body of clause of match must be some expression. It can be some function call such as ignore 0 or it can be some value - in your case it must be some expression of type unit, because printfn ".." is also of type unit.
The unit type is a type that has only one value, which is written as () (and it also means empty tuple with no elements). This is, indeed, somewhat similar to void in C# with the exception that void doesn't have any values.
BTW: The following code may look like a sequence of statements, but it is also an expression:
printf "Hello "
printf "world"
The F# compiler implicitly adds ; between the two lines and ; is a sequencing operator, which has the following structure: <expr>; <expr>. It requires that the first expression returns unit and returns the result of the second expression.
This is a bit surprising when you're coming from C# background, but it makes the langauge surprisingly elegant and consise. It doesn't limit you in any way - you can for example write:
if (a < 10 && (printfn "demo"; true)) then // ...
(This example isn't really useful - just a demonstration of the flexibility)