
testgen.TargetParser.scala Maven / Gradle / Ivy
/*
* Copyright 2011 Kazuhiro Sera.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package testgen
import util.parsing.combinator.JavaTokenParsers
case class TargetParser(fullPackageName: String, importList: List[String]) extends JavaTokenParsers {
type P[T] = Parser[T]
// --- main ---
def allDef = {
(prefixOfClass ~> classWithConstructorDef <~ suffixOfClass) |
(prefixOfClass ~> classDef <~ suffixOfClass) |
(prefixOfObject ~> objectDef <~ suffixOfObject) |
(prefixOfTrait ~> traitDef <~ suffixOfTrait)
}
def parse(t: P[Target], input: String): ParseResult[List[Target]] = {
// e.g. class Person(arg: Name(f:String = "", l:String), age: Bean = new Bean(,),)
val replacedInput = input.replaceAll("\\(\\s*\\)", "(,)").replaceAll("([^,])\\s*\\)", "$1,)")
parseAll(rep(t), replacedInput)
}
def parse(input: String): ParseResult[List[Target]] = parse(allDef, input)
// --- basic ---
def variableName = "\\w+".r
def packageName = "[\\w\\.]+".r
def charLiteral = "'.{1}'".r
// JavaTokenParsers's stringLiteral does not work for string contains backslash, etc..
override def stringLiteral = "\"[^(\")]+\"".r | super.stringLiteral
def literal = {
def tokenWithTypeParameters = "[\\[\\]\\w\\.]+".r
charLiteral |
stringLiteral |
floatingPointNumber |
tokenWithTypeParameters |
packageName
}
// --- type def ---
def typeName = (variableName <~ typeParametersName) | variableName
def typeParametersName: P[Any] = {
"[" <~ rep(variableName | ">:" | "<:" | "+" | "-" | "," | typeParametersName) <~ "]"
}
// --- constructor and args ---
def newLiteral: P[Any] = {
(rep(variableName) ~ "(" ~ argsInNewLiteral ~ ")")
}
def argsInNewLiteral = {
// e.g. new Something() is converted to new Something(,)
rep("," | ((newLiteral | literal) ~ ",") | newLiteral | literal)
}
def args = {
// repeat because it's possible to omit dot
// e.g. "new Something", "someList filter ( _ > 1 )"
def argDefaultValue = rep(newLiteral | literal)
def valDef = "val\\s".r
def varDef = "var\\s".r
def annotationOrValOrVarDef = rep(annotationValue | valDef | varDef)
def argsWithDefaultValue = {
annotationOrValOrVarDef ~> variableName ~ ":" ~ typeName <~ "=" <~ argDefaultValue <~ ","
}
def argsWithoutDefaultValue = {
annotationOrValOrVarDef ~> variableName ~ ":" ~ typeName <~ ","
}
rep(argsWithDefaultValue | argsWithoutDefaultValue) ^^ {
case argList => argList map {
case name ~ ":" ~ typeName => (name, typeName)
}
}
}
// --- modifier ---
def annotationValue = {
def noArg = {
"@" ~ packageName
}
def valueOnly = {
"@" ~ packageName ~ "(" ~ argsInNewLiteral ~ ")"
}
def keyAndValue = {
"@" ~ packageName ~ "(" ~ rep("," | (packageName ~ "=" ~ (newLiteral | literal))) ~ ")"
}
keyAndValue | valueOnly | noArg
}
def finalDef = "final"
def caseDef = "case"
def packagePrivateDef = "private[" ~> packageName ~> "]"
def protectedDef = "protected"
def extendsDef = "extends" ~ packageName
def withDef = rep("with" ~ packageName)
// --- class ---
def prefixOfClass = {
rep(annotationValue | packagePrivateDef | protectedDef | caseDef | finalDef)
}
def suffixOfClass = {
rep(typeParametersName | (extendsDef ~ withDef) | extendsDef)
}
def classDef = "class" ~> typeName ^^ {
name =>
{
new Target(
fullPackageName = fullPackageName,
defType = DefType.Class,
importList = importList,
typeName = name
)
}
}
def classWithConstructorDef = "class" ~> typeName ~ "(" ~ args <~ ")" ^^ {
case name ~ "(" ~ args => {
new Target(
fullPackageName = fullPackageName,
defType = DefType.Class,
importList = importList,
typeName = name,
parameters = args map {
case (name, typeName) => new TargetParameter(name, typeName)
}
)
}
}
// --- object ---
def prefixOfObject = {
rep(annotationValue | packagePrivateDef | protectedDef | caseDef | finalDef)
}
def suffixOfObject = {
rep((extendsDef ~ withDef) | extendsDef)
}
def objectDef = "object" ~> typeName ^^ {
name =>
new Target(
fullPackageName = fullPackageName,
importList = importList,
defType = DefType.Object,
typeName = name
)
}
// --- trait ---
def prefixOfTrait = {
rep(annotationValue | packagePrivateDef | protectedDef)
}
def suffixOfTrait = {
rep(typeParametersName | (extendsDef ~ withDef) | extendsDef)
}
def traitDef = "trait" ~> typeName ^^ {
name =>
new Target(
fullPackageName = fullPackageName,
importList = importList,
defType = DefType.Trait,
typeName = name
)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy