The material I've read generally uses phrases like 'use the # character here to denote the start...' but I want to know what to call such a character. A coworker suggested the word 'token' but I don't think that's correct.
Brifely looking at the source code, the Razor team seem to refer to it as Transition Symbol.
In SyntaxConstants:
namespace System.Web.Razor.Parser
{
public static class SyntaxConstants
{
public static readonly char TransitionCharacter = '#';
public static readonly string TransitionString = "#";
}
}
Also in HtmlSymbolType.Transition:
namespace System.Web.Razor.Tokenizer.Symbols
{
public enum HtmlSymbolType
{
...
Transition, // #
}
}
Still, I doubt you can formally name it "Transition", it's seems more like an internal term of the parser to denote contexts switches (for example from HTML to C# and vice versa).
Related
I'm creating a Money class in Dart and came up with the idea of leveraging the type system to make sure you can't subtract Swiss Francs from Dollars (as opposed to this). This works swimmingly, significantly abbreviated what I have looks as follows:
abstract class Currency {
const Currency(this.precision, this.code);
final int precision;
final String code;
}
class Chf extends Currency {
const Chf() : super(2, 'CHF');
}
class Usd extends Currency {
const Usd() : super(2, 'USD');
}
class Money<T extends Currency> {
Money<T> subtract(Money<T> other) { ... }
}
It is impossible to subtract USDs from CHFs. Great. (More complete code here.)
But I'm receiving JSON payloads with currency representations therein. I now need to go from a String 'CHF' to a Money<Chf> instance. I can't figure out how to do that.
Somewhere I need to map a (currency code) string to a Type.
final t = convertStringToType('CHF');
final m1 = Money<t>(100); // <- I can't do this: 't' isn't a type.'
The only option forward I see is having a large (colossal) switch/case statement:
switch(code) {
case 'CHF':
return Money<Chf>(100);
...
}
Clearly I don't want that. Is there a better way?
Type arguments cannot be created from scratch, they have to be actual types or other type variables. So, if you need <Chf> as a type argument, you need to have <Chf> as an actual type argument somewhere in your program. Then you can piggy-back on that.
I would do something like:
T callWithCurrency<T>(String name, T action<X extends Currency>()) {
if (name == "CHF") return action<Chf>();
if (name == "USD") return action<Usd>();
...
throw ArgumentError.value(name, "name", "Not a recognized currency");
}
and then you can use it as:
final Money m1 = callWithCurrency("CHF", <X extends Currency>() => Money<X>(100));
I want to add a custom xpath extension function to the Saxon-HE transformer. This custom function should accept one or more arguments. Let's use the string concatenation analogy for concatenating one or more string arguments. Following the sample on the saxon page, i wrote the following code:
ExtensionFunction myconcat = new ExtensionFunction() {
public QName getName() {
return new QName("http://mycompany.com/", "myconcat");
}
public SequenceType getResultType() {
return SequenceType.makeSequenceType(
ItemType.STRING, OccurrenceIndicator.ONE
);
}
public net.sf.saxon.s9api.SequenceType[] getArgumentTypes() {
return new SequenceType[]{
SequenceType.makeSequenceType(
ItemType.STRING, OccurrenceIndicator.ONE_OR_MORE)};
}
public XdmValue call(XdmValue[] arguments) throws SaxonApiException {
//concatenate the strings here....
String result = "concatenated string";
return new XdmAtomicValue(result);
}
};
i have expected that the following xpath expression would work in an xsl file
<xsl:value-of select="myconcat('a','b','c','...')">
Unfortunately i got the following exception:
XPST0017: Function myconcat must have 1 argument
What is the right way of creating a custom function for this use case?
Thanks.
The standard mechanisms for creating extension functions don't allow a variable number of arguments (it's not really pukka to have such functions in the XPath view of the world - concat() is very much an exception).
You can do it by creating your own implementation of the class FunctionLibrary and adding your FunctionLibrary to the static context of the XSLT engine - but you're deep into Saxon internals if you attempt that, so be prepared for a rough ride.
I would like to create an abstract class which takes a type parameter and the constructor of that class should be passed another Action eg.
abstract class Action<Tc> {
public function __construct(private ?Action<*> $onSuccess = null) {}
}
How can I express a type parameter wildcard ie. "?" (Java) or "_" (Scala) in Hack?
Hack doesn't have wildcard type parameters right now, so the closest you can get is actually specifying a dummy type parameter that you don't actually need, e.g.,
abstract class Action<Tc, Ta> {
public function __construct(private ?Action<Ta> $onSuccess = null) {}
// ...
}
Depending on how exactly you use the $onSuccess member variable, you may want it to be some specific subclass of Action<T> to be determined later, and so you may want something like this:
abstract class Action<Tc, Ta, To as Action<Ta>> {
public function __construct(private ?To $onSuccess = null) {}
// ...
}
However, I question whether the "dummy" types above above are really a dummy -- the vast, vast majority of use cases of Action<T> are going to care what exactly the T is, otherwise how exactly would you use the Action<T>? (There are certainly rare cases where you don't care about the T at a callsite, but they are, well, rare and so I encourage you to consider whether that is actually your case as you build out this functionality.)
Not sure about a wildcard, but could this achieve what you want?
<?hh
abstract class Action<T1 as Action, T2> {
public function __construct(private ?T1 $onSuccess = null, private ?T2 $bla = null) {}
}
class ActionA<T1 as Action, T2> extends Action<T1, T2> {}
class ActionB<T1 as Action, T2> extends Action<T1, T2> {}
class ActionC<T1 as Action, T2> extends Action<T1, T2> {}
$action = new ActionA(new ActionB(new ActionC(null)));
var_dump($action);
When I run this against HHVM 3.1.0, I get:
object(ActionA)#1 (2) {
["onSuccess":"Action":private]=>
object(ActionB)#2 (2) {
["onSuccess":"Action":private]=>
object(ActionC)#3 (2) {
["onSuccess":"Action":private]=>
NULL
["bla":"Action":private]=>
NULL
}
["bla":"Action":private]=>
NULL
}
["bla":"Action":private]=>
NULL
}
And the 3.1.0 type checker also returns "No errors!".
However, the T1 as Action statement on the abstract class doesn't appear to be enforcing. For instance, I can change the instantiation line to:
$action = new ActionA(new ActionB(new ActionC(new DateTime())));
And it hums along fine, with the typechecker returning no errors still. And this is after taking the class definitions out into their own file with <?hh // strict.
So not really your answer, but perhaps close? The behavior above might suggest Hack has some issues with this sort of pattern?
How can I access alternate labels in ANTLR4 while generically traversing a parse tree? Or alternatively, is there any way of replicating the functionality of the ^ operator of ANTLR3, as that would do the trick.
I'm trying to write an AST pretty printer for any ANTLR4 grammar adhering to a simple methodology (like naming productions with alternate labels). I'd like to be able to pretty print a term like 3 + 5 as (int_expression (plus (int_literal 3) (int_literal 5))), or something similar, given a grammar like the following:
int_expression
: int_expression '+' int_expression # plus
| int_expression '-' int_expression # minus
| raw_int # int_literal
;
raw_int
: Int
;
Int : [0-9]+ ;
I am unable to effectively give names to the plus and minus productions, because pulling them out into their own production causes the tool to complain that the rules are mutually left-recursive. If I can't pull them out, how can I give these productions names?
Note 1: I was able to get rid of the + argument methodologically by putting "good" terminals (e.g., the Int above) in special productions (productions starting with a special prefix, like raw_). Then I could print only those terminals whose parent productions are named "raw_..." and elide all others. This worked great for getting rid of +, while keeping 3 and 5 in the output. This could be done with a ! in ANTLR3.
Note 2: I understand that I could write a specialized pretty printer or use actions for each production of a given language, but I'd like to use ANTLR4 to parse and generate ASTs for a variety of languages, and it seems like I should be able to write such a simple pretty printer generically. Said another way, I only care about getting ASTs, and I'd rather not have to encumber each grammar with a tailored pretty printer just to get an AST. Perhaps I should just go back to ANTLR3?
I suggest implementing the pretty printer as a listener implementation with a nested visitor class to get the names of the various context objects.
private MyParser parser; // you'll have to assign this field
private StringBuilder builder = new StringBuilder();
#Override
public void enterEveryRule(#NotNull ParserRuleContext ctx) {
if (!builder.isEmpty()) {
builder.append(' ');
}
builder.append('(');
}
#Override
public void visitTerminalNode(#NotNull TerminalNode node) {
// TODO: print node text to builder
}
#Override
public void visitErrorNode(#NotNull TerminalNode node) {
// TODO: print node text to builder
}
#Override
public void exitEveryRule(#NotNull ParserRuleContext ctx) {
builder.append(')');
}
protected String getContextName(#NotNull ParserRuleContext ctx) {
return new ContextNameVisitor().visit(ctx);
}
protected class ContextNameVisitor extends MyParserBaseVisitor<String> {
#Override
public String visitChildren() {
return parser.getRuleNames()[ctx.getRuleIndex()];
}
#Override
public String visitPlus(#NotNull PlusContext ctx) {
return "plus";
}
#Override
public String visitMinus(#NotNull MinusContext ctx) {
return "minus";
}
#Override
public String visitInt_literal(#NotNull MinusContext ctx) {
return "int_literal";
}
}
The API doesn't contain a method to access the alternate labels.
However there is a workaround. ANTLR4 uses the alternate labels to generate java class names and those java classes can be accessed at run time.
For example: to access alternate labels in ANTLR4 while generically traversing a parse tree (with a listener) you can use the following function:
// Return the embedded alternate label between
// "$" and "Context" from the class name
String getCtxName(ParserRuleContext ctx) {
String str = ctx.getClass().getName();
str = str.substring(str.indexOf("$")+1,str.lastIndexOf("Context"));
str = str.toLowerCase();
return str;
}
Example use:
#Override
public void exitEveryRule(ParserRuleContext ctx) {
System.out.println(getCtxName(ctx));
}
I apologize in advance for the newbiness of this question; I think I'm not grasping the basics of Actionscript but haven't been able to find an answer elsewhere.
What I want is some global constants like one would have in C++. In C++, I would simply have a file where I would #define MAP_HEIGHT 20, or something like that, and they would be globally accessible when I included the file at the top. In Actionscript, I've tried making a static class instead, like so:
package
{
public class Settings {
public const mapx:int = 20;
public function Settings() {}
}
}
But when I try to reference it in my code with colon syntax
var a:int = Settings::mapx;
I get the error "[Fault] exception, information=TypeError: Error #1034: Type Coercion failed: cannot convert Settings$ to Namespace."
I tried dot syntax:
var a:int = Settings.mapx;
and got a different error, "Access of possibly undefined property mapx through a reference with static type Class."
But what I really want is a file of global static variables, like in C++, and can't find a way to do it in Actionscript.
Mark variables, constants, and functions with the static keyword, as in:
package
{
public class MathUtil
{
public static const PI:Number = 3.141592653589;
public static function deg2rad(angle:Number):Number
{
angle = !isNaN(angle) ? (angle) : (0);
return angle * PI / 180;
}
}
}
Then you may use dot notation.
var pi:Number = MathUtil.PI;
var angle:Number = MathUtil.deg2rad(45);
From ActionScript 3.0 Reference for the Adobe Flash Platform: Statements, Keywords & Directives
Usage
class someClassName {
static var varName;
static const kName;
static function methodName() { }
}
You can use static in class definitions only, not in interface
definitions.
Static class members are not inherited. You cannot refer to a static
class member using the name of a subclass, as you can in Java or C++.
You can, however, refer to a static variable or method within a class
or subclass, without using any qualifier. See the example below.
You cannot use the super statement or the this keyword inside a static
method.