Skip to content

Commit

Permalink
Fix braced list properly
Browse files Browse the repository at this point in the history
  • Loading branch information
sblundy committed Aug 11, 2019
1 parent 06f159a commit 189ed79
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 116 deletions.
14 changes: 7 additions & 7 deletions src/gen/com/github/sblundy/elvish/lang/ElvishParser.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/gen/com/github/sblundy/elvish/psi/ElvishBraced.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/gen/com/github/sblundy/elvish/psi/ElvishTypes.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions src/main/grammars/Elvish.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
BAREWORD_CHAR="regexp:[./@%+!]"
VARIABLE_CHAR="regexp:[0-9a-zA-Z\-_:~]"
COMMAND_BAREWORD_CHAR="regexp:[<>*^]"
BRACED_SEPARATOR="[, ]+"
WILDCARD="*"
KEYWORD_ELSE="else"
KEYWORD_ELIF="elif"
Expand Down Expand Up @@ -113,8 +114,8 @@ OutputCapture ::= OPEN_PARAN Chunk CLOSE_PARAN
Lambda ::= LambdaArguments? OPEN_BRACE Chunk CLOSE_BRACE
LambdaArguments ::=OPEN_BRACKET Space? ((parameter | MapPair) Space?)* CLOSE_BRACKET
parameter ::= AT_SYMBOL? Compound
Braced ::= OPEN_BRACE (Space | EOL)* Compound (BracedSep* Compound)* (Space | EOL)* CLOSE_BRACE
BracedSep ::= (Space | EOL)* ',' (Space | EOL)*
Braced ::= OPEN_BRACE (Space | EOL)* Bareword (BracedSep* Bareword)* (Space | EOL)* CLOSE_BRACE
BracedSep ::= (Space | EOL)* <<parseCommaAsSeparator>> (Space | EOL)*

// Special Commands

Expand Down
97 changes: 7 additions & 90 deletions src/main/kotlin/com/github/sblundy/elvish/lang/parserUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@

package com.github.sblundy.elvish.lang

import com.github.sblundy.elvish.ElvishBundle
import com.github.sblundy.elvish.psi.ElvishTypes
import com.github.sblundy.elvish.psi.ElvishTypes.CONTINUATION
import com.intellij.lang.PsiBuilder
import com.intellij.lang.parser.GeneratedParserUtilBase
import com.intellij.psi.tree.TokenSet

