I have a problem with the if statment.
I have a program with commandline-arguments and utf8 (€ - Symbol).
The error is in works_not in the if statement.
class EURO
insert ARGUMENTS
create {ANY}
make
feature {ANY}
make
do
works_not
works
end
works_not
local ok: BOOLEAN
do
print ("%N%NAnzahl Argumente : " + argument_count.to_string + "%N")
print ("%NArgument -> Programmname : " + argument(0))
print ("%NArgument -> Wert : " + argument(1))
print ("%NArgument -> Währung : " + argument(2) + "%N")
ok := argument(2) = "€"
print ("%NArgument(2) ist Euro ? " + ok.to_string + "%N%N")
print ("don't work")
io.put_new_line
if argument(2) = "€" then
euro_in_dm(argument(1).to_real)
else
dm_in_euro(argument(1).to_real)
end
end
works
do
print ("works ")
io.put_new_line
if argument_count /= 2 then
print("%N%N Error (1) %N%N")
else
inspect
argument(2)
when "€" then
euro_in_dm(argument(1).to_real)
when "DM","dm" then
dm_in_euro(argument(1).to_real)
else
print("%N%N Error (2) %N%N")
end
end
end
feature
euro_in_dm (a: REAL)
do
io.put_string("%N Euro -> DM ")
io.put_real(a * 1.95583)
io.put_string("%N%N")
end
dm_in_euro (a: REAL)
do
io.put_string("%N DM -> Euro ")
io.put_real(a / 1.95583)
io.put_string("%N%N")
end
end
The issue is in the comparison operator argument(2) = "€".
In Eiffel strings have a reference type, so the equality operator = compares references to the string objects, not their contents. If you want to compare the string values instead, you need to use an operator ~ that internally calls is_equal after checking that types of both operands are exactly the same, or a more robust version same_string (provided that it is available in your version of the environment). To summarize, you can try one of the following instead of the equality:
argument(2).same_string ("€")
argument(2) ~ "€"
argument(2).is_equal ("€")
Related
String s = " hello ";
String[] strs = s.split(" ");
When I run this split method, I see that
Strs[0] = " ";
Strs[1] = " ";
Strs[2] = " ";
Strs[3] = " ";
Which makes sense so far.
However, even there is some " " after the word, "hello", java system did not creates any index for those of " " located after the word, "hello".
So, it eventually ended up to
Strs[0] = " ";
Strs[1] = " ";
Strs[2] = " ";
Strs[3] = " ";
Strs[4] = "hello";
Why is it??
This is a prime example of the two overloading methods of java split.
split(String regex) -
Javadoc
split(String regex, int limit) - Javadoc
When you use s.split(" "), the 2nd parameter limit is considered to be 0 by default, and this eliminates any dangling empty strings from result array.
If you want the dangling empty values, you have to explicitly pass -1 as the parameter like s.split(" ", -1) resulting in [, , , , hello, , ]
The limit parameter actually controls the number of times this pattern " " is applied. The Javadoc documentation links I shared has the technical details for further reading.
I want to improve the readability of pyparsing's debugging output by adding indentation. For example, instead of this:
Match part at loc 0(1,1)
Match subpart1 at loc 0(1,1)
Match subsubpart1 at loc 0(1,1)
Matched subsubpart1 at loc 10(2,1) -> ...
Matched subpart1 at loc 20(3,1) -> ...
Match subpart2 at loc 20(3,1)
Match subsubpart2 at loc 20(3,1)
Matched subsubpart2 at loc 30(4,1) -> ...
Matched subpart2 at loc 40(5,1) -> ...
Matched part at loc 50(6,1) -> ...
I would like to have it indented like this to better understand what's going on during parsing:
Match part at loc 0(1,1)
Match subpart1 at loc 0(1,1)
Match subsubpart1 at loc 0(1,1)
Matched subsubpart1 at loc 10(2,1) -> ...
Matched subpart1 at loc 20(3,1) -> ...
Match subpart2 at loc 20(3,1)
Match subsubpart2 at loc 20(3,1)
Matched subsubpart2 at loc 30(4,1) -> ...
Matched subpart2 at loc 40(5,1) -> ...
Matched part at loc 50(6,1) -> ...
So in pyparsing.py, I just changed _defaultStartDebugAction, _defaultSuccessDebugAction and _defaultExceptionDebugAction to:
pos = -1
def _defaultStartDebugAction( instring, loc, expr ):
global pos
pos = pos + 1
print ("\t" * pos + ("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )))
def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ):
print ("\t" * pos + "Matched " + _ustr(expr) + " -> " + str(toks.asList()))
global pos
pos = pos - 1
def _defaultExceptionDebugAction( instring, loc, expr, exc ):
print ("\t" * pos + "Exception raised:" + _ustr(exc))
global pos
pos = pos - 1
(I just added the pos expressions and "\t" * pos to the output to get my desired result)
However, I don't like tampering directly with the pyparsing library. On the other hand, I don't want to use the .setDebugActions method on every parser element I define, I want them all to use my modified default debug actions.
Is there a way I can achieve this without having to tamper with the pyparsing.py library directly?
Thanks!
Python modules are just like any other Python object, and you can manipulate their symbols using standard Python function decorating methods. Often referred to as "monkeypatching", these can be done entirely from your own code, without modifying the actual library source.
The simplest way to implement this change is to just overwrite the symbols. In your code, write:
import pyparsing
# have to import _ustr explicitly, since it does not get pulled in with '*' import
_ustr = pyparsing._ustr
pos = -1
def defaultStartDebugAction_with_indent( instring, loc, expr ):
global pos
pos = pos + 1
print ("\t" * pos + ("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )))
def defaultSuccessDebugAction_with_indent( instring, startloc, endloc, expr, toks ):
global pos
print ("\t" * pos + "Matched " + _ustr(expr) + " -> " + str(toks.asList()))
pos = pos - 1
def defaultExceptionDebugAction_with_indent( instring, loc, expr, exc ):
global pos
print ("\t" * pos + "Exception raised:" + _ustr(exc))
pos = pos - 1
pyparsing._defaultStartDebugAction = defaultStartDebugAction_with_indent
pyparsing._defaultSuccessDebugAction = defaultSuccessDebugAction_with_indent
pyparsing._defaultExceptionDebugAction = defaultExceptionDebugAction_with_indent
Or a cleaner version is to wrap the original methods with your code as a decorator:
pos = -1
def incr_pos(fn):
def _inner(*args):
global pos
pos += 1
print ("\t" * pos , end="")
return fn(*args)
return _inner
def decr_pos(fn):
def _inner(*args):
global pos
print ("\t" * pos , end="")
pos -= 1
return fn(*args)
return _inner
import pyparsing
pyparsing._defaultStartDebugAction = incr_pos(pyparsing._defaultStartDebugAction)
pyparsing._defaultSuccessDebugAction = decr_pos(pyparsing._defaultSuccessDebugAction)
pyparsing._defaultExceptionDebugAction = decr_pos(pyparsing._defaultExceptionDebugAction)
This way, if you update pyparsing and the original code changes, your monkeypatch will get the updates without your having to modify your copies of the original methods.
To make your intentions even clearer, and to avoid duplicating those function names (DRY), this will replace those last 3 lines:
def monkeypatch_decorate(module, name, deco_fn):
setattr(module, name, deco_fn(getattr(module, name)))
monkeypatch_decorate(pyparsing, "_defaultStartDebugAction", incr_pos)
monkeypatch_decorate(pyparsing, "_defaultSuccessDebugAction", decr_pos)
monkeypatch_decorate(pyparsing, "_defaultExceptionDebugAction", decr_pos)
I have a long line of code that I want to break up among multiple lines. What do I use and what is the syntax?
For example, adding a bunch of strings:
val text = "This " + "is " + "a " + "long " + "long " + "line"
There is no symbol for line continuation in Kotlin. As its grammar allows spaces between almost all symbols, you can just break the statement:
val text = "This " + "is " + "a " +
"long " + "long " + "line"
However, if the first line of the statement is a valid statement, it won't work:
val text = "This " + "is " + "a "
+ "long " + "long " + "line" // syntax error
To avoid such issues when breaking long statements across multiple lines you can use parentheses:
val text = ("This " + "is " + "a "
+ "long " + "long " + "line") // no syntax error
For more information, see Kotlin Grammar.
Another approach is to go for the 3 double quotes "" pairs i.e. press the double quotes 3 times to have something like this.
val text = """
This is a long
long
long
line
""".trimIndent()
With this approach you don't have to use + , \n or escape anything; just please Enter to put the string in the next line.
trimIndent() to format multi-line strings - Detects a common minimal indent of all the input lines, removes it from every line and also removes the first and the last lines if they are blank (notice difference blank vs empty).
I'm trying to grab the first characters before a space.
I know it can be done this way
str = "3 Hello World"
str = Mid(str, 1,2)
But how would i do this after a space?
Edit: Looks like you changed your question to get characters BEFORE the first space instead of AFTER. I've updated my examples.
Here's one way:
strTextBeforeFirstSpace = Split(str, " ")(0)
Assuming a space exists in your string, this would return everything up until the first space.
Another way would be:
strTextBeforeFirstSpace = Left(str, InStr(str, " ") - 1)
You can get the index of the first space with the InStr function
InStr(str, " ")
And use this as a parameter in your Mid function
Dim str, index
str = "3 Hello World"
index = InStr(str," ")
'only neccessary if there is a space
If index > 0 Then
str = Mid(str,1,index - 1)
End If
I'm making a JSON parser and I am looking for an algorithm that can find all of the matching brackets ([]) and braces ({}) and put them into a table with the positions of the pair.
Examples of returned values:
table[x][firstPos][secondPos] = type
table[x] = {firstPos, secondPos, bracketType}
EDIT: Let parse() be the function that returns the bracket pairs. Let table be the value returned by the parse() function. Let codeString be the string containing the brackets that I want to detect. Let firstPos be the position of the first bracket in the Nth pair of brackets. Let secondPos be the position of the second bracket in the Nth pair of brackets. Let bracketType be the type of the bracket pair ("bracket" or "brace").
Example:
If you called:
table = parse(codeString)
table[N][firstPos][secondPos] would be equal to type.
Well, In plain Lua, you could do something like this, also taking into account nested brackets:
function bm(s)
local res ={}
if not s:match('%[') then
return s
end
for k in s:gmatch('%b[]') do
res[#res+1] = bm(k:sub(2,-2))
end
return res
end
Of course you can generalize this easy enough to braces, parentheses, whatever (do keep in mind the necessary escaping of [] in patterns , except behind the %b pattern).
If you're not restricted to plain Lua, you could use LPeg for more flexibility
If you are not looking for the contents of the brackets, but the locations, the recursive approach is harder to implement, since you should keep track of where you are. Easier is just walking through the string and match them while going:
function bm(s,i)
local res={}
res.par=res -- Root
local lev = 0
for loc=1,#s do
if s:sub(loc,loc) == '[' then
lev = lev+1
local t={par=res,start=loc,lev=lev} -- keep track of the parent
res[#res+1] = t -- Add to the parent
res = t -- make this the current working table
print('[',lev,loc)
elseif s:sub(loc,loc) == ']' then
lev = lev-1
if lev<0 then error('too many ]') end -- more closing than opening.
print(']',lev,loc)
res.stop=loc -- save bracket closing position
res = res.par -- revert to the parent.
end
end
return res
end
Now that you have all matched brackets, you can loop through the table, extracting all locations.
I figured out my own algorithm.
function string:findAll(query)
local firstSub = 1
local lastSub = #query
local result = {}
while lastSub <= #self do
if self:sub(firstSub, lastSub) == query then
result[#result + 1] = firstSub
end
firstSub = firstSub + 1
lastSub = lastSub + 1
end
return result
end
function string:findPair(openPos, openChar, closeChar)
local counter = 1
local closePos = openPos
while closePos <= #self do
closePos = closePos + 1
if self:sub(closePos, closePos) == openChar then
counter = counter + 1
elseif self:sub(closePos, closePos) == closeChar then
counter = counter - 1
end
if counter == 0 then
return closePos
end
end
return -1
end
function string:findBrackets(bracketType)
local openBracket = ""
local closeBracket = ""
local openBrackets = {}
local result = {}
if bracketType == "[]" then
openBracket = "["
closeBracket = "]"
elseif bracketType == "{}" then
openBracket = "{"
closeBracket = "}"
elseif bracketType == "()" then
openBracket = "("
closeBracket = ")"
elseif bracketType == "<>" then
openBracket = "<"
closeBracket = ">"
else
error("IllegalArgumentException: Invalid or unrecognized bracket type "..bracketType.."\nFunction: findBrackets()")
end
local openBrackets = self:findAll(openBracket)
if not openBrackets[1] then
return {}
end
for i, j in pairs(openBrackets) do
result[#result + 1] = {j, self:findPair(j, openBracket, closeBracket)}
end
return result
end
Will output:
5 14
6 13
7 12
8 11
9 10