How to implement command-line variables in Xtext - parsing

I want my Domain specific language (DSL) to accept command-line arguments as variables like in bash scripts. For example: A user might issue a command runMyDSL myDslFile.dsl -args 10 15 or runMyDSL myDslFile.dsl -nvargs arg1=10 arg2=15. I would like to capture these values into variables $1, $2 for first command or $arg1, $arg2 for second command. These variables can then be treated as any other read-only variables in my DSL:
val someVariable = $1
Since I am new to xtext/parser field, I am looking for best practices people follow for dealing with this situation. For simplicity, let's assume, I am only working on simplified DSL that does addition (based on Expression Language described in http://blog.efftinge.de/2010/08/parsing-expressions-with-xtext.html):
Expression : Variable '+' Variable;
Variable: ('val' ID '=' INT) | CommandLineVariable;
CommandLineVariable: ??;

My first idea for that would be the following:
1.) parse the DSL file and get access to the AST, store the refence in any locally definded variable of the corresponding EClass.
2.) Use the 'MyDslFactory' class to create a new 'Variable' instance, set a value, given by the command line and put it somewhere into the AST.
To do that you should define attribute names in you 'Variable' Parser Rule:
Variable: 'val' name=ID '=' value=INT;
'Variable' creation would look like this (more or less):
Variable newVar = MyDslFactory.eINSTANCE.createVariable();
newVar.setName(args[2].split("=")[0]);
newVar.setValue(new Integer(args[2].split("=")[1]));
Then you put it into the AST and with the modified AST you could either create a temporary DSL file which is then processed as before or you process the AST directly.

Related

lua - How to check if a word is in a string or it is just a word

So I am trying to make a language in lua, and I am replacing the word "output" with "print" and a few more words, but if someone does output("output") it also replaces it. How can i check if it is in a string?
Code:
output('trying to make a new language in lua')
output('\n')
local file = io.open(arg[1],"r")
local code = file:read "*a"
local filename = arg[1]
local function execute()
code = code:gsub("output","print")
code = code:gsub("void","function")
code = code:gsub("{}}","end")
local newfile = io.open(filename:gsub("idk","lua"),"w")
newfile:write(code)
newfile:close()
os.execute("lua test.lua")
end
execute()
Lua patterns are generally unsuitable to build a parser for a programming language; neither do they have the full expressive power of regular expressions required for tokenization (lexical analysis) nor do they get anywhere near the power of a context-free grammar (CFG, syntactical analysis) required for constructing the abstract syntax tree even though they provide some advanced features such as bracket matching which exceed regular expression capabilities.
As a beginner, you'll probably want to start with a handwritten tokenizer; as your language only operates at a token replacement level at this stage, you can simply replace identifier tokens.
You don't need string replacement (gsub) to implement variable renames like print to output when you are in control of how the script is executed: Just replace the global print variable with an output variable holding the print function (you may want to do this only in the environment the scripts written in your language run in):
output = print
print = nil

Erlang script assigning variables

I am trying to assign a pseudo-random number seed to a variable. However, after I tried to assign the stringified seed to the variable, Erlang gave me an error:
code.erl:1: syntax error before: Number
escript: There were compilation errors.
This question might seem a bit foolish, but I have absolutely no idea how to get it working. Here's the old script. (I didn't realize that you can't define global variables outside of functions...)
Number = "7316717653133062491922511".
main([]) -> io:fwrite(Number).
Here's the new script:
Number() -> "7316717653133062491922511".
main([]) -> io:fwrite(Number()).
In Erlang, function names start with a lower-case letter*, so this would work:
number() -> "7316717653133062491922511".
main([]) -> io:fwrite(number()).
There are no global variables; all variables must be assigned inside a function.
* Actually, a function name can contain any character if you single-quote it: 'Number'().
You can’t define global variables outside of functions as with Number in your first example.

FitNesse: Variable assignment and simple arithmetic

