DXL to truncate Object number - ibm-doors

I inherited some DXL code to truncate the Object Number to exclude the last “0”
This works fine for paragraphs numbers less than 10 (or a double digit number). I’ll admit to be new to DXL, but this code stumps me as I am not familiar with RegExp. I know that those on this forum will look at this and get the answer and I will then learn and move forward.
Here is the code:
string s = number(obj)
Regexp paraNumExp = regexp2 "[0-9](\\.[0-9])*"
if(paraNumExp s) obj.attrDXLName = s[match 0]
delete paraNumExp
This is what is produces:
AbsNum, ObjNumber, DXL Attribute
Here is the DXL code for the attached file (output from the test module)
(DXL) Paragraph Number 1
string s = number(obj)
Regexp paraNumExp = regexp2 "[1-9](\\.[1-9])*"
if(paraNumExp s) obj.attrDXLName = s[match 0]
delete paraNumExp
(DXL) Paragraph Number 2
string s = number(obj)
Regexp paraNumExp = regexp2 "^[0-9]+\\.[0-9]+"
if(paraNumExp s) obj.attrDXLName = s[match 0]
delete paraNumExp
(DXL) Paragraph Number 4
Regexp reZero = regexp2 "(\\.0)-"
string s = number(obj)
if (reZero s) {
obj.attrDXLName = s[0:start 1-1]
}
delete reZero
DOORS output with what I want

Not super sure, what you are trying to accomplish, or what is the deeper problem here. But to answer your question for "truncating the pending zeros", I would suggest to use "start" and "end" methods here, e.g.:
Regexp reZero = regexp2 "(\\.0)-"
Module m = current
filtering off
Object o
for o in m do {
string strON = number( o )
string strTruncated = strON
if (reZero strON) {
strTruncated = strON[0:start 1-1] "" strON[end 1+1:]
}
print "" identifier( o ) ": " strON " => '" strTruncated "'\n"
}

With your help and a little bugging of a colleague, I got the results I need.
This is the DXL code:
// Define reZero to detect ".0-"
Regexp reZero = regexp2 "(\\.0)-"
// Get the Object Number
string s = number(obj)
if (reZero s) {
// Found ".0-"? Strip off ".0-" and all following that string
obj.attrDXLName = s[0:start 1-1]
} else {
// Did not find ".0-". Use complete object number.
obj.attrDXLName = s
}
delete reZero

Related

Trying to make function which takes string as input and returns no. of words in whole string

