I am implementing the following grammar in OCamlyacc and OCamllex:
The OCaml type declaration for my IF-ELSE clauses is as such:
(* Some code not shown *)
and stmt = ASSIGN of lv * exp
| IF of exp * stmt * stmt
| WHILE of exp * stmt
| DOWHILE of stmt * exp
| READ of id
| PRINT of exp
| BLOCK of block
(* Some code not shown *)
I can define the IF-ELSE portion in OCamlyacc as such:
stmt:
| IF LPAREN e RPAREN stmt { S.IF ($3, $5, ???) } /*line 1*/
| IF LPAREN e RPAREN stmt ELSE stmt { S.IF ($3, $5, $7) } /*line 2*/
But, how can I put "NULL" for a statement type ("stmt"), where the question marks are for the IF-Statement that does not have an ELSE (line 1)? I do not have access to a statement type that only has an expression ("exp") and only one statement.
I thought about putting a "while(0){print(0)}" statement there, but that is not how you are suppose to do it, especially because it will parse in a while-statement when it shouldn't.
One solution can be to explicitly add a nop statement that does by definition nothing.
stmt = ASSIGN of lv * exp
| IFTE of exp * stmt * stmt
| WHILE of exp * stmt
| DOWHILE of stmt * exp
| READ of id
| PRINT of exp
| BLOCK of block
| NOP
If you can't modify your types, you can still do the dummy assigment : lv = lv
Another solution wich may be cleaner imo, is to add explicitly add the
if-then operation to your statements :
stmt = ASSIGN of lv * exp
| IFTE of exp * stmt * stmt
| IFT of exp * stmt
| WHILE of exp * stmt
| DOWHILE of stmt * exp
| READ of id
| PRINT of exp
| BLOCK of block
Thank you ghilesZ for your post, but I am not able to modify the type rules in OCaml. Therefore, adding in a new rule or extending any types is forbidden.
I finally figured out what I had to do. I thought there was something special in OCaml that I was missing, so I purposely left out details of this specific assignment that I thought would just over cloud my question, but in fact were useful.
Let me show my answer to this, but first let me give some extra details:
Therefore, by using the grammar rules up above and the provided OCaml below, the solution would be:
stmt:
| IF LPAREN e RPAREN stmt ELSE stmt { S.IF ($3, $5, $7) } /*line 1*/
| IF LPAREN e RPAREN stmt { S.IF ($3, $5, S.BLOCK ([],[])) } /*line 2*/
You basically keep the ELSE, but you just put in empty curly braces, effectively putting in a "NULL" there or a "do-nothing" action.
Lastly, I flipped the ordering, because for these two IF-statements to be parsed correctly, you need to set precedence, which can be done with:
%nonassoc RPAREN /* Right parenthesis */
%nonassoc ELSE
Related
I have a sympy code which has a expression as follows
$$
z = \frac{x - 0.5}{\epsilon}
$$
$$
\phi = \frac{1}{1 + e^{-z}}
$$
from sympy import *
x = symbols("x")
z = symbols("z")
phi = 1/(1 + exp(-z))
phi_x = diff(phi,x)
After differentiation, $\phi_x$ provides an expression
$$
\frac{e^{- \frac{x - 0.5}{\epsilon}}}{\epsilon \left(1 + e^{- \frac{x - 0.5}{\epsilon}}\right)^{2}}
$$
However, I just want to get the answer as below, where z is replaced for $(x - 0.5)/\epsilon$
$$
\frac{e^{-z}}{\epsilon \left(1 + e^{-z}\right)^{2}}
$$
I have tried both phi_x.subs(x-0.5/eps, z) and phi_x.replace(x-0.5/eps, z). Both does not seems to give a proper subsitution as above.
I'm trying to interact with this List[Option[Map[String, DataFrame]]] but I'm having a bit of trouble.
Inside it has something like this:
customer1 -> dataframeX
customer2 -> dataframeY
customer3 -> dataframeZ
Where the customer is an identifier that will become a new column.
I need to do an union of dataframeX, dataframeY and dataframeZ (all df have the same columns). Before I had this:
map(_.get).reduce(_ union _).select(columns:_*)
And it was working fine because I only had a List[Option[DataFrame]] and didn't need the identifier but I'm having trouble with the new list. My idea is to modify my old mapping, I know I can do stuff like "(0).get" and that would bring me "Map(customer1 -> dataframeX)" but I'm not quite sure how to do that iteration in the mapping and get the final dataframe that is the union of all three plus the identifier. My idea:
map(/*get identifier here along with dataframe*/).reduce(_ union _).select(identifier +: columns:_*)
The final result would be something like:
-------------------------------
|identifier | product |State |
-------------------------------
| customer1| prod1 | VA |
| customer1| prod132 | VA |
| customer2| prod32 | CA |
| customer2| prod51 | CA |
| customer2| prod21 | AL |
| customer2| prod52 | AL |
-------------------------------
You could use collect to unnest Option[Map[String, Dataframe]] to Map[String, DataFrame]. To put an identifier into the column you should use withColumn. So your code could look like:
import org.apache.spark.sql.functions.lit
val result: DataFrame = frames.collect {
case Some(m) =>
m.map {
case (identifier, dataframe) => dataframe.withColumn("identifier", lit(identifier))
}.reduce(_ union _)
}.reduce(_ union _)
Something like this perhaps?
list
.flatten
.flatMap {
_.map { case (id, df) =>
df.withColumn("identifier", id) }
}.reduce(_ union _)
I'm using ANTLR4 and the CSS grammar from https://github.com/antlr/grammars-v4/tree/master/css3. The grammar defines the following ( pared down a little for brevity )
dimension
: ( Plus | Minus )? Dimension
;
fragment FontRelative
: Number E M
| Number E X
| Number C H
| Number R E M
;
fragment AbsLength
: Number P X
| Number C M
| Number M M
| Number I N
| Number P T
| Number P C
| Number Q
;
fragment Angle
: Number D E G
| Number R A D
| Number G R A D
| Number T U R N
;
fragment Length
: AbsLength
| FontRelative
;
Dimension
: Length
| Angle
;
The matching works fine but I don't see an obvious way to extract the units. The parser creates a DimensionContext which has 3 TerminalNode members - Dimension, Plus and Minus. I'd like to be able to extract the unit during parse without having to do additional string parsing.
I know that one issue that the Length and Angle are fragments. I changed the grammar not use fragments
Unit
: 'em'
| 'ex'
| 'ch'
| 'rem'
| 'vw'
| 'vh'
| 'vmin'
| 'vmax'
| 'px'
| 'cm'
| 'mm'
| 'in'
| 'pt'
| 'q'
| 'deg'
| 'rad'
| 'grad'
| 'turn'
| 'ms'
| 's'
| 'hz'
| 'khz'
;
Dimension : Number Unit;
And things still parse but I don't get any more context about what the units are - the Dimension is still a single TerminalNode. Is there a way to deal with this without having to pull apart the full token string?
You will want to do as little as possible in the lexer:
NUMBER
: Dash? Dot Digit+ { atNumber(); }
| Dash? Digit+ ( Dot Digit* )? { atNumber(); }
;
UNIT
: { aftNumber() }?
( 'px' | 'cm' | 'mm' | 'in'
| 'pt' | 'pc' | 'em' | 'ex'
| 'deg' | 'rad' | 'grad' | '%'
| 'ms' | 's' | 'hz' | 'khz'
)
;
The trick is to produce the NUMBER and UNIT as separate tokens, yet limited to the required ordering. The actions in the NUMBER rule just set a flag and the UNIT predicate ensures that a UNIT can only follow a NUMBER:
protected void atNumber() {
_number = true;
}
protected boolean aftNumber() {
if (_number && Character.isWhitespace(_input.LA(1))) return false;
if (!_number) return false;
_number = false;
return true;
}
The parser rule is trivial, but preserves the detail required:
number
: NUMBER UNIT?
;
Use a tree-walk, parse the NUMBER to a Double and an enum (or equivalent) to provide the semantic UNIT characterization:
public enum Unit {
CM("cm", true, true), // 1cm = 96px/2.54
MM("mm", true, true),
IN("in", true, true), // 1in = 2.54cm = 96px
PX("px", true, true), // 1px = 1/96th
PT("pt", true, true), // 1pt = 1/72th
EM("em", false, true), // element font size
REM("rem", false, true), // root element font size
EX("ex", true, true), // element font x-height
CAP("cap", true, true), // element font nominal capital letters height
PER("%", false, true),
DEG("deg", true, false),
RAD("rad", true, false),
GRAD("grad", true, false),
MS("ms", true, false),
S("s", true, false),
HZ("hz", true, false),
KHZ("khz", true, false),
NONE(Strings.EMPTY, true, false), // 'no unit specified'
INVALID(Strings.UNKNOWN, true, false);
public final String symbol;
public final boolean abs;
public final boolean len;
private Unit(String symbol, boolean abs, boolean len) {
this.symbol = symbol;
this.abs = abs;
this.len = len;
}
public boolean isAbsolute() { return abs; }
public boolean isLengthUnit() { return len; }
// call from the visitor to resolve from `UNIT` to Unit
public static Unit find(TerminalNode node) {
if (node == null) return NONE;
for (Unit unit : values()) {
if (unit.symbol.equalsIgnoreCase(node.getText())) return unit;
}
return INVALID;
}
#Override
public String toString() {
return symbol;
}
}
So I have a FileNet search query like this
SELECT * from MyPurchase_Docs
WHERE Purchase_Amount > 100.50
Very simple query but my problem is that Purchase_Amount is defined as string
so I get results where
Purchase_Amount is 2.5, 30.25 etc (because it is comparing strings)
I tried CAST function but it does not work with FileNet.
I do not have access to change Field type in Filenet so I am stuck here.
Please let me know if there is a way to solve this problem.
That is not possible, data type conversion is not supported.
<predicate> ::= <comparison_predicate>
| <null_test>
| <in_test>
| <existence_test>
| <isclass_test>
| <isOfclass_test>
| <content_test>
| <satisfies_test>
| <intersects_test>
<comparison_predicate> ::= <scalar_exp> <comparison_op> <scalar_exp>
<scalar_exp> ::= <literal>
| <property_exp>
| ( '(' <scalar_exp> ')' )
| ( <scalar_exp> <arith_op> <scalar_exp> )
| <property_spec> [<arith_op> <timespan_exp>]
| <now> [<arith_op> <timespan_exp>]
SQL Statement Grammar
how do I generate the code corresponding to a bytecode instruction IF THEN - ELSE with the optioanal ELSE branch?
For example, the program If-else.pas is considered correct, while the program If.pas isn't considered correct, because it doesn't contains the ELSE branch.
If-else.pas
var a, b : integer;
begin
a := 3;
b := 5;
if a > b then
print(a)
else
print(b)
end
If.pas
var a, b : integer;
begin
a := 3;
b := 5;
if a > b then
print(a)
end
So Jasmin give me this error:
Output.j:62: JAS Error: Label: L11 has not been added to the code.
Output.j: Found 1 errors
My grammar .g has this rule:
stmt -> ID := expr
| print( expr )
| if( expr ) then ( stmt ) [ else stmt ]?
| while( expr ) do stmt
| begin stmt [ ; stmt ]* end
For the if-else statement I wrote this:
'if'
{
int lfalse = code.newLabel(); //Generates a new number for the LABEL
int lnext = lfalse;
}
( expr )
{
if($expr.type != Type.BOOLEAN) //Checking the condition is boolean
throw new IllegalArgumentException("Type error in '( expr )': expr is not a boolean.");
code.emit(Opcode.IFEQ, lfalse); //I create the instruction IFEQ L(lfalse)
}
'then' s1 = stmt
{
lnext = code.newLabel(); //Generates a new number for the LABEL
code.emit(Opcode.GOTO, lnext); //I create the instruction GOTO L(lnext)
code.emit(Opcode.LABEL, lfalse); //I create the instruction L(lfalse):
}
( 'else' s2 = stmt
{
code.emit(Opcode.LABEL, lnext); //I create the instruction L(lnext):
})?
But in this way the second branch is not optional, but must always be present.
How do I make it optional? I thought it was necessary the question mark (( 'else' s2 = stmt )?), but no.
I am using ANTLR.
Thanks.
I do not know if the bytecode files (. J) generated by Jasmin will be useful, but I write it.
If-else.j
ldc 3
istore 1
ldc 5
istore 0
iload 1
iload 0
if_icmpgt L7
ldc 0
goto L8
L7:
ldc 1
L8:
ifeq L4
iload 1
invokestatic Output/printInt(I)V
goto L11
L4:
iload 0
invokestatic Output/printInt(I)V
L11:
return
If.j
ldc 3
istore 1
ldc 5
istore 0
iload 1
iload 0
if_icmpgt L7
ldc 0
goto L8
L7:
ldc 1
L8:
ifeq L4
iload 1
invokestatic Output/printInt(I)V
goto L11
L4:
return
The problem here is that you're always generating a jump to LNEXT, but you don't generate the label itself when there's no else clause, leading to invalid code. You need to generate the label unconditionally.
I'm not familiar with Antlr, but based on the way your code is written, I suspect this is the correct way to do it.
'if'
{
int lfalse = code.newLabel(); //Generates a new number for the LABEL
int lnext = lfalse;
}
( expr )
{
if($expr.type != Type.BOOLEAN) //Checking the condition is boolean
throw new IllegalArgumentException("Type error in '( expr )': expr is not a boolean.");
code.emit(Opcode.IFEQ, lfalse); //I create the instruction IFEQ L(lfalse)
}
'then' s1 = stmt
{
lnext = code.newLabel(); //Generates a new number for the LABEL
code.emit(Opcode.GOTO, lnext); //I create the instruction GOTO L(lnext)
code.emit(Opcode.LABEL, lfalse); //I create the instruction L(lfalse):
}
( 'else' s2 = stmt )?
{
code.emit(Opcode.LABEL, lnext); //I create the instruction L(lnext):
}