3 ms·
Defining a variable before use makes a language context sensitive. So does e.g. typedef in C - is (a)*b multiplying a by b or typecasting what b points to? Depe
by beagle3 7y ago
Defining a variable before use makes a language context sensitive. So does e.g. typedef in C - is (a)*b multiplying a by b or typecasting what b points to? Depends on the types.
We usually semantically patch that at the right stage through the lexer or the AST so things still work in a CF setting, but almost no modern language is CF.
- seanmcdirmid 7y agoUse before declaration is resolved at the type checker level, not during parsing. C-style casting isn’t context sensitive if you don’t mind treating the casting type has an expression and then pulling a type out of it in the type checker (or evaluator if dynamic). Type checking is where all the complexity really is. Parsing and lexing are just easy things you do before the hard stuff.
- beagle3 7y agoC has a lot of things which are context sensitive, and you can't treat the casting type as an expression: c*(a)-b parses under (double a, b, c;) as ((ca)-b) ; but under (typedef double a; double b, c) it parses as c-b, (with a type conversion applied after the negation) which is a different parse, and which can be more complicated than that to the point that fixing the AST is equivalent to reparsing the source. Use before declaration can only be resolved at the typechecker if you assume every name is a variable, but the introduction of typedefs makes that assumption wrong, so you can't wait for the type checker - every C parser I know patches that information back into the lexer so that it would parse correctly. Indeed, the "typename" keyword was added to C++ because you can't leave that to the typechecker if you want a unique parse before instantiation.
- seanmcdirmid 7y agoParsing with type information is not the norm. It was only done in C because no one knew any better back then. Later language that adopt C-style casting (C#, Java) do not need to know if something is a type to deal with parens, they look for the follow on and evaluate the tree accordingly. That is why in C#: var x = (Foo) - foo; Will be rejected with a type error (must enclose -foo in parentheses because Foo is a type) rather than a parse error.