Persistence 2.0
This is a revised version of the old parser persistence format.
Symbols
Symbols reside in a common preprocessor table (Symbols), and in high
level symbol
scopes (Globals, Statics, modules, procedures).
The symbols in the preprocessor table can have several meanings, at the
same time:
- directives
- pragmas
- keywords (of the source language)
- macros
- symbols (in source code)
Directives, pragmas and keywords are implemented as appropriate to a
source language.
Macros and symbols are added from the actual source code; only these
symbols occur in meta-files.
Macros (#define) can be classified further into:
- default - to be expanded by the preprocessor
- dummy - when the body is empty
- constant - when the body is a constant expression
- type - when the body specifies an type
- template - the macro is a generic subroutine
The preprocessor expands all default and dummy macros, so that no macro
names occur in the meta-code, unless they are marked for special
treatment (by the user). The default macros occur in meta files, so
that the user can assign more appropriate types to each macro, for use
in the next run of the parser.
Meta files come in two flavours, either as module files
<module>.txt, or as project files <prj>.txt.
Module files contain all symbols which are defined in the according
module (*.c).
All other symbols, i.e. macros and undefined symbols, go into the
project file.
Every symbol is stored as one or multiple lines.
Macros are stored as found in the source files, i.e. all but the last
line end with a backslash. Defined procedure symbols always are stored
in multiple lines, the last line contains a single semicolon ";". Other
symbols can be broken on a special character (currently ";"), when the
lines are longer than allowed in the Delphi IDE.
The first character in a non-continuation line indicates the symbol
type:
- typesym, structsym, various subclasses
- varsym, constsym
- procsym
- labelsym(?)
- macrosym, various subclasses
TypeSym ::= "t" (StructType | SimpleType) .
SimpleType ::= ident "=" Type .
StructType ::= ("E"|"S"|"U") ":" (ident|#) "=" "{" { Field ";" }
"}" .
//everything to the left of "=" is part of the typename!
Field ::= [ident] ":" [Bitfield] Type ["="
Expression] .
Bitfield ::= "{" Value "}" .
ProcSym ::= "p" ident ":" [Scope] ProcType [Block] [";"]
.
ProcType ::= "(" {Param ";"} [":~;"] ")"
[Call] [Type] .
Param ::= [ident]":"[Ref][Type][Values] .
Ref ::= "@"|"&"|"#"|"?" .
//var,ref,const,out - default: value
VarConstSym ::= ("v"|"c"|"e") [Scope] ident ":" Type
[Values] .
//LabSym ::= "L" ident .
MacroSym ::= ("#"|"M"...) ident [ "(" { Ident"," } ")" ] [Body]
.
Type ::= Qualified | Array | Pointer | StructUnion | Enum |
Typename
| Basetype .
Qualified ::= ["#"|"V"] Type . //Const/Volatile
Array ::= "[" ExprList "]" Type .
Pointer ::= "*" Type .
StructUnion ::= ("S"|"U"|"I") (":"(ident|#)
| "{" { Field "," } "}") .
Enum ::= "E" (":"(ident|#) | "{" { ident [Value]
"," } "}") .
Typename ::= '"' ident '"' .
Basetype ::= ["+"|"-"]
(num|"v"|"c"|"s"|"i"|"l"|"L"|"f"|"d"|"D"|"~")
.
Value ::= (num|string|char|ident|[op]"(" ExprList ")" | ":" Type
"="
Value) .
//op is any C operator.
ExprList ::= { Value "," } .
Values ::= "=" Value .
Block ::= "{(" { (Value|stmt) ";"} "}" .
Possibly expression lists should be enclosed in "[...]"?
-> Intentionally ambigous with array type!
-> Separate by "=" from preceding type.
Otherwise "[" could be used as array-index operator!
Blocks (with declarations and statements) instead are enclosed in
"{...}".