Skip to content

Commit

Permalink
Issue #2: Changed parser to distinguish keywords from identifiers.
Browse files Browse the repository at this point in the history
  • Loading branch information
cliu369 committed Jun 11, 2024
1 parent 88075d4 commit 4c50b40
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 11 deletions.
11 changes: 8 additions & 3 deletions src/main/scala/gvc/parser/Lexer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ import fastparse._
trait Lexer extends Whitespace {
def ident[_: P] =
P(CharIn("A-Za-z_") ~~ CharIn("A-Za-z0-9_").repX)

def identifier[_: P] =
P(span(ident.!)).map({
P(span(!keywords ~ ident.!)).map({
case (id, span) => Identifier(id, span)
})

def keywords[_: P] = {
StringIn("while", "if", "for", "assert", "NULL", "else", "true",
"false", "struct", "alloc", "alloc_array", "typedef", "error", "return",
"int", "char", "bool", "void") ~~ !CharIn("A-Za-z0-9_")
}

def decimalNumber[_: P] =
P("0" | (CharIn("1-9") ~~ CharIn("0-9").repX))
Expand All @@ -23,7 +29,6 @@ trait Lexer extends Whitespace {
def library[_: P] = P("<" ~~/ libraryChar.repX ~~ ">")

def stringChar[_: P] = P(normalChar | escape)

def charChar[_: P] = P(normalChar | escape | "\"" | "\\0")

def normalChar[_: P] =
Expand Down
37 changes: 29 additions & 8 deletions src/main/scala/gvc/parser/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,46 @@ import fastparse._

trait Types extends Lexer {
def typeReference[_: P]: P[Type] =
P(pos ~~ kw("struct").!.? ~ identifier ~ typeModifier.rep)
P(pos ~~ structReference ~ typeModifier.rep)
.map({
case (start, hasStruct, id, modifiers) => {
case (start, (hasStruct, id), modifiers) => {
val baseSpan = SourceSpan(start, id.span.end)
val baseType = hasStruct match {
case None => NamedType(id, baseSpan)
case Some(_) => NamedStructType(id, baseSpan)
}
val baseType = if (hasStruct) {
NamedStructType(id, baseSpan)
} else { NamedType(id, baseSpan) }

modifiers.foldLeft(baseType)((t, mod) => {
val span = SourceSpan(start, mod.end)
mod match {
mod match {
case _: PointerModifier => PointerType(t, span)
case _: ArrayModifier => ArrayType(t, span)
}
})
}
} })

//If struct, cannot be followed by int, void, bool, or char, must be identifier.
//If not struct, can be int, void, bool, char or identifier.
def structReference[_: P]: P[(Boolean, Identifier)] =
P(kw("struct").!.?.flatMap({
case None => typeIdentifier.map({
case(id) => (false, id)
})
case Some(_) => identifier.map({
case(id) => (true, id)
})
}))

def typeIdentifier[_: P]: P[Identifier] =
P(span(!typeKeywords ~ ident.!)).map({
case(id, span) => Identifier(id ,span)
})

def typeKeywords[_: P] = {
StringIn("while", "if", "for", "assert", "NULL", "else", "true",
"false", "struct", "alloc", "alloc_array", "typedef", "error", "return") ~~
!CharIn("A-Za-z0-9_")
}

trait TypeModifier {
val end: SourcePosition
}
Expand Down

0 comments on commit 4c50b40

Please sign in to comment.