According to the user guide it is possible to assign values to variables and then perform simple arithmetic.
Imagine I have fixture designed to take an element on the page and extracting the numerical value as a Double (i do this now using the HSAC Slim BrowserTest fixture and my own code)
|script |numbers extraction |
|$testval1=|numeric value of |element1 | |
|$testval2=|numeric value of |element2 | |
Running this gives me something like:
|script |numbers extraction |
|$testval1<-[20.04]|numeric value of |element1 ->[€ 20,04] | |
|$testval2<-[5.1] |numeric value of |element2 ->[€ 5,1] | |
Now say I want to compare the sum of the two doubles with the numeric value of a third element:
|script|numbers extraction |
|check |numeric value of |element3|{=${ ${testval1} + ${testval2} =}|
No matter what combination of parentheses and dollar-signs I use in the last cell, I always get 'invalid expression'.
${= $testval1 + $testval2 =} invalid expression: $testval1 + $testval2
{${=$testval1 + $testval2 =}} {invalid expression: $testval1 + $testval2}
${=${testval1} + ${testval2} =} [invalid expression: undefined variable: testval1 + undefined variable: testval2]
${= !-$testval1-! + !-$testval2-! =} invalid expression: $testval1 + $testval2
${= !-${testval1}-! + !-${testval2}-! =} invalid expression: ${testval1} + ${testval2}
Running the last line (without parenthesis around testval1 and testval2) returns:
|check|numeric value of|element3 ->[€ 25.14]| [25.14] expected [invalid expression: $testval1->[20.04] + $testval2->[5.1]] |
Unfortunately you can can't do what you are looking for. The variables you assign the value of the elements to are actually SLIM symbols, and not variables at the wiki level. If you scroll a bit down on the user guide page you linked to in the question you will find a section called "Difference between variables and SLIM symbols":
Variables are evaluated at render time, before the test executes. This allows for values to be set based on page hierarchy and other things that are purely inputs to the tests.
Symbols only exist at execution time. They can be changed at runtime, so are distinct from variables, which cannot.
I find the three types of variables in FitNesse/SLIM are confusing to people and their different usage, syntax and possibilities cause many issues. My understanding is:
Markup variables (aka wiki variables). For instance ${myVar}, defined using !define. They get their value at page render time, so even before a test is started, so you see their value when you browse to a wiki page, and only in the page's source do you see it is a variable. These can be used in markup expressions, which is what you are trying to do in the question.
Scenario parameters. For instance #{myVar} (or #myVar), defined in the first row of a SLIM scenario table. These are the 'formal parameters' to the scenario, which get their actual value based on the invocation of the scenario (i.e. each usage of the scenario, either from a script table, other scenario or row in a decision table defines their value). They get their value at the start of a test, before its first action is performed. You see the variable when you look at the scenario table that defines it. (When you use the 'table template' table type defined by hsac-fitnesse-plugin (which is included in hsac-fitnesse-fixtures project baseline) you don't need to define the variable names in the first row of the table, they are automatically found based on their occurrence (e.g. #{myVar}) inside the table.)
SLIM symbols. For instance $myVar, they are assigned their value using $myVar=. These are 'runtime variables' that get their value during test execution, they are global to a test suite and their value might be changed during test execution. These are the only kind of variables that can get their value from a property obtained from the 'system under test', and they are the variables you are using in your question's tables. They are actually references to objects inside the SLIM process so fixtures might change the internal state of the object the variable refers to, without this change showing in the wiki representation of the variable (which is just the object's toString() result at time of last assignment).
P.S. The conversion of a string to a double does not require a custom fixture (like your numbers extraction) when you using the hsac-fitnesse-fixtures. You could just use the convert to double method of the library's string fixture.
You seem to be using browser test, this is an HSAC installation I take it? Please mention this in the question as HSAC is a FitNesse fixture.
Anyway, removing the curly brackets should do the trick. With curly brackets it is expecting a global variable, those that are implemented using !define var {foo}
When using variables that are locally defined such as with |$bar=|value of|foo| have to be called in the test using the variable without curly brackets.
|$bar=|value of|foo|
|enter|$bar|as|inputField|
Find more stuff on HSAC usage here: https://github.com/fhoeben/hsac-fitnesse-fixtures/wiki/2.-Slim-Fixtures
Sidenote:
Then there are also table templates that use #var or #{var}, where the use of #{var} is preferred because #{var} will look for the column var and #var will accept a column v or va, if you happen to implement that. Using curly brackets here ensures the full variable name is used.

Lua heredoc with variable interpolation?

Is there a way to use a heredoc type of notation in Lua that references variables within the string?
The basic idea of what I'm trying to do would look something like follows. The heredoc piece is fine, but within Lua you can't actually reference the variable in the manner I'm showing below.
username = "bigtunacan"
sql=[=[
SELECT * FROM users WHERE username='$bigtunacan';
]=]
There's no built-in string interpolation, but it can be trivially implemented with gsub and replacement table.
sql=[=[
SELECT * FROM users WHERE username='$username';
]=]
print((sql:gsub('$(%w+)', { username = 'bigtucan' })))
-- SELECT * FROM users WHERE username='bigtucan';
Note an extra set of () - this is so only first return - the interpolated string is used from gsub and the 2nd - number of replacements made - silently discarded. This might be important if you use result of gsub as last in list of arguments to some function where adding one more argument might produce different behavior.
Also if you want to use this in SQL context, you really should use placeholders instead.
There is no Lua construct that allows variable interpolation within any string. See Literal Strings in the official reference guide.
You could of course write a function that would parse it and do the substitutions.

AntlrWorks 2 output

So i am using Antlrworks 2, working on a rather large grammar. Problem is that in this grammar there are multiple ambiguities that i am trying to work through.
I was wondering if there is a way to interpret which rules were invoked when there was a failure.
For instance, when i run my rule i get following output
[#0,0:1='99',<20>,1:0]
[#1,2:1='<EOF>',<-1>,1:2]
line 1:0 mismatched input '99' expecting Digit2
(dummy 99)
I am wondering what [#0,0:1='99',<20>,1:0] means. Do the #0 or <20> have any relationship to the rule number in my grammar or something ?
Here is a breakdown of the default token formatting.
[#{TokenIndex},{StartIndex}:{StopIndex}={Text},<{TokenType}>,{Line}:{Column}]
The {TokenType} field generally corresponds to a particular lexer rule (the constant will be declared in your generated lexer). However, the -> type(X) command can be used in any lexer rule to reassign tokens produced by that rule to another type. If the value 20 is assigned to the token named Foo, then the first token in your listing was produced by either a lexer rule named Foo or a lexer rule containing the action -> type(foo) or you have a user-defined action which explicitly assigns the type Foo to a token produced by some other rule (this will be code you wrote, not code generated by ANTLR).

Resources