Skip to content

Commit

Permalink
flesh out proper parser versioning
Browse files Browse the repository at this point in the history
  • Loading branch information
jrudolph committed Jun 7, 2010
1 parent e0f28de commit 4bbc632
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 12 deletions.
20 changes: 19 additions & 1 deletion src/main/scala/net/virtualvoid/string/ESParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,25 @@ object AST{

class ParseException(msg:String) extends Exception(msg)

object EnhancedStringFormatParser extends RegexParsers{
// syntax flavor name and version
case class VersionInfo(flavor: String, version: Int)

trait ESParser {
def parse(input:String): AST.FormatElementList
def Version: VersionInfo
}

object ParserFactory {
val defaultVersion: VersionInfo = VersionInfo("poros", 1)
def parser(info: VersionInfo = defaultVersion): Option[ESParser] = info match {
case EnhancedStringFormatParser.Version => Some(EnhancedStringFormatParser)
case _ => None
}
}

object EnhancedStringFormatParser extends RegexParsers with ESParser {
val Version = VersionInfo("poros", 1)

import AST._

override type Elem = Char
Expand Down
40 changes: 29 additions & 11 deletions src/main/scala/net/virtualvoid/string/EnhancedStringsPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class EnhancedStringsPlugin(val global: Global) extends Plugin {

class ESTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
localTyper = analyzer.newTyper(analyzer.rootContext(unit, EmptyTree, false))
import unit.error

val it = ValDef(Modifiers(Flags.PARAM), "it", TypeTree(), EmptyTree)

Expand Down Expand Up @@ -95,8 +96,8 @@ class EnhancedStringsPlugin(val global: Global) extends Plugin {
def postTransform(tree: Tree): Tree = tree match {
case Literal(Constant(str: String)) =>
try {
println(version)
atPos(tree.pos)(compiled(EnhancedStringFormatParser.parse(str), tree.pos))
println(parser.get.Version)
atPos(tree.pos)(compiled(parser.get.parse(str), tree.pos))
} catch {
case p: ParseException => p.printStackTrace; unit.error(tree.pos, p.getMessage); tree
case e: TypeError => localTyper.reportTypeError(tree.pos, e); tree
Expand All @@ -106,35 +107,52 @@ class EnhancedStringsPlugin(val global: Global) extends Plugin {

val ESType = "EnhancedString".toTypeName
val SyntaxParam = "syntax".toTermName
val versionExtractor: PartialFunction[Tree, String] = { case Apply(Select(New(Ident(ESType)), nme.CONSTRUCTOR), List(AssignOrNamedArg(Ident(SyntaxParam), Literal(Constant(version: String))))) => version }
val VersionParam = "version".toTermName

val annotationMatcher: PartialFunction[Tree, List[Tree]] = { case Apply(Select(New(Ident(ESType)), nme.CONSTRUCTOR), args) => args }

def versionExtractor(cur: VersionInfo, arg: Tree): VersionInfo = arg match {
case AssignOrNamedArg(Ident(SyntaxParam), Literal(Constant(flavor: String))) => cur.copy(flavor = flavor)
case AssignOrNamedArg(Ident(SyntaxParam), c@Literal(Constant(flavor))) => error(c.pos, "The "+SyntaxParam+" attribute of "+ESType+" must be a String value"); cur

case AssignOrNamedArg(Ident(VersionParam), Literal(Constant(version: Int))) => cur.copy(version = version)
case AssignOrNamedArg(Ident(VersionParam), c@Literal(Constant(version))) => error(c.pos, "The "+VersionParam+" attribute of "+ESType+" must be an integer value"); cur

case _ => error(arg.pos, "Unknown parameter of "+ESType+": "+arg); cur
}

def extractVersion(m: Modifiers): (Modifiers, Option[String]) = m match {
def extractVersion(m: Modifiers): (Modifiers, Option[VersionInfo]) = m match {
case Modifiers(a, b, anns, d) =>
val (version, rest) = anns.partition(versionExtractor.isDefinedAt _)
val (args, rest) = anns.partition(annotationMatcher.isDefinedAt _)

(Modifiers(a, b, rest, d), version.headOption.map(versionExtractor))
(Modifiers(a, b, rest, d), args.headOption.map(annotationMatcher).map(args => args.foldLeft(ParserFactory.defaultVersion)(versionExtractor)))
case _ => (m, None)
}

var version: Option[String] = None
var parser: Option[ESParser] = None

override def transform(tree: Tree): Tree = tree match {
case d@DefDef(mods, _, _, _, _, _) =>
val (newMods, newVersion) = extractVersion(mods)

newVersion match {
case Some(v) =>
val old = version
version = Some(v)
val oldParser = parser

parser = ParserFactory.parser(v)
if (!parser.isDefined)
error(d.pos, "EnhancedString syntax with version "+v+" not found.")

println("Version now " + v)
val res = super.transform(tree)
version = old

parser = oldParser
res.asInstanceOf[DefDef].copy(mods = newMods)
case None =>
super.transform(tree)
}
case Apply(Select(New(Ident(ESType)), nme.CONSTRUCTOR), List(x)) => println(x.getClass); super.transform(tree)
case _ if version.isDefined => postTransform(super.transform(tree))
case _ if parser.isDefined => postTransform(super.transform(tree))
case _ => super.transform(tree)
}
}
Expand Down

0 comments on commit 4bbc632

Please sign in to comment.