Example of Parsing Cangjie Source Code into AST Objects
Example of Using parseDecl Function to Parse Cangjie Source Code into Decl Object
Here is a class named Data:
class Data {
var a: Int32
init(a_: Int32) {
a = a_
}
}
Using the parsing function to convert the above code into a Decl object, the code is shown below:
import std.ast.*
main() {
let input: Tokens = quote(
class Data {
var a: Int32
init(a_: Int32) {
a = a_
}
}
)
let decl = parseDecl(input) // Obtain a Decl declaration node
var classDecl = match (decl as ClassDecl) { // The specific type of decl is ClassDecl, perform type conversion.
case Some(v) => v
case None => throw Exception()
}
classDecl.dump()
}
Execution result:
ClassDecl {
-keyword: Token {
value: "class"
kind: CLASS
pos: 5: 9
}
-identifier: Token {
value: "Data"
kind: IDENTIFIER
pos: 5: 15
}
-body: Body {
-decls: 0, VarDecl {
-keyword: Token {
value: "var"
kind: VAR
pos: 6: 13
}
-identifier: Token {
value: "a"
kind: IDENTIFIER
pos: 6: 17
}
-declType: PrimitiveType {
-keyword: Token {
value: "Int32"
kind: INT32
pos: 6: 20
}
}
}
-decls: 1, FuncDecl {
-keyword: Token {
value: "init"
kind: INIT
pos: 7: 13
}
-identifier: Token {
value: "init"
kind: IDENTIFIER
pos: 7: 13
}
-funcParams: 0, FuncParam {
-identifier: Token {
value: "a_"
kind: IDENTIFIER
pos: 7: 18
}
-colon: Token {
value: ":"
kind: COLON
pos: 7: 20
}
-paramType: PrimitiveType {
-keyword: Token {
value: "Int32"
kind: INT32
pos: 7: 22
}
}
}
-block: Block {
-nodes: 0, AssignExpr {
-leftExpr: RefExpr {
-identifier: Token {
value: "a"
kind: IDENTIFIER
pos: 8: 17
}
}
-assign: Token {
value: "="
kind: ASSIGN
pos: 8: 19
}
-rightExpr: RefExpr {
-identifier: Token {
value: "a_"
kind: IDENTIFIER
pos: 8: 21
}
}
}
}
}
}
}
Example of Using parseProgram Function to Parse Cangjie Source Code into Program Object
The content of the Cangjie source file test_macro_define.cj to be parsed is as follows:
/**
* This cj file serves as input parameter for testing parseProgram();
**/
macro package m
internal import std.ast.*
internal import base as mybase
public macro M(input: Tokens) {
return input
}
Using the parseProgram function to parse the above code into a Program node object, the code is shown below:
internal import std.ast.*
internal import std.fs.*
internal import std.io.*
main() {
let path: String = "./test_macro_define.cj"
let file: File = File(path, Read)
let reader: StringReader<File> = StringReader(file)
let code: String = reader.readToEnd() // Read source file content as string
let tokens: Tokens = cangjieLex(code)
let fileNode = parseProgram(tokens) // Parse into Program node
fileNode.dump()
return 0
}
Execution result:
Program {
-packageHeader: PackageHeader {
-keywordM: Token {
value: "macro"
kind: MACRO
}
-keywordP: Token {
value: "package"
kind: PACKAGE
}
-packageIdentifier: Token {
value: "m"
kind: IDENTIFIER
}
}
-importLists: 0, ImportList {
-modifier: Token {
value: "internal"
kind: INTERNAL
}
-keywordI: Token {
value: "import"
kind: IMPORT
}
-importKind: All
prefixPath: 0: Token {
value: "std"
kind: IDENTIFIER
}
prefixPath: 1: Token {
value: "ast"
kind: IDENTIFIER
}
-identifier: Token {
value: "*"
kind: MUL
}
}
-importLists: 1, ImportList {
-modifier: Token {
value: "internal"
kind: INTERNAL
}
-keywordI: Token {
value: "import"
kind: IMPORT
}
-importKind: Alias
-identifier: Token {
value: "base"
kind: IDENTIFIER
}
-importAlias 0: Token {
value: "as"
kind: AS
}
-importAlias 1: Token {
value: "mybase"
kind: IDENTIFIER
}
}
-decls: 0, MacroDecl {
-modifiers: 0, Modifier {
-keyword: Token {
value: "public"
kind: PUBLIC
}
}
-keyword: Token {
value: "macro"
kind: MACRO
}
-identifier: Token {
value: "M"
kind: IDENTIFIER
}
-funcParams: 0, FuncParam {
-identifier: Token {
value: "input"
kind: IDENTIFIER
}
-colon: Token {
value: ":"
kind: COLON
}
-paramType: RefType {
-identifier: Token {
value: "Tokens"
kind: IDENTIFIER
}
}
}
-block: Block {
-nodes: 0, ReturnExpr {
-keyword: Token {
value: "return"
kind: RETURN
}
-expr: RefExpr {
-identifier: Token {
value: "input"
kind: IDENTIFIER
}
}
}
}
}
}