**It takes Input as a string such as this - 'Nice one'
And Output gives - 4,3 (which is no. Of words in sentence or string)
**
function countx(str)
local count = {}
for i = 1, string.len(str) do
s = ''
while (i<=string.len(str) and string.sub(str, i, i) ~= ' ' ) do
s = s .. string.sub(str, i, i)
i = i+1
end
if (string.len(s)>0) then
table.insert(count,string.len(s))
end
end
return table.concat(count, ',')
end
You can find a simple alternative with your new requirements:
function CountWordLength (String)
local Results = { }
local Continue = true
local Position = 1
local SpacePosition
while Continue do
SpacePosition = string.find(String, " ", Position)
if SpacePosition then
Results[#Results + 1] = SpacePosition - Position
Position = SpacePosition + 1
-- if needed to print the string
-- local SubString = String:sub(Position, SpacePosition)
-- print(SubString)
else
Continue = false
end
end
Results[#Results + 1] = #String - Position + 1
return Results
end
Results = CountWordLength('I am a boy')
for Index, Value in ipairs(Results) do
print(Value)
end
Which gives the following results:
1
2
1
3
def countLenWords(s):
s=s.split(" ")
s=map(len,s)
s=map(str,s)
s=list(s)
return s
The above functions returns a list containing number of characters in each word
s=s.split(" ") splits string with delimiter " " (space)
s=map(len,s) maps the words into length of the words in int
s=map(str,s) maps the values into string
s=list(s) converts map object to list
Short version of above function (all in one line)
def countLenWords(s):
return list(map(str,map(len,s.split(" "))))
-- Localise for performance.
local insert = table.insert
local text = 'I am a poor boy straight. I do not need sympathy'
local function word_lengths (text)
local lengths = {}
for word in text:gmatch '[%l%u]+' do
insert (lengths, word:len())
end
return lengths
end
print ('{' .. table.concat (word_lengths (text), ', ') .. '}')
gmatch returns an iterator over matches of a pattern in a string.
[%l%u]+ is a Lua regular expression (see http://lua-users.org/wiki/PatternsTutorial) matching at least one lowercase or uppercase letter:
[] is a character class: a set of characters. It matches anything inside brackets, e.g. [ab] will match both a and b,
%l is any lowercase Latin letter,
%u is any uppercase Latin letter,
+ means one or more repeats.
Therefore, text:gmatch '[%l%u]+' will return an iterator that will produce words, consisting of Latin letters, one by one, until text is over. This iterator is used in generic for (see https://www.lua.org/pil/4.3.5.html); and on any iteration word will contain a full match of the regular expression.

How to copy one line from one attribute to another attribute in DOORs

I'm trying to copy a line from DOORS one attribute and write that line into another attribute in DOORS.
more or less straight from the DXL manual
Object o = current // might be set in a loop
Regexp line = regexp2 ".*"
string sTextValue = o."Object Text"""
string sLastLine = ""
while (!null sTextValue && line sTextValue) {
sLastLine = sTextValue[match 0]
sTextValue = sTextValue [end 0 + 2:]
}
print "->" sLastLine "<-\n"
o."Other Attribute" = sLastLine

Lua: replace a substring

I have something like
str = "What a wonderful string //011// this is"
I have to replace the //011// with something like convertToRoman(011) and then get
str = "What a wonderful string XI this is"
However, the conversion into roman numbers is no problem here.
It is also possible that the string str didn't has a //...//. In this case it should simply return the same string.
function convertSTR(str)
if not string.find(str,"//") then
return str
else
replace //...// with convertToRoman(...)
end
return str
end
I know that I can use string.find to get the complete \\...\\ sequence. Is there an easier solution with pattern matching or something similiar?
string.gsub accepts a function as a replacement. So, this should work
new = str:gsub("//(.-)//", convertToRoman)
I like LPEG, therefore here is a solution with LPEG:
local lpeg = require"lpeg"
local C, Ct, P, R = lpeg.C, lpeg.Ct, lpeg.P, lpeg.R
local convert = function(x)
return "ROMAN"
end
local slashed = P"//" * (R("09")^1 / convert) * P"//"
local other = C((1 - slashed)^0)
local grammar = Ct(other * (slashed * other)^0)
print(table.concat(grammar:match("What a wonderful string //011// this is"),""))

LPeg Increment for Each Match

I'm making a serialization library for Lua, and I'm using LPeg to parse the string. I've got K/V pairs working (with the key explicitly named), but now I'm going to add auto-indexing.
It'll work like so:
#"value"
#"value2"
Will evaluate to
{
[1] = "value"
[2] = "value2"
}
I've already got the value matching working (strings, tables, numbers, and Booleans all work perfectly), so I don't need help with that; what I'm looking for is the indexing. For each match of #[value pattern], it should capture the number of #[value pattern]'s found - in other words, I can match a sequence of values ("#"value1" #"value2") but I don't know how to assign them indexes according to the number of matches. If that's not clear enough, just comment and I'll attempt to explain it better.
Here's something of what my current pattern looks like (using compressed notation):
local process = {} -- Process a captured value
process.number = tonumber
process.string = function(s) return s:sub(2, -2) end -- Strip of opening and closing tags
process.boolean = function(s) if s == "true" then return true else return false end
number = [decimal number, scientific notation] / process.number
string = [double or single quoted string, supports escaped quotation characters] / process.string
boolean = P("true") + "false" / process.boolean
table = [balanced brackets] / [parse the table]
type = number + string + boolean + table
at_notation = (P("#") * whitespace * type) / [creates a table that includes the key and value]
As you can see in the last line of code, I've got a function that does this:
k,v matched in the pattern
-- turns into --
{k, v}
-- which is then added into an "entry table" (I loop through it and add it into the return table)
Based on what you've described so far, you should be able to accomplish this using a simple capture and table capture.
Here's a simplified example I knocked up to illustrate:
lpeg = require 'lpeg'
l = lpeg.locale(lpeg)
whitesp = l.space ^ 0
bool_val = (l.P "true" + "false") / function (s) return s == "true" end
num_val = l.digit ^ 1 / tonumber
string_val = '"' * l.C(l.alnum ^ 1) * '"'
val = bool_val + num_val + string_val
at_notation = l.Ct( (l.P "#" * whitesp * val * whitesp) ^ 0 )
local testdata = [[
#"value1"
#42
# "value2"
#true
]]
local res = l.match(at_notation, testdata)
The match returns a table containing the contents:
{
[1] = "value1",
[2] = 42,
[3] = "value2",
[4] = true
}

VBA parsing of numeric ranges from string

I need to parse numeric range from User Form (VBA, Excel).
For example: {1-3,5,9} -> {1,2,3,5,9,}
The question has already been discussed here:
Advanced parsing of numeric ranges from string
The task is quite standart, is there any ready-made solution for VBA?
I am assuming that the encompassing braces are not part of the string. Consider the following UDF:
Public Function DashFiller(sIn As String) As String
Dim N As Long, NN As Long
DashFiller = ""
ary = Split(sIn, ",")
For N = LBound(ary) To UBound(ary)
If InStr(1, ary(N), "-") > 0 Then
ary2 = Split(ary(N), "-")
ary(N) = ary2(0)
For NN = ary2(0) + 1 To ary2(1)
ary(N) = ary(N) & "," & NN
Next NN
End If
Next N
DashFiller = Join(ary, ",")
End Function
So if A1 contains:
1-2,3,4,5,9-12
and B1 contains:
=DashFiller(A1)
then B1 would display:
1,2,3,4,5,9,10,11,12

Resources