CxCodeUnit
Description
- Derived from
-
CxNode abstract
ICxFullNameContainer
IPathInfo
IPsiNodeWithInput
Represents a Code-X unit:
// Comment
using Usings.First;
using Usings.Second;
...
#pragma ... (ignored)
// ... (ignored)
namespace Namespace
{
class Declaration
{
...
}
}
The Tinman 3D SDK is developed and maintained in Code-X, which is a subset of the C# Language Specification Version 8.0 (see https://www.microsoft.com/en-us/download/details.aspx?id=7029), with additional syntactic and semantic rules and concepts (see https://manual.tinman3d.com/STABLE-PREVIEW/software-architecture.html#_code_concepts). The syntax of a Code-X source code unit is defined by the following Grammar:
# := w ;
root := code-unit ;
!code-unit := comment? usings? (comment-line | pragma-line)* namespace ;
!comment := comment-line comment-line* ;
!namespace := 'namespace' w+ (id .. '.') '{' decl '}' ;
!pragma-line := '#pragma' ~lb* lb ;
usings := using using* ;
!decl := xmldoc? attribs? modifiers (class | delegate | enum | interface
| struct) ;
!using := 'using' w+ name ';' ;
!class := 'class' w+ name-id type-params? base-types? constraints? regions ;
!delegate := 'delegate' w+ var-decl type-params? params constraints? ';' ;
!enum := 'enum' w+ name-id '{' (item .. comma) '}' ;
!interface := 'interface' w+ name-id type-params? base-types? constraints?
regions ;
!struct := 'struct' w+ name-id type-params? base-types? constraints?
regions ;
base-types := ':' (type .. comma) ;
item := xmldoc? name-id '=' expr ;
regions := '{' region* '}' ;
region := '#region' ws ~lb+ lb member* '#endregion' ;
member := xmldoc? attribs? modifiers (constant | constructor | field
| indexer | method | operator | property) ;
!constant := 'const' w+ var-def ';' ;
!constructor := name-id params (':' 'base' '(' (expr .. comma)? ')')? stat-block ;
!field := var ';' ;
!indexer := type 'this' '[' var-decl ']' '{' getter? setter? '}' ;
!method := var-decl type-params? params constraints? (stat-block | ';') ;
modifiers := ('public' w+)? ('protected' w+)? ('internal' w+)? ('new' w+)?
('abstract' w+)? ('virtual' w+)? ('override' w+)? ('sealed' w+)?
('static' w+)? ('readonly' w+)? ('volatile' w+)? ('partial' w+)? ;
!operator := type 'operator' operator-op params stat-block ;
!property := var-decl '{' getter? setter? '}' ;
!xmldoc := (ws* xmldoc-line)+ ;
constraints := constraint constraint* ;
getter := 'get' (';' | stat-block) ;
operator-op := '==' | '!=' | '>=' | '<=' | '<<' | '>>' | '&' | '/'
| '>' | '~' | '<' | '%' | '*' | '-' | '!' | '|' | '+' | '^' ;
params := '(' (param .. comma)? ')' ;
setter := 'set' (';' | stat-block) ;
type-params := '<' (type-param .. comma) '>' ;
xmldoc-line := '///' (ws ]\n\r[*)? lb ;
constraint := 'where' w+ name-id ':' (constraint-item .. comma)? ;
param := attribs? (('ref' | 'out' | 'this') w+)? var ;
type-param := (('in' | 'out') w+)? name-id ;
attribs := '[' (attrib .. comma) ']' ;
constraint-item := 'class' | 'struct' | 'new()' | type-generic ;
attrib := name-id ('(' (expr .. comma) ')')? ;
!arg := (('out' | 'ref') w+)? expr ;
expr := expr-assign ;
!expr-add := expr-mul !> (expr-add-op expr-mul)+ ;
!expr-assign := expr-cond !> (expr-assign-op expr-cond)+ ;
!expr-brace := '(' expr ')' ;
!expr-cond := expr-cond-or !> '?' expr-cond ':' expr-cond ;
!expr-cond-and := expr-logic-or !> ('&&' expr-logic-or)+ ;
!expr-cond-or := expr-cond-and !> ('||' expr-cond-and)+ ;
!expr-default := 'default' '(' type ')' ;
!expr-equal := expr-relate !> expr-equal-op expr-relate ;
!expr-generic := expr-name !> '<' (type .. comma) '>' ;
!expr-logic-and := expr-equal !> ('&' expr-equal)+ ;
!expr-logic-or := expr-logic-xor !> ('|' expr-logic-xor)+ ;
!expr-logic-xor := expr-logic-and !> ('^' expr-logic-and)+ ;
!expr-mul := expr-unary !> (expr-mul-op expr-unary)+ ;
!expr-new := 'new' w+ type (expr-new-object | expr-new-array1
| expr-new-array2) ;
!expr-new-array1 := '{' (expr .. comma)? '}' ;
!expr-new-array2 := '[' expr ']' '[]'* ;
!expr-new-object := '(' (expr .. comma)? ')' ;
!expr-primary := expr-brace | expr-new | expr-literal | expr-default
| expr-generic ;
!expr-relate := expr-shift !> expr-relate-op expr-shift ;
!expr-shift := expr-add !> (expr-shift-op expr-add)+ ;
!expr-suffix := expr-primary !> expr-suffix-op+ ;
expr-suffix-op := '(' (arg .. comma)? ')' | '.' expr-generic | '[' expr ']' | '++'
| '--' ;
!expr-unary := expr-unary-op+ <! expr-suffix ;
expr-unary-op := '++' | '+' | '--' | '-' \ literal-number | '!' | '~' | '(' type
')' <expr> ;
for-cond := expr ;
for-next := expr (comma expr)* ;
stat := stat-block | stat-debug | stat-do | stat-foreach | stat-for
| stat-if | stat-native | stat-return | stat-simple | stat-switch
| stat-throw | stat-try | stat-while | stat-variable | stat-expr
| stat-comment ;
!stat-block := '{' stat* '}' ;
!stat-debug := '#if' 'DEBUG' stat* '#endif' ;
!stat-do := 'do' stat-block 'while' '(' expr ')' ';' ;
stat-expr := expr ';' ;
!stat-for := 'for' '(' var-def? ';' for-cond ';' for-next? ')' stat ;
!stat-foreach := 'foreach' '(' var-decl 'in' expr ')' stat ;
!stat-if := 'if' '(' expr ')' stat ('else' stat)? ;
!stat-return := 'return' (w+ expr)? ';' ;
!stat-switch := 'switch' '(' expr ')' '{' switch-case* switch-default? '}' ;
!stat-throw := 'throw' (w+ expr)? ';' ;
!stat-try := 'try' stat-block try-catch? try-finally? ;
!stat-variable := ('using' w+)? var ';' (ws* '//' ws* '[' ws* ('!' ws*)? ('*' ws*)?
']' ws* lb)? ;
!stat-while := 'while' '(' expr ')' stat ;
switch-case := 'case' w+ expr ':' stat* ;
switch-default := 'default:' stat* ;
try-catch := 'catch' '(' type (w+ name-id)? ')' stat-block ;
try-finally := 'finally' stat-block ;
!type := type-no-array !> '[]'+ ;
type-generic := type-name !> '<' (type .. comma) '>' ;
type-no-array := type-simple | type-generic ;
var := type w+ name-id ('=' expr)? ;
var-decl := type w+ name-id ;
var-def := type w+ name-id '=' expr ;
!expr-literal := literal ;
literal := literal-simple | literal-string | literal-char | literal-hex
| literal-number ;
!stat-comment := comment-prefix (comment-tag | ws?) comment-text (ws*
comment-line)* ;
type-name := name ;
comment-tag := ws* id ':' ws ;
!expr-name := id ;
!literal-char := '\'' (escape | ]'\\[) '\'' ;
!literal-string := '"' (escape | ]"\\[+)* '"' | '@"' ('""' | ]"[+)* '"' ;
name := 'global::'? (id .. '.') ;
name-id := id ;
!stat-native := '#region' ws 'Native' ws '{' guid '}' lb (]\n\r[+ | ~native-end)*
native-end lb ;
comment-line := comment-prefix ws? comment-text ;
escape := '\\"' | '\\0' | '\\\'' | '\\\\' | '\\b' | '\\f' | '\\n' | '\\r'
| '\\t' | '\\u' hex-digit[4] | '\\U' hex-digit[8] ;
!guid := hex-digit[8] ('-' hex-digit[4])[3] '-' hex-digit[12] ;
!id := letter id-char* ;
!literal-hex := @'0x' hex-digit+ @'L'? ;
!literal-simple := ('null' | 'this' | 'base' | 'true' | 'false') >id-char< ;
!type-simple := ('bool' | 'sbyte' | 'char' | 'short' | 'int' | 'long' | 'float'
| 'double' | 'string' | 'object' | 'void') >id-char< ;
comment-text := ]\n\r[* lb ;
hex-digit := dec-digit | 'a'..'f' | 'A'..'F' ;
id-char := letter | dec-digit ;
!literal-number := '-'? dec-digit+ ('.' dec-digit+)? (@'E' ('-' | '+')? dec-digit+)?
[FLfl]? ;
native-end := lb ws* '#endregion' ;
w := ws | lb ;
comma := ',' ;
comment-prefix := '//' \ '///' ;
dec-digit := '0'..'9' ;
expr-add-op := '+' | '-' ;
expr-assign-op := '=' | '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>='
| '&=' | '^=' | '|=' ;
expr-equal-op := '==' | '!=' ;
expr-mul-op := '*' | '/' \ '//' | '%' ;
expr-relate-op := '<=' | '<' | '>=' | '>' | 'is' | 'as' ;
expr-shift-op := '<<' | '>>' ;
lb := '\r' '\n'? | '\n' ;
letter := 'a'..'z' | 'A'..'Z' | '_' ;
!stat-simple := ('break' | 'continue') ';' ;
ws := '\t' | ' ' ;
The CxNode class represents a single node of the program structure information (PSI) model of a Code-X unit. To obtain a CxNode from source code, use one of the following parse methods:
-
CxCodeUnit via FromSource1 using
root. -
CxDeclaration via CxDeclaration.FromSource using
decl. -
CxExpression via CxExpression.FromSource using
expr. -
CxId via CxId.FromSource using
id. -
CxLiteral via CxLiteral.FromSource using
literal. -
CxMember via CxMember.FromSource using
member. -
CxName via CxName.FromSource using
name. -
CxStatement via CxStatement.FromSource using
stat. -
CxType via CxType.FromSource using
type.
Alternatively, a PSI model may be created by instantiating CxNode classes directly. To obtain parsable source code from CxNode objects, use ICodeOutput.WriteSourceCode or - as a shortcut - object.ToString.
Public / Constructors
FromFile
2 overloads
Parses the given Code-X unit, without providing file path information (see IPathInfo.PathInfo).
- ValidatingException
-
If the syntax of file in is invalid.
- IOException
-
If an I/O error has occurred.
Parses the given Code-X unit and provides file path information (see IPathInfo.PathInfo).
- ValidatingException
-
If the syntax of file in is invalid.
- IOException
-
If an I/O error has occurred.
FromSource
2 overloads
Parses the given Code-X unit, without providing file path information (see IPathInfo.PathInfo).
- ValidatingException
-
If the syntax of source in is invalid.
Parses the given Code-X unit and provides file path information (see IPathInfo.PathInfo).
- ValidatingException
-
If the syntax of source in is invalid.