简单的语法制导翻译
第一步 文法
模拟写出文法匹配过程
package Project;
import java.util.HashSet;
import java.util.Set;
public class simpleTranslation {
public static void main(String[] args) {
String str = "2+3-5+5";
caculate caculate = new caculate(str);
caculate.expr();
}
}
class caculate{
//向前看符号
char lookahead;
//储存数字终结符
Set<Integer> dight = new HashSet<>();
//待匹配的串
String syntax;
//向前看指针,用于移动改变向前看符号
int index;
public caculate(String str){
syntax = str;
if(syntax==null||syntax.length()<=0){
System.out.println("syntax is null");
}
lookahead = syntax.charAt(0);
for (int i=0;i<10;i++){
dight.add(i);
}
}
public void expr(){
term();
rest();
}
/**
* p匹配0-9的数字
*/
public void term(){
if(dight.contains(Integer.parseInt(lookahead+""))){
char t = lookahead;//因为match会改变向前看符号,所有需要保存数字
match(lookahead);
System.out.print(t);
}
}
/**
* 匹配表达式
*/
public void rest(){
switch (lookahead){
case '+':
match('+');//这里写死的打印+所以不需要保存
term();
System.out.print('+');
rest();
break;
case '-':
match('-');
term();
System.out.print('-');
rest();
break;
default:
break;
}
}
/**
* 匹配并移动向前看符号
* @param c 向前看符号
*/
public void match(char c){
if(lookahead==c){
if(index>=syntax.length()-1){
return;
}
lookahead =syntax.charAt(++index);
}
else
System.out.println("Syntax error");
}
}
优化
如果一个过程体执行的最后一条语句是对该过程的递归调用,那么这个调用称为尾递归。
对应没有参数的过程,一个尾递归调用可以被替换为跳转到开头的语句,即变为循环。
package Project;
import java.util.HashSet;
import java.util.Set;
public class simpleTranslation {
public static void main(String[] args) {
String str = "2+3-5+5";
caculate caculate = new caculate(str);
caculate.expr();
}
}
class caculate{
//向前看符号
char lookahead;
//储存数字终结符
Set<Integer> dight = new HashSet<>();
//待匹配的串
String syntax;
//向前看指针,用于移动改变向前看符号
int index;
public caculate(String str){
syntax = str;
if(syntax==null||syntax.length()<=0){
System.out.println("syntax is null");
}
lookahead = syntax.charAt(0);
for (int i=0;i<10;i++){
dight.add(i);
}
}
public void expr(){
term();
rest();
}
/**
* p匹配0-9的数字
*/
public void term(){
if(dight.contains(Integer.parseInt(lookahead+""))){
char t = lookahead;//因为match会改变向前看符号,所有需要保存数字
match(lookahead);
System.out.print(t);
}
}
/**
* 优化尾递归
*/
public void rest(){
while (true){
switch (lookahead){
case '+':
match('+');//这里写死的打印+所以不需要保存
term();
System.out.print('+');
rest();
continue;
case '-':
match('-');
term();
System.out.print('-');
rest();
continue;
default:
break;
}
break;
}
}
/**
* 匹配并移动向前看符号
* @param c 向前看符号
*/
public void match(char c){
if(lookahead==c){
if(index>=syntax.length()-1){
return;
}
lookahead =syntax.charAt(++index);
}
else
System.out.println("Syntax error");
}
}
一个简单的词法分析器
package Project;
//词素类,用整型数字作为ID
public class Token {
public final int tag;
public Token(int t){
tag=t;
}
@Override
public String toString() {
return "Token{" +
"tag=" + tag +
'}';
}
}
package Project;
//以字符串记录值
public class Word extends Token {
public final String lexme;
public Word(int t,String str){
super(t);
lexme = new String(str);
}
@Override
public String toString() {
return "Word{" +
"laxme='" + lexme + '\'' +
", tag=" + tag +
'}';
}
}
package Project;
//枚举常量
public class Tag {
public final static int
NUM = 256,ID=257,TRUE=258,FALSE=259;
}
第一版词法分析器,可扩展
package Project;
import com.rabbitmq.client.AMQP;
import java.util.*;
public class Lexer {
//待分析字符串。
public String syntax;
//储存词素。
public Map<String,Token> map = new HashMap<>();
//记录下一个char或空白。
public char peek;
//索引
public int index=0;
//行数
public int line = 0;
public Lexer(String s){
syntax = s;
reserve(new Word(Tag.TRUE,"true"));
reserve(new Word(Tag.FALSE,"false"));
}
private void reserve (Word w){
map.put(w.lexme,w);
}
/**
*
* @return 返回一个词素,只有在是字符串时才会加入map集合中
*/
public Token scan(){
clearTab();
Token cur = analysisNum();
if(cur!=null){
return cur;
}
cur = analysisWord();
if(cur!=null){
return cur;
}
Token t = new Token(peek);
index++;
return t;
}
/**
*
* @return Token of word or null
*/
public Token analysisWord(){
//处理单词
if(Character.isLetter(peek)){
StringBuffer sb = new StringBuffer();
do{
index++;
sb.append(peek);
if(index>syntax.length()-1)
break;
peek = syntax.charAt(index);
}while (Character.isLetterOrDigit(peek));
String str = sb.toString();
Word w = (Word) map.get(str);
if(w!=null){//区分保留字与描述符
return w;
}
w = new Word(Tag.ID,str);
map.put(str,w);
return w;
}
return null;
}
/**
*
* @return Token of Num or null
*/
public Token analysisNum(){
//处理数字
if(Character.isDigit(peek)){
int value = 0;
do{
index++;
value = 10*value+Character.digit(peek,10);
if(index>syntax.length()-1)
break;
peek = syntax.charAt(index);
}while (Character.isDigit(peek));
return new Num(value);
}
return null;
}
/**
* 清除空格以及制表符
*/
public void clearTab(){
//剔除空白,制表符,换行符
for (;;){
if(index>syntax.length()-1)
return ;
peek = syntax.charAt(index);
if(peek==' '||peek=='\t'){
index++;
continue;
}else if(peek=='\n'){
index++;
line++;
}else {
break;
}
}
}
public void analysis(){
while (index<syntax.length()){
System.out.println(scan());
}
for (Map.Entry<String,Token> item:map.entrySet()){
System.out.println(item.getValue());
}
}
}