ARGENTO CUORE

 May the code be with you.

--.--.--[--] スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

2010.06.03[木] ただコードを貼り付けてみる

字句解析?を書き直してみた。当社比1/10くらいまでnewが減ったよ! 
でもまだnewしてるよ……。字句解析、全行1回済ませば終わりだし、この部分はあまりこだわらなくても平気かなー……。

class ScanLine {
val LINE_COMMENT = KEY.SHARP
val COMMENT_NONE = 0
val COMMENT_BEGIN = 1
val COMMENT_END = 2

var count = 0 //有効文字数
var comment_mode = 0 //コメントモード
val data = new Array[Byte](PREF.LINE_MAX_BUFF)

def init():Unit = {
if(comment_mode == LINE_COMMENT){
comment_mode = COMMENT_NONE
}
if(count > 0) count = 0
}

def set(ch:Int):Unit = {
checkComment(ch)
if(comment_mode == COMMENT_NONE){
//スペース以外の時、処理を実行(ただし、文字列の場合にはスペースの時も実行)
if(ch != KEY.SPACE || isString == true){
if(checkLine(ch)){
addData(KEY.NL)
}
}
}else if(comment_mode == COMMENT_END){
comment_mode = COMMENT_NONE
}
}

def getData():Array[Byte] = {
if(count > 0){
return data
}else{
return null
}
}

//文字列を保持するバッファ
val keyword_buffer = new Array[Byte](100)
//文字数をカウントする変数
var keyword_count = 0
//有効な文字が存在する場合はtrue
var isExist = false
//""で囲まれた文字リテラルの読み込み中はtrue
var isString = false

//一文字を得るためのString変数
var str:String = null
//一文字をUTF-8のバイト列に変換したものを入れる
var bytes:Array[Byte] = null

/**
* checkLine
* 行の文字列を貯めてチェックし、もし有効な文字(命令や変数や計算)が存在するならtrueを返す
*/
def checkLine(ch:Int):Boolean = {
str = String.valueOf(ch.asInstanceOf[Char])
bytes = str.getBytes("UTF-8")

if(isSplitter(ch)){
//区切り文字で、文字列内ではない場合
if(keyword_count > 0){
val key = new String(keyword_buffer, 0, keyword_count)
//キーワードに合致する場合は、それに対応するバイトコードをセット
if(!isOrder(key)){
if(isNumber(keyword_buffer(0))) addData(KEY.NUMBER) //数値
if(isVariable(keyword_buffer(0))) addData(KEY.VARIABLE) //変数
if(data(count-1) == KEY.NUMBER){
setNumber(Integer.valueOf(key).asInstanceOf[Int])//数値をバイト列に変換
}else{
for(n <- 0 until keyword_count){
addData(keyword_buffer(n)) //変数名はdataに値をそのまま入れる
}
}
}
//改行、終端でない場合はセット
if(!isEndOfLine(bytes(0))) addData(bytes(0))
keyword_count = 0
}else{
//文字列中ではなく、ブロック{}であった場合は、1文字だけでもそのままデータとしてセットする
if(!isString && isBlock(bytes(0))){
addData(bytes(0))
isExist = true
}
}
}else{
for(b <- bytes){
flipByDoubleQuote(b)
keyword_buffer(keyword_count) = b
keyword_count += 1
}
isExist = true
}
//改行かファイルの終端の場合
//文字が1つも入っていない(空行とか、コメント行)場合はfalseを返す
if(isEndOfLine(ch) && isExist){
isExist = false
return true
}
return false
}

/**
* 1バイトのデータを追加しインクリメントする
*/
def addData(d:Byte):Unit = {
data(count) = d
count += 1
}

/**
* ダブルクォートと現在文字列内かどうかを判別し、isStringの値を変更
*/
def flipByDoubleQuote(d:Byte):Unit = {
if(d == KEY.DQUOTE && isString == false){
isString = true
}else if(d == KEY.DQUOTE && isString == true){
isString = false
}
}

/**
* Int型に直したデータを受け取り、4バイト配列としてデータに追加する
*/
def setNumber(num:Int):Unit = {
addData(((num >>> 24) & 0xFF).asInstanceOf[Byte])
addData(((num >>> 16) & 0xFF).asInstanceOf[Byte])
addData(((num >>> 8) & 0xFF).asInstanceOf[Byte])
addData(((num >>> 0) & 0xFF).asInstanceOf[Byte])
}

/**
* ファイル終端、もしくは改行を判別する
*/
def isEndOfLine(ch:Int):Boolean = {
if(ch == KEY.EOF || ch == KEY.NL){
return true
}
return false
}

/**
* ブロックの場合はtrueを返す
*/
def isBlock(b:Byte):Boolean = {
if(b == KEY.RBRACE || b == KEY.LBRACE || b == KEY.LPAREN || b == KEY.RBRACE || b == KEY.LBRACKET || b == KEY.RBRACKET){
return true
}
return false
}

/**
* 命令キーワードだった場合にはtrueを返す。
* データに、命令に対応する1バイトをセット
*/
def isOrder(key:String):Boolean = {
keyword_count += 1
key match {
case ORDER.DEF => addData(KEY.DEF)
case ORDER.IF => addData(KEY.IF)
case ORDER.SWITCH => addData(KEY.SWITCH)
case ORDER.WHILE => addData(KEY.WHILE)
case ORDER.FOR => addData(KEY.FOR)
case ORDER.PRINT => addData(KEY.PRINT)
case ORDER.INPUT => addData(KEY.INPUT)
case ORDER.PIXEL => addData(KEY.PIXEL)

case _ => {
keyword_count -= 1
return false
}
}
return true
}

/**
* 変数かどうかを判別
* ""で囲まれていない文字列は全て変数として扱う。
* ただし、name()のように、後方に括弧のある変数は、間数名として扱う
*/
def isVariable(b:Byte):Boolean = {
if((b >= KEY.VAR_BEGIN1 && b <= KEY.VAR_END1) || (b >= KEY.VAR_BEGIN2 && b <= KEY.VAR_END2)){
return true
}
return false
}

/**
* 数値かどうかを判別
*/
def isNumber(b:Byte):Boolean = {
if(b >= KEY.NUMBER_BEGIN && b <= KEY.NUMBER_END) return true
return false
}

/**
* 字句解析で分割する文字の場合はtrueを返す。
* ""で囲まれた文字列には、どんな文字が来たとしてもfalseを返す。
*/
def isSplitter(ch:Int):Boolean = {
if(ch == KEY.COMMA
|| ch == KEY.PLUS
|| ch == KEY.MINUS
|| ch == KEY.SLASH
|| ch == KEY.ASTERISK
|| ch == KEY.GT
|| ch == KEY.LT
|| ch == KEY.EQUAL
|| ch == KEY.LPAREN
|| ch == KEY.RPAREN
|| ch == KEY.LBRACE
|| ch == KEY.RBRACE
|| ch == KEY.LBRACKET
|| ch == KEY.RBRACKET
|| ch == KEY.NL
|| ch == -1){
if(!isString){
return true
}
}
return false
}


//範囲コメント時、アスタリスクがあった場合にその値を入れておく。
//次の値がスラッシュでなければ、この値は初期化される。
var comment_buff = 0
/**
* 行コメント、範囲コメントのモードを変更する
*/
def checkComment(ch:Int):Unit = {
if(ch < 0xFF){
if(ch == LINE_COMMENT){ //行コメント
comment_mode = LINE_COMMENT
}else if(ch == KEY.SLASH && comment_mode == 0){
comment_buff = KEY.SLASH
}else if(ch == KEY.ASTERISK && comment_mode == 0){ // /*の時
if(comment_buff == KEY.SLASH){
comment_mode = COMMENT_BEGIN
}
}else if(comment_mode == COMMENT_BEGIN){ // */の時
if(ch == KEY.ASTERISK){
comment_buff = KEY.ASTERISK
}else if(ch == KEY.SLASH && comment_buff == KEY.ASTERISK){
comment_buff = 0
comment_mode = COMMENT_END
}else{
comment_buff = 0
comment_mode = COMMENT_NONE
}
}else if(comment_buff == KEY.SLASH){
comment_buff = 0
}
}
}
}
スポンサーサイト

Comment






(編集・削除用)


管理者にだけ表示を許可

Trackback

http://ronor.blog81.fc2.com/tb.php/105-10e553eb

この記事にトラックバック(FC2Blog User)

Scala Feed

scala feed

FC2カウンター

プロフィール

RoNor

Author:RoNor
得意呪文はScalaですって言えるようになるのが夢です。
デスマーチ中、パーティメンバーの防御力を向上させたりさせなかったり。

検索フォーム

QRコード

QRコード

Copyright © 2009-2010 ARGENTO CUORE and RoNor All rights reserved.

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。