I'm trying to create a if/else verification in prolog, but actually i cant pass a parenthesis as a predicate "parameter", the code follows bellow
s(Z):- si(X), vp(Y), append(X,Y,Z).
si(Z):- i(X), openParent(Y), append(X,Y,Z).
vp(Z):- cond(X), closeParent(Y), append(X,Y,Z).
i([if]).
openParent(['(']).
closeParent([')']).
cond([cond]).
%running s(X) to see all the possibilities:
%expected : if, (, cond, )
%output : if, '(', cond, ')'
On openParent and closeParent i want to pass the parenthesis without quotes, but if do, the execution gives an error.
Prolog constants start with lower case letters, if you want to have constants that do not follow this convention you have to escape them via '('. To distinguish them from the reserved keywords the escaping needs to stay in place. This is still better than C for example, where int void = 0 is a forbidden statement and there's no escaping to write it down.
You might also want to think about what your predicate is supposed to do. A unary predicate like s/1 can only tell you if the term you pass fulfils your requirements. If you want to create something out of it (for example an evaluation of the if-then-else) you would need two arguments s(Ast, Evaluation).
Another observation is that you are already working on a symbolic representation: your code produces e.g. a list [if, '(', Cond, ')', TrueBranch] where if only takes one space (a string would use two). But if the representation is symbolic, why not just represent parenthesis as lparen and rparen? Or even better, if has only two / three arguments, why not represent it as if(Cond, TrueBranch) and if(Cond, TrueBranch, ElseBranch)?
Related
When using SWI-prolog, it will print output that doesn't need to be quoted (output that doesn't contain special characters), without quotes.
As an example:
?- p('this_is_a_string').
true.
?- p(X).
X = this_is_a_string.
I would like Prolog to always output with quotes. It is okay if my output ends up quoting stuff like functor names, which were not originally quoted when input. How can I achieve this?
To change the default behaviour of SWI-Prolog's top-level output, you want to look towards setting a flag. If you query the appropriate flag, you should find this is your default output:
?- current_prolog_flag(print_write_options, Options).
Options = [portray('true'), quoted('true'), numbervars('true')].
In this particular case, the needed flag is already set: we have portray('true') in our Options.
portray/1 is a dynamic predicate that you can assert. It's called with a ground term when it is being printed, if it succeeds then it's assumed the the term has been printed.
So in your case you can assert the following:
portray(Term) :- atom(Term), format("'~s'", Term).
Now you'll get the desired behaviour:
?- p(this_is_an_atom).
true.
?- p(X).
X = 'this_is_an_atom'.
You could add this to your .swiplrc file if it's something you want all the time. Note, this will have no effect on write/1 and similar predicates, you'll need to use this instead:
?- write_term(foo, [portray(true)]).
'foo'.
To add the additional requirement of escaping characters in the the atom, you'll either need to implement your own DCG to the ISO standard for escaping characters, or abuse the built-in one. To do this you can write out to an atom and see if you need to add your single-quotes, or if they would already be there. The case of X = (\). is most easily handled in its own clause, you can then choose if you wish to print '\\' or (\).
portray(\) :-
format("'\\\\'"), !.
portray(Term) :-
atom(Term), \+ Term = (\),
( with_output_to(chars(['\''|_]),
write_term(Term, [quoted(true), character_escapes(true), portrayed(false)]))
-> format("~q", Term)
; format("'~s'", Term)
).
I'm new to prolog and I'm trying to reassign operators in prolog by changing their precedence. I'm running into 4 errors for the following:
:-op(1000,yf,+). %unary plus%
:-op(1000,yf,-). %unary minus%
:-op(750,yfx,"%"). %modulo%
The first two give me a similar error that goes like this:
warning: directive failed (op(1000,xf,+)) with exception (error(permission_error(create,operator,+),op/3))
I also get an error with the modulo one (a different error), but I suspect it's because I'm not supposed to enclose % in quotes (but how am I supposed to differentiate it from a comment marker?).
I've redefined a bunch of other operators (such as the addition operator :-op(500,yfx,+).) and they give me no problems. Only the 3 listed above give me errors.
Can anyone shed some light on this?
Thanks!
GNU Prolog documentation states that
An atom can have multiple operator definitions (e.g. prefix and infix like +) however an atom cannot have both an infix and a postfix operator definitions.
from here the errors on first two declaration. Then you should change the specifier to fy.
The modulo operator will need single quotes around.
You are attempting to define + as a postfix operator. However, + is also defined as an infix operator and the standard does not permit to define an operator both as postfix and infix. If you really want to do this you have to first undefine the infix operator using priority 0.
However, I can only recommend that you do not change standard operators like + or -. It's like you would change the operator precedence in C, C++, C#, Java, Perl, PHP, Javascript and the like: It would make your life as a programmer very, very miserable.
I cannot recommend to use % as operator in Prolog: % starts a comment. If you want to use it as an operator, you would have to write '%' quoted all the time. Prolog has already mod and rem defined as operators. Isn't that enough?
You are probably using GNU Prolog which is quite ISO conforming. Other Prologs permit you to define infix and postfix at the same time. See #237. But those other Prologs do a lot of things differently.
As a general remark: As a beginner, better stay away from changing the operator table. You really need to get used to the standard operators first. And with more experience you will most probably prefer to only add new operators with similar precedence than existing ones.
iso-prolog: ISO/IEC 13211-1:1995 6.3.4.3 Operators, last paragraph:
There shall not be an infix and a postfix operator with thesame name.
I have defined ! (factorial) function and registered it as arithmetic function and an operator, so that I can execute: A is 6!.
Now I'd like to define !! (factorial of odd numbers), but the same way - writing clauses, registering arithmetic_function and operator, calling A is 7!! - results in
SyntaxError: Operator expected
How should I, if possible, register !! operator ?
Yes, I realize, ! is normally the cut.
! is a so-called solo character, you cannot have two in a row. If it were not, you could not write for example:
c :- !.
but would instead have to write:
c :- ! .
because "!." would otherwise be interpreted as a single token.
Also, if you let ! be an operator, both versions are invalid syntax (yes, SWI still accepts it, but for example GNU Prolog does not). You need to write:
c :- (!).
because operators that are operands need to be bracketed. Instead of !, use for example "f" and "ff", or fitting Unicode characters for your use case.
This question was asked to me in an interview question:
Write a code to generate the parse tree like compilers do internally for any given expression. For example:
a+(b+c*(e/f)+d)*g
Start by defining the language. No one can implement a parser or a compiler to a language that isn't very well defined. You give an example: 'a+(b+c*(e/f)+d)*g', which should trigger the following questions:
Is the language a single expression, or there may be multiple statements (separated by ';' maybe?
what are the 'a', 'b', ... 'g' tokens? Is it variable? What is the syntax of variables? Is it a C-like variable, or is it a single alphanumeric character as your example may imply.
There are 3 binary expression in your example. Is that all? Does the language also support '-'. Does your language support logical, and bit-wise operators?
Does the language support number literals? integer only? double? Does the language support string literals? Do you quote string literals?
Syntax for comments?
Which operator has precedence? Does '*' operator has precedence over '+' as in the example? Does operands evaluated right to left or left to right?
Any Pre-processing?
Once you are equipped with a good definition of the language syntax, start with implementing a tokenizer. A tokenizer gets a stream of characters and generates a list of tokens. In the example above, each character is a token, but in var*12 (var power 12) there are 3 tokens: 'var', '*' and '12'. If regular expression is permitted, it is possible you can do this part of the parsing with regular expressions.
Next, have a function that identify each token by type: is it an operator, is it a variable, a number literal, string literal, etc. Package all in a method called NextToken that returns a token and its type.
Finally, start parsing. In your sample above the root of the parsing tree will be a node with the '+' operator (which has precedence over the ''). The left child is a variable token 'a' and the right child is a tree with a root element the '' token. Work recursively.
Simple way out is to convert your expression into postfix notation (abcef/*++) & then refer to the answer to this question (http://stackoverflow.com/questions/423898/postfix-notation-to-expression-tree) for converting the postfix expression to a Tree.
This is what the interviewer expected :)
Whenever you intend to write a parser, the main question to ask is if you want to do it manually, or to use a parser generator framework.
In this case, I would say that it's a good exercise to write it all yourself.
Start with a good representation for the tree itself. This will be be output of your algorithm. For example, this could be a collection of objects, where one object kind could represent a "label" like a, b, and c in your example. Others could represent numbers. You could then defined a representation of operators, for example + is a binary operator, which would have two subobjects, representing the left and right subexpression.
Next step is the actual parser, I would suggest a classical recursive decent parser. One text describing this, and provides a standard pseudo-code implementation is this text by Theodore Norvell
I'd start with a simple grammar, something like those used by ANTLR and JavaCC.
Say I have a field on a datawindow that is the value of a database column ("Insert > Column). It has conditions in which it needs to be protected (Properties>General>Protect).
I want to have the field background grey when it's protect. At the moment, the only way I can work out how to do this is to copy the protect conditional, no matter how complex, substituting the 1 (protect) and 0 (not protect) for colour values.
Is there some sort of syntax I can use in the Expression field for the column's background colour that references the protect value of the column? I tried
if (column.protect=1, Grey, White)
but it returns errorous saying it expects a TRUE/FALSE condition.
Is what I'm after impossible, or is it just a matter of getting the right syntax.
Cheers.
Wow. You like complex, layered questions.
The first problem is accessing the value, which isn't done as directly as you described. As a matter of fact, you use a Describe() to get the value. The only problem with that is that it comes back as a string in the following format, with quotes around (note that we're using standard PowerScript string notation where ~t is a tab)
"<DefaultValue>~t<Expression>"
You want the expression, so you'll have to parse it out, dropping the quotes as well.
Once you've got the expression, you'll need to evaluate it for the given row. That can be done with another Describe () call, particularly:
Describe ("Evaluate('<expression>', <rownum>)")
The row number that an expression is being evaluated on can be had with the GetRow() function.
This may sound like it needs PowerScript and some interim value storage, but as long as you're willing to make redundant function calls to get a given value more than once, you can do this in an expression, something like (for an example column b):
if (Describe ("Evaluate (~"" + Mid (Describe ("b.protect"),
Pos (Describe ("b.protect"), "~t")+1,
Len (Describe ("b.protect")) - Pos (Describe ("b.protect"), "~t") - 1)
+ "~", " + String (GetRow()) + ")")='1',
rgb(128, 128, 128),
rgb(255,255,255))
This looks complex, but if you put the Mid() expression in a compute field so you can see the result, you'll see that simply parses out the Protect expression and puts it into the Describe (Evaluate()) syntax described above.
I have put one cheat into my code for simplicity. I used the knowledge that I only had single quotes in my Protect expression, and chose to put the Evaluate() expression string in double quotes. If I was trying to do this generically for any column, and couldn't assume an absence of double quotes in my Protect expression, I'd have use a global function to do a replace of any double quotes in the Protect expression with escaped quotes (~"), which I believe in your code would look like a triple tilde and a quote. Then again, if I had to make a global function call (note that global function calls in expressions can have a significant performance impact if there are a lot of rows), I'd just pass it the Describe ("column.protect") and GetRow() and build the entire expression in PowerScript, which would be easier to understand and maintain.
Good luck,
Terry.