private val keywords = setOf(
ElvishTypes.KEYWORD_DEL,
Expand All @@ -21,94 +17,15 @@ private val keywords = setOf(
ElvishTypes.KEYWORD_TRY,
ElvishTypes.KEYWORD_WHILE)

fun parseKeywordAsBareword(builder: PsiBuilder, level: Int): Boolean {
if (!(builder.tokenType in keywords)) return false
builder.remapCurrentToken(ElvishTypes.BAREWORD_CHAR)
return true
}

fun parseArgList(
builder: PsiBuilder,
level: Int,
arg: GeneratedParserUtilBase.Parser,
lineTerminator: GeneratedParserUtilBase.Parser
): Boolean {
if (!GeneratedParserUtilBase.recursion_guard_(builder, level, "parseArgList")) return false
while (true) {
val pos_ = GeneratedParserUtilBase.current_position_(builder)
GeneratedParserUtilBase.consumeToken(builder, CONTINUATION)
val result = lineTerminator.parse(builder, level)
if (result) return true
val marker = builder.mark()
if (!arg.parse(builder, level)) {
marker.drop()
break
} else if (builder.trailingWhitespaceContainsEOL(builder.currentOffset)) {
marker.rollbackTo()
builder.remap(builder.whiteSpaceRange())
arg.parse(builder, level)
lineTerminator.parse(builder, level)
break
}
marker.drop()
if (!GeneratedParserUtilBase.empty_element_parsed_guard_(builder, "parseArgList", pos_)) break
}
fun parseCommaAsSeparator(builder: PsiBuilder, level: Int): Boolean {
if (builder.tokenText != ",") return false
builder.remapCurrentToken(ElvishTypes.BRACED_SEPARATOR)
builder.advanceLexer()
return true
}

fun parseBlockBody(
builder: PsiBuilder,
level: Int,
command: GeneratedParserUtilBase.Parser
): Boolean {
if (!GeneratedParserUtilBase.recursion_guard_(builder, level, "parseBlockBody")) return false
while (true) {
val pos_ = GeneratedParserUtilBase.current_position_(builder)
if (!command.parse(builder, level)) {
if (builder.tokenType == ElvishTypes.CLOSE_BRACE) {
break
}

val marker = builder.mark()
skipCountingBraces(builder, TokenSet.create(ElvishTypes.CLOSE_BRACE))
marker.error(ElvishBundle.message("psi.error.command"))
}
if (!GeneratedParserUtilBase.empty_element_parsed_guard_(builder, "parseBlockBody", pos_)) break
}
fun parseKeywordAsBareword(builder: PsiBuilder, level: Int): Boolean {
if (!(builder.tokenType in keywords)) return false
builder.remapCurrentToken(ElvishTypes.BAREWORD_CHAR)
return true
}

fun parseCompoundExpressionSegment(builder: PsiBuilder,
level: Int,
parser: GeneratedParserUtilBase.Parser,
following: GeneratedParserUtilBase.Parser): Boolean {
if (!GeneratedParserUtilBase.recursion_guard_(builder, level, "parseCompoundExpressionSegment")) return false
val marker_ = GeneratedParserUtilBase.enter_section_(builder)
var result: Boolean = parser.parse(builder, level) && !builder.hasTrailingWhitespace()
if (result) {
result = following.parse(builder, level)
}

GeneratedParserUtilBase.exit_section_(builder, marker_, null, result)
return result
}

private fun skipCountingBraces(builder: PsiBuilder, until: TokenSet): Boolean {
var braceLevel = 0
while (true) {
if (builder.eof()) {
return false
}
val type = builder.tokenType
if (braceLevel == 0 && until.contains(type)) {
return true
}

if (ElvishTypes.OPEN_BRACE === type) {
braceLevel++
} else if (ElvishTypes.CLOSE_BRACE === type) {
braceLevel--
}
builder.advanceLexer()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ElvishTokenType.VARIABLE_CHAR ('ls')
ElvishTokenType.INLINE_WHITESPACE (' ')
ElvishTokenType.VARIABLE_CHAR ('01')
ElvishTokenType.BAREWORD_CHAR ('/')
ElvishTokenType.{ ('{')
ElvishTokenType.VARIABLE_CHAR ('03')
BAD_CHARACTER (',')
ElvishTokenType.VARIABLE_CHAR ('10')
BAD_CHARACTER (',')
ElvishTokenType.VARIABLE_CHAR ('17')
ElvishTokenType.} ('}')
ElvishTokenType.BAREWORD_CHAR ('/')
ElvishTokenType.VARIABLE_CHAR ('2000-logs')
ElvishTokenType.BAREWORD_CHAR ('.')
ElvishTokenType.VARIABLE_CHAR ('txt')
19 changes: 8 additions & 11 deletions src/test/resources/com/github/sblundy/elvish/lang/braced-list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,16 @@ Elvish File
PsiElement(ElvishTokenType.BAREWORD_CHAR)('/')
ElvishBracedImpl(BRACED)
PsiElement(ElvishTokenType.{)('{')
ElvishCompoundImpl(COMPOUND)
ElvishBarewordImpl(BAREWORD)
PsiElement(ElvishTokenType.VARIABLE_CHAR)('03')
ElvishBarewordImpl(BAREWORD)
PsiElement(ElvishTokenType.VARIABLE_CHAR)('03')
ElvishBracedSepImpl(BRACED_SEP)
PsiElement(BAD_CHARACTER)(',')
ElvishCompoundImpl(COMPOUND)
ElvishBarewordImpl(BAREWORD)
PsiElement(ElvishTokenType.VARIABLE_CHAR)('10')
PsiElement(ElvishTokenType.[, ]+)(',')
ElvishBarewordImpl(BAREWORD)
PsiElement(ElvishTokenType.VARIABLE_CHAR)('10')
ElvishBracedSepImpl(BRACED_SEP)
PsiElement(BAD_CHARACTER)(',')
ElvishCompoundImpl(COMPOUND)
ElvishBarewordImpl(BAREWORD)
PsiElement(ElvishTokenType.VARIABLE_CHAR)('17')
PsiElement(ElvishTokenType.[, ]+)(',')
ElvishBarewordImpl(BAREWORD)
PsiElement(ElvishTokenType.VARIABLE_CHAR)('17')
PsiElement(ElvishTokenType.})('}')
ElvishBarewordImpl(BAREWORD)
PsiElement(ElvishTokenType.BAREWORD_CHAR)('/')
Expand Down

0 comments on commit 189ed79

Please sign in to comment.