I have the following rule in the grammar:
NonTerminal linker = new NonTerminal("linker");
NonTerminal list = new NonTerminal("list ");
NonTerminal item = new NonTerminal("item");
KeyTerm AND = ToTerm("AND");
KeyTerm OR = ToTerm("OR");
list.Rule = MakePlusRule(list, linker, item);
linker.Rule = AND | OR | Empty;
I get the list parsed correctly and returns a list of items as ChildNodes but I was wondering how can I get the "linkers" non-terminals as well?
It has been a year, i hope you have already solved it. But for whoever in the same situation. You could try something like this,
list.Rule = expression | item;
expression.Rule = list + linker + list
linker.Rule = AND | OR | Empty;
Related
In F# best way to set up a SQLCommand with parameters
some very neat solutions were given for constructing SQLCommand input parameters. Now I need to do some output parameters for calling a stored procedure that returns two output parameters.
So far I have:
let cmd = (createSqlCommand query conn)
let pec = (new SqlParameter("#errorCode", SqlDbType.Int))
pec.Direction <- ParameterDirection.Output
ignore (cmd.Parameters.Add(pec))
let pet = new SqlParameter("#errorMessage", SqlDbType.VarChar, 2000)
pet.Direction <- ParameterDirection.Output
ignore (cmd.Parameters.Add(pet))
let rc = cmd.ExecuteNonQuery()
let errorCode = cmd.Parameters.Item("#errorCode").Value.ToString()
let errorText = cmd.Parameters.Item("#errorMessage").Value.ToString()
Which works, but I find it ugly and too imperative. How can I expand the solutions in the previous example, (especially Tomas, which I'm now using) to handle output parameters too? So input and output in the same command to be issued.
So I tried this:
type Command =
{ Query : string
Timeout : int
Parameters : (string * Parameter) list
OutParameters : Option<(string * OutParameter)> list}
followed by this:
let createSqlCommand cmd connection =
let sql = new SqlCommand(cmd.Query, connection)
sql.CommandTimeout <- cmd.Timeout
for name, par in cmd.Parameters do
let sqlTyp, value =
match par with
| Int n -> SqlDbType.Int, box n
| VarChar s -> SqlDbType.VarChar, box s
| Text s -> SqlDbType.Text, box s
| DateTime dt -> SqlDbType.DateTime, box dt
sql.Parameters.Add(name, sqlTyp).Value <- value
match cmd.OutParameters with
| Some <string * OutParameter> list ->
for name, par in list do
let sqlParameter =
match par with
| OutInt -> new SqlParameter(name, SqlDbType.Int)
| OutVarChar len -> new SqlParameter(name, SqlDbType.VarChar, len)
sqlParameter.Direction <- ParameterDirection.Output
sql.Parameters.Add sqlParameter |> ignore
| _ -> ()
But I can't work out the syntax for the match near the end. I tried:
Some list -> and got
Error 52 This expression was expected to have type
Option list but here has type
'a option
Then I tried:
| Some Option<string * OutParameter> list ->
got the same error, So I tried:
| Some <string * OutParameter> list ->
got a different error:
Error 53 Unexpected identifier in pattern. Expected infix operator,
quote symbol or other token.
Then tried:
| Some <(string * OutParameter)> list ->
got the error:
Error 53 Unexpected symbol '(' in pattern. Expected infix operator,
quote symbol or other token.
Finally tried:
| Some (string * OutParameter) list ->
and got the first error again.
Then, I gave up.
What syntax is needed here?
Thought up a new one:
| Some list : (string * OutParameter) ->
for name, par in list do
but that errors on "for"
Error 53 Unexpected keyword 'for' in type
New Attempt:
I thought maybe I could define a function to build a sql command expecting output parameters and still use the first createSqlCommand function. I tried this:
type OutCommand =
{ Query : string
Timeout : int
Parameters : (string * Parameter) list
OutParameters : (string * OutParameter) list
}
let createSqlCommandOut (cmd : OutCommand) connection =
let sql = createSqlCommand {cmd.Query; cmd.Timeout; cmd.Parameters} connection
for name, par in cmd.OutParameters do
let sqlParameter =
match par with
| OutInt -> new SqlParameter(name, SqlDbType.Int)
| OutVarChar len -> new SqlParameter(name, SqlDbType.VarChar, len)
sqlParameter.Direction <- ParameterDirection.Output
sql.Parameters.Add sqlParameter |> ignore
sql
The idea is to grab the parameters passed in and send them on to the original function to do the work. You probably guessed that this doesn't work. I get the errors;
Error 53 Invalid object, sequence or record expression
On the call to createSqlCommand in the new function. Is this kind of thing possible? Can I make a Command record using the members of an OutCommand record? If so, how do I do the casting? (It seems to be neither an upcast downcast)
Tomas is of course much better qualified to answer this, but I'll give it a try. If he does answer, It'll be interesting to see if I'm on the right track. I guess I'm slightly off.
Bear with me if this doesn't quite run well, since I won't test it. I will base this on the code Tomas gave us.
I think we need a new OutParameter type.
type OutParameter =
| OutInt
| OutVarChar of int // the length is needed?
In the Command type we add an extra field named OutParameters.
type Command =
{ Query : string
Timeout : int
Parameters : (string * Parameter) list
OutParameters : (string * OutParameter) list }
In the cmd function, this must be added.
OutParameters =
[ "#errorCode", OutInt
"#errorMessage", OutVarChar 2000 ]
The function createSqlCommand must now also handle OutParameters. The last for-loop is the only modification here.
let createSqlCommand cmd connection =
let sql = new SqlCommand(cmd.Query, connection)
sql.CommandTimeout <- cmd.Timeout
for name, par in cmd.Parameters do
let sqlTyp, value =
match par with
| Int n -> SqlDbType.Int, box n
| VarChar s -> SqlDbType.VarChar, box s
| Text s -> SqlDbType.Text, box s
| DateTime dt -> SqlDbType.DateTime, box dt
sql.Parameters.Add(name, sqlTyp).Value <- value
for name, par in cmd.OutParameters do
let sqlParameter =
match par with
| OutInt -> new SqlParameter(name, SqlDbType.Int)
| OutVarChar len -> new SqlParameter(name, SqlDbType.VarChar, len)
sqlParameter.Direction <- ParameterDirection.Output
sql.Parameters.Add sqlParameter |> ignore
sql
After you have run your ExecuteNonQuery, you can again take advantage of your list of OutParameters to parse the output.
Now a function to extract the values.
let extractOutParameters (cmd: SqlCommand) (outParms: (string * OutParameter) list) =
outParms
|> List.map (fun (name, outType) ->
match outType with
| OutInt -> cmd.Parameters.Item(name).Value :?> int |> Int
| OutVarChar _ -> cmd.Parameters.Item(name).Value.ToString() |> VarChar
)
I am not at all sure that casting the values like this is good, and you probably should match on the type instead, to handle errors properly. Test it. But that's a minor issue not much related to what I'm trying to demonstrate.
Notice that this function uses the Parameter type for returning the values, rather than the OutParameter type. At this point I would consider changing the names of one or both types, to better reflect their use.
UPDATE
You can use this to create specific functions for commands and queries. Here is a slightly pseudo-codish F# snippet.
type UserInfo = { UserName: string; Name: string; LastLogin: DateTime }
let getUserInfo con userName : UserInfo =
let cmd = {
Query = "some sql to get the data"
Timeout = 1000
Parameters = ... the user name here
OutParameters = ... the userName, Name and LastLogin here
}
let sqlCommand = createSqlCommand cmd con
... run the ExecuteNonQuery or whatever here
let outs = extractOutParameters sqlCommand cmd.OutParameters
{
UserName = getValOfParam outs "#userName"
Name = getValOfParam outs "#name"
LastLogin = getValOfParam outs "#lastLogin"
}
You will have to create the function getValOfParam, which just searches outs for the parameter with the correct name, and returns its value.
You can then use getUserInfo like this.
let userInfo = getUserInfo con "john_smith"
Even if there were ten fields returned, you'd get them in one record, so it's simple to ignore the fields you don't want.
And if you had built another function with results you weren't interested in at all when calling it, you'd call it like this.
startEngineAndGetStatus con "mainEngine" |> ignore
I'm stuck on this problem for a while now, hope you can help. I've got the following (shortened) language grammar:
lexical Id = [a-zA-Z][a-zA-Z]* !>> [a-zA-Z] \ MyKeywords;
lexical Natural = [1-9][0-9]* !>> [0-9];
lexical StringConst = "\"" ![\"]* "\"";
keyword MyKeywords = "value" | "Male" | "Female";
start syntax Program = program: Model* models;
syntax Model = Declaration;
syntax Declaration = decl: "value" Id name ':' Type t "=" Expression v ;
syntax Type = gender: "Gender";
syntax Expression = Terminal;
syntax Terminal = id: Id name
| constructor: Type t '(' {Expression ','}* ')'
| Gender;
syntax Gender = male: "Male"
| female: "Female";
alias ASLId = str;
data TYPE = gender();
public data PROGRAM = program(list[MODEL] models);
data MODEL = decl(ASLId name, TYPE t, EXPR v);
data EXPR = constructor(TYPE t, list[EXPR] args)
| id(ASLId name)
| male()
| female();
Now, I'm trying to parse:
value mannetje : Gender = Male
This parses fine, but fails on implode, unless I remove the id: Id name and it's constructor from the grammar. I expected that the /MyKeywords would prevent this, but unfortunately it doesn't. Can you help me fix this, or point me in the right direction to how to debug? I'm having some trouble with debugging the Concrete and Abstract syntax.
Thanks!
It does not seem to be parsing at all (I get a ParseError if I try your example).
One of the problems is probably that you don't define Layout. This causes the ParseError with you given example. One of the easiest fixes is to extend the standard Layout in lang::std::Layout. This layout defines all the default white spaces (and comment) characters.
For more information on nonterminals see here.
I took the liberty in simplifying your example a bit further so that parsing and imploding works. I removed some unused nonterminals to keep the parse tree more concise. You probably want more that Declarations in your Program but I leave that up to you.
extend lang::std::Layout;
lexical Id = ([a-z] !<< [a-z][a-zA-Z]* !>> [a-zA-Z]) \ MyKeywords;
keyword MyKeywords = "value" | "Male" | "Female" | "Gender";
start syntax Program = program: Declaration* decls;
syntax Declaration = decl: "value" Id name ':' Type t "=" Expression v ;
syntax Type = gender: "Gender";
syntax Expression
= id: Id name
| constructor: Type t '(' {Expression ','}* ')'
| Gender
;
syntax Gender
= male: "Male"
| female: "Female"
;
data PROGRAM = program(list[DECL] exprs);
data DECL = decl(str name, TYPE t, EXPR v);
data EXPR = constructor(TYPE t, list[EXPR] args)
| id(str name)
| male()
| female()
;
data TYPE = gender();
Two things:
The names of the ADTs should correspond to the nonterminal names (you have difference cases and EXPR is not Expression). That is the only way implode can now how to do its work. Put the data decls in their own module and implode as follows: implode(#AST::Program, pt) where pt is the parse tree.
The grammar was ambiguous: the \ MyKeywords only applied to the tail of the identifier syntax. Use the fix: ([a-zA-Z][a-zA-Z]* !>> [a-zA-Z]) \ MyKeywords;.
Here's what worked for me (grammar unchanged except for the fix):
module AST
alias ASLId = str;
data Type = gender();
public data Program = program(list[Model] models);
data Model = decl(ASLId name, Type t, Expression v);
data Expression = constructor(Type t, list[Expression] args)
| id(ASLId name)
| male()
| female();
I found myself in the position of needing to increment a value which was deeply nested in a series of erlang records. My first attempts at doing this with list comprehensions were dismal failures. Originally, the list contained a number of records where the target value would be absent because the record that contained it would, at some level, be undefined.
I dealt with that easily enough by using lists:partition to filter out only those entries that actually needed incrementing, but I was still unable to come up with a list comprehension that would do such a simple operation.
The code sample below probably doesn't compile - it is simply to demonstrate what I was trying to accomplish. I put the "case (blah) of undefined" sections to illustrate my original problem:
-record(l3, {key, value}).
-record(l2, {foo, bar, a_thing_of_type_l3}).
-record(l1, {foo, bar, a_thing_of_type_l2}).
increment_values_recursive([], Acc
increment_values_recursive([L1 | L1s], Acc) ->
case L1#l1.a_thing_of_type_l2 of
undefined -> NewRecord = L1;
L2 ->
case L2#l2.a_thing_of_type_l3 of
undefined -> NewRecord = L2;
{Key, Value} ->
NewRecord = L1#l1{l2 = L2#l2{l3 = {Key, Value + 1}}}
end
end,
increment_values_recursive(L1s, [NewRecord | Acc]).
increment_values(L1s) ->
lists:reverse(increment_values_recursive(L1s, [])).
........
NewList = increment_values(OldList).
That was what I started with, but I'd be happy to see a list comprehension that would process this when the list didn't have to check for undefined members. Something like this, really:
increment_values_recursive([], Acc
increment_values_recursive([L1 | L1s], Acc) ->
%I'm VERY SURE that this doesn't actually compile:
#l1{l2 = #l2{l3 = #l3{_Key, Value} = L3} = L2} = L1,
%same here:
NewRecord = L1#l1{l2=L2#l2{l3=L3#l3{value = Value+1}}},
increment_values_recursive(L1s, [NewRecord | Acc]).
increment_values(L1s) ->
lists:reverse(increment_values_recursive(L1s, [])).
AKA:
typedef struct { int key, value; } l3;
typedef struct { int foo, bar; l3 m_l3 } l2;
typedef struct { int foo, bar; l2 m_l2 } l1;
for (int i=0; i<NUM_IN_LIST; i++)
{
objs[i].m_l2.m_l3.value++;
}
You can use a list comprehension and even don't need to filter out records that don't have the nesting.
To avoid readability problems I shortened your record definition.
-record(l3, {key, value}).
-record(l2, {foo, bar, al3}).
-record(l1, {foo, bar, al2}).
Define a helper function to increment the value:
inc_value(#l1{al2=#l2{al3=#l3{value=Value}=L3}=L2}=L1) ->
L1#l1{al2=L2#l2{al3=L3#l3{value=Value+1}}};
inc_value(R) ->
R.
Note the last clause that maps any other stuff that doesn't match the pattern to itself.
Lets define example records to try this out:
1> R=#l1{foo=1, bar=2}.
#l1{foo = 1,bar = 2,al2 = undefined}
This is a record that doesn't have the full nesting defined.
2> R1=#l1{foo=1, bar=2, al2=#l2{foo=3, bar=4, al3=#l3{key=mykey, value=10}}}.
#l1{foo = 1,bar = 2,
al2 = #l2{foo = 3,bar = 4,
al3 = #l3{key = mykey,value = 10}}}
Another one that has the full structure.
Try out the helper function:
4> inc_value(R).
#l1{foo = 1,bar = 2,al2 = undefined}
It leaves alone the not fully nested record.
3> inc_value(R1).
#l1{foo = 1,bar = 2,
al2 = #l2{foo = 3,bar = 4,
al3 = #l3{key = mykey,value = 11}}}
It increments the fully nested record ok.
Now the list comprehension is simple and readable:
5> [ inc_value(X) || X <- [R, R1] ].
[#l1{foo = 1,bar = 2,al2 = undefined},
#l1{foo = 1,bar = 2,
al2 = #l2{foo = 3,bar = 4,
al3 = #l3{key = mykey,value = 11}}}]
This is waaaay messier than it would be in a language with destructive mutation, but it is definitely possible. Here's the dirt:
increment(Records) ->
[L1#l1{l2 = (L1#l1.l2)#l2{l3 = ((L1#l1.l2)#l2.l3)#l3{value = ((L1#l1.l2)#l2.l3)#l3.value + 1}}} || L1 <- Records].
As you can see, this is ugly as hell; furthermore, it's difficult to immediately apprehend what this comprehension is doing. It's straightforward to figure out what's going on, but I'd have a talk with anyone in my shop who wrote something like this. Much better to simply accumulate and reverse - the Erlang compiler and runtime are very good at optimizing this sort of pattern.
It is not as hard as it seems. #Peer Stritzinger gave a good answer, but here is my take, with a clean list comprehension:
-record(l3, {key, value}).
-record(l2, {foo=foo, bar=bar, al3}).
-record(l1, {foo=foo, bar=bar, al2}).
increment(#l1{al2 = Al2}=L1) -> L1#l1{al2 = increment(Al2)};
increment(#l2{al3 = Al3}=L2) -> L2#l2{al3 = increment(Al3)};
increment(#l3{value = V}=L3) -> L3#l3{value = V + 1}.
test() ->
List =
[ #l1{al2=#l2{al3=#l3{key=0, value = 100}}}
, #l1{al2=#l2{al3=#l3{key=1, value = 200}}}
, #l1{al2=#l2{al3=#l3{key=2, value = 300}}}
, #l1{al2=#l2{al3=#l3{key=3, value = 400}}}],
[increment(L) || L <- List].
The best solution is probably to look into the concept of lenses in functional programming. A lens is a functional getter and setter for mutation of records. Done correctly, you can then write higher-order lenses which compose primitive lenses.
The result is that you can construct a mutator for your purpose and then run the mutator through all the records by a comprehension.
It is one of those things I wanna write some day for Erlang but never really got the time to write up :)
Productions
program = cls*;
cls = clsdef name openbrace clsdata closingbrace;
clsdata = (clsfield|clsmethod)*;
clsfield = [variabletype]:name [variablename]:name semi;
clsmethod = [returntype]:name [methodname]:name openmethodbrace closingmethodbrace openbrace closingbrace;
The problem resides in
clsdata = (clsfield|clsmethod)*;
If I set clsdata to
clsdata = clsfield*;
or to
clsdata = clsmethod*;
it works fine, though, as you can imagine, it doesn't mean the same thing as what I intended it to. I want a class to allow for both methods and fields (in no specific order!).
So my question is in how should I define clsdata so that I don't get errors. I can think of recursive alternatives, but I'd like to keep this as clean as possible!
Thanks
clsdata = (clsfield|clsmethod)*;
SableCC has an EBNF like syntax, but does not support this type of grammar rule. As you've already done, the non-terminal alternatives clsfield and clsmethod need be refractored into their own production.
yet I am not sure this is the best way to do this
If you look at any of the SableeCC example grammars you'll see that is the standard way of defining 'class members'. Although you could perhaps simplify your grammar by removing clsmembers:
Productions
program = cls*;
cls = clsdef name openbrace clsmember* closingbrace;
clsmember = {clsfield} clsfield | {clsmethod} clsmethod;
clsfield = [variabletype]:name [variablename]:name semi;
clsmethod = [returntype]:name [methodname]:name openmethodbrace closingmethodbrace openbrace closingbrace
This works:
Productions
program = cls*;
cls = clsdef name openbrace clsmembers closingbrace;
clsmembers = clsmember*;
clsmember = {clsfield} clsfield | {clsmethod} clsmethod;
clsfield = [variabletype]:name [variablename]:name semi;
clsmethod = [returntype]:name [methodname]:name openmethodbrace closingmethodbrace openbrace closingbrace;
yet I am not sure this is the best way to do this. I welcome other approaches!
I am writing a custom read function for one of the data types in my module. For eg, when I do read "(1 + 1)" :: Data, I want it to return Plus 1 1. My data declaration is data Data = Plus Int Int. Thanks
This sounds like something better suited to a parser; Parsec is a powerful Haskell parser combinator library, which I would recommend.
I'd like to second the notion of using a parser. However, if you absolutely have to use a pattern-matching, go like this:
import Data.List
data Expr = Plus Int Int | Minus Int Int deriving Show
test = [ myRead "(1 + 1)", myRead "(2-1)" ]
myRead = match . lexer
where
match ["(",a,"+",b,")"] = Plus (read a) (read b)
match ["(",a,"-",b,")"] = Minus (read a) (read b)
match garbage = error $ "Cannot parse " ++ show garbage
lexer = unfoldr next_lexeme
where
next_lexeme "" = Nothing
next_lexeme str = Just $ head $ lex str
You could use GHC's ReadP.