ARDUINO COMPUTER (Parte IV)
Interprete iArduino
En este tutorial explicaré como he adaptado el interprete iArduino para que lo podamos utilizar en nuestro proyecto del ordenador arduino.
#include <SoftwareSerial.h>
// A C interpreter for Arduino
// Copyright(c) 2012 Noriaki Mitsunaga
// $Id: iArduino.ino,v 1.4 2012/02/13 11:15:23 kurobox Exp kurobox $
// See http://n.mtng.org/ele/arduino/iarduino-j.html (in Japanese)
SoftwareSerial puertoUno(10, 9);
#define INPUT_LEN 80 // Size of input buffer
int runAnimate = 0;
int runDelay = 0;
int runStep = 0;
//char progbuf[1000] = "a=1;b=1;\r\nc=1;\r\na=a+b+c;\r\nprint(a);\r\nprint(b);\r\n";
//char progbuf[1000] = "a=0;while(a<5)a=a+1;print(a);\r\na=5;while(a>0) {print(a);a=a-1;}\r\n";
//char progbuf[1000] = "if(a>b)print(10);else print(-10);";
//char progbuf[1000] = "if(a>b)print(10); print(-10);";
//char progbuf[1000] = "print(i);for(i=0;i<5;i=i+1)print(i);";
//char progbuf[1000] = "print(i);for(i=0;i<5;i=i+1){print(i);if(i>2)break; print(0);} print(i);\r\n";
char progbuf[800] = "for(i=0;;i=i+1){print(i);}";
// 999 文字まで(多くても1022まで, EEPROMの最後の2バイトをマジックナンバーに使うため)
char *prog;
#ifdef ARDUINO
#include <EEPROM.h>
#include <Servo.h>
Servo servo[12];
const int SERVO_NUM = 12;
void setup()
{
puertoUno.begin(4800);
Serial.begin(9600);
Serial.println(F("Arduino PC"));
puertoUno.println(("Arduino PC"));
Serial.println(("M Avila2012"));
puertoUno.println(F("M Avila2012"));
prog = progbuf;
if (EEPROM.read(0x3ff) == 'P') {
ReadProg();
if (EEPROM.read(0x3fe) == 'R') {
int err;
Serial.println(F("Starting program"));
puertoUno.println(("Starting program"));
runStep = 0;
runAnimate = 0;
runDelay = 0;
if ((err = run(prog, strlen(prog))) != 0)
printError(err);
}
}
Serial.println(F("OK"));
puertoUno.println(("OK"));
}
#else
#include <stdio.h>
#include <windows.h>
void printSln(const char *s);
void printS(const char *s);
#define getcharS() getchar()
#endif
void edit(char *prog, int lNum, char *line);
int eval2(char *s, int len, int *val);
void getsS(char *buf, size_t len);
void printError(int err);
int run(char *prog, int len);
char *skipSpace(char *s, char *e);
void list(char *prog);
void loop()
{
int err, v;
char buf[INPUT_LEN+1];
char *p;
getsS(buf, INPUT_LEN);
p = buf + strlen(buf) -1;
*p = 0; /* remove \r or \n */
p = skipSpace(buf, p);
if (*p == 0)
return;
if (strncmp(buf, "animate", 7) == 0) {
runStep = 0;
runAnimate = 1;
runDelay = 500;
if ((err = run(prog, strlen(prog))) != 0)
printError(err);
} else if (strncmp(buf, "autorun", 7) == 0) {
#ifdef ARDUINO
EEPROM.write(0x3fe, 'R');
#endif
} else if (strncmp(buf, "debug", 5) == 0) {
runStep = 0;
runAnimate = 1;
runDelay = 0;
if ((err = run(prog, strlen(prog))) != 0)
printError(err);
} else if (strncmp(buf, "edit", 4) == 0) {
int l = atoi(buf+4);
getsS(buf, INPUT_LEN);
edit(prog, l, buf);
} else if (strncmp(buf, "list", 4) == 0) {
list(prog);
} else if (strncmp(buf, "noauto", 6) == 0) {
#ifdef ARDUINO
EEPROM.write(0x3fe, 0);
#endif
} else if (strncmp(buf, "prog", 4) == 0) {
int i;
char *p;
prog = NULL;
p = progbuf;
for (i=0; i<sizeof(progbuf); i = p - progbuf) {
//fprintf(stderr, "%d: %d\n", i, sizeof(progbuf));
getsS(buf, INPUT_LEN);
if (strncmp(buf, "end", 3) == 0) {
*p = 0;
prog = progbuf;
break;
}
if (p-progbuf + strlen(buf) > sizeof(progbuf)-1) {
break;
}
strcpy(p, buf);
p = progbuf + strlen(progbuf);
}
if (prog == NULL) {
printSln("Prog muy larg");
progbuf[0] = 0;
prog = progbuf;
}
} else if (strncmp(buf, "run", 3) == 0) {
runStep = 0;
runAnimate = 0;
runDelay = 0;
if ((err = run(prog, strlen(prog))) != 0)
printError(err);
} else if (strncmp(buf, "step", 4) == 0) {
runStep = 1;
if ((err = run(prog, strlen(prog))) != 0)
printError(err);
} else if (strncmp(buf, "save", 4) == 0) {
#ifdef ARDUINO
SaveProg();
#endif
} else {
if ((err = eval2(buf, strlen(buf), &v)) != 0)
printError(err);
else
print(v);
}
printSln("OK");
}
//////////////////////////////////////////////////////////////////////////////
// Definitions of enums & structs
//////////////////////////////////////////////////////////////////////////////
enum ERRORS {
STOPPED = 10,
FOUND_CONTINUE = 1,
FOUND_BREAK = 2,
ERROR_DIV0 = -1,
ERROR_SYNTAX = -2,
ERROR_INTERNAL = -3
};
struct ArduinoConstValues {
char *name;
int len;
int val;
};
struct Function1 {
char *name;
int len;
int (*func)(int);
};
struct Function2 {
char *name;
int len;
int (*func)(int, int);
};
struct Function3 {
char *name;
int len;
int (*func)(int, int, int);
};
//////////////////////////////////////////////////////////////////////////////
// Test and wrapper functions
//////////////////////////////////////////////////////////////////////////////
#ifndef ARDUINO
// Test functions
int rand_(int a)
{
return rand();
}
int plus(int a, int b)
{
return a+b;
}
int print(int a)
{
printf("%d\n", a);
return a;
}
#else // ARDUINO //
// Wrapper functions
int rand(int)
{
return random(0, 32767);
}
int analogRead_(int pin)
{
return analogRead(pin);
}
int delay_(int ms)
{
delay(ms);
return 0;
}
int digitalRead_(int pin)
{
return digitalRead(pin);
}
int plus(int a, int b)
{
return a+b;
}
int analogWrite_(int pin, int val)
{
analogWrite(pin, val);
return 0;
}
int digitalWrite_(int pin, int val)
{
digitalWrite(pin, val);
return 0;
}
int millis_(int dummy)
{
return millis();
}
int min_(int a, int b)
{
return min(a, b);
}
int max_(int a, int b)
{
return max(a, b);
}
int noTone_(int pin)
{
noTone(pin);
return 0;
}
int pinMode_(int pin, int mode)
{
pinMode(pin, mode);
return 0;
}
int print(int a)
{
Serial.println(a);
puertoUno.println(a);
return a;
}
int tone2(int pin, int freq)
{
tone(pin, freq);
return 0;
}
int tone3(int pin, int freq, int duration)
{
tone(pin, freq, duration);
return 0;
}
#endif
//////////////////////////////////////////////////////////////////////////////
// Global variables
//////////////////////////////////////////////////////////////////////////////
int variables[26] = {0};
const struct ArduinoConstValues constants[] = {
{"LOW", 3, 0},
{"HIGH", 4, 1},
{"false", 5, 0},
{"true", 4, 1},
{"INPUT", 5, 0},
{"OUTPUT", 6, 1},
};
#define CONST_NUM 6
// ----- Function tables -----
#ifndef ARDUINO
const struct Function1 func1[] = {
{"rand(", 5, rand_},
{"print(", 6, print},
};
#define FUNC1_NUM 2
const struct Function2 func2[] = {
{"plus(", 5, plus},
};
#define FUNC2_NUM 1
#else /* ARDUINO */
const struct Function1 func1[] = {
{"abs(", 4, abs},
{"analogRead(", 11, analogRead_},
{"delay(", 6, delay_},
{"digitalRead(", 12, digitalRead_},
{"millis(", 7, millis_},
{"noTone(", 7, noTone_},
{"rand(", 5, rand},
{"print(", 6, print},
// {"sq(", 3, sq},
// {"sqrt(", 5, sqrt},
};
#define FUNC1_NUM 7
const struct Function2 func2[] = {
{"analogWrite(", 12, analogWrite_},
{"digitalWrite(", 13, digitalWrite_},
{"min(", 4, min_},
{"max(", 4, max_},
{"pinMode(", 8, pinMode_},
{"tone(", 5, tone2},
// {"plus(", 5, plus},
};
#define FUNC2_NUM 6
const struct Function3 func3[] = {
{"tone3(", 5, tone3}
};
#define FUNC3_NUM 1
#endif
///////////////////////////////////////////////////////////////////////////
// Fucntion declarations
///////////////////////////////////////////////////////////////////////////
#ifdef ARDUINO
int kbhit()
{
return Serial.available();
}
int getch()
{
return Serial.read();
}
void Sleep(int s)
{
delay(s);
}
#endif
int eval2(char *s, int len, int *val);
void printError(int err);
int stepRun();
///////////////////////////////////////////////////////////////////////////
// Fucntions
///////////////////////////////////////////////////////////////////////////
#ifndef ARDUINO
void getsS(char *buf, size_t len)
{
fgets(buf, len, stdin);
buf[len+1] = 0;
}
void printSln(const char *s)
{
fprintf(stderr, "%s\n", s);
}
void printS(const char *s)
{
fprintf(stderr, "%s", s);
}
void putcS(char c)
{
fputc(c, stderr);
}
void writeS(const char *s, int len)
{
fwrite(s, 1, len, stderr);
}
#else
byte getcharS()
{
byte c;
while (Serial.available() == 0)
;
c = Serial.read();
Serial.write(c);
return c;
}
void getsS(char *buf, size_t len)
{
static char prev = 0;
char c, *p;
p = buf;
do {
if (Serial.available() > 0) {
c = Serial.read();
if (p == buf && c == '\n' && prev == '\r') {
prev = c = 0;
continue;
}
if (c == 8 /* backspace*/) {
p --;
Serial.write(8);
Serial.write(' ');
Serial.write(8);
if (p<buf)
p = buf;
} else {
Serial.write(c);
*p = c;
p ++;
}
}
} while (c != '\n' && c!= '\r' && c != 3 && (p-buf)<len);
prev = c;
if (c == '\r') {
*(p-1) = '\n';
Serial.write('\n');
} else if (c == '\n') {
Serial.write('\r');
}
*p = 0;
}
void printS(const char *s)
{
Serial.print(s);
puertoUno.print(s);
}
void printS(const uint8_t *s)
{
Serial.print((const char *)s);
puertoUno.print((const char *)s);
}
void printSln(const char *s)
{
Serial.println(s);
puertoUno.println(s);
}
void printSln(const uint8_t *s)
{
Serial.println((const char *)s);
puertoUno.println((const char *)s);
}
void putcS(char c)
{
Serial.write(c);
}
void writeS(const char *s, int len)
{
Serial.write((uint8_t *)s, len);
}
void ReadProg()
{
int i;
for (i=0; i<(sizeof(progbuf)-1); i++) {
progbuf[i] = EEPROM.read(i);
if (progbuf[i] == 0)
break;
}
if (progbuf[i] != 0)
progbuf[i] = 0;
}
void SaveProg()
{
int len = strlen(prog);
for (int i=0; i<=len; i++) {
EEPROM.write(i, prog[i]);
}
EEPROM.write(0x3ff, 'P'); // Magic number
}
#endif
int stepRun()
{
char buf[INPUT_LEN+1], *p;
int err, v;
if (runStep == 0) {
char c;
if (runDelay>0)
Sleep(runDelay);
if (kbhit() == 0)
return 0;
c = getch();
if (c != 3) /* Control-c */
printSln("Paused");
else
return STOPPED;
runStep = 1;
}
for (;;) {
putcS('>');
getsS(buf, INPUT_LEN);
if (buf[0] == 3)
return STOPPED;
p = buf + strlen(buf) -1;
*p = 0; /* remove \r or \n */
if (buf[0] == 0)
break;
if (strcmp(buf, "a") == 0 || strcmp(buf, "animate") == 0) {
runStep = 0;
runAnimate = 1;
runDelay = 500;
break;
} else if (strcmp(buf, "c") == 0 || strcmp(buf, "continue") == 0) {
runStep = 0;
break;
} else if (strcmp(buf, "d") == 0 || strcmp(buf, "debug") == 0) {
runStep = 0;
runAnimate = 1;
runDelay = 0;
break;
} else if (strcmp(buf, "S") == 0) {
return STOPPED;
} else if (strcmp(buf, "r") == 0 || strcmp(buf, "run") == 0) {
runStep = 0;
runAnimate = 0;
runDelay = 0;
break;
} else {
p = skipSpace(buf, p);
if ((err = eval2(p, strlen(p), &v)) != 0)
printError(err);
else
print(v);
}
}
return 0;
}
void printError(int err)
{
switch (err)
{
case ERROR_DIV0:
#ifdef ARDUINO
Serial.println(F("Divided by 0"));
puertoUno.println(F("Divided by 0"));
#else
printSln("Divided by 0");
#endif
break;
case ERROR_SYNTAX:
#ifdef ARDUINO
Serial.println(F("Syntax error"));
puertoUno.println(F("Syn error"));
#else
printSln("Syntax error");
#endif
break;
case STOPPED:
#ifdef ARDUINO
Serial.println(F("Stopped"));
puertoUno.println(F("Stopped"));
#else
printSln("Stopped");
#endif
break;
case ERROR_INTERNAL:
default:
#ifdef ARDUINO
Serial.println(F("Syntax error"));
puertoUno.println(F("Syn error"));
#else
printSln("Syntax error");
#endif
//printSln("Intenal error");
break;
}
}
int
eval2(char *s, int len, int *val)
{
int i, l;
char *e;
int v, varn = -1, err;
//fwrite(s, 1, len, stderr);
//fprintf(stderr, "\n");
e = s + len;
// Skip space
while (*s != 0 && s<e && (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n'))
s ++;
if (*s == 0 || s == e) {
*val = 1;
return 0;
}
if (*s == '(') {
// ( で始まる場合
char *p;
int in = 1;
s ++;
while (*s != 0 && s<e && (*s == ' ' || *s == '\t'))
s ++;
if (*s == 0 || *s == ')')
return ERROR_SYNTAX;
p = s;
while (*s != 0 && s<e) {
if (*s == '(') {
in ++;
} else if (*s == ')') {
in --;
if (in == 0) {
s ++;
break;
}
}
s ++;
}
if (in > 0)
return ERROR_SYNTAX;
if ((err = eval2(p, s-p-1, &v)) != 0)
return err;
} else if ((*s == '!' && *(s+1) != '=') || *s == '~' || *s == '-' || *s == '+') {
// トークンが1項演算子の場合
char *p, op;
int in = 0;
op = *s;
s ++;
while (*s != 0 && s<e && (*s == ' ' || *s == '\t'))
s ++;
if (*s == 0 || s == e)
return ERROR_SYNTAX;
p = s;
while (*s != 0 && s<e && (in>0 || (*s != '+' && *s != '-' && *s != '>' && *s != '<' && *s != '='))) {
if (*s == '(') {
in ++;
} else if (*s == ')') {
in --;
}
s ++;
}
if (eval2(p, s-p, &v) != 0)
return ERROR_SYNTAX;
if (op == '!')
v = !v;
else if (op == '~')
v = ~v;
else if (op == '-')
v = -v;
} else if (*s>='0' && *s<='9') {
// トークンが数値の場合
if (*s == '0' && *(s+1) == 'x') {
v = 0;
s += 2;
while (*s != 0 && s<e && ((*s>='0' && *s<='9') ||
(*s>='a' && *s<='f') || (*s>='A' && *s<='F'))) {
if (*s>='0' && *s<='9')
v = (v<<4) + (*s - '0');
else if (*s>='a' && *s<='f')
v = (v<<4) + (*s - 'a' + 0xa);
else if (*s>='A' && *s<='F')
v = (v<<4) + (*s - 'A' + 0xa);
s ++;
}
} else if (*s == '0' && *(s+1) == 'b') {
v = 0;
s += 2;
while (*s != 0 && s<e && (*s>='0' && *s<='1')) {
v = (v<<1) + (*s - '0');
s ++;
}
} else {
v = 0;
while (*s != 0 && s<e && *s>='0' && *s<='9') {
v = v*10 + (*s - '0');
s ++;
}
}
} else if (((*s>='a' && *s<='z') || (*s>='A' && *s<='Z')) &&
(!(*(s+1)>='a' && *(s+1)<='z') && !(*(s+1)>='A' && *(s+1)<='Z'))) {
// The token is a varibale
if (*s>='a' && *s<='z')
varn = *s - 'a';
else
varn = *s - 'A';
v = variables[varn];
s ++;
} else {
// 定数かどうかをチェックする
for (i=0; i<CONST_NUM; i++) {
const struct ArduinoConstValues *c = constants+i;
if (e-s>=c->len && strncmp(c->name, s, 3) == 0) {
v = c->val;
s += c->len;
break;
}
}
// Check if the token is a supported function
// 引数が1つの関数
for (i=0; i<FUNC1_NUM; i++) {
const struct Function1 *f = func1+i;
if (e-s>=f->len && strncmp(f->name, s, f->len) == 0) {
char *p;
int in = 1, v1;
s += f->len;
p = s;
while (*s != 0 && s<e && in>0) {
if (*s == '(') {
in ++;
} else if (*s == ')') {
in --;
}
s ++;
}
if (in>0)
return ERROR_SYNTAX;
if (eval2(p, s-p-1, &v1) != 0)
return ERROR_SYNTAX;
v = (*f->func)(v1);
}
}
// servo?.attach(), servo?.write()
for (i=0; i<SERVO_NUM; i++) {
char f[20];
int attach_write = 0, len;
sprintf(f, "servo%d.attach(", i);
len = strlen(f);
if (e-s>=len && strncmp(f, s, len) == 0) {
attach_write = 1;
} else {
sprintf(f, "servo%d.write(", i);
len = strlen(f);
if (e-s>=len && strncmp(f, s, len) == 0) {
attach_write = 2;
}
}
if (attach_write > 0) {
char *p;
int in = 1, v1;
s += len;
p = s;
while (*s != 0 && s<e && in>0) {
if (*s == '(') {
in ++;
} else if (*s == ')') {
in --;
}
s ++;
}
if (in>0)
return ERROR_SYNTAX;
if (eval2(p, s-p-1, &v1) != 0)
return ERROR_SYNTAX;
if (attach_write == 1)
servo[i].attach(v1);
else
servo[i].write(v1);
v = 0;
break;
}
}
// 引数が2つの関数
for (i=0; i<FUNC2_NUM; i++) {
const struct Function2 *f = func2+i;
if (e-s>=f->len && strncmp(f->name, s, f->len) == 0) {
char *p;
int in = 0, v1, v2;
s += f->len;
p = s;
while (*s != 0 && s<e && !(in == 0 && *s == ',')) {
if (*s == '(')
in ++;
else if (*s == ')')
in --;
s ++;
}
if (*s != ',')
return ERROR_SYNTAX;
if (eval2(p, s-p, &v1) != 0)
return ERROR_SYNTAX;
s ++;
p = s;
in = 1;
while (*s != 0 && s<e && in>0) {
if (*s == '(')
in ++;
else if (*s == ')')
in --;
s ++;
}
if (in>0)
return ERROR_SYNTAX;
if (eval2(p, s-p-1, &v2) != 0)
return ERROR_SYNTAX;
v = (*f->func)(v1, v2);
break;
}
}
// 引数が3つの関数
for (i=0; i<FUNC3_NUM; i++) {
const struct Function3 *f = func3+i;
if (e-s>=f->len && strncmp(f->name, s, f->len) == 0) {
char *p;
int in = 0, v1, v2, v3;
s += f->len;
p = s;
while (*s != 0 && s<e && !(in == 0 && *s == ',')) {
if (*s == '(')
in ++;
else if (*s == ')')
in --;
s ++;
}
if (*s != ',')
return ERROR_SYNTAX;
if (eval2(p, s-p, &v1) != 0)
return ERROR_SYNTAX;
s ++;
p = s;
in = 0;
while (*s != 0 && s<e && !(in == 0 && *s == ',')) {
if (*s == '(')
in ++;
else if (*s == ')')
in --;
s ++;
}
if (*s != ',')
return ERROR_SYNTAX;
if (eval2(p, s-p-1, &v2) != 0)
return ERROR_SYNTAX;
s ++;
p = s;
in = 1;
while (*s != 0 && s<e && in>0) {
if (*s == '(')
in ++;
else if (*s == ')')
in --;
s ++;
}
if (in>0)
return ERROR_SYNTAX;
if (eval2(p, s-p-1, &v3) != 0)
return ERROR_SYNTAX;
v = (*f->func)(v1, v2, v3);
break;
}
}
}
// 次のトークンを確かめる
{
int v2;
// Skip space
while (*s != 0 && s<e && (*s == ' ' || *s == '\t'))
s ++;
if (*s == 0 || s == e) { // 後ろに演算子はなかった
*val = v;
return 0;
}
if (*s == '=' && *(s+1) != '=') {
char *p;
int op = *s, in = 0;
s ++;
while (*s != 0 && s<e && (*s == ' ' || *s == '\t'))
s ++;
if (*s == 0 || s == e)
return ERROR_SYNTAX;
p = s;
while (*s != 0 && s<e && (in>0 ||
!(*s == '=' && *(s+1) == '='))) {
if (*s == '(') {
in ++;
} else if (*s == ')') {
in --;
}
s ++;
}
if ((err = eval2(p, s-p, &v2)) != 0)
return err;
if (varn < 0 || varn>=sizeof(variables))
return ERROR_INTERNAL;
v = variables[varn] = v2;
if (*s == 0 || s == e) {
*val = v;
return 0;
}
}
while (*s == '*' || *s == '/' || *s == '%') {
char *p;
int op = *s, in = 0;
s ++;
while (*s != 0 && s<e && (*s == ' ' || *s == '\t'))
s ++;
if (*s == 0 || s == e)
return ERROR_SYNTAX;
p = s;
while (*s != 0 && s<e && (in>0 ||
(*s != '*' && *s != '/' && *s != '%' &&
*s != '+' && *s != '-' && *s != '>' && *s != '<' &&
!(*s == '=' && *(s+1) == '=') && *s != '!'))) {
if (*s == '(') {
in ++;
} else if (*s == ')') {
in --;
}
s ++;
}
if ((err = eval2(p, s-p, &v2)) != 0)
return err;
switch (op) {
case '*':
v = v*v2;
break;
case '/':
v = v/v2;
break;
case '%':
v = v%v2;
break;
}
if (*s == 0 || s == e) {
*val = v;
return 0;
}
}
if (*s == '+' || *s == '-') {
char *p;
int op = *s, in = 0;
p = s;
while (*s != 0 && s<e && (in>0 || (*s != '>' && *s != '<' && *s != '=' && *s != '!'))) {
if (*s == '(') {
in ++;
} else if (*s == ')') {
in --;
}
s ++;
}
if (in != 0)
return ERROR_SYNTAX;
// 演算子の右側を計算する
if ((err = eval2(p, s-p, &v2)) != 0)
return err;
// 左と右を足す
v = v + v2;
if (*s == 0 || s==e) {
*val = v;
return 0;
}
}
if (*s == '>' || *s == '<' || (*s == '=' && *(s+1) == '=')
|| (*s == '!' && *(s+1) == '=')) {
char *p;
int op = *s, op2 = *(s+1), in = 0;
s ++;
if (op2 == '=' || op2 == '<' || op2 == '>')
s ++;
p = s;
while (*s != 0 && s<e && (in>0 || (*s != '&' && *s != '^' && *s != '|'))) {
if (*s == '(') {
in ++;
} else if (*s == ')') {
in --;
}
s ++;
}
if (in != 0)
return ERROR_SYNTAX;
// 演算子の右側を計算する
if ((err = eval2(p, s-p, &v2)) != 0)
return err;
if (op == '>') {
if (op2 == '=') {
v = v>=v2;
} else if (op2 == '>') {
v = v>>v2;
} else {
v = v>v2;
}
} else if (op == '<') {
if (op2 == '=') {
v = v<=v2;
} else if (op2 == '<') {
v = v<<v2;
} else {
v = v<v2;
}
} else if (op == '=' && op2 == '=') {
v = (v == v2);
} else if (op == '!' && op2 == '=') {
v = (v != v2);
}
if (*s == 0 || s==e) {
*val = v;
return 0;
}
}
if ((*s == '&' && *(s+1) != '&') || (*s == '|' && *(s+1) != '|') ||
*s == '^') {
char *p;
int op = *s, in = 0;
s ++;
p = s;
while (*s != 0 && s<e && (in>0 || !((*s == '&' && *(s+1) == '&') ||
(*s == '|' && *(s+1) == '|')))) {
if (*s == '(') {
in ++;
} else if (*s == ')') {
in --;
}
s ++;
}
if (in != 0)
return ERROR_SYNTAX;
// 演算子の右側を計算する
if ((err = eval2(p, s-p, &v2)) != 0)
return err;
if (op == '&')
v = v & v2;
else if (op == '|')
v = v | v2;
else if (op == '^')
v = v ^ v2;
if (*s == 0 || s==e) {
*val = v;
return 0;
}
}
if ((*s == '&' && *(s+1) == '&') || (*s == '|' && *(s+1) == '|')) {
int op = *s;
s += 2;
// 演算子の右側を計算する
if ((err = eval2(s, e-s, &v2)) != 0)
return err;
if (op == '&')
v = v && v2;
else if (op == '|')
v = v || v2;
*val = v;
return 0;
}
}
error:
return ERROR_INTERNAL;
}
char *skipSpace(char *s, char *e)
{
while (*s != 0 && s<e && (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n'))
s ++;
return s;
}
int
run(char *prog, int len)
{
char *cur, *s, *e;
int err, in, v, skip;
s = prog;
e = prog + len;
for (;;) {
char *p;
s = skipSpace(s, e);
if (*s == 0 || s>=e)
break;
skip = 0;
// fprintf(stderr, s);
if ((strncmp(s, "continue", 8) == 0
&& (*(s+8) == ';' ||
*(s+8) == ' ' || *(s+8) == '\t' ||
*(s+8) == '\r' || *(s+8) == '\n')) ||
(strncmp(s, "break", 5) == 0
&& (*(s+5) == ';' ||
*(s+5) == ' ' || *(s+5) == '\t' ||
*(s+5) == '\r' || *(s+5) == '\n'))) {
char *cond, *cond_e, *p1, *statement, *statement_e;
char *statement2 = NULL, *statement2_e;
int continue_break = 0;
p1 = s;
if (strncmp(s, "continue",8) == 0) {
continue_break = 1;
s += 8;
} else {
s += 5;
}
s = skipSpace(s, e);
if (*s != ';') {
writeS(p1, 20);
return ERROR_SYNTAX;
}
s ++;
if (continue_break == 0)
return FOUND_BREAK;
return FOUND_CONTINUE;
} else if ((strncmp(s, "while", 5) == 0
&& (*(s+5) == '(' ||
*(s+5) == ' ' || *(s+5) == '\t' ||
*(s+5) == '\r' || *(s+5) == '\n')) ||
(strncmp(s, "if", 2) == 0
&& (*(s+2) == '(' ||
*(s+2) == ' ' || *(s+2) == '\t' ||
*(s+2) == '\r' || *(s+2) == '\n'))) {
char *cond, *cond_e, *p1, *statement, *statement_e;
char *statement2 = NULL, *statement2_e;
int while_if = 0;
if (strncmp(s, "while", 5) == 0) {
while_if = 1;
s += 5;
} else
s += 2;
p1 = s;
s = skipSpace(s, e);
if (*s != '(') {
writeS(p1, 20);
return ERROR_SYNTAX;
}
s ++;
cond = s;
in = 1;
while (*s !=0 && s<e && (in>0 || *s != ')')) {
if (*s == '(')
in ++;
if (*s == ')') {
in --;
if (in == 0)
break;
}
s ++;
}
if (*s != ')') {
writeS(p1, s-p1);
return ERROR_SYNTAX;
}
cond_e = s;
s ++;
s = skipSpace(s, e);
if (*s == 0 || s>=e) {
writeS(p1, s-p1);
return ERROR_SYNTAX;
}
statement = s;
in = 0;
while (*s !=0 && s<e && (in>0 || (*s != '}' && *s != ';'))) {
if (*s == '{')
in ++;
else if (*s == '}') {
in --;
if (in == 0)
break;
}
s ++;
}
if (*s == 0 || s>=e || (*s != ';' && *s != '}') || in > 0) {
writeS(p1, s-p1);
return ERROR_SYNTAX;
}
s ++;
statement_e = s;
// 必要なら else 部分を取り出す
s = skipSpace(s, e);
// fprintf(stderr, "*1 %s\n", s);
if (while_if == 0 && strncmp(s, "else", 4) == 0
&& (*(s+4) == '{' ||
*(s+4) == ' ' || *(s+4) == '\t' ||
*(s+4) == '\r' || *(s+4) == '\n')) {
s += 4;
s = skipSpace(s, e);
if (*s == 0 || s>=e) {
writeS(p1, s-p1);
return ERROR_SYNTAX;
}
//fprintf(stderr, "*2 %s\n", s);
statement2 = s;
in = 0;
while (*s !=0 && s<e && (in>0 || (*s != '}' && *s != ';'))) {
if (*s == '{')
in ++;
else if (*s == '}') {
in --;
if (in == 0)
break;
}
s ++;
}
if (*s == 0 || s>=e || (*s != ';' && *s != '}') || in > 0) {
writeS(p1, s-p1);
return ERROR_SYNTAX;
}
statement2_e = s;
}
if (while_if>0) {
// while 文の処理
if (runAnimate || runStep) {
printS("while (");
writeS(cond, cond_e-cond);
printS(")\n");
}
if ((err = stepRun()) != 0)
return err;
for (;;) {
err = eval2(cond, cond_e-cond, &v);
if (err)
return err;
if (runAnimate || runStep) {
writeS(cond, cond_e-cond);
printS(": ");
printS(v ? "true" : "false");
printSln("");
}
//fwrite(cond, 1, cond_e-cond, stderr);
//fprintf(stderr, ": %d\n", v);
if (v == 0)
break;
if (runAnimate || runStep) {
if ((err = stepRun()) != 0)
return err;
}
err = run(statement, statement_e-statement);
if (err == FOUND_CONTINUE)
continue;
else if (err == FOUND_BREAK)
break;
else if (err)
return err;
}
} else {
// if 文の処理
if (runAnimate || runStep) {
printS("if (");
writeS(cond, cond_e-cond);
printS(")");
}
err = eval2(cond, cond_e-cond, &v);
if (err) {
if (runAnimate || runStep)
printSln("");
return err;
}
if (runAnimate || runStep) {
printS(": ");
printS(v ? "true" : "false");
printSln("");
}
//fwrite(cond, 1, cond_e-cond, stderr);
//fprintf(stderr, ": %d\n", v);
if (v != 0) {
err = run(statement, statement_e-statement);
if (err)
return err;
} else {
if (statement2 != NULL) {
err = run(statement2, statement2_e-statement2);
if (err)
return err;
}
}
}
} else if ((strncmp(s, "for", 3) == 0
&& (*(s+3) == '(' ||
*(s+3) == ' ' || *(s+3) == '\t' ||
*(s+3) == '\r' || *(s+3) == '\n'))) {
char *init, *init_e;
char *cond, *cond_e, *inc, *inc_e;
char *statement, *statement_e, *p1;
p1 = s;
s += 3;
s = skipSpace(s, e);
if (*s != '(') {
writeS(p1, 20);
return ERROR_SYNTAX;
}
s ++;
s = skipSpace(s, e);
init = s;
while (*s !=0 && s<e && *s != ';')
s ++;
if (*s == 0 || s>=e) {
writeS(p1, 20);
return ERROR_SYNTAX;
}
init_e = s;
s ++;
s = skipSpace(s, e);
cond = s;
while (*s !=0 && s<e && *s != ';')
s ++;
if (*s == 0 || s>=e) {
writeS(p1, s-p1);
return ERROR_SYNTAX;
}
cond_e = s;
s ++;
inc = s = skipSpace(s, e);
in = 1;
while (*s !=0 && s<e && (in>0 || *s != ')')) {
if (*s == '(')
in ++;
else if (*s == ')') {
in --;
if (in == 0)
break;
}
s ++;
}
if (*s == 0 || s>=e) {
writeS(p1, s-p1);
return ERROR_SYNTAX;
}
inc_e = s;
s ++;
s = skipSpace(s, e);
statement = s;
in = 0;
while (*s !=0 && s<e && (in>0 || (*s != '}' && *s != ';'))) {
if (*s == '{')
in ++;
else if (*s == '}') {
in --;
if (in == 0)
break;
}
s ++;
}
if (*s == 0 || s>=e || (*s != ';' && *s != '}') || in > 0) {
writeS(p1, s-p1);
return ERROR_SYNTAX;
}
s ++;
statement_e = s;
// for 文の処理
if (runAnimate || runStep) {
printS("for (");
writeS(init, init_e-init);
printS("; ");
writeS(cond, cond_e-cond);
printS("; ");
writeS(inc, inc_e-inc);
printS(")\n");
}
if ((err = stepRun()) != 0)
return err;
if (runAnimate || runStep) {
writeS(init, init_e-init);
printSln("");
}
if ((err = eval2(init, init_e-init, &v)) != 0) {
return err;
}
if ((err = stepRun()) != 0)
return err;
for (;;) {
if ((err = eval2(cond, cond_e-cond, &v)) != 0)
return err;
if (runAnimate || runStep) {
writeS(cond, cond_e-cond);
printS(": ");
printS(v ? "true" : "false");
printSln("");
}
if (v == 0)
break;
if (runAnimate || runStep) {
if ((err = stepRun()) != 0)
return err;
}
//fwrite(statement, 1, statement_e-statement, stderr);
if ((err = run(statement, statement_e-statement)) != 0) {
if (err == FOUND_CONTINUE)
; /* DO_NOTHING */
else if (err == FOUND_BREAK)
break;
else return err;
}
if ((err = eval2(inc, inc_e-inc, &v)) != 0)
return err;
if (runAnimate || runStep) {
writeS(inc, inc_e-inc);
printSln("");
}
}
} else if (*s == '{' || *s == '}') {
s ++;
skip = 1;
} else {
// 式文の処理
p = s;
in = 0;
while (*s != 0 && s<e && (in>0 || *s != ';'))
s ++;
if (*s == 0 && in>0) {
writeS(p, s-p);
return ERROR_SYNTAX;
}
if (runAnimate != 0) {
writeS(p, s-p);
printSln("");
}
if ((err = eval2(p, s-p, &v)) != 0) {
writeS(p, s-p);
printSln("");
return err;
}
s ++;
#if 0
printf("%d\n", v);
#endif
}
if (skip == 0) {
if ((err = stepRun()) != 0)
return err;
}
}
return 0;
}
void edit(char *prog, int lNum, char *nLine)
{
char *p, *q;
int editLine;
int l;
#if 0
// Get line number to edit
lNum = 0;
p = nLine;
while (*p != ' ') {
if (*p>='0' && *p<='9')
lNum = lNum*10 + (*p - '0');
else {
printSln("Invalid line number");
return;
}
p ++;
}
nLine = p + 1;
#endif
p = q = prog;
l = 1;
while (*q && l<=lNum)
{
if (*q == '\r' || *q =='\n') {
if (*q == '\r' && *(q+1) == '\n')
q ++;
q ++;
if (l == lNum || *q == 0)
break;
l ++;
p = q;
continue;
}
q ++;
}
// Append given line to the program if the line number is larger than current list.
if (lNum>l && *q == 0) {
strcat(prog, nLine);
return;
}
// Replace the line with given one
if ((q - p)<strlen(nLine)) {
int sz = strlen(nLine) - (q-p);
char *pp = prog + strlen(prog) + 1;
char *qq = pp + sz;
for (int i=strlen(q)+1; i>=0; i--) {
*qq = *pp;
qq --; pp --;
}
q = p + strlen(nLine);
}
for (int i=strlen(nLine); i>0; i--) {
*p = *nLine;
p ++; nLine ++;
}
if (p == q)
return;
for (int i=strlen(q); i>0; i--) {
*p = *q;
p ++; q ++;
}
*p = 0;
}
void list(char *prog)
{
char *p, *q;
int l = 1;
p = q = prog;
while (*q)
{
if (*q == '\r' || *q =='\n') {
#ifdef ARDUINO
Serial.print(l);
puertoUno.print(l);
Serial.print(F(" "));
puertoUno.print(F(" "));
#else
printf("%d ", l);
#endif
writeS(p, q-p);
printSln("");
l ++;
if (*q == '\r' && *(q+1) == '\n')
q ++;
q ++;
p = q;
continue;
}
q ++;
}
}
///////////////////////////////////////////////////////////////////////////
// Main function for PC and UNIX
///////////////////////////////////////////////////////////////////////////
#ifndef ARDUINO
int
main(int argc, char **argv)
{
int v;
if (argc == 2) {
if (eval2(argv[1], strlen(argv[1]), &v) != 0)
printf("error\n");
print(v);
} else {
prog = progbuf;
for (;;)
loop();
}
return 0;
}
#endif
/// TODO
// デバッグ用の出力(プログラムの位置、ピンの状態、変数の値)
// プログラムの編集
// メモリ(RAM)の節約
// プログラムの例 //
/* // LED の点滅 (1) //
pinMode(13, OUTPUT);
for(;;) {
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
delay(500);
}
*/
No hay comentarios:
Publicar un comentario