CxCodeUnit
Description
- Derived from
-
CxNode abstract
ICxFullNameContainer
IPathInfo
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 ~lb*)? 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 ~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 := ~lb* 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.