Tier 2 golden trees, and #scope_file is a statement not a modifier
isDeclarationAhead used to skip *any* directive, so '#scope_file' was absorbed as
a modifier of the declaration after it. That misreports scope, since a scope
directive governs everything that follows it. Only #as, #overlay, #add_context
and #no_reset actually prefix a declaration in the corpus; the rest are
statements now, which the regenerated Directives.txt shows.
Golden fixtures cover the reference doc's gotcha list: declaration forms,
procedures (named/multiple/variadic/polymorphic/foreign returns), structs, enums,
unions, array and pointer types, the 'if x == { case }' switch form, for
modifiers, ifx, and directives including a here-string.
DebugParseTest is now inert by default and documented as the scratch loop.
generateParser wipes its output through a Delete task rather than a doFirst,
because a lambda added from a Kotlin build script captures the script object and
breaks the configuration cache ('./jaigradle check' failed to store it).
check and verifyPlugin (IU-253/261/262) both green.
This commit is contained in:
@@ -8,9 +8,11 @@ plugins {
|
||||
}
|
||||
|
||||
// Grammar-Kit output. Committed so diffs are reviewable, never hand-edited.
|
||||
val generatedSourceDir = file("src/main/gen")
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java.srcDirs("src/main/gen")
|
||||
java.srcDirs(generatedSourceDir)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,20 +30,25 @@ dependencies {
|
||||
}
|
||||
}
|
||||
|
||||
// purgeOldFiles is not enough: Grammar-Kit rewrites only the files whose rule
|
||||
// changed, so a PSI interface can keep an accessor its regenerated Impl no longer has
|
||||
// (`JaiDeclaration.getArgumentList()` with no override) and the build then fails
|
||||
// inside generated code. Wiping first makes every generation self-consistent.
|
||||
//
|
||||
// This is a separate Delete task rather than a doFirst, because any lambda added to a
|
||||
// task from a Kotlin build script captures the script object, which the configuration
|
||||
// cache cannot serialize.
|
||||
val cleanGeneratedSources by tasks.registering(Delete::class) {
|
||||
delete(generatedSourceDir)
|
||||
}
|
||||
|
||||
tasks.generateParser {
|
||||
dependsOn(cleanGeneratedSources)
|
||||
sourceFile.set(file("src/main/grammar/Jai.bnf"))
|
||||
targetRootOutputDir.set(file("src/main/gen"))
|
||||
targetRootOutputDir.set(generatedSourceDir)
|
||||
pathToParser.set("dev/hgh/jai/parser/JaiParser.java")
|
||||
pathToPsiRoot.set("dev/hgh/jai/psi")
|
||||
purgeOldFiles.set(true)
|
||||
|
||||
// purgeOldFiles is not enough: Grammar-Kit rewrites only the files whose rule
|
||||
// changed, so a PSI interface can keep an accessor its regenerated Impl no longer
|
||||
// has (`JaiDeclaration.getArgumentList()` with no override) and the build fails on
|
||||
// generated code. Always regenerate the whole tree.
|
||||
doFirst {
|
||||
delete(file("src/main/gen"))
|
||||
}
|
||||
}
|
||||
|
||||
// Without this the compile tasks read src/main/gen with no ordering guarantee, so an
|
||||
|
||||
@@ -2509,7 +2509,8 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// <<isReturnGroupAhead>> returnGroup | returnItem (',' returnItem)*
|
||||
// <<isReturnGroupAhead>> returnGroup
|
||||
// | returnItem (',' <<notPolyParamAhead>> returnItem)*
|
||||
static boolean returnTypes_(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "returnTypes_")) return false;
|
||||
boolean result_;
|
||||
@@ -2531,7 +2532,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
return result_;
|
||||
}
|
||||
|
||||
// returnItem (',' returnItem)*
|
||||
// returnItem (',' <<notPolyParamAhead>> returnItem)*
|
||||
private static boolean returnTypes__1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "returnTypes__1")) return false;
|
||||
boolean result_;
|
||||
@@ -2542,7 +2543,7 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
return result_;
|
||||
}
|
||||
|
||||
// (',' returnItem)*
|
||||
// (',' <<notPolyParamAhead>> returnItem)*
|
||||
private static boolean returnTypes__1_1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "returnTypes__1_1")) return false;
|
||||
while (true) {
|
||||
@@ -2553,12 +2554,13 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ',' returnItem
|
||||
// ',' <<notPolyParamAhead>> returnItem
|
||||
private static boolean returnTypes__1_1_0(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "returnTypes__1_1_0")) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = consumeToken(builder_, COMMA);
|
||||
result_ = result_ && notPolyParamAhead(builder_, level_ + 1);
|
||||
result_ = result_ && returnItem(builder_, level_ + 1);
|
||||
exit_section_(builder_, marker_, null, result_);
|
||||
return result_;
|
||||
@@ -3222,65 +3224,61 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
return result_;
|
||||
}
|
||||
|
||||
// 'cast' directiveFlag_* '(' [expr (',' expr)*] ')' [expr]
|
||||
// 'cast' directiveFlag_* '(' expr ',' expr (',' expr)* ')'
|
||||
// | 'cast' directiveFlag_* '(' [expr] ')' expr
|
||||
public static boolean castExpr(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr")) return false;
|
||||
if (!nextTokenIsSmart(builder_, KW_CAST)) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = consumeTokenSmart(builder_, KW_CAST);
|
||||
result_ = result_ && castExpr_1(builder_, level_ + 1);
|
||||
result_ = result_ && consumeToken(builder_, LPAREN);
|
||||
result_ = result_ && castExpr_3(builder_, level_ + 1);
|
||||
result_ = result_ && consumeToken(builder_, RPAREN);
|
||||
result_ = result_ && castExpr_5(builder_, level_ + 1);
|
||||
result_ = castExpr_0(builder_, level_ + 1);
|
||||
if (!result_) result_ = castExpr_1(builder_, level_ + 1);
|
||||
exit_section_(builder_, marker_, CAST_EXPR, result_);
|
||||
return result_;
|
||||
}
|
||||
|
||||
// directiveFlag_*
|
||||
private static boolean castExpr_1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr_1")) return false;
|
||||
while (true) {
|
||||
int pos_ = current_position_(builder_);
|
||||
if (!directiveFlag_(builder_, level_ + 1)) break;
|
||||
if (!empty_element_parsed_guard_(builder_, "castExpr_1", pos_)) break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// [expr (',' expr)*]
|
||||
private static boolean castExpr_3(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr_3")) return false;
|
||||
castExpr_3_0(builder_, level_ + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// expr (',' expr)*
|
||||
private static boolean castExpr_3_0(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr_3_0")) return false;
|
||||
// 'cast' directiveFlag_* '(' expr ',' expr (',' expr)* ')'
|
||||
private static boolean castExpr_0(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr_0")) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = expr(builder_, level_ + 1, -1);
|
||||
result_ = result_ && castExpr_3_0_1(builder_, level_ + 1);
|
||||
result_ = consumeTokenSmart(builder_, KW_CAST);
|
||||
result_ = result_ && castExpr_0_1(builder_, level_ + 1);
|
||||
result_ = result_ && consumeToken(builder_, LPAREN);
|
||||
result_ = result_ && expr(builder_, level_ + 1, -1);
|
||||
result_ = result_ && consumeToken(builder_, COMMA);
|
||||
result_ = result_ && expr(builder_, level_ + 1, -1);
|
||||
result_ = result_ && castExpr_0_6(builder_, level_ + 1);
|
||||
result_ = result_ && consumeToken(builder_, RPAREN);
|
||||
exit_section_(builder_, marker_, null, result_);
|
||||
return result_;
|
||||
}
|
||||
|
||||
// (',' expr)*
|
||||
private static boolean castExpr_3_0_1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr_3_0_1")) return false;
|
||||
// directiveFlag_*
|
||||
private static boolean castExpr_0_1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr_0_1")) return false;
|
||||
while (true) {
|
||||
int pos_ = current_position_(builder_);
|
||||
if (!castExpr_3_0_1_0(builder_, level_ + 1)) break;
|
||||
if (!empty_element_parsed_guard_(builder_, "castExpr_3_0_1", pos_)) break;
|
||||
if (!directiveFlag_(builder_, level_ + 1)) break;
|
||||
if (!empty_element_parsed_guard_(builder_, "castExpr_0_1", pos_)) break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// (',' expr)*
|
||||
private static boolean castExpr_0_6(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr_0_6")) return false;
|
||||
while (true) {
|
||||
int pos_ = current_position_(builder_);
|
||||
if (!castExpr_0_6_0(builder_, level_ + 1)) break;
|
||||
if (!empty_element_parsed_guard_(builder_, "castExpr_0_6", pos_)) break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ',' expr
|
||||
private static boolean castExpr_3_0_1_0(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr_3_0_1_0")) return false;
|
||||
private static boolean castExpr_0_6_0(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr_0_6_0")) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = consumeTokenSmart(builder_, COMMA);
|
||||
@@ -3289,9 +3287,35 @@ public class JaiParser implements PsiParser, LightPsiParser {
|
||||
return result_;
|
||||
}
|
||||
|
||||
// 'cast' directiveFlag_* '(' [expr] ')' expr
|
||||
private static boolean castExpr_1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr_1")) return false;
|
||||
boolean result_;
|
||||
Marker marker_ = enter_section_(builder_);
|
||||
result_ = consumeTokenSmart(builder_, KW_CAST);
|
||||
result_ = result_ && castExpr_1_1(builder_, level_ + 1);
|
||||
result_ = result_ && consumeToken(builder_, LPAREN);
|
||||
result_ = result_ && castExpr_1_3(builder_, level_ + 1);
|
||||
result_ = result_ && consumeToken(builder_, RPAREN);
|
||||
result_ = result_ && expr(builder_, level_ + 1, -1);
|
||||
exit_section_(builder_, marker_, null, result_);
|
||||
return result_;
|
||||
}
|
||||
|
||||
// directiveFlag_*
|
||||
private static boolean castExpr_1_1(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr_1_1")) return false;
|
||||
while (true) {
|
||||
int pos_ = current_position_(builder_);
|
||||
if (!directiveFlag_(builder_, level_ + 1)) break;
|
||||
if (!empty_element_parsed_guard_(builder_, "castExpr_1_1", pos_)) break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// [expr]
|
||||
private static boolean castExpr_5(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr_5")) return false;
|
||||
private static boolean castExpr_1_3(PsiBuilder builder_, int level_) {
|
||||
if (!recursion_guard_(builder_, level_, "castExpr_1_3")) return false;
|
||||
expr(builder_, level_ + 1, -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -305,7 +305,8 @@ arrayTypeExpr ::= '[' ['..' | expr] ']' expr
|
||||
// (modules/Shared_Memory_Channel/module.jai:113).
|
||||
derefCastExpr ::= '(' '.*' ')' expr
|
||||
|
||||
castExpr ::= 'cast' directiveFlag_* '(' [expr (',' expr)*] ')' [expr]
|
||||
castExpr ::= 'cast' directiveFlag_* '(' expr ',' expr (',' expr)* ')'
|
||||
| 'cast' directiveFlag_* '(' [expr] ')' expr
|
||||
autoCastExpr ::= 'xx' [',' IDENT] expr
|
||||
inlineExpr ::= ('inline' | 'no_inline') expr
|
||||
ifxExpr ::= ifxKeyword_ expr ['then'] [ifxBranch_] ['else' ifxBranch_]
|
||||
@@ -385,7 +386,8 @@ private paramTypeTail_ ::= ':' [<<exprNoAssign>>] ['=' initializer]
|
||||
| ':=' initializer
|
||||
| '::' initializer
|
||||
|
||||
private returnTypes_ ::= <<isReturnGroupAhead>> returnGroup | returnItem (',' returnItem)*
|
||||
private returnTypes_ ::= <<isReturnGroupAhead>> returnGroup
|
||||
| returnItem (',' <<notPolyParamAhead>> returnItem)*
|
||||
returnGroup ::= '(' [returnItem (',' returnItem)*] ')'
|
||||
returnItem ::= <<isParamNameAhead>> IDENT (':' [<<exprNoAssign>>] ['=' returnDefault_] | ':=' returnDefault_)
|
||||
| <<exprNoAssign>>
|
||||
|
||||
@@ -91,6 +91,17 @@ object JaiParserUtil : GeneratedParserUtilBase() {
|
||||
"this",
|
||||
)
|
||||
|
||||
/**
|
||||
* Directives that modify the declaration that follows them, rather than standing
|
||||
* alone as a statement.
|
||||
*
|
||||
* The distinction matters for the tree shape: `#scope_file` changes visibility for
|
||||
* everything *after* it, so attaching it to the next declaration would misreport
|
||||
* that declaration's scope. Taken from the corpus, where only these four appear
|
||||
* directly in front of a `name :` / `name ::` / `name :=`.
|
||||
*/
|
||||
private val DIRECTIVES_ON_DECLARATIONS = setOf("as", "overlay", "add_context", "no_reset")
|
||||
|
||||
// ---------------------------------------------------------------- directives
|
||||
|
||||
/**
|
||||
@@ -343,7 +354,13 @@ object JaiParserUtil : GeneratedParserUtilBase() {
|
||||
var inPrefix = false
|
||||
loop@ while (true) {
|
||||
when (b.lookAhead(i)) {
|
||||
T.DIRECTIVE, T.KW_USING -> {
|
||||
T.DIRECTIVE -> {
|
||||
if (!isDeclarationDirective(b, i)) break@loop
|
||||
i++
|
||||
inPrefix = true
|
||||
}
|
||||
|
||||
T.KW_USING -> {
|
||||
i++
|
||||
inPrefix = true
|
||||
}
|
||||
@@ -378,6 +395,20 @@ object JaiParserUtil : GeneratedParserUtilBase() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the DIRECTIVE at lookahead [index] modifies the declaration that
|
||||
* follows. Only the first token can be read as text through the builder, which is
|
||||
* enough: a declaration-modifying directive is always the first thing we look at.
|
||||
*/
|
||||
private fun isDeclarationDirective(
|
||||
b: PsiBuilder,
|
||||
index: Int,
|
||||
): Boolean {
|
||||
if (index != 0) return true
|
||||
val text = b.tokenText ?: return false
|
||||
return text.removePrefix("#") in DIRECTIVES_ON_DECLARATIONS
|
||||
}
|
||||
|
||||
/**
|
||||
* Index just past the closer matching the bracket at [start], or -1 if unbalanced.
|
||||
* Covers `(…)`, `[…]`, `.[…]` and `.{…}`, which all appear in declaration
|
||||
@@ -479,6 +510,22 @@ object JaiParserUtil : GeneratedParserUtilBase() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* True when the next token cannot start a polymorph capture.
|
||||
*
|
||||
* An unparenthesised return list is comma-separated, and so is the parameter list
|
||||
* that may enclose it. A `$T` after the comma can only be a parameter, so the
|
||||
* return list has to stop there.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun notPolyParamAhead(
|
||||
b: PsiBuilder,
|
||||
level: Int,
|
||||
): Boolean {
|
||||
val t = b.tokenType
|
||||
return t !== T.DOLLAR && t !== T.DOUBLE_DOLLAR
|
||||
}
|
||||
|
||||
/** `IDENT ':'` — a loop label. */
|
||||
@JvmStatic
|
||||
fun isLabelAhead(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package dev.hgh.jai.parser
|
||||
|
||||
import com.intellij.psi.PsiErrorElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiFileFactory
|
||||
import com.intellij.psi.PsiRecursiveElementWalkingVisitor
|
||||
import com.intellij.testFramework.fixtures.BasePlatformTestCase
|
||||
@@ -9,70 +8,77 @@ import dev.hgh.jai.JaiLanguage
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Scratch harness for grammar work. Not a gate — the gate is [JaiCorpusParserTest].
|
||||
* Edit [snippets] and [corpusFiles] freely while iterating on `Jai.bnf`.
|
||||
* Scratch harness for grammar work. **Not a gate** — the gate is [JaiCorpusParserTest].
|
||||
*
|
||||
* Both lists are empty on purpose, so this is silent until someone is working on
|
||||
* `Jai.bnf`. To iterate: paste failing snippets into [snippets] or corpus-relative
|
||||
* paths into [corpusFiles], run `./jaitest`, and read the printed first error. Add
|
||||
* `-Djai.debug.tree=1` to dump the PSI tree as well.
|
||||
*
|
||||
* The loop this supports is: read the sample errors printed by [JaiCorpusParserTest],
|
||||
* reduce one to a snippet here, fix the grammar, then re-check the corpus percentage.
|
||||
*/
|
||||
class DebugParseTest : BasePlatformTestCase() {
|
||||
private val snippets =
|
||||
listOf(
|
||||
"T :: struct {\n p := .06;\n b: BG;\n b.shape.kind = .ABS;\n b.color = V4.{.00, .10, 1};\n}\n",
|
||||
"T :: struct {\n orientation: enum u8 {\n H :: 0;\n V :: 1;\n }\n\n d: BT;\n}\n",
|
||||
"T :: struct {\n using,except .[\"x\"] orientation: Quaternion;\n}\n",
|
||||
"operator *[] :: (b: *Bucket, index: int) -> *int { return null; }\n",
|
||||
"code :: #code a := Vector3.{1, 1, 1};\n",
|
||||
)
|
||||
/** Jai source snippets to parse. */
|
||||
private val snippets = emptyList<String>()
|
||||
|
||||
/** Corpus files to dump the first error of. */
|
||||
private val corpusFiles =
|
||||
listOf(
|
||||
"modules/GetRect/widgets/color_picker.jai",
|
||||
"modules/GetRect/widgets/slidable_region.jai",
|
||||
"how_to/094_array_operators.jai",
|
||||
"how_to/044_using_advanced/main.jai",
|
||||
"how_to/630_compiler_get_nodes.jai",
|
||||
"modules/Bucket_Array.jai",
|
||||
"modules/Android/Toolchain/adb.jai",
|
||||
"modules/Hash_Table.jai",
|
||||
/** Paths under `~/.local/jai` to parse. */
|
||||
private val corpusFiles = emptyList<String>()
|
||||
|
||||
fun testSnippets() {
|
||||
val factory = PsiFileFactory.getInstance(project)
|
||||
for (text in snippets) {
|
||||
val file = factory.createFileFromText("scratch.jai", JaiLanguage, text)
|
||||
val error = errorsIn(file).firstOrNull()
|
||||
val label = text.replace("\n", "\\n")
|
||||
if (error == null) {
|
||||
println("ok $label")
|
||||
} else {
|
||||
println("FAIL $label")
|
||||
println(" ${error.errorDescription} | at '${around(text, error.textOffset)}'")
|
||||
}
|
||||
if (System.getProperty("jai.debug.tree") != null) {
|
||||
println(
|
||||
com.intellij.psi.impl.DebugUtil
|
||||
.psiToString(file, true, false),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun testCorpusFiles() {
|
||||
val root = File(System.getProperty("user.home"), ".local/jai")
|
||||
if (!root.exists()) return
|
||||
for (relative in corpusFiles) {
|
||||
val file = File(root, relative)
|
||||
if (file.exists()) dumpFile(file) else println("missing: $relative")
|
||||
if (!file.exists()) {
|
||||
println("missing: $relative")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
fun testSnippets() {
|
||||
val factory = PsiFileFactory.getInstance(project)
|
||||
var failures = 0
|
||||
for (text in snippets) {
|
||||
val file = factory.createFileFromText("t.jai", JaiLanguage, text)
|
||||
val error = firstError(file)
|
||||
if (error == null) {
|
||||
println("ok ${text.replace("\n", "\\n")}")
|
||||
if (System.getProperty("jai.debug.tree") != null) {
|
||||
println(com.intellij.psi.impl.DebugUtil.psiToString(file, true, false))
|
||||
}
|
||||
} else {
|
||||
failures++
|
||||
val at = text.substring(error.textOffset).take(28).replace("\n", "\\n")
|
||||
println("FAIL ${text.replace("\n", "\\n")}")
|
||||
println(" ${error.errorDescription} | at '$at'")
|
||||
if (System.getProperty("jai.debug.tree") != null) {
|
||||
println(com.intellij.psi.impl.DebugUtil.psiToString(file, true, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
println("$failures/${snippets.size} snippets failed")
|
||||
}
|
||||
|
||||
private fun dumpFile(file: File) {
|
||||
val text = file.readText()
|
||||
val psi = PsiFileFactory.getInstance(project).createFileFromText(file.name, JaiLanguage, text)
|
||||
val errors = errorsIn(psi)
|
||||
if (errors.isEmpty()) {
|
||||
println("$relative: clean")
|
||||
continue
|
||||
}
|
||||
println("$relative: ${errors.size} error(s)")
|
||||
for (error in errors.take(REPORTED_ERRORS)) {
|
||||
val line = text.substring(0, error.textOffset).count { it == '\n' } + 1
|
||||
println(" :$line ${error.errorDescription}")
|
||||
println(" at '${around(text, error.textOffset)}'")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun around(
|
||||
text: String,
|
||||
offset: Int,
|
||||
): String = text.substring(offset).take(SNIPPET_WIDTH).replace("\n", "\\n")
|
||||
|
||||
private fun errorsIn(file: com.intellij.psi.PsiFile): List<PsiErrorElement> {
|
||||
val errors = mutableListOf<PsiErrorElement>()
|
||||
psi.accept(
|
||||
file.accept(
|
||||
object : PsiRecursiveElementWalkingVisitor() {
|
||||
override fun visitErrorElement(element: PsiErrorElement) {
|
||||
errors.add(element)
|
||||
@@ -80,28 +86,11 @@ class DebugParseTest : BasePlatformTestCase() {
|
||||
}
|
||||
},
|
||||
)
|
||||
if (errors.isEmpty()) {
|
||||
println("${file.name}: clean")
|
||||
return
|
||||
}
|
||||
println("${file.name}: ${errors.size} error(s)")
|
||||
for (error in errors.take(6)) {
|
||||
val line = text.substring(0, error.textOffset).count { it == '\n' } + 1
|
||||
println(" :$line ${error.errorDescription}")
|
||||
println(" at '${text.substring(error.textOffset).take(70).replace("\n", "\\n")}'")
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
private fun firstError(file: PsiFile): PsiErrorElement? {
|
||||
var first: PsiErrorElement? = null
|
||||
file.accept(
|
||||
object : PsiRecursiveElementWalkingVisitor() {
|
||||
override fun visitErrorElement(element: PsiErrorElement) {
|
||||
if (first == null) first = element
|
||||
super.visitErrorElement(element)
|
||||
}
|
||||
},
|
||||
)
|
||||
return first
|
||||
private companion object {
|
||||
const val REPORTED_ERRORS = 6
|
||||
const val SNIPPET_WIDTH = 70
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
package dev.hgh.jai.parser
|
||||
|
||||
/**
|
||||
* Tier 2 (docs/BUILD_PLAN.md §3): golden PSI trees for the constructs listed as
|
||||
* gotchas in `docs/JAI_LANGUAGE_REFERENCE.md` §14.
|
||||
*
|
||||
* The corpus gate proves the grammar *accepts* real code; these prove it builds the
|
||||
* tree we intend, so a refactor that quietly reshapes the PSI shows up as a diff.
|
||||
*
|
||||
* `ParsingTestCase` writes the expected `.txt` when it is missing, which makes adding
|
||||
* a case cheap — but the generated tree must be read before committing, or the test
|
||||
* asserts nothing.
|
||||
*/
|
||||
class JaiParserGoldenTest : JaiParsingTestCase() {
|
||||
fun testSimpleDeclarations() {
|
||||
doTest(true)
|
||||
}
|
||||
fun testDeclarations() = doTest(true)
|
||||
|
||||
fun testExpressions() {
|
||||
doTest(true)
|
||||
}
|
||||
fun testProcedures() = doTest(true)
|
||||
|
||||
fun testTypes() = doTest(true)
|
||||
|
||||
fun testControlFlow() = doTest(true)
|
||||
|
||||
fun testDirectives() = doTest(true)
|
||||
}
|
||||
|
||||
15
src/test/testData/parsing/ControlFlow.jai
Normal file
15
src/test/testData/parsing/ControlFlow.jai
Normal file
@@ -0,0 +1,15 @@
|
||||
run :: () {
|
||||
if cond { } else if other { } else { }
|
||||
if flag then quit = true;
|
||||
if value == {
|
||||
case .BANANA; print("b");
|
||||
case; print("d");
|
||||
}
|
||||
while running { break; }
|
||||
for 1..7 { print("%", it); }
|
||||
for < * v, i: array { remove v; }
|
||||
for :expansion holder { }
|
||||
defer free(p);
|
||||
push_context ctx { work(); }
|
||||
s := ifx a then b else c;
|
||||
}
|
||||
221
src/test/testData/parsing/ControlFlow.txt
Normal file
221
src/test/testData/parsing/ControlFlow.txt
Normal file
@@ -0,0 +1,221 @@
|
||||
Jai File(0,390)
|
||||
JaiStatementImpl(STATEMENT)(0,390)
|
||||
JaiDeclarationImpl(DECLARATION)(0,390)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(0,3)
|
||||
JaiDeclNameImpl(DECL_NAME)(0,3)
|
||||
PsiElement(Jai:IDENT)('run')(0,3)
|
||||
PsiElement(Jai:::)('::')(4,6)
|
||||
JaiInitializerImpl(INITIALIZER)(7,390)
|
||||
JaiProcLiteralExprImpl(PROC_LITERAL_EXPR)(7,390)
|
||||
PsiElement(Jai:()('(')(7,8)
|
||||
PsiElement(Jai:))(')')(8,9)
|
||||
JaiBlockImpl(BLOCK)(10,390)
|
||||
PsiElement(Jai:{)('{')(10,11)
|
||||
JaiStatementImpl(STATEMENT)(16,54)
|
||||
JaiIfStatementImpl(IF_STATEMENT)(16,54)
|
||||
PsiElement(Jai:if)('if')(16,18)
|
||||
JaiRefExprImpl(REF_EXPR)(19,23)
|
||||
PsiElement(Jai:IDENT)('cond')(19,23)
|
||||
JaiStatementImpl(STATEMENT)(24,27)
|
||||
JaiBlockImpl(BLOCK)(24,27)
|
||||
PsiElement(Jai:{)('{')(24,25)
|
||||
PsiElement(Jai:})('}')(26,27)
|
||||
JaiElseClauseImpl(ELSE_CLAUSE)(28,54)
|
||||
PsiElement(Jai:else)('else')(28,32)
|
||||
JaiStatementImpl(STATEMENT)(33,54)
|
||||
JaiIfStatementImpl(IF_STATEMENT)(33,54)
|
||||
PsiElement(Jai:if)('if')(33,35)
|
||||
JaiRefExprImpl(REF_EXPR)(36,41)
|
||||
PsiElement(Jai:IDENT)('other')(36,41)
|
||||
JaiStatementImpl(STATEMENT)(42,45)
|
||||
JaiBlockImpl(BLOCK)(42,45)
|
||||
PsiElement(Jai:{)('{')(42,43)
|
||||
PsiElement(Jai:})('}')(44,45)
|
||||
JaiElseClauseImpl(ELSE_CLAUSE)(46,54)
|
||||
PsiElement(Jai:else)('else')(46,50)
|
||||
JaiStatementImpl(STATEMENT)(51,54)
|
||||
JaiBlockImpl(BLOCK)(51,54)
|
||||
PsiElement(Jai:{)('{')(51,52)
|
||||
PsiElement(Jai:})('}')(53,54)
|
||||
JaiStatementImpl(STATEMENT)(59,84)
|
||||
JaiIfStatementImpl(IF_STATEMENT)(59,84)
|
||||
PsiElement(Jai:if)('if')(59,61)
|
||||
JaiRefExprImpl(REF_EXPR)(62,66)
|
||||
PsiElement(Jai:IDENT)('flag')(62,66)
|
||||
PsiElement(Jai:then)('then')(67,71)
|
||||
JaiStatementImpl(STATEMENT)(72,84)
|
||||
JaiExpressionStatementImpl(EXPRESSION_STATEMENT)(72,84)
|
||||
JaiAssignExprImpl(ASSIGN_EXPR)(72,83)
|
||||
JaiRefExprImpl(REF_EXPR)(72,76)
|
||||
PsiElement(Jai:IDENT)('quit')(72,76)
|
||||
PsiElement(Jai:=)('=')(77,78)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(79,83)
|
||||
PsiElement(Jai:true)('true')(79,83)
|
||||
PsiElement(Jai:;)(';')(83,84)
|
||||
JaiStatementImpl(STATEMENT)(89,176)
|
||||
JaiIfStatementImpl(IF_STATEMENT)(89,176)
|
||||
PsiElement(Jai:if)('if')(89,91)
|
||||
JaiRefExprImpl(REF_EXPR)(92,97)
|
||||
PsiElement(Jai:IDENT)('value')(92,97)
|
||||
JaiSwitchBodyImpl(SWITCH_BODY)(98,176)
|
||||
PsiElement(Jai:==)('==')(98,100)
|
||||
PsiElement(Jai:{)('{')(101,102)
|
||||
JaiCaseClauseImpl(CASE_CLAUSE)(111,136)
|
||||
PsiElement(Jai:case)('case')(111,115)
|
||||
JaiUnaryDotExprImpl(UNARY_DOT_EXPR)(116,123)
|
||||
PsiElement(Jai:.)('.')(116,117)
|
||||
JaiMemberNameImpl(MEMBER_NAME)(117,123)
|
||||
PsiElement(Jai:IDENT)('BANANA')(117,123)
|
||||
PsiElement(Jai:;)(';')(123,124)
|
||||
JaiStatementImpl(STATEMENT)(125,136)
|
||||
JaiExpressionStatementImpl(EXPRESSION_STATEMENT)(125,136)
|
||||
JaiCallExprImpl(CALL_EXPR)(125,135)
|
||||
JaiRefExprImpl(REF_EXPR)(125,130)
|
||||
PsiElement(Jai:IDENT)('print')(125,130)
|
||||
PsiElement(Jai:()('(')(130,131)
|
||||
JaiArgumentImpl(ARGUMENT)(131,134)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(131,134)
|
||||
PsiElement(Jai:STRING)('"b"')(131,134)
|
||||
PsiElement(Jai:))(')')(134,135)
|
||||
PsiElement(Jai:;)(';')(135,136)
|
||||
JaiCaseClauseImpl(CASE_CLAUSE)(145,170)
|
||||
PsiElement(Jai:case)('case')(145,149)
|
||||
PsiElement(Jai:;)(';')(149,150)
|
||||
JaiStatementImpl(STATEMENT)(159,170)
|
||||
JaiExpressionStatementImpl(EXPRESSION_STATEMENT)(159,170)
|
||||
JaiCallExprImpl(CALL_EXPR)(159,169)
|
||||
JaiRefExprImpl(REF_EXPR)(159,164)
|
||||
PsiElement(Jai:IDENT)('print')(159,164)
|
||||
PsiElement(Jai:()('(')(164,165)
|
||||
JaiArgumentImpl(ARGUMENT)(165,168)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(165,168)
|
||||
PsiElement(Jai:STRING)('"d"')(165,168)
|
||||
PsiElement(Jai:))(')')(168,169)
|
||||
PsiElement(Jai:;)(';')(169,170)
|
||||
PsiElement(Jai:})('}')(175,176)
|
||||
JaiStatementImpl(STATEMENT)(181,205)
|
||||
JaiWhileStatementImpl(WHILE_STATEMENT)(181,205)
|
||||
PsiElement(Jai:while)('while')(181,186)
|
||||
JaiRefExprImpl(REF_EXPR)(187,194)
|
||||
PsiElement(Jai:IDENT)('running')(187,194)
|
||||
JaiStatementImpl(STATEMENT)(195,205)
|
||||
JaiBlockImpl(BLOCK)(195,205)
|
||||
PsiElement(Jai:{)('{')(195,196)
|
||||
JaiStatementImpl(STATEMENT)(197,203)
|
||||
JaiBreakStatementImpl(BREAK_STATEMENT)(197,203)
|
||||
PsiElement(Jai:break)('break')(197,202)
|
||||
PsiElement(Jai:;)(';')(202,203)
|
||||
PsiElement(Jai:})('}')(204,205)
|
||||
JaiStatementImpl(STATEMENT)(210,238)
|
||||
JaiForStatementImpl(FOR_STATEMENT)(210,238)
|
||||
PsiElement(Jai:for)('for')(210,213)
|
||||
JaiRangeExprImpl(RANGE_EXPR)(214,218)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(214,215)
|
||||
PsiElement(Jai:NUMBER)('1')(214,215)
|
||||
PsiElement(Jai:..)('..')(215,217)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(217,218)
|
||||
PsiElement(Jai:NUMBER)('7')(217,218)
|
||||
JaiStatementImpl(STATEMENT)(219,238)
|
||||
JaiBlockImpl(BLOCK)(219,238)
|
||||
PsiElement(Jai:{)('{')(219,220)
|
||||
JaiStatementImpl(STATEMENT)(221,236)
|
||||
JaiExpressionStatementImpl(EXPRESSION_STATEMENT)(221,236)
|
||||
JaiCallExprImpl(CALL_EXPR)(221,235)
|
||||
JaiRefExprImpl(REF_EXPR)(221,226)
|
||||
PsiElement(Jai:IDENT)('print')(221,226)
|
||||
PsiElement(Jai:()('(')(226,227)
|
||||
JaiArgumentImpl(ARGUMENT)(227,230)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(227,230)
|
||||
PsiElement(Jai:STRING)('"%"')(227,230)
|
||||
PsiElement(Jai:,)(',')(230,231)
|
||||
JaiArgumentImpl(ARGUMENT)(232,234)
|
||||
JaiRefExprImpl(REF_EXPR)(232,234)
|
||||
PsiElement(Jai:IDENT)('it')(232,234)
|
||||
PsiElement(Jai:))(')')(234,235)
|
||||
PsiElement(Jai:;)(';')(235,236)
|
||||
PsiElement(Jai:})('}')(237,238)
|
||||
JaiStatementImpl(STATEMENT)(243,276)
|
||||
JaiForStatementImpl(FOR_STATEMENT)(243,276)
|
||||
PsiElement(Jai:for)('for')(243,246)
|
||||
PsiElement(Jai:<)('<')(247,248)
|
||||
PsiElement(Jai:*)('*')(249,250)
|
||||
JaiForNamesImpl(FOR_NAMES)(251,255)
|
||||
JaiForNameImpl(FOR_NAME)(251,252)
|
||||
PsiElement(Jai:IDENT)('v')(251,252)
|
||||
PsiElement(Jai:,)(',')(252,253)
|
||||
JaiForNameImpl(FOR_NAME)(254,255)
|
||||
PsiElement(Jai:IDENT)('i')(254,255)
|
||||
PsiElement(Jai::)(':')(255,256)
|
||||
JaiRefExprImpl(REF_EXPR)(257,262)
|
||||
PsiElement(Jai:IDENT)('array')(257,262)
|
||||
JaiStatementImpl(STATEMENT)(263,276)
|
||||
JaiBlockImpl(BLOCK)(263,276)
|
||||
PsiElement(Jai:{)('{')(263,264)
|
||||
JaiStatementImpl(STATEMENT)(265,274)
|
||||
JaiRemoveStatementImpl(REMOVE_STATEMENT)(265,274)
|
||||
PsiElement(Jai:remove)('remove')(265,271)
|
||||
JaiRefExprImpl(REF_EXPR)(272,273)
|
||||
PsiElement(Jai:IDENT)('v')(272,273)
|
||||
PsiElement(Jai:;)(';')(273,274)
|
||||
PsiElement(Jai:})('}')(275,276)
|
||||
JaiStatementImpl(STATEMENT)(281,306)
|
||||
JaiForStatementImpl(FOR_STATEMENT)(281,306)
|
||||
PsiElement(Jai:for)('for')(281,284)
|
||||
PsiElement(Jai::)(':')(285,286)
|
||||
JaiRefExprImpl(REF_EXPR)(286,295)
|
||||
PsiElement(Jai:IDENT)('expansion')(286,295)
|
||||
JaiRefExprImpl(REF_EXPR)(296,302)
|
||||
PsiElement(Jai:IDENT)('holder')(296,302)
|
||||
JaiStatementImpl(STATEMENT)(303,306)
|
||||
JaiBlockImpl(BLOCK)(303,306)
|
||||
PsiElement(Jai:{)('{')(303,304)
|
||||
PsiElement(Jai:})('}')(305,306)
|
||||
JaiStatementImpl(STATEMENT)(311,325)
|
||||
JaiDeferStatementImpl(DEFER_STATEMENT)(311,325)
|
||||
PsiElement(Jai:defer)('defer')(311,316)
|
||||
JaiStatementImpl(STATEMENT)(317,325)
|
||||
JaiExpressionStatementImpl(EXPRESSION_STATEMENT)(317,325)
|
||||
JaiCallExprImpl(CALL_EXPR)(317,324)
|
||||
JaiRefExprImpl(REF_EXPR)(317,321)
|
||||
PsiElement(Jai:IDENT)('free')(317,321)
|
||||
PsiElement(Jai:()('(')(321,322)
|
||||
JaiArgumentImpl(ARGUMENT)(322,323)
|
||||
JaiRefExprImpl(REF_EXPR)(322,323)
|
||||
PsiElement(Jai:IDENT)('p')(322,323)
|
||||
PsiElement(Jai:))(')')(323,324)
|
||||
PsiElement(Jai:;)(';')(324,325)
|
||||
JaiStatementImpl(STATEMENT)(330,358)
|
||||
JaiPushContextStatementImpl(PUSH_CONTEXT_STATEMENT)(330,358)
|
||||
PsiElement(Jai:push_context)('push_context')(330,342)
|
||||
JaiRefExprImpl(REF_EXPR)(343,346)
|
||||
PsiElement(Jai:IDENT)('ctx')(343,346)
|
||||
JaiBlockImpl(BLOCK)(347,358)
|
||||
PsiElement(Jai:{)('{')(347,348)
|
||||
JaiStatementImpl(STATEMENT)(349,356)
|
||||
JaiExpressionStatementImpl(EXPRESSION_STATEMENT)(349,356)
|
||||
JaiCallExprImpl(CALL_EXPR)(349,355)
|
||||
JaiRefExprImpl(REF_EXPR)(349,353)
|
||||
PsiElement(Jai:IDENT)('work')(349,353)
|
||||
PsiElement(Jai:()('(')(353,354)
|
||||
PsiElement(Jai:))(')')(354,355)
|
||||
PsiElement(Jai:;)(';')(355,356)
|
||||
PsiElement(Jai:})('}')(357,358)
|
||||
JaiStatementImpl(STATEMENT)(363,388)
|
||||
JaiDeclarationImpl(DECLARATION)(363,388)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(363,364)
|
||||
JaiDeclNameImpl(DECL_NAME)(363,364)
|
||||
PsiElement(Jai:IDENT)('s')(363,364)
|
||||
PsiElement(Jai::=)(':=')(365,367)
|
||||
JaiInitializerImpl(INITIALIZER)(368,387)
|
||||
JaiIfxExprImpl(IFX_EXPR)(368,387)
|
||||
PsiElement(Jai:ifx)('ifx')(368,371)
|
||||
JaiRefExprImpl(REF_EXPR)(372,373)
|
||||
PsiElement(Jai:IDENT)('a')(372,373)
|
||||
PsiElement(Jai:then)('then')(374,378)
|
||||
JaiRefExprImpl(REF_EXPR)(379,380)
|
||||
PsiElement(Jai:IDENT)('b')(379,380)
|
||||
PsiElement(Jai:else)('else')(381,385)
|
||||
JaiRefExprImpl(REF_EXPR)(386,387)
|
||||
PsiElement(Jai:IDENT)('c')(386,387)
|
||||
PsiElement(Jai:;)(';')(387,388)
|
||||
PsiElement(Jai:})('}')(389,390)
|
||||
7
src/test/testData/parsing/Declarations.jai
Normal file
7
src/test/testData/parsing/Declarations.jai
Normal file
@@ -0,0 +1,7 @@
|
||||
a : float = 37.0;
|
||||
b : float;
|
||||
c := 111.0;
|
||||
d : float : -123.45;
|
||||
e :: 42;
|
||||
f : Vector3 = ---;
|
||||
x, y, z: float;
|
||||
85
src/test/testData/parsing/Declarations.txt
Normal file
85
src/test/testData/parsing/Declarations.txt
Normal file
@@ -0,0 +1,85 @@
|
||||
Jai File(0,105)
|
||||
JaiStatementImpl(STATEMENT)(0,17)
|
||||
JaiDeclarationImpl(DECLARATION)(0,17)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(0,1)
|
||||
JaiDeclNameImpl(DECL_NAME)(0,1)
|
||||
PsiElement(Jai:IDENT)('a')(0,1)
|
||||
PsiElement(Jai::)(':')(2,3)
|
||||
JaiRefExprImpl(REF_EXPR)(4,9)
|
||||
PsiElement(Jai:IDENT)('float')(4,9)
|
||||
PsiElement(Jai:=)('=')(10,11)
|
||||
JaiInitializerImpl(INITIALIZER)(12,16)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(12,16)
|
||||
PsiElement(Jai:NUMBER)('37.0')(12,16)
|
||||
PsiElement(Jai:;)(';')(16,17)
|
||||
JaiStatementImpl(STATEMENT)(18,28)
|
||||
JaiDeclarationImpl(DECLARATION)(18,28)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(18,19)
|
||||
JaiDeclNameImpl(DECL_NAME)(18,19)
|
||||
PsiElement(Jai:IDENT)('b')(18,19)
|
||||
PsiElement(Jai::)(':')(20,21)
|
||||
JaiRefExprImpl(REF_EXPR)(22,27)
|
||||
PsiElement(Jai:IDENT)('float')(22,27)
|
||||
PsiElement(Jai:;)(';')(27,28)
|
||||
JaiStatementImpl(STATEMENT)(29,40)
|
||||
JaiDeclarationImpl(DECLARATION)(29,40)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(29,30)
|
||||
JaiDeclNameImpl(DECL_NAME)(29,30)
|
||||
PsiElement(Jai:IDENT)('c')(29,30)
|
||||
PsiElement(Jai::=)(':=')(31,33)
|
||||
JaiInitializerImpl(INITIALIZER)(34,39)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(34,39)
|
||||
PsiElement(Jai:NUMBER)('111.0')(34,39)
|
||||
PsiElement(Jai:;)(';')(39,40)
|
||||
JaiStatementImpl(STATEMENT)(41,61)
|
||||
JaiDeclarationImpl(DECLARATION)(41,61)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(41,42)
|
||||
JaiDeclNameImpl(DECL_NAME)(41,42)
|
||||
PsiElement(Jai:IDENT)('d')(41,42)
|
||||
PsiElement(Jai::)(':')(43,44)
|
||||
JaiRefExprImpl(REF_EXPR)(45,50)
|
||||
PsiElement(Jai:IDENT)('float')(45,50)
|
||||
PsiElement(Jai::)(':')(51,52)
|
||||
JaiInitializerImpl(INITIALIZER)(53,60)
|
||||
JaiPrefixExprImpl(PREFIX_EXPR)(53,60)
|
||||
PsiElement(Jai:-)('-')(53,54)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(54,60)
|
||||
PsiElement(Jai:NUMBER)('123.45')(54,60)
|
||||
PsiElement(Jai:;)(';')(60,61)
|
||||
JaiStatementImpl(STATEMENT)(62,70)
|
||||
JaiDeclarationImpl(DECLARATION)(62,70)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(62,63)
|
||||
JaiDeclNameImpl(DECL_NAME)(62,63)
|
||||
PsiElement(Jai:IDENT)('e')(62,63)
|
||||
PsiElement(Jai:::)('::')(64,66)
|
||||
JaiInitializerImpl(INITIALIZER)(67,69)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(67,69)
|
||||
PsiElement(Jai:NUMBER)('42')(67,69)
|
||||
PsiElement(Jai:;)(';')(69,70)
|
||||
JaiStatementImpl(STATEMENT)(71,89)
|
||||
JaiDeclarationImpl(DECLARATION)(71,89)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(71,72)
|
||||
JaiDeclNameImpl(DECL_NAME)(71,72)
|
||||
PsiElement(Jai:IDENT)('f')(71,72)
|
||||
PsiElement(Jai::)(':')(73,74)
|
||||
JaiRefExprImpl(REF_EXPR)(75,82)
|
||||
PsiElement(Jai:IDENT)('Vector3')(75,82)
|
||||
PsiElement(Jai:=)('=')(83,84)
|
||||
JaiInitializerImpl(INITIALIZER)(85,88)
|
||||
PsiElement(Jai:---)('---')(85,88)
|
||||
PsiElement(Jai:;)(';')(88,89)
|
||||
JaiStatementImpl(STATEMENT)(90,105)
|
||||
JaiDeclarationImpl(DECLARATION)(90,105)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(90,97)
|
||||
JaiDeclNameImpl(DECL_NAME)(90,91)
|
||||
PsiElement(Jai:IDENT)('x')(90,91)
|
||||
PsiElement(Jai:,)(',')(91,92)
|
||||
JaiDeclNameImpl(DECL_NAME)(93,94)
|
||||
PsiElement(Jai:IDENT)('y')(93,94)
|
||||
PsiElement(Jai:,)(',')(94,95)
|
||||
JaiDeclNameImpl(DECL_NAME)(96,97)
|
||||
PsiElement(Jai:IDENT)('z')(96,97)
|
||||
PsiElement(Jai::)(':')(97,98)
|
||||
JaiRefExprImpl(REF_EXPR)(99,104)
|
||||
PsiElement(Jai:IDENT)('float')(99,104)
|
||||
PsiElement(Jai:;)(';')(104,105)
|
||||
13
src/test/testData/parsing/Directives.jai
Normal file
13
src/test/testData/parsing/Directives.jai
Normal file
@@ -0,0 +1,13 @@
|
||||
#import "Basic";
|
||||
#load "other.jai";
|
||||
#scope_file
|
||||
Sort :: #import "Sort";
|
||||
BODY :: #string DONE
|
||||
raw text
|
||||
DONE
|
||||
#if OS == .WINDOWS {
|
||||
lib :: #library,system,link_always "user32";
|
||||
} else {
|
||||
#assert false "unsupported";
|
||||
}
|
||||
c :: #char "a";
|
||||
97
src/test/testData/parsing/Directives.txt
Normal file
97
src/test/testData/parsing/Directives.txt
Normal file
@@ -0,0 +1,97 @@
|
||||
Jai File(0,236)
|
||||
JaiStatementImpl(STATEMENT)(0,16)
|
||||
JaiExpressionStatementImpl(EXPRESSION_STATEMENT)(0,16)
|
||||
JaiDirectiveExprImpl(DIRECTIVE_EXPR)(0,15)
|
||||
PsiElement(Jai:DIRECTIVE)('#import')(0,7)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(8,15)
|
||||
PsiElement(Jai:STRING)('"Basic"')(8,15)
|
||||
PsiElement(Jai:;)(';')(15,16)
|
||||
JaiStatementImpl(STATEMENT)(17,35)
|
||||
JaiExpressionStatementImpl(EXPRESSION_STATEMENT)(17,35)
|
||||
JaiDirectiveExprImpl(DIRECTIVE_EXPR)(17,34)
|
||||
PsiElement(Jai:DIRECTIVE)('#load')(17,22)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(23,34)
|
||||
PsiElement(Jai:STRING)('"other.jai"')(23,34)
|
||||
PsiElement(Jai:;)(';')(34,35)
|
||||
JaiStatementImpl(STATEMENT)(36,47)
|
||||
JaiDirectiveStatementImpl(DIRECTIVE_STATEMENT)(36,47)
|
||||
PsiElement(Jai:DIRECTIVE)('#scope_file')(36,47)
|
||||
JaiStatementImpl(STATEMENT)(48,71)
|
||||
JaiDeclarationImpl(DECLARATION)(48,71)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(48,52)
|
||||
JaiDeclNameImpl(DECL_NAME)(48,52)
|
||||
PsiElement(Jai:IDENT)('Sort')(48,52)
|
||||
PsiElement(Jai:::)('::')(53,55)
|
||||
JaiInitializerImpl(INITIALIZER)(56,70)
|
||||
JaiDirectiveExprImpl(DIRECTIVE_EXPR)(56,70)
|
||||
PsiElement(Jai:DIRECTIVE)('#import')(56,63)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(64,70)
|
||||
PsiElement(Jai:STRING)('"Sort"')(64,70)
|
||||
PsiElement(Jai:;)(';')(70,71)
|
||||
JaiStatementImpl(STATEMENT)(72,106)
|
||||
JaiDeclarationImpl(DECLARATION)(72,106)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(72,76)
|
||||
JaiDeclNameImpl(DECL_NAME)(72,76)
|
||||
PsiElement(Jai:IDENT)('BODY')(72,76)
|
||||
PsiElement(Jai:::)('::')(77,79)
|
||||
JaiInitializerImpl(INITIALIZER)(80,106)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(80,106)
|
||||
PsiElement(Jai:HERE_STRING)('#string DONE\nraw text\nDONE')(80,106)
|
||||
JaiStatementImpl(STATEMENT)(107,220)
|
||||
JaiIfStatementImpl(IF_STATEMENT)(107,220)
|
||||
PsiElement(Jai:DIRECTIVE)('#if')(107,110)
|
||||
JaiEqualityExprImpl(EQUALITY_EXPR)(111,125)
|
||||
JaiRefExprImpl(REF_EXPR)(111,113)
|
||||
PsiElement(Jai:IDENT)('OS')(111,113)
|
||||
PsiElement(Jai:==)('==')(114,116)
|
||||
JaiUnaryDotExprImpl(UNARY_DOT_EXPR)(117,125)
|
||||
PsiElement(Jai:.)('.')(117,118)
|
||||
JaiMemberNameImpl(MEMBER_NAME)(118,125)
|
||||
PsiElement(Jai:IDENT)('WINDOWS')(118,125)
|
||||
JaiStatementImpl(STATEMENT)(126,178)
|
||||
JaiBlockImpl(BLOCK)(126,178)
|
||||
PsiElement(Jai:{)('{')(126,127)
|
||||
JaiStatementImpl(STATEMENT)(132,176)
|
||||
JaiDeclarationImpl(DECLARATION)(132,176)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(132,135)
|
||||
JaiDeclNameImpl(DECL_NAME)(132,135)
|
||||
PsiElement(Jai:IDENT)('lib')(132,135)
|
||||
PsiElement(Jai:::)('::')(136,138)
|
||||
JaiInitializerImpl(INITIALIZER)(139,175)
|
||||
JaiDirectiveExprImpl(DIRECTIVE_EXPR)(139,175)
|
||||
PsiElement(Jai:DIRECTIVE)('#library')(139,147)
|
||||
PsiElement(Jai:,)(',')(147,148)
|
||||
PsiElement(Jai:IDENT)('system')(148,154)
|
||||
PsiElement(Jai:,)(',')(154,155)
|
||||
PsiElement(Jai:IDENT)('link_always')(155,166)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(167,175)
|
||||
PsiElement(Jai:STRING)('"user32"')(167,175)
|
||||
PsiElement(Jai:;)(';')(175,176)
|
||||
PsiElement(Jai:})('}')(177,178)
|
||||
JaiElseClauseImpl(ELSE_CLAUSE)(179,220)
|
||||
PsiElement(Jai:else)('else')(179,183)
|
||||
JaiStatementImpl(STATEMENT)(184,220)
|
||||
JaiBlockImpl(BLOCK)(184,220)
|
||||
PsiElement(Jai:{)('{')(184,185)
|
||||
JaiStatementImpl(STATEMENT)(190,218)
|
||||
JaiExpressionStatementImpl(EXPRESSION_STATEMENT)(190,218)
|
||||
JaiDirectiveExprImpl(DIRECTIVE_EXPR)(190,217)
|
||||
PsiElement(Jai:DIRECTIVE)('#assert')(190,197)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(198,203)
|
||||
PsiElement(Jai:false)('false')(198,203)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(204,217)
|
||||
PsiElement(Jai:STRING)('"unsupported"')(204,217)
|
||||
PsiElement(Jai:;)(';')(217,218)
|
||||
PsiElement(Jai:})('}')(219,220)
|
||||
JaiStatementImpl(STATEMENT)(221,236)
|
||||
JaiDeclarationImpl(DECLARATION)(221,236)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(221,222)
|
||||
JaiDeclNameImpl(DECL_NAME)(221,222)
|
||||
PsiElement(Jai:IDENT)('c')(221,222)
|
||||
PsiElement(Jai:::)('::')(223,225)
|
||||
JaiInitializerImpl(INITIALIZER)(226,235)
|
||||
JaiDirectiveExprImpl(DIRECTIVE_EXPR)(226,235)
|
||||
PsiElement(Jai:DIRECTIVE)('#char')(226,231)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(232,235)
|
||||
PsiElement(Jai:STRING)('"a"')(232,235)
|
||||
PsiElement(Jai:;)(';')(235,236)
|
||||
@@ -1,2 +0,0 @@
|
||||
x = a + b * c;
|
||||
foo(x, y + 1);
|
||||
@@ -1,37 +0,0 @@
|
||||
Jai File(0,29)
|
||||
JaiStatementImpl(STATEMENT)(0,14)
|
||||
JaiExpressionStatementImpl(EXPRESSION_STATEMENT)(0,14)
|
||||
JaiAssignExprImpl(ASSIGN_EXPR)(0,13)
|
||||
JaiRefExprImpl(REF_EXPR)(0,1)
|
||||
PsiElement(Jai:IDENT)('x')(0,1)
|
||||
PsiElement(Jai:=)('=')(2,3)
|
||||
JaiAddExprImpl(ADD_EXPR)(4,13)
|
||||
JaiRefExprImpl(REF_EXPR)(4,5)
|
||||
PsiElement(Jai:IDENT)('a')(4,5)
|
||||
PsiElement(Jai:+)('+')(6,7)
|
||||
JaiMulExprImpl(MUL_EXPR)(8,13)
|
||||
JaiRefExprImpl(REF_EXPR)(8,9)
|
||||
PsiElement(Jai:IDENT)('b')(8,9)
|
||||
PsiElement(Jai:*)('*')(10,11)
|
||||
JaiRefExprImpl(REF_EXPR)(12,13)
|
||||
PsiElement(Jai:IDENT)('c')(12,13)
|
||||
PsiElement(Jai:;)(';')(13,14)
|
||||
JaiStatementImpl(STATEMENT)(15,29)
|
||||
JaiExpressionStatementImpl(EXPRESSION_STATEMENT)(15,29)
|
||||
JaiCallExprImpl(CALL_EXPR)(15,28)
|
||||
JaiRefExprImpl(REF_EXPR)(15,18)
|
||||
PsiElement(Jai:IDENT)('foo')(15,18)
|
||||
PsiElement(Jai:()('(')(18,19)
|
||||
JaiArgumentImpl(ARGUMENT)(19,20)
|
||||
JaiRefExprImpl(REF_EXPR)(19,20)
|
||||
PsiElement(Jai:IDENT)('x')(19,20)
|
||||
PsiElement(Jai:,)(',')(20,21)
|
||||
JaiArgumentImpl(ARGUMENT)(22,27)
|
||||
JaiAddExprImpl(ADD_EXPR)(22,27)
|
||||
JaiRefExprImpl(REF_EXPR)(22,23)
|
||||
PsiElement(Jai:IDENT)('y')(22,23)
|
||||
PsiElement(Jai:+)('+')(24,25)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(26,27)
|
||||
PsiElement(Jai:NUMBER)('1')(26,27)
|
||||
PsiElement(Jai:))(')')(27,28)
|
||||
PsiElement(Jai:;)(';')(28,29)
|
||||
7
src/test/testData/parsing/Procedures.jai
Normal file
7
src/test/testData/parsing/Procedures.jai
Normal file
@@ -0,0 +1,7 @@
|
||||
main :: () { }
|
||||
named :: (a: int) -> named: string { return "x"; }
|
||||
multi :: () -> A, B { return a, b; }
|
||||
variadic :: (fmt: string, args: ..Any) { }
|
||||
polymorph :: (x: $T/interface Matchable) -> T { return x; }
|
||||
foreign_proc :: (fd: s32) -> s32 #foreign libc "inotify_init1";
|
||||
lambda :: x => x.count;
|
||||
190
src/test/testData/parsing/Procedures.txt
Normal file
190
src/test/testData/parsing/Procedures.txt
Normal file
@@ -0,0 +1,190 @@
|
||||
Jai File(0,293)
|
||||
JaiStatementImpl(STATEMENT)(0,14)
|
||||
JaiDeclarationImpl(DECLARATION)(0,14)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(0,4)
|
||||
JaiDeclNameImpl(DECL_NAME)(0,4)
|
||||
PsiElement(Jai:IDENT)('main')(0,4)
|
||||
PsiElement(Jai:::)('::')(5,7)
|
||||
JaiInitializerImpl(INITIALIZER)(8,14)
|
||||
JaiProcLiteralExprImpl(PROC_LITERAL_EXPR)(8,14)
|
||||
PsiElement(Jai:()('(')(8,9)
|
||||
PsiElement(Jai:))(')')(9,10)
|
||||
JaiBlockImpl(BLOCK)(11,14)
|
||||
PsiElement(Jai:{)('{')(11,12)
|
||||
PsiElement(Jai:})('}')(13,14)
|
||||
JaiStatementImpl(STATEMENT)(15,65)
|
||||
JaiDeclarationImpl(DECLARATION)(15,65)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(15,20)
|
||||
JaiDeclNameImpl(DECL_NAME)(15,20)
|
||||
PsiElement(Jai:IDENT)('named')(15,20)
|
||||
PsiElement(Jai:::)('::')(21,23)
|
||||
JaiInitializerImpl(INITIALIZER)(24,65)
|
||||
JaiProcLiteralExprImpl(PROC_LITERAL_EXPR)(24,65)
|
||||
PsiElement(Jai:()('(')(24,25)
|
||||
JaiParameterImpl(PARAMETER)(25,31)
|
||||
JaiParamNamesImpl(PARAM_NAMES)(25,26)
|
||||
JaiParamNameImpl(PARAM_NAME)(25,26)
|
||||
PsiElement(Jai:IDENT)('a')(25,26)
|
||||
PsiElement(Jai::)(':')(26,27)
|
||||
JaiRefExprImpl(REF_EXPR)(28,31)
|
||||
PsiElement(Jai:IDENT)('int')(28,31)
|
||||
PsiElement(Jai:))(')')(31,32)
|
||||
PsiElement(Jai:->)('->')(33,35)
|
||||
JaiReturnItemImpl(RETURN_ITEM)(36,49)
|
||||
PsiElement(Jai:IDENT)('named')(36,41)
|
||||
PsiElement(Jai::)(':')(41,42)
|
||||
JaiRefExprImpl(REF_EXPR)(43,49)
|
||||
PsiElement(Jai:IDENT)('string')(43,49)
|
||||
JaiBlockImpl(BLOCK)(50,65)
|
||||
PsiElement(Jai:{)('{')(50,51)
|
||||
JaiStatementImpl(STATEMENT)(52,63)
|
||||
JaiReturnStatementImpl(RETURN_STATEMENT)(52,63)
|
||||
PsiElement(Jai:return)('return')(52,58)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(59,62)
|
||||
PsiElement(Jai:STRING)('"x"')(59,62)
|
||||
PsiElement(Jai:;)(';')(62,63)
|
||||
PsiElement(Jai:})('}')(64,65)
|
||||
JaiStatementImpl(STATEMENT)(66,102)
|
||||
JaiDeclarationImpl(DECLARATION)(66,102)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(66,71)
|
||||
JaiDeclNameImpl(DECL_NAME)(66,71)
|
||||
PsiElement(Jai:IDENT)('multi')(66,71)
|
||||
PsiElement(Jai:::)('::')(72,74)
|
||||
JaiInitializerImpl(INITIALIZER)(75,102)
|
||||
JaiProcLiteralExprImpl(PROC_LITERAL_EXPR)(75,102)
|
||||
PsiElement(Jai:()('(')(75,76)
|
||||
PsiElement(Jai:))(')')(76,77)
|
||||
PsiElement(Jai:->)('->')(78,80)
|
||||
JaiReturnItemImpl(RETURN_ITEM)(81,82)
|
||||
JaiRefExprImpl(REF_EXPR)(81,82)
|
||||
PsiElement(Jai:IDENT)('A')(81,82)
|
||||
PsiElement(Jai:,)(',')(82,83)
|
||||
JaiReturnItemImpl(RETURN_ITEM)(84,85)
|
||||
JaiRefExprImpl(REF_EXPR)(84,85)
|
||||
PsiElement(Jai:IDENT)('B')(84,85)
|
||||
JaiBlockImpl(BLOCK)(86,102)
|
||||
PsiElement(Jai:{)('{')(86,87)
|
||||
JaiStatementImpl(STATEMENT)(88,100)
|
||||
JaiReturnStatementImpl(RETURN_STATEMENT)(88,100)
|
||||
PsiElement(Jai:return)('return')(88,94)
|
||||
JaiRefExprImpl(REF_EXPR)(95,96)
|
||||
PsiElement(Jai:IDENT)('a')(95,96)
|
||||
PsiElement(Jai:,)(',')(96,97)
|
||||
JaiRefExprImpl(REF_EXPR)(98,99)
|
||||
PsiElement(Jai:IDENT)('b')(98,99)
|
||||
PsiElement(Jai:;)(';')(99,100)
|
||||
PsiElement(Jai:})('}')(101,102)
|
||||
JaiStatementImpl(STATEMENT)(103,145)
|
||||
JaiDeclarationImpl(DECLARATION)(103,145)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(103,111)
|
||||
JaiDeclNameImpl(DECL_NAME)(103,111)
|
||||
PsiElement(Jai:IDENT)('variadic')(103,111)
|
||||
PsiElement(Jai:::)('::')(112,114)
|
||||
JaiInitializerImpl(INITIALIZER)(115,145)
|
||||
JaiProcLiteralExprImpl(PROC_LITERAL_EXPR)(115,145)
|
||||
PsiElement(Jai:()('(')(115,116)
|
||||
JaiParameterImpl(PARAMETER)(116,127)
|
||||
JaiParamNamesImpl(PARAM_NAMES)(116,119)
|
||||
JaiParamNameImpl(PARAM_NAME)(116,119)
|
||||
PsiElement(Jai:IDENT)('fmt')(116,119)
|
||||
PsiElement(Jai::)(':')(119,120)
|
||||
JaiRefExprImpl(REF_EXPR)(121,127)
|
||||
PsiElement(Jai:IDENT)('string')(121,127)
|
||||
PsiElement(Jai:,)(',')(127,128)
|
||||
JaiParameterImpl(PARAMETER)(129,140)
|
||||
JaiParamNamesImpl(PARAM_NAMES)(129,133)
|
||||
JaiParamNameImpl(PARAM_NAME)(129,133)
|
||||
PsiElement(Jai:IDENT)('args')(129,133)
|
||||
PsiElement(Jai::)(':')(133,134)
|
||||
JaiPrefixExprImpl(PREFIX_EXPR)(135,140)
|
||||
PsiElement(Jai:..)('..')(135,137)
|
||||
JaiRefExprImpl(REF_EXPR)(137,140)
|
||||
PsiElement(Jai:IDENT)('Any')(137,140)
|
||||
PsiElement(Jai:))(')')(140,141)
|
||||
JaiBlockImpl(BLOCK)(142,145)
|
||||
PsiElement(Jai:{)('{')(142,143)
|
||||
PsiElement(Jai:})('}')(144,145)
|
||||
JaiStatementImpl(STATEMENT)(146,205)
|
||||
JaiDeclarationImpl(DECLARATION)(146,205)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(146,155)
|
||||
JaiDeclNameImpl(DECL_NAME)(146,155)
|
||||
PsiElement(Jai:IDENT)('polymorph')(146,155)
|
||||
PsiElement(Jai:::)('::')(156,158)
|
||||
JaiInitializerImpl(INITIALIZER)(159,205)
|
||||
JaiProcLiteralExprImpl(PROC_LITERAL_EXPR)(159,205)
|
||||
PsiElement(Jai:()('(')(159,160)
|
||||
JaiParameterImpl(PARAMETER)(160,185)
|
||||
JaiParamNamesImpl(PARAM_NAMES)(160,161)
|
||||
JaiParamNameImpl(PARAM_NAME)(160,161)
|
||||
PsiElement(Jai:IDENT)('x')(160,161)
|
||||
PsiElement(Jai::)(':')(161,162)
|
||||
JaiMulExprImpl(MUL_EXPR)(163,185)
|
||||
JaiPrefixExprImpl(PREFIX_EXPR)(163,165)
|
||||
PsiElement(Jai:$)('$')(163,164)
|
||||
JaiRefExprImpl(REF_EXPR)(164,165)
|
||||
PsiElement(Jai:IDENT)('T')(164,165)
|
||||
PsiElement(Jai:/)('/')(165,166)
|
||||
JaiInterfaceExprImpl(INTERFACE_EXPR)(166,185)
|
||||
PsiElement(Jai:interface)('interface')(166,175)
|
||||
JaiRefExprImpl(REF_EXPR)(176,185)
|
||||
PsiElement(Jai:IDENT)('Matchable')(176,185)
|
||||
PsiElement(Jai:))(')')(185,186)
|
||||
PsiElement(Jai:->)('->')(187,189)
|
||||
JaiReturnItemImpl(RETURN_ITEM)(190,191)
|
||||
JaiRefExprImpl(REF_EXPR)(190,191)
|
||||
PsiElement(Jai:IDENT)('T')(190,191)
|
||||
JaiBlockImpl(BLOCK)(192,205)
|
||||
PsiElement(Jai:{)('{')(192,193)
|
||||
JaiStatementImpl(STATEMENT)(194,203)
|
||||
JaiReturnStatementImpl(RETURN_STATEMENT)(194,203)
|
||||
PsiElement(Jai:return)('return')(194,200)
|
||||
JaiRefExprImpl(REF_EXPR)(201,202)
|
||||
PsiElement(Jai:IDENT)('x')(201,202)
|
||||
PsiElement(Jai:;)(';')(202,203)
|
||||
PsiElement(Jai:})('}')(204,205)
|
||||
JaiStatementImpl(STATEMENT)(206,269)
|
||||
JaiDeclarationImpl(DECLARATION)(206,269)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(206,218)
|
||||
JaiDeclNameImpl(DECL_NAME)(206,218)
|
||||
PsiElement(Jai:IDENT)('foreign_proc')(206,218)
|
||||
PsiElement(Jai:::)('::')(219,221)
|
||||
JaiInitializerImpl(INITIALIZER)(222,268)
|
||||
JaiProcLiteralExprImpl(PROC_LITERAL_EXPR)(222,268)
|
||||
PsiElement(Jai:()('(')(222,223)
|
||||
JaiParameterImpl(PARAMETER)(223,230)
|
||||
JaiParamNamesImpl(PARAM_NAMES)(223,225)
|
||||
JaiParamNameImpl(PARAM_NAME)(223,225)
|
||||
PsiElement(Jai:IDENT)('fd')(223,225)
|
||||
PsiElement(Jai::)(':')(225,226)
|
||||
JaiRefExprImpl(REF_EXPR)(227,230)
|
||||
PsiElement(Jai:IDENT)('s32')(227,230)
|
||||
PsiElement(Jai:))(')')(230,231)
|
||||
PsiElement(Jai:->)('->')(232,234)
|
||||
JaiReturnItemImpl(RETURN_ITEM)(235,238)
|
||||
JaiRefExprImpl(REF_EXPR)(235,238)
|
||||
PsiElement(Jai:IDENT)('s32')(235,238)
|
||||
JaiProcModifierImpl(PROC_MODIFIER)(239,268)
|
||||
JaiDirectiveExprImpl(DIRECTIVE_EXPR)(239,268)
|
||||
PsiElement(Jai:DIRECTIVE)('#foreign')(239,247)
|
||||
JaiRefExprImpl(REF_EXPR)(248,252)
|
||||
PsiElement(Jai:IDENT)('libc')(248,252)
|
||||
PsiElement(Jai:STRING)('"inotify_init1"')(253,268)
|
||||
PsiElement(Jai:;)(';')(268,269)
|
||||
JaiStatementImpl(STATEMENT)(270,293)
|
||||
JaiDeclarationImpl(DECLARATION)(270,293)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(270,276)
|
||||
JaiDeclNameImpl(DECL_NAME)(270,276)
|
||||
PsiElement(Jai:IDENT)('lambda')(270,276)
|
||||
PsiElement(Jai:::)('::')(277,279)
|
||||
JaiInitializerImpl(INITIALIZER)(280,292)
|
||||
JaiLambdaExprImpl(LAMBDA_EXPR)(280,292)
|
||||
JaiRefExprImpl(REF_EXPR)(280,281)
|
||||
PsiElement(Jai:IDENT)('x')(280,281)
|
||||
PsiElement(Jai:=>)('=>')(282,284)
|
||||
JaiMemberExprImpl(MEMBER_EXPR)(285,292)
|
||||
JaiRefExprImpl(REF_EXPR)(285,286)
|
||||
PsiElement(Jai:IDENT)('x')(285,286)
|
||||
PsiElement(Jai:.)('.')(286,287)
|
||||
JaiMemberNameImpl(MEMBER_NAME)(287,292)
|
||||
PsiElement(Jai:IDENT)('count')(287,292)
|
||||
PsiElement(Jai:;)(';')(292,293)
|
||||
@@ -1,4 +0,0 @@
|
||||
a : float = 37.0;
|
||||
b := 10;
|
||||
c :: 42;
|
||||
return a + b;
|
||||
@@ -1,44 +0,0 @@
|
||||
Jai File(0,49)
|
||||
JaiStatementImpl(STATEMENT)(0,17)
|
||||
JaiDeclarationImpl(DECLARATION)(0,17)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(0,1)
|
||||
JaiDeclNameImpl(DECL_NAME)(0,1)
|
||||
PsiElement(Jai:IDENT)('a')(0,1)
|
||||
PsiElement(Jai::)(':')(2,3)
|
||||
JaiRefExprImpl(REF_EXPR)(4,9)
|
||||
PsiElement(Jai:IDENT)('float')(4,9)
|
||||
PsiElement(Jai:=)('=')(10,11)
|
||||
JaiInitializerImpl(INITIALIZER)(12,16)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(12,16)
|
||||
PsiElement(Jai:NUMBER)('37.0')(12,16)
|
||||
PsiElement(Jai:;)(';')(16,17)
|
||||
JaiStatementImpl(STATEMENT)(18,26)
|
||||
JaiDeclarationImpl(DECLARATION)(18,26)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(18,19)
|
||||
JaiDeclNameImpl(DECL_NAME)(18,19)
|
||||
PsiElement(Jai:IDENT)('b')(18,19)
|
||||
PsiElement(Jai::=)(':=')(20,22)
|
||||
JaiInitializerImpl(INITIALIZER)(23,25)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(23,25)
|
||||
PsiElement(Jai:NUMBER)('10')(23,25)
|
||||
PsiElement(Jai:;)(';')(25,26)
|
||||
JaiStatementImpl(STATEMENT)(27,35)
|
||||
JaiDeclarationImpl(DECLARATION)(27,35)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(27,28)
|
||||
JaiDeclNameImpl(DECL_NAME)(27,28)
|
||||
PsiElement(Jai:IDENT)('c')(27,28)
|
||||
PsiElement(Jai:::)('::')(29,31)
|
||||
JaiInitializerImpl(INITIALIZER)(32,34)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(32,34)
|
||||
PsiElement(Jai:NUMBER)('42')(32,34)
|
||||
PsiElement(Jai:;)(';')(34,35)
|
||||
JaiStatementImpl(STATEMENT)(36,49)
|
||||
JaiReturnStatementImpl(RETURN_STATEMENT)(36,49)
|
||||
PsiElement(Jai:return)('return')(36,42)
|
||||
JaiAddExprImpl(ADD_EXPR)(43,48)
|
||||
JaiRefExprImpl(REF_EXPR)(43,44)
|
||||
PsiElement(Jai:IDENT)('a')(43,44)
|
||||
PsiElement(Jai:+)('+')(45,46)
|
||||
JaiRefExprImpl(REF_EXPR)(47,48)
|
||||
PsiElement(Jai:IDENT)('b')(47,48)
|
||||
PsiElement(Jai:;)(';')(48,49)
|
||||
9
src/test/testData/parsing/Types.jai
Normal file
9
src/test/testData/parsing/Types.jai
Normal file
@@ -0,0 +1,9 @@
|
||||
Person :: struct { name: string; }
|
||||
Holder :: struct ($T: Type, $N: s64) { }
|
||||
Fruits :: enum u32 #specified { BANANA :: 5; APPLE; }
|
||||
Flags :: enum_flags u8 { A :: 0x1; }
|
||||
U :: union { a: int; b: float; }
|
||||
Phone :: [9] u8;
|
||||
view: [] float;
|
||||
dynamic: [..] int;
|
||||
pointer: *Person;
|
||||
190
src/test/testData/parsing/Types.txt
Normal file
190
src/test/testData/parsing/Types.txt
Normal file
@@ -0,0 +1,190 @@
|
||||
Jai File(0,269)
|
||||
JaiStatementImpl(STATEMENT)(0,34)
|
||||
JaiDeclarationImpl(DECLARATION)(0,34)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(0,6)
|
||||
JaiDeclNameImpl(DECL_NAME)(0,6)
|
||||
PsiElement(Jai:IDENT)('Person')(0,6)
|
||||
PsiElement(Jai:::)('::')(7,9)
|
||||
JaiInitializerImpl(INITIALIZER)(10,34)
|
||||
JaiStructExprImpl(STRUCT_EXPR)(10,34)
|
||||
PsiElement(Jai:struct)('struct')(10,16)
|
||||
JaiBlockImpl(BLOCK)(17,34)
|
||||
PsiElement(Jai:{)('{')(17,18)
|
||||
JaiStatementImpl(STATEMENT)(19,32)
|
||||
JaiDeclarationImpl(DECLARATION)(19,32)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(19,23)
|
||||
JaiDeclNameImpl(DECL_NAME)(19,23)
|
||||
PsiElement(Jai:IDENT)('name')(19,23)
|
||||
PsiElement(Jai::)(':')(23,24)
|
||||
JaiRefExprImpl(REF_EXPR)(25,31)
|
||||
PsiElement(Jai:IDENT)('string')(25,31)
|
||||
PsiElement(Jai:;)(';')(31,32)
|
||||
PsiElement(Jai:})('}')(33,34)
|
||||
JaiStatementImpl(STATEMENT)(35,75)
|
||||
JaiDeclarationImpl(DECLARATION)(35,75)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(35,41)
|
||||
JaiDeclNameImpl(DECL_NAME)(35,41)
|
||||
PsiElement(Jai:IDENT)('Holder')(35,41)
|
||||
PsiElement(Jai:::)('::')(42,44)
|
||||
JaiInitializerImpl(INITIALIZER)(45,75)
|
||||
JaiStructExprImpl(STRUCT_EXPR)(45,75)
|
||||
PsiElement(Jai:struct)('struct')(45,51)
|
||||
PsiElement(Jai:()('(')(52,53)
|
||||
JaiParameterImpl(PARAMETER)(53,61)
|
||||
JaiParamNamesImpl(PARAM_NAMES)(53,55)
|
||||
JaiParamNameImpl(PARAM_NAME)(53,55)
|
||||
PsiElement(Jai:$)('$')(53,54)
|
||||
PsiElement(Jai:IDENT)('T')(54,55)
|
||||
PsiElement(Jai::)(':')(55,56)
|
||||
JaiRefExprImpl(REF_EXPR)(57,61)
|
||||
PsiElement(Jai:IDENT)('Type')(57,61)
|
||||
PsiElement(Jai:,)(',')(61,62)
|
||||
JaiParameterImpl(PARAMETER)(63,70)
|
||||
JaiParamNamesImpl(PARAM_NAMES)(63,65)
|
||||
JaiParamNameImpl(PARAM_NAME)(63,65)
|
||||
PsiElement(Jai:$)('$')(63,64)
|
||||
PsiElement(Jai:IDENT)('N')(64,65)
|
||||
PsiElement(Jai::)(':')(65,66)
|
||||
JaiRefExprImpl(REF_EXPR)(67,70)
|
||||
PsiElement(Jai:IDENT)('s64')(67,70)
|
||||
PsiElement(Jai:))(')')(70,71)
|
||||
JaiBlockImpl(BLOCK)(72,75)
|
||||
PsiElement(Jai:{)('{')(72,73)
|
||||
PsiElement(Jai:})('}')(74,75)
|
||||
JaiStatementImpl(STATEMENT)(76,129)
|
||||
JaiDeclarationImpl(DECLARATION)(76,129)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(76,82)
|
||||
JaiDeclNameImpl(DECL_NAME)(76,82)
|
||||
PsiElement(Jai:IDENT)('Fruits')(76,82)
|
||||
PsiElement(Jai:::)('::')(83,85)
|
||||
JaiInitializerImpl(INITIALIZER)(86,129)
|
||||
JaiEnumExprImpl(ENUM_EXPR)(86,129)
|
||||
PsiElement(Jai:enum)('enum')(86,90)
|
||||
JaiRefExprImpl(REF_EXPR)(91,94)
|
||||
PsiElement(Jai:IDENT)('u32')(91,94)
|
||||
JaiProcModifierImpl(PROC_MODIFIER)(95,105)
|
||||
JaiDirectiveExprImpl(DIRECTIVE_EXPR)(95,105)
|
||||
PsiElement(Jai:DIRECTIVE)('#specified')(95,105)
|
||||
JaiBlockImpl(BLOCK)(106,129)
|
||||
PsiElement(Jai:{)('{')(106,107)
|
||||
JaiStatementImpl(STATEMENT)(108,120)
|
||||
JaiDeclarationImpl(DECLARATION)(108,120)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(108,114)
|
||||
JaiDeclNameImpl(DECL_NAME)(108,114)
|
||||
PsiElement(Jai:IDENT)('BANANA')(108,114)
|
||||
PsiElement(Jai:::)('::')(115,117)
|
||||
JaiInitializerImpl(INITIALIZER)(118,119)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(118,119)
|
||||
PsiElement(Jai:NUMBER)('5')(118,119)
|
||||
PsiElement(Jai:;)(';')(119,120)
|
||||
JaiStatementImpl(STATEMENT)(121,127)
|
||||
JaiExpressionStatementImpl(EXPRESSION_STATEMENT)(121,127)
|
||||
JaiRefExprImpl(REF_EXPR)(121,126)
|
||||
PsiElement(Jai:IDENT)('APPLE')(121,126)
|
||||
PsiElement(Jai:;)(';')(126,127)
|
||||
PsiElement(Jai:})('}')(128,129)
|
||||
JaiStatementImpl(STATEMENT)(130,166)
|
||||
JaiDeclarationImpl(DECLARATION)(130,166)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(130,135)
|
||||
JaiDeclNameImpl(DECL_NAME)(130,135)
|
||||
PsiElement(Jai:IDENT)('Flags')(130,135)
|
||||
PsiElement(Jai:::)('::')(136,138)
|
||||
JaiInitializerImpl(INITIALIZER)(139,166)
|
||||
JaiEnumExprImpl(ENUM_EXPR)(139,166)
|
||||
PsiElement(Jai:enum_flags)('enum_flags')(139,149)
|
||||
JaiRefExprImpl(REF_EXPR)(150,152)
|
||||
PsiElement(Jai:IDENT)('u8')(150,152)
|
||||
JaiBlockImpl(BLOCK)(153,166)
|
||||
PsiElement(Jai:{)('{')(153,154)
|
||||
JaiStatementImpl(STATEMENT)(155,164)
|
||||
JaiDeclarationImpl(DECLARATION)(155,164)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(155,156)
|
||||
JaiDeclNameImpl(DECL_NAME)(155,156)
|
||||
PsiElement(Jai:IDENT)('A')(155,156)
|
||||
PsiElement(Jai:::)('::')(157,159)
|
||||
JaiInitializerImpl(INITIALIZER)(160,163)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(160,163)
|
||||
PsiElement(Jai:NUMBER)('0x1')(160,163)
|
||||
PsiElement(Jai:;)(';')(163,164)
|
||||
PsiElement(Jai:})('}')(165,166)
|
||||
JaiStatementImpl(STATEMENT)(167,199)
|
||||
JaiDeclarationImpl(DECLARATION)(167,199)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(167,168)
|
||||
JaiDeclNameImpl(DECL_NAME)(167,168)
|
||||
PsiElement(Jai:IDENT)('U')(167,168)
|
||||
PsiElement(Jai:::)('::')(169,171)
|
||||
JaiInitializerImpl(INITIALIZER)(172,199)
|
||||
JaiUnionExprImpl(UNION_EXPR)(172,199)
|
||||
PsiElement(Jai:union)('union')(172,177)
|
||||
JaiBlockImpl(BLOCK)(178,199)
|
||||
PsiElement(Jai:{)('{')(178,179)
|
||||
JaiStatementImpl(STATEMENT)(180,187)
|
||||
JaiDeclarationImpl(DECLARATION)(180,187)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(180,181)
|
||||
JaiDeclNameImpl(DECL_NAME)(180,181)
|
||||
PsiElement(Jai:IDENT)('a')(180,181)
|
||||
PsiElement(Jai::)(':')(181,182)
|
||||
JaiRefExprImpl(REF_EXPR)(183,186)
|
||||
PsiElement(Jai:IDENT)('int')(183,186)
|
||||
PsiElement(Jai:;)(';')(186,187)
|
||||
JaiStatementImpl(STATEMENT)(188,197)
|
||||
JaiDeclarationImpl(DECLARATION)(188,197)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(188,189)
|
||||
JaiDeclNameImpl(DECL_NAME)(188,189)
|
||||
PsiElement(Jai:IDENT)('b')(188,189)
|
||||
PsiElement(Jai::)(':')(189,190)
|
||||
JaiRefExprImpl(REF_EXPR)(191,196)
|
||||
PsiElement(Jai:IDENT)('float')(191,196)
|
||||
PsiElement(Jai:;)(';')(196,197)
|
||||
PsiElement(Jai:})('}')(198,199)
|
||||
JaiStatementImpl(STATEMENT)(200,216)
|
||||
JaiDeclarationImpl(DECLARATION)(200,216)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(200,205)
|
||||
JaiDeclNameImpl(DECL_NAME)(200,205)
|
||||
PsiElement(Jai:IDENT)('Phone')(200,205)
|
||||
PsiElement(Jai:::)('::')(206,208)
|
||||
JaiInitializerImpl(INITIALIZER)(209,215)
|
||||
JaiArrayTypeExprImpl(ARRAY_TYPE_EXPR)(209,215)
|
||||
PsiElement(Jai:[)('[')(209,210)
|
||||
JaiLiteralExprImpl(LITERAL_EXPR)(210,211)
|
||||
PsiElement(Jai:NUMBER)('9')(210,211)
|
||||
PsiElement(Jai:])(']')(211,212)
|
||||
JaiRefExprImpl(REF_EXPR)(213,215)
|
||||
PsiElement(Jai:IDENT)('u8')(213,215)
|
||||
PsiElement(Jai:;)(';')(215,216)
|
||||
JaiStatementImpl(STATEMENT)(217,232)
|
||||
JaiDeclarationImpl(DECLARATION)(217,232)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(217,221)
|
||||
JaiDeclNameImpl(DECL_NAME)(217,221)
|
||||
PsiElement(Jai:IDENT)('view')(217,221)
|
||||
PsiElement(Jai::)(':')(221,222)
|
||||
JaiArrayTypeExprImpl(ARRAY_TYPE_EXPR)(223,231)
|
||||
PsiElement(Jai:[)('[')(223,224)
|
||||
PsiElement(Jai:])(']')(224,225)
|
||||
JaiRefExprImpl(REF_EXPR)(226,231)
|
||||
PsiElement(Jai:IDENT)('float')(226,231)
|
||||
PsiElement(Jai:;)(';')(231,232)
|
||||
JaiStatementImpl(STATEMENT)(233,251)
|
||||
JaiDeclarationImpl(DECLARATION)(233,251)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(233,240)
|
||||
JaiDeclNameImpl(DECL_NAME)(233,240)
|
||||
PsiElement(Jai:IDENT)('dynamic')(233,240)
|
||||
PsiElement(Jai::)(':')(240,241)
|
||||
JaiArrayTypeExprImpl(ARRAY_TYPE_EXPR)(242,250)
|
||||
PsiElement(Jai:[)('[')(242,243)
|
||||
PsiElement(Jai:..)('..')(243,245)
|
||||
PsiElement(Jai:])(']')(245,246)
|
||||
JaiRefExprImpl(REF_EXPR)(247,250)
|
||||
PsiElement(Jai:IDENT)('int')(247,250)
|
||||
PsiElement(Jai:;)(';')(250,251)
|
||||
JaiStatementImpl(STATEMENT)(252,269)
|
||||
JaiDeclarationImpl(DECLARATION)(252,269)
|
||||
JaiDeclNamesImpl(DECL_NAMES)(252,259)
|
||||
JaiDeclNameImpl(DECL_NAME)(252,259)
|
||||
PsiElement(Jai:IDENT)('pointer')(252,259)
|
||||
PsiElement(Jai::)(':')(259,260)
|
||||
JaiPrefixExprImpl(PREFIX_EXPR)(261,268)
|
||||
PsiElement(Jai:*)('*')(261,262)
|
||||
JaiRefExprImpl(REF_EXPR)(262,268)
|
||||
PsiElement(Jai:IDENT)('Person')(262,268)
|
||||
PsiElement(Jai:;)(';')(268,269)
|
||||
Reference in New Issue
Block a user