Swift3 : how to handle precedencegroup now operator should be declare with a body?
As per SE-0077, the precedence of an operator is no longer determined by a magic number – instead you now use the higherThan
and (if the group resides in another module) lowerThan
precedencegroup
relationships in order to define precedence relative to other groups.
For example (from the evolution proposal):
// module Swift
precedencegroup Additive { higherThan: Range }
precedencegroup Multiplicative { higherThan: Additive }
// module A
precedencegroup Equivalence {
higherThan: Comparative
lowerThan: Additive // possible, because Additive lies in another module
}
infix operator ~ : Equivalence
1 + 2 ~ 3 // same as (1 + 2) ~ 3, because Additive > Equivalence
1 * 2 ~ 3 // same as (1 * 2) ~ 3, because Multiplicative > Additive > Equivalence
1 < 2 ~ 3 // same as 1 < (2 ~ 3), because Equivalence > Comparative
1 += 2 ~ 3 // same as 1 += (2 ~ 3), because Equivalence > Comparative > Assignment
1 ... 2 ~ 3 // error, because Range and Equivalence are unrelated
Although in your case, as it appears that your operator is used for multiplication, you could simply use the standard library's MultiplicationPrecedence
group, which is used for the *
operator:
infix operator × : MultiplicationPrecedence
It is defined as:
precedencegroup MultiplicationPrecedence {
associativity: left
higherThan: AdditionPrecedence
}
For a full list of standard library precedence groups, as well as more info about this change, see the evolution proposal.
How to declare exponent/power operator with new precedencegroup in Swift 3?
Your code already compiles and runs – you don't need to define a precedence relationship or an associativity if you're simply using the operator in isolation, such as in the example you gave:
10 ^^ -12
10 ^^ -24
However, if you want to work with other operators, as well as chaining together multiple exponents, you'll want to define a precedence relationship that's higher than the MultiplicationPrecedence
and a right associativity.
precedencegroup ExponentiativePrecedence {
associativity: right
higherThan: MultiplicationPrecedence
}
Therefore the following expression:
let x = 2 + 10 * 5 ^^ 2 ^^ 3
will be evaluated as:
let x = 2 + (10 * (5 ^^ (2 ^^ 3)))
// ^^ ^^ ^^--- Right associativity
// || \--------- ExponentiativePrecedence > MultiplicationPrecedence
// \--------------- MultiplicationPrecedence > AdditionPrecedence,
// as defined by the standard library
The full list of standard library precedence groups is available on the evolution proposal.
Swift - how to create custom operators to use in other modules?
I can confirm that that what you are seeing is what really happens. I just tried it myself and I've seen the same result.
My opinion is that >>=
is somehow conflicting with some other operator (probably the bite shift operator: >>
) or is being declared somewhere else too (you can see why I think that here). I did successfully declared custom operators in a framework and used those in the main app code before (you can see that here for example).
What I would suggest is rename your custom operator to something else. When I did that (renamed the custom operator to >>>=
) the compiler stopped complaining and my app compiled just fine.
Later edit
Ok. So this might help a bit more. Basically when an operator is already declared and you want to add extra functionality to that operator (for example doing things like 3 * "Hello"
like Johan Kool said he wanted to) all you have to do is overload that operator's method.
Basically, in your specific case I am now 100% that >>=
is an already declared operator and you can go ahead and just add these lines in your framework:
public func >>=<A, B>(a: A?, f: A -> B?) -> B? {
if let a = a { return f(a) }
else { return .None }
}
This will make your operator work. BUT it will inherit the precedence and associativity of the original operator thus giving you less control over how it's supposed to behave.
Why must a protocol operator be implemented as a global function?
UPDATE
From the Xcode 8 beta 4 release notes:
Operators can be defined within types or extensions thereof. For example:
struct Foo: Equatable {
let value: Int
static func ==(lhs: Foo, rhs: Foo) -> Bool {
return lhs.value == rhs.value
}
}
Such operators must be declared as
static
(or, within a class,class final
), and have the same
signature as their global counterparts. As part of this change, operator requirements declared in
protocols must also be explicitly declaredstatic
:protocol Equatable {
static func ==(lhs: Self, rhs: Self) -> Bool
}
ORIGINAL
This was discussed on the swift-evolution list recently (2016-01-31 through 2016-02-09 so far). Here's what Chris Lattner said, regarding declaring operators in a struct or class scope:
Yep, this is a generally desirable feature (at least for symmetric operators). This would also be great to get dynamic dispatch of operators within class declarations. I don’t think we have a firm proposal nailing down how name lookup works with this though.
And later (replying to Haravikk):
What are the name lookup issues? Do you mean cases where an operator for Foo == Foo exists in more than one location?
Yes. Name lookup has to have a well defined search order, which
defines shadowing and invalid multiple definition rules.Personally I’d just stick with what we have now, i.e- treat operator implementations within a specific class/struct as being globally
defined anyway and throw an error if the same signature is declared
more than once.
We need multiple modules to be able to define instances of an
operator, we need operators in extensions, and we need retroactive
conformance to work, as with any other member.
Equation (expression) parser with precedence?
The hard way
You want a recursive descent parser.
To get precedence you need to think recursively, for example, using your sample string,
1+11*5
to do this manually, you would have to read the 1
, then see the plus and start a whole new recursive parse "session" starting with 11
... and make sure to parse the 11 * 5
into its own factor, yielding a parse tree with 1 + (11 * 5)
.
This all feels so painful even to attempt to explain, especially with the added powerlessness of C. See, after parsing the 11, if the * was actually a + instead, you would have to abandon the attempt at making a term and instead parse the 11
itself as a factor. My head is already exploding. It's possible with the recursive decent strategy, but there is a better way...
The easy (right) way
If you use a GPL tool like Bison, you probably don't need to worry about licensing issues since the C code generated by bison is not covered by the GPL (IANAL but I'm pretty sure GPL tools don't force the GPL on generated code/binaries; for example Apple compiles code like say, Aperture with GCC and they sell it without having to GPL said code).
Download Bison (or something equivalent, ANTLR, etc.).
There is usually some sample code that you can just run bison on and get your desired C code that demonstrates this four function calculator:
http://www.gnu.org/software/bison/manual/html_node/Infix-Calc.html
Look at the generated code, and see that this is not as easy as it sounds. Also, the advantages of using a tool like Bison are 1) you learn something (especially if you read the Dragon book and learn about grammars), 2) you avoid NIH trying to reinvent the wheel. With a real parser-generator tool, you actually have a hope at scaling up later, showing other people you know that parsers are the domain of parsing tools.
Update:
People here have offered much sound advice. My only warning against skipping the parsing tools or just using the Shunting Yard algorithm or a hand rolled recursive decent parser is that little toy languages1 may someday turn into big actual languages with functions (sin, cos, log) and variables, conditions and for loops.
Flex/Bison may very well be overkill for a small, simple interpreter, but a one off parser+evaluator may cause trouble down the line when changes need to be made or features need to be added. Your situation will vary and you will need to use your judgement; just don't punish other people for your sins [2] and build a less than adequate tool.
My favorite tool for parsing
The best tool in the world for the job is the Parsec library (for recursive decent parsers) which comes with the programming language Haskell. It looks a lot like BNF, or like some specialized tool or domain specific language for parsing (sample code [3]), but it is in fact just a regular library in Haskell, meaning that it compiles in the same build step as the rest of your Haskell code, and you can write arbitrary Haskell code and call that within your parser, and you can mix and match other libraries all in the same code. (Embedding a parsing language like this in a language other than Haskell results in loads of syntactic cruft, by the way. I did this in C# and it works quite well but it is not so pretty and succinct.)
Notes:
1 Richard Stallman says, in Why you should not use Tcl
The principal lesson of Emacs is that
a language for extensions should not
be a mere "extension language". It
should be a real programming language,
designed for writing and maintaining
substantial programs. Because people
will want to do that!
[2] Yes, I am forever scarred from using that "language".
Also note that when I submitted this entry, the preview was correct, but SO's less than adequate parser ate my close anchor tag on the first paragraph, proving that parsers are not something to be trifled with because if you use regexes and one off hacks you will probably get something subtle and small wrong.
[3] Snippet of a Haskell parser using Parsec: a four function calculator extended with exponents, parentheses, whitespace for multiplication, and constants (like pi and e).
aexpr = expr `chainl1` toOp
expr = optChainl1 term addop (toScalar 0)
term = factor `chainl1` mulop
factor = sexpr `chainr1` powop
sexpr = parens aexpr
<|> scalar
<|> ident
powop = sym "^" >>= return . (B Pow)
<|> sym "^-" >>= return . (\x y -> B Pow x (B Sub (toScalar 0) y))
toOp = sym "->" >>= return . (B To)
mulop = sym "*" >>= return . (B Mul)
<|> sym "/" >>= return . (B Div)
<|> sym "%" >>= return . (B Mod)
<|> return . (B Mul)
addop = sym "+" >>= return . (B Add)
<|> sym "-" >>= return . (B Sub)
scalar = number >>= return . toScalar
ident = literal >>= return . Lit
parens p = do
lparen
result <- p
rparen
return result
Strange behavior about WEXITSTATUS with `G++ 4.9.4`
The WEXITSTATUS
macro is a matter of the C standard library implementation, not the compiler per se. Typically (and in the case of GCC) the compiler doesn't supply the C standard library implementation. It is an independent package.
Most Linux distributions, including Ubuntu, use glibc as C standard library implementation.
In glibc until version 2.23, inclusive, the macro was defined in the following way when using C++ and __USE_MISC
is set (see commit link below):
# define __WAIT_INT(status) (*(const int *) &(status))
// ...
# define WEXITSTATUS(status) __WEXITSTATUS (__WAIT_INT (status))
The actual implementation of the macro is inside __WEXITSTATUS
, but the use of __WAIT_INT
seems to be for the purpose of supporting the non-POSIX "union wait" variant of the wait
interface. With this definition, a prvalue cannot be used with the macro, because it tries to take the address of status
.
In 2016, with commit b49ab5f4503f36dcbf43f821f817da66b2931fe6 support for union wait - according to the NEWS
entry deprecated in the early 1990s - has been removed and now the definition is simply
# define WEXITSTATUS(status) __WEXITSTATUS (status)
Now it would work with a prvalue as well.
It seems that Ubuntu 16.04 still uses a glibc version from before that change, which isn't surprising since it was released at the time of the commit.
I don't know what POSIX has to say about whether or not it should be possible to use the macro with a int
rvalue rather than the name of a variable.
That WEXITSTATUS
can't always be used directly on a call to pclose
seems to be known issue. Apparently the above-mentioned extension, which is now not present in glibc anymore, was (is?) also present in (some?) BSDs (and may originate from them?). See e.g. this question, in which the answer also expresses doubts about POSIX-compliance. However, OpenBSD, mentioned in the linked question, also removed union wait in 2014. According to the changelog it had been deprecated since 4.3BSD (released 1986).
Related Topics
Enable + Disable Auto-Layout Constraints
Is Self Captured Within a Nested Function
Accessing a String Enum by Index
Perform a Segue Programmatically
Optionals VS Throwing Functions
Nspredicate with Swift and Core Data
Subclassing VS Extension in Swift
How to Record Video in Realitykit
How to Fix Error: This Class Is Not Key Value Coding-Compliant for the Key Tableview.'
Accessing Self from Instance Properties Which Are Closures
How to Install Package in Xcode via Swift Package Manager
Hide Tab Bar in View with Push
Should Iboutlet Be Weak or Strong Var
Swift - Lazy Var VS. Let When Creating Views Programmatically (Saving Memory)
Duplicating a Particle Emitter Effect in Sprite Kit
What Is a Good Alternative for Static Stored Properties of Generic Types in Swift