I came up with this grammar that manages to sucessfully add/sub numbers in brackets and whatnot. However I find it very difficult to expand it for pow(^) and root(#) logic. I am grateful for any help as Im hardstuck now...
nonZeroDigit = "1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9";
digit = "0" | nonZeroDigit;
naturalNumber = nonZeroDigit , {digit};
secondPriorityOperators= "+" |"-";
firstPriorityOperators= "*" | "/";
syntax=expr;
expr=term, {secondPriorityOperators, term};
term=factor, {firstPriorityOperators, factor};
factor="(", expr , ")" | naturalNumber;
root = "#" , root | factor;
power = root, "^" , power| root;
For testing I used this site: https://planetcalc.com/6385/
Simply add another priority level:
thirdPriorityOperators= "+" |"-";
secondPriorityOperators= "*" | "/";
firstPriorityOperators= "#" | "^";
term3rd=term2nd, {thirdPriorityOperators, term2nd};
term2nd=term1st, {secondPriorityOperators, term1st};
term1st=factor, {firstPriorityOperators, factor};
Related
This is an example output:
/usr/local/bin/node /usr/local/bin/elm-make src/elm/Main.elm --output=builds/main.js
-- TYPE MISMATCH ---------------------------------------------- src/elm/Main.elm
The type annotation for `init` does not match its definition.
35| init : Maybe Route.Location -> ( Model, Cmd Msg )
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The type annotation is saying:
Maybe Route.Location -> ( { route : Maybe Route.Location }, Cmd Msg )
But I am inferring that the definition has this type:
Maybe Route.Location
-> ( { route : Maybe Route.Location -> Route.Model }, Cmd a )
Detected errors in 1 module.
Process finished with exit code 1
This is the regex that i came up with:
http://regexr.com/3egqu
However, creating output filter out of it like this:
doesn't work.
Thus far, I only know that the following works: ------ ($FILE_PATH$)
And it turns the file path into a link:
Help me find a way to include the line numbers into the links.
Here's what I've come up with;
First,
elm-make --report json
outputs the build errors in structured JSON;
$ elm-make --report json src/main.elm
[{"tag":"unused import","overview":"Module `Bootstrap.CDN` is unused.","details":"Best to remove it. Don't save code quality for later!","region":{"start":{"line":3,"column":1},"end":{"line":3,"column":28}},"type":"warning","file":"src/main.elm"}]
Now you can pipe that output through jq (see here). to reformat it into
elm make src/main.elm --report json --output ./public/app.js | \
jq '.[] | { type: .type, file: .file, line: .region.start.line|tostring, tag: .tag, column: .region.start.column|tostring, tag: .tag, details: .details }' | \
jq --raw-output '. | "[" + (.type|ascii_upcase) + "] " + .file + ":" + .line + ":" + .column + " " + .tag + " -- " + .details + "\n"'
that gives you a reformatted output;
[WARNING] src/main.elm:9:1 unused import -- Best to remove it. Don't save code quality for later!
[WARNING] src/main.elm:17:1 missing type annotation -- I inferred the type annotation so you can copy it into your code:
main : Program Never Model Main.Msg
Which you pick up in intellij using the format
$FILE_PATH$:$LINE$:$COLUMN$ $MESSAGE$
You then get to click on an error message to jump to the file, and the error text in a tooltip.
I am working on an arduino uno + supercollider 3 project.
Basicly: I have an arduino set up with potentiometers, a sensor and some buttons. I put the data of inputs in an array and send it to my computer trough serial.
Currently, my output in the Arduino serial monitor is as this:
271:189:75:0:0:0:1:0:0:0:0:0
If I open the serial connection in Supercollider, what arrives is this:
271
Only the first value in the array arrives correctly. (The same setup with just 1 Arduino input to Supercollider worked like a charm, by the way. I just can't get it working with an array of inputs from arduino to SC3.)
arduino code to send data at this moment:
teSturen = String(val_lichtPin) + ":" + String(val_Pot1Pin) + ":" + String(val_Pot2Pin) + ":" + String(val_Pot3Pin) + ":" + String(val_Pot4Pin) + ":" + String(val_Pot5Pin) + ":" + String(knop1Staat) + ":" + String(knop2Staat) + ":" + String(knop3Staat) + ":" + String(knop4Staat) + ":" + String(knop5Staat) + ":" + String(knop6Staat);
Serial.println(String(teSturen));
I put all the numbers together in one string with an : as seperator, then send this.
SC3 code to receive:
~ino = ArduinoSMS("/dev/ttyACM0",9600);
~ino.action = {
arg msg;
var amsg;
//amsg = msg.split($:);
msg.postln;
};
There is more code, but that is for appointing vars and args, defining synths, et cetera. I limited this to the bits where it doesn't work.
Any ideas on why SC3 only receives the first number? I have tried for example to recplace the seperator : by , or ;, to send it as multiple integers in stead of one string, ...
The goal of it for me, is to be able to control various synths in supercollider with fysical control potentiometers, because that's a lot more fun to play with than keyboard or mouse controlling synths...
I appreciate any help, thank you!
Pretty late, but this still might help. I used the same setup some years ago. I used
p = ArduinoSMS("/dev/tty.usbmodem3d11", 115200);
while{state==0}{
p.action = { |... msg| m=[msg[0],msg[1]];
do something with m[0] and m[1] ...
};
to parse the message stream. My setup only read arrays of two bytes (msg[0]and msg[1]), but this should be expandable.
The full source code is available on https://github.com/symbolrush/FridgeKiller and another project with the same setup on https://github.com/symbolrush/ColliDuino.
Hope this helps and good luck!
I'm writing an LPeg-based parser. How can I make it so a parsing error returns nil, errmsg?
I know I can use error(), but as far as I know that creates a normal error, not nil, errmsg.
The code is pretty long, but the relevant part is this:
local eof = lpeg.P(-1)
local nl = (lpeg.P "\r")^-1 * lpeg.P "\n" + lpeg.P "\\n" + eof -- \r for winblows compat
local nlnoeof = (lpeg.P "\r")^-1 * lpeg.P "\n" + lpeg.P "\\n"
local ws = lpeg.S(" \t")
local inlineComment = lpeg.P("`") * (1 - (lpeg.S("`") + nl * nl)) ^ 0 * lpeg.P("`")
local wsc = ws + inlineComment -- comments count as whitespace
local backslashEscaped
= lpeg.P("\\ ") / " " -- escaped spaces
+ lpeg.P("\\\\") / "\\" -- escaped escape character
+ lpeg.P("\\#") / "#"
+ lpeg.P("\\>") / ">"
+ lpeg.P("\\`") / "`"
+ lpeg.P("\\n") -- \\n newlines count as backslash escaped
+ lpeg.P("\\") * lpeg.P(function(_, i)
error("Unknown backslash escape at position " .. i) -- this error() is what I wanna get rid of.
end)
local Line = lpeg.C((wsc + (backslashEscaped + 1 - nl))^0) / function(x) return x end * nl * lpeg.Cp()
I want Line:match(...) to return nil, errmsg when there's an invalid escape.
LPeg itself doesn't provide specific functions to help you with error reporting. A quick fix to your problem would be to make a protected call (pcall) to match like this:
local function parse(text)
local ok, result = pcall(function () return Line:match(text) end)
if ok then
return result
else
-- `result` will contain the error thrown. If it is a string
-- Lua will add additional information to it (filename and line number).
-- If you do not want this, throw a table instead like `{ msg = "error" }`
-- and access the message using `result.msg`
return nil, result
end
end
However, this will also catch any other error, which you probably don't want. A better solution would be to use LPegLabel instead. LPegLabel is an extension of LPeg that adds support for labeled failures. Just replace require"lpeg" with require"lpeglabel" and then use lpeg.T(L) to throw labels where L is an integer from 1-255 (0 is used for regular PEG failures).
local unknown_escape = 1
local backslashEscaped = ... + lpeg.P("\\") * lpeg.T(unknown_escape)
Now Line:match(...) will return nil, label, suffix if there is a label thrown (suffix is the remaining unprocessed input, which you can use to compute for the error position via its length). With this, you can print out the appropriate error message based on the label. For more complex grammars, you would probably want a more systematic way of mapping the error labels and messages. Please check the documentation found in the readme of the LPegLabel repository to see examples of how one may do so.
LPegLabel also allows you to catch the labels in the grammar by the way (via labeled choice); this is useful for implementing things like error recovery. For more information on labeled failures and examples, please check the documentation.
I am using FeatureBNF (and so in essence I am using JavaCC) to try and write a grammar that will produce a (very) simple parser to parse Gherkin files.
An example Gherkin file:
Feature: Calculator
In order to avoid silly mistakes
As a math idiot
I want to be told the sum of two numbers
Scenario: Add two numbers
Given I have entered 50 into the calculator
And I have also entered 70 into the calculator
When I press add
Then the result should be 120 on the screen
All I want to do, to begin with, is parse this into a Feature that has the name Calculator and a Body, which is the entirety of the rest of the file.
I have struggled with the part where I'm trying to read the rest of the file into the Body however. I think maybe partially because there is no 'natural' delimiters for when one section ends - it's denoted by a newline.
Trying the following grammar:
<DEFAULT> TOKEN :
{
<FEATURE: "Feature: " >
| <#LETTER: ["\u0027","\u0041"-"\u005a","\u005f","\u0061"-"\u007a"] >
| <FEATURE_NAME: (<LETTER>)+ >
| <NEWLINE: ("\r\n" | "\n\r" | "\r" | "\n") >
| <TEXT : ~[] >
}
GRAMMARSTART
Feature :
<FEATURE> FeatureName <NEWLINE>
Body
<EOF>
;
FeatureName: <FEATURE_NAME>;
Body: (<TEXT>)*;
I get the error:
[java] java.lang.reflect.InvocationTargetException
... lots of stack trace removed...
[java] Caused by: cide.gparser.ParseException: Encountered "\r\n" (5) at line 2, column 1.
[java] Was expecting one of:
[java] <EOF>
[java] <TEXT> ...
I have been able to achieve what I want by adding some delimiters in to the Gherkin file and using lexical states, like so:
Feature: Calculator #TITLEEND
#BODYSTART
In order to avoid silly mistakes
As a math idiot
I want to be told the sum of two numbers
Scenario: Add two numbers
Given I have entered 50 into the calculator
And I have also entered 70 into the calculator
When I press add
Then the result should be 120 on the screen
#BODYEND
With the following relevant parts of the grammar:
<DEFAULT, IN_BODY> SPECIAL_TOKEN : {
" " | "\t" | "\n" | "\r" | "\f"
}
<DEFAULT> TOKEN : {
<FEATURE: "Feature: " >
| <#LETTER: ["\u0027", "\u0041"-"\u005a", "\u005f", "\u0061"-"\u007a"] >
| <FEATURE_NAME: (<LETTER>)+ >
| <ENDFEATURETITLE: "#TITLEEND" >
}
<DEFAULT> TOKEN : { <BODYSTART : "#BODYSTART"> : IN_BODY }
<IN_BODY> TOKEN : { <TEXT : ~[] > }
<IN_BODY> TOKEN : { <BODYEND : "#BODYEND"> : DEFAULT }
GRAMMARSTART
Feature:
<FEATURE> FeatureName <ENDFEATURETITLE>
Body
<EOF>;
FeatureName: <FEATURE_NAME>;
Body: <BODYSTART> Text <BODYEND>;
Text: (<TEXT>)*;
But I am sure I must be missing something and would like to be able to achieve this without having to annotate the feature files. What is a better way to do this?
SIDE NOTE
FeatureBNF builds on top of JavaCC and outputs a grammar file for JavaCC to process. I am completely new to both FeatureBNF and JavaCC, but they seem similar enough that I hope this question might be applicable to JavaCC gurus. (FeatureBNF uses JavaCC syntax for the lexical specifications and then its own format for the grammar's production rules.)
Based on your grammar, you can switch states after the first newline, so the following lexical grammar will suffice:
<DEFAULT> TOKEN : {
<FEATURE: "Feature: " >
| <#LETTER: ["\u0027", "\u0041"-"\u005a", "\u005f", "\u0061"-"\u007a"] >
| <FEATURE_NAME: (<LETTER>)+ >
| <ENDFEATURETITLE: "#TITLEEND" >
| <NEWLINE: ("\r\n" | "\n\r" | "\r" | "\n") > : IN_BODY
}
<IN_BODY> TOKEN : { <TEXT : ~[] > }
Now the syntactic grammar is
Feature:
<FEATURE> FeatureName <NEWLINE>
Body
<EOF>;
FeatureName: <FEATURE_NAME>;
Body: (<TEXT>)*;
I have the following grammar:
rule : (PATH)=> (PATH) SLASH WORD
{System.out.println("file: " + $WORD.text + " path: " + $PATH.text);};
WORD : ('a'..'z')+;
SLASH : '/';
PATH : (WORD SLASH)* WORD;
but it does not work for a string like "a/b/c/filename".
I thought I could solve this "path"-problem with the syntactic predicate feature. Maybe I am doing something wrong here and I have to redefine the grammar. Any suggestion for this problem?
You must understand that a syntactic predicate will not cause the parser to give the lexer some sort of direction w.r.t. what token the parser would "like" to retrieve. A syntactic predicate is used to force the parser to look ahead in an existing token stream to resolve ambiguities (emphasis on 'existing': the parser has no control over what token are created!).
The lexer operates independently from the parser, creating tokens in a systematic way:
it tries to match as much characters as possible;
whenever 2 (or more) rules match the same amount of characters, the rule defined first will get precedence over the rule(s) defined later.
So in your case, given the input "a/b/c/filename", the lexer will greedily match the entire input as a single PATH token.
If you want to get the file name, either retrieve it from the PATH:
rule : PATH
{
String file = $PATH.text.substring($PATH.text.lastIndexOf('/') + 1);
System.out.println("file: " + file + ", path: " + $PATH.text);
}
;
WORD : ('a'..'z')+;
SLASH : '/';
PATH : (WORD SLASH)* WORD;
or create a parser rule that matches a path:
rule : dir WORD
{
System.out.println("file: " + $WORD.text + ", dir: " + $dir.text);
}
;
dir : (WORD SLASH)+;
WORD : ('a'..'z')+;
SLASH : '/';